{"model_name":"gemini-2.5-flash-thinking","codes":{"1":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // for std::iota\n\n// Use a custom random number generator for better control and performance\nstd::mt19937_64 mt_rand(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Company data structure\nstruct Company {\n    int id;\n    int x, y, r; // desired location (cell x,y) and desired area\n};\n\n// Rectangle structure\nstruct Rect {\n    int x1, y1, x2, y2; // [x1, x2) x [y1, y2)\n    long long area() const {\n        return (long long)(x2 - x1) * (y2 - y1);\n    }\n    // Check if point (px, py) is contained (for 0.5 offset points, this means cell (px, py) is contained)\n    bool contains(int px, int py) const {\n        return x1 <= px && px < x2 && y1 <= py && py < y2;\n    }\n};\n\n// Node in the D&C tree\nstruct Node {\n    Rect rect; // The bounding box for this node\n    bool is_leaf;\n    int company_id; // Valid if is_leaf is true\n    bool is_vertical_cut; // True for vertical, false for horizontal\n    int cut_coord; // The coordinate of the cut\n    std::vector<int> company_indices; // Indices of companies in this node's rectangle\n    int parent_idx; // Index to parent node\n    int left_child_idx; // Index to left/bottom child\n    int right_child_idx; // Index to right/top child\n\n    Node(Rect r, bool leaf, int id, const std::vector<int>& indices)\n        : rect(r), is_leaf(leaf), company_id(id), is_vertical_cut(false), cut_coord(-1),\n          company_indices(indices), parent_idx(-1), left_child_idx(-1), right_child_idx(-1) {}\n};\n\nstd::vector<Company> companies_data;\nstd::vector<Rect> final_ad_rects;\nstd::vector<Node> tree_nodes;\nint N_global;\n\n// Calculate satisfaction for a single company\ndouble calculate_satisfaction(const Company& company, const Rect& ad_rect) {\n    if (!ad_rect.contains(company.x, company.y)) {\n        return 0.0;\n    }\n    long long s_i = ad_rect.area();\n    long long r_i = company.r;\n    if (s_i == 0) return 0.0; // Should not happen with positive area constraint\n    double ratio = (double)std::min(r_i, s_i) / std::max(r_i, s_i);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Calculate total score for current final_ad_rects\ndouble calculate_total_score() {\n    double total_p = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        total_p += calculate_satisfaction(companies_data[i], final_ad_rects[i]);\n    }\n    return total_p;\n}\n\n// Recursive function to build the D&C tree and determine initial rectangle placements\nvoid build_tree_and_solve(int node_idx, int x1, int y1, int x2, int y2, std::vector<int>&& indices) {\n    tree_nodes[node_idx].rect = {x1, y1, x2, y2};\n    tree_nodes[node_idx].company_indices = indices; // Store indices for SA\n\n    if (indices.empty()) {\n        tree_nodes[node_idx].is_leaf = true; // Mark as leaf, no company\n        return;\n    }\n    if (indices.size() == 1) {\n        tree_nodes[node_idx].is_leaf = true;\n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    int best_v_cut_coord = -1;\n    long long min_v_area_diff = -1;\n    int best_v_split_point_idx = -1;\n\n    int best_h_cut_coord = -1;\n    long long min_h_area_diff = -1;\n    int best_h_split_point_idx = -1;\n\n    long long total_r_sum = 0;\n    for (int idx : indices) total_r_sum += companies_data[idx].r;\n\n    // Try Vertical Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].x < companies_data[j].x;\n    });\n    long long current_left_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_left_r_sum += companies_data[indices[k]].r;\n        int max_x_left_group = companies_data[indices[k]].x;\n        int min_x_right_group = companies_data[indices[k+1]].x;\n        \n        // The cut coordinate must be strictly greater than max_x_left_group\n        // and less than or equal to min_x_right_group.\n        // Also must be within the current node's bounds (x1, x2)\n        int candidate_cut_coord = max_x_left_group + 1;\n        \n        // Ensure candidate_cut_coord is within parent bounds and valid for split\n        if (candidate_cut_coord > min_x_right_group || candidate_cut_coord < x1 + 1 || candidate_cut_coord > x2 - 1) {\n             continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_left_r_sum - (total_r_sum - current_left_r_sum));\n        if (best_v_cut_coord == -1 || diff < min_v_area_diff) {\n            min_v_area_diff = diff;\n            best_v_cut_coord = candidate_cut_coord;\n            best_v_split_point_idx = k + 1;\n        }\n    }\n\n    // Try Horizontal Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].y < companies_data[j].y;\n    });\n    long long current_bottom_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_bottom_r_sum += companies_data[indices[k]].r;\n        int max_y_bottom_group = companies_data[indices[k]].y;\n        int min_y_top_group = companies_data[indices[k+1]].y;\n        \n        int candidate_cut_coord = max_y_bottom_group + 1;\n\n        if (candidate_cut_coord > min_y_top_group || candidate_cut_coord < y1 + 1 || candidate_cut_coord > y2 - 1) {\n            continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_bottom_r_sum - (total_r_sum - current_bottom_r_sum));\n        if (best_h_cut_coord == -1 || diff < min_h_area_diff) {\n            min_h_area_diff = diff;\n            best_h_cut_coord = candidate_cut_coord;\n            best_h_split_point_idx = k + 1;\n        }\n    }\n    \n    // Choose the best cut among vertical and horizontal\n    int final_cut_coord = -1;\n    int final_split_point_idx = -1;\n    bool is_vertical_cut_chosen = false;\n\n    // Prioritize the cut along the longer side if area differences are comparable\n    bool preferred_vertical = (x2 - x1 >= y2 - y1);\n\n    if (best_v_cut_coord != -1 && best_h_cut_coord != -1) {\n        // If both are possible, choose the one with smaller area diff, or prefer longer side cut if diffs are close\n        if (min_v_area_diff < min_h_area_diff - total_r_sum / 20) { // vertical is significantly better\n            final_cut_coord = best_v_cut_coord;\n            final_split_point_idx = best_v_split_point_idx;\n            is_vertical_cut_chosen = true;\n        } else if (min_h_area_diff < min_v_area_diff - total_r_sum / 20) { // horizontal is significantly better\n            final_cut_coord = best_h_cut_coord;\n            final_split_point_idx = best_h_split_point_idx;\n            is_vertical_cut_chosen = false;\n        } else { // differences are similar, prefer cutting the longer side\n            if (preferred_vertical) {\n                final_cut_coord = best_v_cut_coord;\n                final_split_point_idx = best_v_split_point_idx;\n                is_vertical_cut_chosen = true;\n            } else {\n                final_cut_coord = best_h_cut_coord;\n                final_split_point_idx = best_h_split_point_idx;\n                is_vertical_cut_chosen = false;\n            }\n        }\n    } else if (best_v_cut_coord != -1) {\n        final_cut_coord = best_v_cut_coord;\n        final_split_point_idx = best_v_split_point_idx;\n        is_vertical_cut_chosen = true;\n    } else if (best_h_cut_coord != -1) {\n        final_cut_coord = best_h_cut_coord;\n        final_split_point_idx = best_h_split_point_idx;\n        is_vertical_cut_chosen = false;\n    } else {\n        // This case should ideally not be reached for indices.size() > 1\n        // It implies all points are effectively \"at the same spot\" relative to cuts,\n        // or the region is too small for any valid cut for multiple points.\n        // For distinct (x,y) points, this means the current area is 1x1, which implies only one company.\n        // If not, it's an error in logic or a very degenerate input that cannot be split.\n        // Fallback: assign to first company, but this is a rare undesirable scenario.\n        tree_nodes[node_idx].is_leaf = true; \n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    tree_nodes[node_idx].cut_coord = final_cut_coord;\n    tree_nodes[node_idx].is_vertical_cut = is_vertical_cut_chosen;\n\n    // Re-sort indices based on the chosen cut dimension for partitioning\n    if (is_vertical_cut_chosen) {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].x < companies_data[j].x;\n        });\n    } else {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].y < companies_data[j].y;\n        });\n    }\n\n    std::vector<int> left_indices(indices.begin(), indices.begin() + final_split_point_idx);\n    std::vector<int> right_indices(indices.begin() + final_split_point_idx, indices.end());\n\n    tree_nodes[node_idx].left_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    tree_nodes[node_idx].right_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    if (is_vertical_cut_chosen) {\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, final_cut_coord, y2, std::move(left_indices));\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, final_cut_coord, y1, x2, y2, std::move(right_indices));\n    } else { // Horizontal cut\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, x2, final_cut_coord, std::move(left_indices)); // 'left' means bottom here\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, x1, final_cut_coord, x2, y2, std::move(right_indices)); // 'right' means top here\n    }\n}\n\n// Function to update rectangles in a subtree after a cut coordinate changes\nvoid update_subtree_rects(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = tree_nodes[node_idx];\n    node.rect = {x1, y1, x2, y2};\n\n    if (node.is_leaf) {\n        if (node.company_id != -1) { \n            final_ad_rects[node.company_id] = {x1, y1, x2, y2};\n        }\n        return;\n    }\n\n    if (node.is_vertical_cut) {\n        update_subtree_rects(node.left_child_idx, x1, y1, node.cut_coord, y2);\n        update_subtree_rects(node.right_child_idx, node.cut_coord, y1, x2, y2);\n    } else { // Horizontal cut\n        update_subtree_rects(node.left_child_idx, x1, y1, x2, node.cut_coord);\n        update_subtree_rects(node.right_child_idx, x1, node.cut_coord, x2, y2);\n    }\n}\n\nvoid simulated_annealing(double time_limit_ms) {\n    auto start_time = std::chrono::steady_clock::now();\n    \n    // Initial solution and score\n    double current_score = calculate_total_score();\n    double best_score = current_score;\n    std::vector<Rect> best_ad_rects = final_ad_rects;\n    // We don't need to copy the entire tree_nodes for best_tree_nodes, \n    // as final_ad_rects holds the actual solution output.\n    // However, for SA, we do need to revert tree_nodes if a move is rejected.\n    // So, we'll make a copy of the specific node's cut_coord and revert.\n\n    // SA parameters\n    double T_start = 0.5; // Tuned for typical score changes\n    double T_end = 1e-9;\n    \n    std::uniform_real_distribution<double> dist_01(0.0, 1.0);\n    // Only choose internal nodes for modification\n    std::uniform_int_distribution<int> dist_internal_node(0, N_global - 2); // There are N-1 internal nodes for N leaves in a binary tree\n    \n    // Cache min/max x/y for subtrees to speed up neighbor generation\n    // This is precalculated, actual coordinates might need to be retrieved from children's company_indices.\n    // Let's retrieve this dynamically.\n\n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms >= time_limit_ms) {\n            break;\n        }\n\n        // Cooling schedule (exponential)\n        double T = T_start * std::pow(T_end / T_start, elapsed_ms / time_limit_ms);\n\n        // Pick a random internal node to modify its cut (skip leaf nodes)\n        // Note: dist_internal_node generates index from 0 to N_global-2.\n        // If tree_nodes contains nodes in depth-first order of the D&C,\n        // then the first N_global-1 nodes are typically internal nodes.\n        // A simple way is to iterate random node_idx until an internal node is found.\n        int node_idx_to_modify;\n        do {\n             node_idx_to_modify = dist_internal_node(mt_rand); // Get an index for an internal node\n        } while (tree_nodes[node_idx_to_modify].is_leaf);\n\n\n        Node& node_to_modify = tree_nodes[node_idx_to_modify];\n        \n        // Find valid range for cut_coord based on parent's rect and child points\n        int min_cut_coord_bound = -1, max_cut_coord_bound = -1;\n        \n        // Parent's rect boundaries are stored in node_to_modify.rect from update_subtree_rects call\n        int parent_x1 = node_to_modify.rect.x1;\n        int parent_y1 = node_to_modify.rect.y1;\n        int parent_x2 = node_to_modify.rect.x2;\n        int parent_y2 = node_to_modify.rect.y2;\n        \n        if (node_to_modify.is_vertical_cut) {\n            int max_x_in_left_subtree = -1;\n            for (int company_idx : tree_nodes[node_to_modify.left_child_idx].company_indices) {\n                if (max_x_in_left_subtree == -1 || companies_data[company_idx].x > max_x_in_left_subtree) {\n                    max_x_in_left_subtree = companies_data[company_idx].x;\n                }\n            }\n            int min_x_in_right_subtree = 10001; // Max X is 9999\n            for (int company_idx : tree_nodes[node_to_modify.right_child_idx].company_indices) {\n                if (min_x_in_right_subtree == 10001 || companies_data[company_idx].x < min_x_in_right_subtree) {\n                    min_x_in_right_subtree = companies_data[company_idx].x;\n                }\n            }\n            \n            // Valid range for vertical cut: (max_x_left_subtree, min_x_right_subtree]\n            // Also must be within parent bounds: (parent_x1, parent_x2)\n            min_cut_coord_bound = std::max(parent_x1 + 1, max_x_in_left_subtree + 1);\n            max_cut_coord_bound = std::min(parent_x2 - 1, min_x_in_right_subtree);\n\n        } else { // Horizontal cut\n            int max_y_in_bottom_subtree = -1;\n            for (int company_idx : tree_nodes[node_to_modify.left_child_idx].company_indices) { // Left child refers to bottom here\n                if (max_y_in_bottom_subtree == -1 || companies_data[company_idx].y > max_y_in_bottom_subtree) {\n                    max_y_in_bottom_subtree = companies_data[company_idx].y;\n                }\n            }\n            int min_y_in_top_subtree = 10001; // Max Y is 9999\n            for (int company_idx : tree_nodes[node_to_modify.right_child_idx].company_indices) { // Right child refers to top here\n                if (min_y_in_top_subtree == 10001 || companies_data[company_idx].y < min_y_in_top_subtree) {\n                    min_y_in_top_subtree = companies_data[company_idx].y;\n                }\n            }\n            min_cut_coord_bound = std::max(parent_y1 + 1, max_y_in_bottom_subtree + 1);\n            max_cut_coord_bound = std::min(parent_y2 - 1, min_y_in_top_subtree);\n        }\n\n        if (min_cut_coord_bound > max_cut_coord_bound) {\n            continue; // Cannot move this cut, it's fixed\n        }\n\n        // Store old cut_coord for backtracking\n        int original_cut_coord = node_to_modify.cut_coord;\n        \n        // Generate new cut_coord randomly within valid range\n        std::uniform_int_distribution<int> dist_cut(min_cut_coord_bound, max_cut_coord_bound);\n        node_to_modify.cut_coord = dist_cut(mt_rand);\n        \n        if (original_cut_coord == node_to_modify.cut_coord) { // If random pick same as old, no change\n            continue;\n        }\n\n        // Update rectangles and calculate new score\n        update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        double new_score = calculate_total_score();\n\n        if (new_score > current_score || dist_01(mt_rand) < std::exp((new_score - current_score) / T)) {\n            // Accept new state\n            current_score = new_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ad_rects = final_ad_rects;\n            }\n        } else {\n            // Revert to old state\n            node_to_modify.cut_coord = original_cut_coord;\n            update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        }\n    }\n    \n    final_ad_rects = best_ad_rects;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N_global;\n\n    companies_data.resize(N_global);\n    final_ad_rects.resize(N_global);\n    std::vector<int> initial_company_indices(N_global);\n\n    for (int i = 0; i < N_global; ++i) {\n        companies_data[i].id = i;\n        std::cin >> companies_data[i].x >> companies_data[i].y >> companies_data[i].r;\n        initial_company_indices[i] = i;\n    }\n\n    // Build the initial D&C tree\n    tree_nodes.reserve(2 * N_global); // Max nodes in binary tree is 2N-1\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{}); // Root node\n    \n    build_tree_and_solve(0, 0, 0, 10000, 10000, std::move(initial_company_indices));\n    \n    // Simulated Annealing\n    // Using 4.9 seconds out of 5.0s total time limit.\n    simulated_annealing(4900.0); \n    \n    // Output the results\n    for (int i = 0; i < N_global; ++i) {\n        std::cout << final_ad_rects[i].x1 << \" \" << final_ad_rects[i].y1 << \" \"\n                  << final_ad_rects[i].x2 << \" \" << final_ad_rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <bitset>\n#include <random>\n#include <numeric> // For iota\n#include <tuple>   // For std::tuple\n\n// Using standard namespace for convenience in competitive programming\nusing namespace std;\n\n// Constants\nconst int GRID_SIZE = 50;\nconst int MAX_TILES = GRID_SIZE * GRID_SIZE; // Max possible number of tiles (all 1x1)\n\n// Global variables to store input data\nint si, sj; // Start row, start column\nint tile_id_grid[GRID_SIZE][GRID_SIZE]; // tile_id_grid[i][j] stores the tile ID for square (i,j)\nint p_grid[GRID_SIZE][GRID_SIZE];       // p_grid[i][j] stores the score value for square (i,j)\n\n// Global variables for best path found so far\nlong long max_score_global = 0;\nstring best_path_string_global = \"\";\n\n// Random number generator. Using std::mt19937 for better randomness than rand().\nmt19937 rng;\n\n// Structure to represent a potential move\nstruct Move {\n    int r, c;           // Next square's row and column\n    char move_char;     // Character representing the move ('U', 'D', 'L', 'R')\n    int score_value;    // Score obtained by moving to (r, c)\n    int tile_id;        // Tile ID of the next square\n};\n\n// Function to get all valid next moves from the current position (r, c)\n// A move is valid if it stays within grid boundaries and leads to an unvisited tile.\nvector<Move> get_valid_moves(int r, int c, const bitset<MAX_TILES>& visited_tiles) {\n    vector<Move> valid_moves;\n    // Possible movements: Up, Down, Left, Right\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1}; \n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n\n        // Check if the next position is within grid boundaries\n        if (nr >= 0 && nr < GRID_SIZE && nc >= 0 && nc < GRID_SIZE) {\n            int next_tile_id = tile_id_grid[nr][nc];\n            // Check if the tile has not been visited yet\n            if (!visited_tiles[next_tile_id]) {\n                valid_moves.push_back({nr, nc, move_chars[k], p_grid[nr][nc], next_tile_id});\n            }\n        }\n    }\n    return valid_moves;\n}\n\n// Function to generate a single path using a randomized greedy approach.\n// It stops when no more valid moves are available or the time limit for this path generation is near.\npair<long long, string> generate_path(chrono::high_resolution_clock::time_point global_start_time, chrono::milliseconds total_time_limit) {\n    long long current_score = p_grid[si][sj]; // Start with score of initial square\n    string current_path_str = \"\";\n    bitset<MAX_TILES> visited_tiles; // Keep track of visited tiles\n    visited_tiles[tile_id_grid[si][sj]] = true; // Mark initial tile as visited\n    int curr_r = si;\n    int curr_c = sj;\n\n    // Use a local random number generator for path generation, seeded by the global one.\n    // This ensures different paths are generated across calls to generate_path.\n    mt19937 local_rng(rng()); \n\n    // Continue extending the path until no more moves or global time limit is approached\n    while (true) {\n        // Periodically check remaining time to avoid exceeding total_time_limit\n        // Stop if less than 10ms remaining to finish current path and update best.\n        // This small buffer helps ensure the program terminates gracefully within the limit.\n        if (chrono::high_resolution_clock::now() - global_start_time >= total_time_limit - chrono::milliseconds(10)) {\n            break; \n        }\n\n        vector<Move> moves = get_valid_moves(curr_r, curr_c, visited_tiles);\n        if (moves.empty()) {\n            break; // No more valid moves from current position\n        }\n\n        // Sort valid moves by their score value in descending order.\n        // This prioritizes moves that give higher immediate scores.\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.score_value > b.score_value;\n        });\n\n        // Heuristic: consider a \"beam\" of top N moves, and pick one randomly.\n        // This balances greedy exploitation (higher scores) with exploration (trying other options).\n        // `effective_beam_width` is set to 5, meaning we consider the top 5 highest-scoring moves.\n        int effective_beam_width = min((int)moves.size(), 5); \n        \n        // Randomly pick an index within the `effective_beam_width`.\n        // This introduces randomness while still preferring high-scoring moves.\n        uniform_int_distribution<int> dist(0, effective_beam_width - 1);\n        int choice_idx = dist(local_rng);\n        \n        const Move& chosen_move = moves[choice_idx];\n\n        // Update current state based on the chosen move\n        curr_r = chosen_move.r;\n        curr_c = chosen_move.c;\n        current_score += chosen_move.score_value;\n        current_path_str += chosen_move.move_char;\n        visited_tiles[chosen_move.tile_id] = true;\n    }\n    return {current_score, current_path_str};\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed the random number generator using the current time.\n    // This provides a different sequence of random numbers for each execution,\n    // which is crucial for iterated randomized algorithms.\n    rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Read input: starting position (si, sj)\n    cin >> si >> sj;\n\n    // Read tile IDs for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> tile_id_grid[i][j];\n        }\n    }\n\n    // Read score values for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> p_grid[i][j];\n        }\n    }\n\n    // Initialize global best score with the score of the starting square.\n    // The path string is initially empty as no moves have been made yet (start square is implicitly visited).\n    max_score_global = p_grid[si][sj];\n    best_path_string_global = \"\"; \n\n    // Record the start time of the entire program execution\n    auto global_start_time = chrono::high_resolution_clock::now();\n    // Set a total time limit slightly less than 2 seconds (e.g., 1950 ms) to ensure output completes.\n    const auto TOTAL_TIME_LIMIT = chrono::milliseconds(1950); \n\n    // Iteratively generate paths and keep the best one found within the time limit.\n    while (chrono::high_resolution_clock::now() - global_start_time < TOTAL_TIME_LIMIT) {\n        // Call generate_path with the global start time and total time limit.\n        // The path generation function itself will manage its internal time checking.\n        pair<long long, string> result = generate_path(global_start_time, TOTAL_TIME_LIMIT);\n        \n        // If the newly generated path has a higher score, update the global best.\n        if (result.first > max_score_global) {\n            max_score_global = result.first;\n            best_path_string_global = result.second;\n        }\n    }\n\n    // Output the sequence of moves for the highest scoring path found.\n    cout << best_path_string_global << endl;\n\n    return 0;\n}\n","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <algorithm> // For std::reverse\n\n// Constants\nconst int GRID_SIZE = 30;\nconst int NUM_VERTICES = GRID_SIZE * GRID_SIZE;\n\n// Edge structures\n// h_len[i][j] is edge between (i,j) and (i,j+1)\n// v_len[i][j] is edge between (i,j) and (i+1,j)\n// These arrays store estimated lengths and usage counts for each individual edge.\ndouble estimated_h_len[GRID_SIZE][GRID_SIZE - 1];\ndouble estimated_v_len[GRID_SIZE - 1][GRID_SIZE];\n\nlong long usage_h_count[GRID_SIZE][GRID_SIZE - 1];\nlong long usage_v_count[GRID_SIZE - 1][GRID_SIZE];\n\n// Node to index mapping for Dijkstra's\nint node_to_idx(int r, int c) {\n    return r * GRID_SIZE + c;\n}\n\n// Index to node mapping (not strictly needed in find_path but good for debugging)\nstd::pair<int, int> idx_to_node(int idx) {\n    return {idx / GRID_SIZE, idx % GRID_SIZE};\n}\n\n// Dijkstra's algorithm to find the shortest path based on current estimates\nstd::string find_path(int start_r, int start_c, int end_r, int end_c, double& path_estimated_len) {\n    int start_idx = node_to_idx(start_r, start_c);\n    int end_idx = node_to_idx(end_r, end_c);\n\n    // dist[u_idx] stores the shortest estimated distance from start_idx to u_idx\n    std::vector<double> dist(NUM_VERTICES, 1e18); // Initialize with a very large value\n    // prev_node[u_idx] stores the predecessor node in the shortest path to u_idx\n    std::vector<int> prev_node(NUM_VERTICES, -1);\n    // prev_dir[u_idx] stores the direction taken from prev_node[u_idx] to u_idx\n    std::vector<char> prev_dir(NUM_VERTICES, ' ');\n\n    // Priority queue for Dijkstra: {distance, node_index}\n    std::priority_queue<std::pair<double, int>, std::vector<std::pair<double, int>>, std::greater<std::pair<double, int>>> pq;\n\n    dist[start_idx] = 0;\n    pq.push({0, start_idx});\n\n    while (!pq.empty()) {\n        double d = pq.top().first;\n        int u_idx = pq.top().second;\n        pq.pop();\n\n        // If we found a shorter path already, skip this one\n        if (d > dist[u_idx]) continue;\n        // If we reached the destination, we can stop\n        if (u_idx == end_idx) break;\n\n        int ur = idx_to_node(u_idx).first;\n        int uc = idx_to_node(u_idx).second;\n\n        // Explore neighbors (Up, Down, Left, Right)\n        // U: (ur-1, uc)\n        if (ur > 0) {\n            int v_idx = node_to_idx(ur - 1, uc);\n            // Edge is between (ur-1,uc) and (ur,uc)\n            double weight = estimated_v_len[ur - 1][uc]; \n            if (dist[u_idx] + weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'U'; // Direction to get to v_idx from u_idx\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // D: (ur+1, uc)\n        if (ur < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur + 1, uc);\n            // Edge is between (ur,uc) and (ur+1,uc)\n            double weight = estimated_v_len[ur][uc]; \n            if (dist[u_idx] + weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'D';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // L: (ur, uc-1)\n        if (uc > 0) {\n            int v_idx = node_to_idx(ur, uc - 1);\n            // Edge is between (ur,uc-1) and (ur,uc)\n            double weight = estimated_h_len[ur][uc - 1]; \n            if (dist[u_idx] + weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'L';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // R: (ur, uc+1)\n        if (uc < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur, uc + 1);\n            // Edge is between (ur,uc) and (ur,uc+1)\n            double weight = estimated_h_len[ur][uc]; \n            if (dist[u_idx] + weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'R';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n    }\n\n    // Reconstruct path string by backtracking from end_idx to start_idx\n    std::string path_str = \"\";\n    int curr_idx = end_idx;\n    // Loop until we reach the start node or an unreachable node\n    while (curr_idx != start_idx && curr_idx != -1) {\n        if (prev_node[curr_idx] == -1) { // Path is not found (shouldn't happen in a connected grid graph)\n             path_estimated_len = 1e18; // Indicate path not found\n             return \"\";\n        }\n        path_str += prev_dir[curr_idx];\n        curr_idx = prev_node[curr_idx];\n    }\n    std::reverse(path_str.begin(), path_str.end()); // Reverse to get path from start to end\n    \n    path_estimated_len = dist[end_idx]; // The total estimated length of the path\n    return path_str;\n}\n\n// Function to clamp a double value within a specified range\ndouble clamp(double val, double min_val, double max_val) {\n    if (val < min_val) return min_val;\n    if (val > max_val) return max_val;\n    return val;\n}\n\nvoid solve() {\n    // Initialize estimated edge lengths to average possible value (5000)\n    // Initialize usage counts to 1 to prevent division by zero and provide a base for alpha decay\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            estimated_h_len[i][j] = 5000.0;\n            usage_h_count[i][j] = 1; \n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            estimated_v_len[i][j] = 5000.0;\n            usage_v_count[i][j] = 1; \n        }\n    }\n\n    // Main query loop\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        std::cin >> si >> sj >> ti >> tj;\n\n        double current_path_estimated_len;\n        std::string path = find_path(si, sj, ti, tj, current_path_estimated_len);\n        \n        std::cout << path << std::endl;\n        std::cout.flush(); // IMPORTANT: Flush output after each path\n\n        int observed_path_len_int;\n        std::cin >> observed_path_len_int;\n        double observed_path_len = static_cast<double>(observed_path_len_int);\n\n        // Update edge length estimates\n        // Calculate a scaling factor based on the observed path length vs. estimated path length\n        // This factor is applied to all edges on the path.\n        // It reflects how much our overall path estimate was off.\n        double scaling_factor = observed_path_len / current_path_estimated_len;\n        \n        // C constant for alpha calculation. A larger C makes alpha decay slower.\n        // This value is a heuristic; tuning might improve performance.\n        const double C = 10.0; \n\n        int curr_r = si;\n        int curr_c = sj;\n\n        // Iterate through the path's directions to identify each edge used\n        for (char dir : path) {\n            switch (dir) {\n                case 'U': // Moving from (curr_r, curr_c) to (curr_r-1, curr_c)\n                    // This uses the vertical edge connecting (curr_r-1, curr_c) and (curr_r, curr_c)\n                    {\n                        // Alpha for weighted average update, decreases with more usage\n                        double alpha = 1.0 / (usage_v_count[curr_r - 1][curr_c] + C);\n                        // The 'new_estimate' for this specific edge, assuming uniform scaling\n                        double new_estimate = estimated_v_len[curr_r - 1][curr_c] * scaling_factor;\n                        // Update the edge's estimate using the weighted average and clamp it\n                        estimated_v_len[curr_r - 1][curr_c] = clamp((1.0 - alpha) * estimated_v_len[curr_r - 1][curr_c] + alpha * new_estimate, 500.0, 10000.0);\n                        usage_v_count[curr_r - 1][curr_c]++; // Increment usage count\n                    }\n                    curr_r--; // Move to the new current position\n                    break;\n                case 'D': // Moving from (curr_r, curr_c) to (curr_r+1, curr_c)\n                    // Uses vertical edge connecting (curr_r, curr_c) and (curr_r+1, curr_c)\n                    {\n                        double alpha = 1.0 / (usage_v_count[curr_r][curr_c] + C);\n                        double new_estimate = estimated_v_len[curr_r][curr_c] * scaling_factor;\n                        estimated_v_len[curr_r][curr_c] = clamp((1.0 - alpha) * estimated_v_len[curr_r][curr_c] + alpha * new_estimate, 500.0, 10000.0);\n                        usage_v_count[curr_r][curr_c]++;\n                    }\n                    curr_r++;\n                    break;\n                case 'L': // Moving from (curr_r, curr_c) to (curr_r, curr_c-1)\n                    // Uses horizontal edge connecting (curr_r, curr_c-1) and (curr_r, curr_c)\n                    {\n                        double alpha = 1.0 / (usage_h_count[curr_r][curr_c - 1] + C);\n                        double new_estimate = estimated_h_len[curr_r][curr_c - 1] * scaling_factor;\n                        estimated_h_len[curr_r][curr_c - 1] = clamp((1.0 - alpha) * estimated_h_len[curr_r][curr_c - 1] + alpha * new_estimate, 500.0, 10000.0);\n                        usage_h_count[curr_r][curr_c - 1]++;\n                    }\n                    curr_c--;\n                    break;\n                case 'R': // Moving from (curr_r, curr_c) to (curr_r, curr_c+1)\n                    // Uses horizontal edge connecting (curr_r, curr_c) and (curr_r, curr_c+1)\n                    {\n                        double alpha = 1.0 / (usage_h_count[curr_r][curr_c] + C);\n                        double new_estimate = estimated_h_len[curr_r][curr_c] * scaling_factor;\n                        estimated_h_len[curr_r][curr_c] = clamp((1.0 - alpha) * estimated_h_len[curr_r][curr_c] + alpha * new_estimate, 500.0, 10000.0);\n                        usage_h_count[curr_r][curr_c]++;\n                    }\n                    curr_c++;\n                    break;\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <tuple> // For std::tie and std::tuple\n\n// Global constants\nconst int N_MATRIX = 20; // N is fixed to 20\nint M;\nstd::vector<std::string> S; // Input strings\n\n// Character to integer mapping for internal use (A=0, ..., H=7, .=8)\nstd::map<char, int> char_to_int_map;\nstd::vector<char> int_to_char_map;\n\n// Simulated Annealing parameters\nlong long MAX_ITERATIONS = 50000000; \ndouble START_TEMP = 2.0;\ndouble END_TEMP = 1e-9;\n\n// Random number generator\nstd::mt19937 mt;\n\n// Time measurement\nstd::chrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 2.9; // seconds\n\n// --- State Variables for SA ---\nstd::vector<std::string> current_grid;\nint num_dots; // number of '.' in current_grid\nint num_matched_strings; // current 'c' value (number of unique strings found at least once)\n\n// For each string s_idx, how many distinct (start_r, start_c, dir) locations does it currently match?\nstd::vector<int> num_actual_matches_for_string; // size M\n\n// --- Precomputed data structures for efficient updates ---\n// Each struct represents a unique \"match window\" (a string starting at a specific cell in a specific direction)\nstruct PotentialMatchInfoBase {\n    int s_idx;\n    int sr, sc; // start row, start col\n    int dir;    // 0 for horizontal, 1 for vertical\n};\n\n// Vector storing all unique PotentialMatchInfoBase instances\nstd::vector<PotentialMatchInfoBase> all_potential_match_info_bases; \n\n// Maps (s_idx, sr, sc, dir) to its index in all_potential_match_info_bases\nstd::map<std::tuple<int, int, int, int>, int> potential_match_key_to_idx; \n\n// For each grid cell (r_covered, c_covered), this list stores pairs of:\n// <index to all_potential_match_info_bases, p_in_s>\n// `p_in_s` is the position of (r_covered, c_covered) within the string S[s_idx]\nstd::vector<std::pair<int, int>> cell_covers[N_MATRIX][N_MATRIX];\n\n// For each potential match (identified by its index `pm_idx`), the number of mismatches (chars don't match or are '.')\nstd::vector<int> num_mismatches_for_potential_match; \n// For each potential match (identified by `pm_idx`), true if it currently matches the grid perfectly\nstd::vector<bool> is_potential_match_active; \n\n// Helper for modulo arithmetic (for negative numbers)\nint mod(int i, int n) {\n    return (i % n + n) % n;\n}\n\nvoid init_char_maps() {\n    char_to_int_map['A'] = 0; char_to_int_map['B'] = 1; char_to_int_map['C'] = 2; char_to_int_map['D'] = 3;\n    char_to_int_map['E'] = 4; char_to_int_map['F'] = 5; char_to_int_map['G'] = 6; char_to_int_map['H'] = 7;\n    char_to_int_map['.'] = 8;\n\n    int_to_char_map.resize(9);\n    int_to_char_map[0] = 'A'; int_to_char_map[1] = 'B'; int_to_char_map[2] = 'C'; int_to_char_map[3] = 'D';\n    int_to_char_map[4] = 'E'; int_to_char_map[5] = 'F'; int_to_char_map[6] = 'G'; int_to_char_map[7] = 'H';\n    int_to_char_map[8] = '.';\n}\n\n// Score calculation: objective function for SA (values are scaled to be continuous and prioritize c=M)\ndouble calculate_objective(int c, int d) {\n    if (c < M) {\n        return (double)c / M;\n    } else {\n        // Add 1.0 to ensure this score range is strictly higher than c < M range\n        // Max value for 2*N_MATRIX*N_MATRIX / (2*N_MATRIX*N_MATRIX - d) is 2.0 (when d=N_MATRIX*N_MATRIX)\n        // Min value is 1.0 (when d=0)\n        return 1.0 + (double)(2.0 * N_MATRIX * N_MATRIX) / (2.0 * N_MATRIX * N_MATRIX - d);\n    }\n}\n\nvoid precompute_potential_matches() {\n    int pm_counter = 0; // Counts unique potential match windows\n\n    for (int r_covered = 0; r_covered < N_MATRIX; ++r_covered) {\n        for (int c_covered = 0; c_covered < N_MATRIX; ++c_covered) {\n            for (int s_idx = 0; s_idx < M; ++s_idx) {\n                int k = S[s_idx].length();\n\n                // Horizontal matches that cover (r_covered, c_covered)\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) { \n                    int sr = r_covered;\n                    int sc = mod(c_covered - p_in_s, N_MATRIX);\n                    \n                    std::tuple<int, int, int, int> pm_key = {s_idx, sr, sc, 0}; // 0 for horizontal\n                    if (potential_match_key_to_idx.find(pm_key) == potential_match_key_to_idx.end()) {\n                        potential_match_key_to_idx[pm_key] = pm_counter++;\n                        all_potential_match_info_bases.push_back({s_idx, sr, sc, 0});\n                    }\n                    int pm_idx = potential_match_key_to_idx[pm_key];\n                    cell_covers[r_covered][c_covered].push_back({pm_idx, p_in_s}); \n                }\n\n                // Vertical matches that cover (r_covered, c_covered)\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int sr = mod(r_covered - p_in_s, N_MATRIX);\n                    int sc = c_covered;\n\n                    std::tuple<int, int, int, int> pm_key = {s_idx, sr, sc, 1}; // 1 for vertical\n                    if (potential_match_key_to_idx.find(pm_key) == potential_match_key_to_idx.end()) {\n                        potential_match_key_to_idx[pm_key] = pm_counter++;\n                        all_potential_match_info_bases.push_back({s_idx, sr, sc, 1});\n                    }\n                    int pm_idx = potential_match_key_to_idx[pm_key];\n                    cell_covers[r_covered][c_covered].push_back({pm_idx, p_in_s}); \n                }\n            }\n        }\n    }\n\n    num_mismatches_for_potential_match.resize(pm_counter);\n    is_potential_match_active.resize(pm_counter, false);\n}\n\nvoid initialize_state() {\n    current_grid.assign(N_MATRIX, std::string(N_MATRIX, '.')); // Start with all empty cells\n    num_dots = N_MATRIX * N_MATRIX;\n    num_matched_strings = 0;\n    num_actual_matches_for_string.assign(M, 0);\n\n    // Calculate initial mismatch counts for all potential match windows\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        const std::string& s = S[pm_info_base.s_idx];\n        int k = s.length();\n        int mismatches = 0;\n\n        for (int p = 0; p < k; ++p) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n            \n            // A mismatch occurs if the grid character doesn't match the string character OR if it's '.'\n            if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                mismatches++;\n            }\n        }\n        num_mismatches_for_potential_match[pm_idx] = mismatches;\n\n        if (mismatches == 0) { // This potential match is currently active\n            is_potential_match_active[pm_idx] = true;\n            num_actual_matches_for_string[pm_info_base.s_idx]++;\n            if (num_actual_matches_for_string[pm_info_base.s_idx] == 1) { // First match for this string\n                num_matched_strings++;\n            }\n        }\n    }\n}\n\nvoid solve() {\n    start_time = std::chrono::high_resolution_clock::now();\n    \n    init_char_maps();\n    precompute_potential_matches();\n    initialize_state();\n\n    std::uniform_int_distribution<int> dist_rc(0, N_MATRIX - 1);\n    std::uniform_int_distribution<int> dist_char(0, int_to_char_map.size() - 1); // 9 options: A-H, .\n    std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    double best_score = calculate_objective(num_matched_strings, num_dots);\n    std::vector<std::string> best_grid = current_grid;\n\n    for (long long iter = 0; iter < MAX_ITERATIONS; ++iter) {\n        double current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            std::chrono::high_resolution_clock::now() - start_time).count() / 1e9;\n        if (current_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = START_TEMP * std::pow(END_TEMP / START_TEMP, (double)iter / MAX_ITERATIONS);\n\n        int r_changed = dist_rc(mt);\n        int c_changed = dist_rc(mt);\n        char old_char = current_grid[r_changed][c_changed];\n        char new_char = int_to_char_map[dist_char(mt)];\n\n        if (new_char == old_char) continue; // No change, no need to proceed\n\n        // --- Store current state for potential revert ---\n        int prev_num_dots = num_dots;\n        int prev_num_matched_strings_overall = num_matched_strings;\n        \n        // Map to store original match counts for affected strings\n        // s_idx -> old count for this string (before the current perturbation)\n        std::map<int, int> s_idx_to_old_actual_match_count_snapshot; \n\n        // Temporarily store original mismatch counts for affected potential matches for quick revert\n        std::vector<int> original_mismatches_for_affected_pm;\n        std::vector<int> affected_pm_indices;\n\n        // --- Apply change and calculate deltas ---\n        // Update num_dots\n        if (old_char == '.' && new_char != '.') { num_dots--; }\n        else if (old_char != '.' && new_char == '.') { num_dots++; }\n        \n        // Iterate through all potential match windows affected by this cell change\n        for (auto const& p : cell_covers[r_changed][c_changed]) {\n            int pm_idx = p.first;\n            int p_in_s = p.second; // Position of (r_changed, c_changed) within S[s_idx]\n\n            affected_pm_indices.push_back(pm_idx);\n            original_mismatches_for_affected_pm.push_back(num_mismatches_for_potential_match[pm_idx]);\n\n            const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n            int s_idx = pm_info_base.s_idx;\n            char required_char = S[s_idx][p_in_s];\n\n            // Store original match count for this string if not already done in the snapshot\n            if (s_idx_to_old_actual_match_count_snapshot.find(s_idx) == s_idx_to_old_actual_match_count_snapshot.end()) {\n                s_idx_to_old_actual_match_count_snapshot[s_idx] = num_actual_matches_for_string[s_idx];\n            }\n\n            // Determine if old/new chars are a mismatch\n            bool old_char_was_bad = (old_char != required_char || old_char == '.');\n            bool new_char_is_bad = (new_char != required_char || new_char == '.');\n\n            // Update mismatch count for this potential match window\n            if (old_char_was_bad && !new_char_is_bad) { // Cell character changed from bad to good for this match\n                num_mismatches_for_potential_match[pm_idx]--;\n            } else if (!old_char_was_bad && new_char_is_bad) { // Cell character changed from good to bad for this match\n                num_mismatches_for_potential_match[pm_idx]++;\n            }\n\n            // Update active status for this potential match window and string's actual match count\n            bool was_match_active = is_potential_match_active[pm_idx];\n            bool is_match_active = (num_mismatches_for_potential_match[pm_idx] == 0);\n\n            if (!was_match_active && is_match_active) {\n                is_potential_match_active[pm_idx] = true;\n                num_actual_matches_for_string[s_idx]++;\n            } else if (was_match_active && !is_match_active) {\n                is_potential_match_active[pm_idx] = false;\n                num_actual_matches_for_string[s_idx]--;\n            }\n        }\n\n        // Calculate actual change in num_matched_strings (c) for the proposed state\n        int proposed_num_matched_strings_overall = prev_num_matched_strings_overall;\n        for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n            if (old_count == 0 && num_actual_matches_for_string[s_idx] > 0) proposed_num_matched_strings_overall++;\n            if (old_count > 0 && num_actual_matches_for_string[s_idx] == 0) proposed_num_matched_strings_overall--;\n        }\n\n        // --- Decision (Accept/Revert) ---\n        double current_objective = calculate_objective(prev_num_matched_strings_overall, prev_num_dots);\n        double proposed_objective = calculate_objective(proposed_num_matched_strings_overall, num_dots);\n\n        if (proposed_objective >= current_objective || dist_prob(mt) < std::exp((proposed_objective - current_objective) / T)) {\n            // Accept the change:\n            current_grid[r_changed][c_changed] = new_char;\n            num_matched_strings = proposed_num_matched_strings_overall; // Update global c\n            // num_dots, num_mismatches_for_potential_match, is_potential_match_active,\n            // num_actual_matches_for_string are already updated for the proposed state\n        } else {\n            // Revert the change:\n            num_dots = prev_num_dots; // Revert num_dots\n\n            // Revert mismatch counts and active status for affected potential matches\n            for (size_t i = 0; i < affected_pm_indices.size(); ++i) {\n                int pm_idx = affected_pm_indices[i];\n                num_mismatches_for_potential_match[pm_idx] = original_mismatches_for_affected_pm[i];\n                is_potential_match_active[pm_idx] = (num_mismatches_for_potential_match[pm_idx] == 0);\n            }\n\n            // Revert num_actual_matches_for_string for affected strings\n            for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n                num_actual_matches_for_string[s_idx] = old_count;\n            }\n            // num_matched_strings remains prev_num_matched_strings_overall (it was not globally updated in the proposed path)\n        }\n\n        // Update best score and grid\n        if (proposed_objective > best_score) { // Use proposed_objective as the comparison point, even if rejected. This helps escape local optima\n            best_score = proposed_objective;\n            best_grid = current_grid;\n        }\n    }\n\n    current_grid = best_grid; // Output the best grid found\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N_input; // Read N, but use N_MATRIX as fixed constant\n    std::cin >> N_input >> M; // N_input should be 20\n    S.resize(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> S[i];\n    }\n\n    solve();\n\n    for (int i = 0; i < N_MATRIX; ++i) {\n        std::cout << current_grid[i] << std::endl;\n    }\n\n    return 0;\n}\n","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n// No external libraries other than standard C++ ones are strictly necessary for this approach.\n\nusing namespace std;\n\n// Global data to avoid passing many arguments and simplify access\nint N_global;\nint SI_global, SJ_global;\nvector<string> grid_global;\nvector<vector<int>> costs_global; // Stores char '5'-'9' as int\nvector<vector<bool>> is_road_global;\n// visible_left/right/up/down store the inclusive boundaries of the visible segment\n// For example, visible_left_global[r][c] is the minimum column index k such that (r,k) is road and on the path to (r,c)\nvector<vector<int>> visible_left_global, visible_right_global, visible_up_global, visible_down_global; \nint total_road_squares_global = 0;\nvector<vector<bool>> covered_status_global; // True if the square has been made visible\nint current_covered_count_global = 0;\n\n// Structure for Dijkstra's priority queue\nstruct State {\n    int r, c;\n    long long cost;\n    // For priority queue: min-heap based on cost\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Precomputation of visible ranges for each road square (O(N^3))\n// This populates visible_left/right/up/down_global arrays\nvoid precompute_visibility() {\n    visible_left_global.assign(N_global, vector<int>(N_global));\n    visible_right_global.assign(N_global, vector<int>(N_global));\n    visible_up_global.assign(N_global, vector<int>(N_global));\n    visible_down_global.assign(N_global, vector<int>(N_global));\n\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            if (!is_road_global[i][j]) continue; // Only process road squares\n\n            // Horizontal visibility (left)\n            int left_bound = j;\n            while (left_bound > 0 && is_road_global[i][left_bound - 1]) {\n                left_bound--;\n            }\n            visible_left_global[i][j] = left_bound;\n\n            // Horizontal visibility (right)\n            int right_bound = j;\n            while (right_bound < N_global - 1 && is_road_global[i][right_bound + 1]) {\n                right_bound++;\n            }\n            visible_right_global[i][j] = right_bound;\n\n            // Vertical visibility (up)\n            int up_bound = i;\n            while (up_bound > 0 && is_road_global[up_bound - 1][j]) {\n                up_bound--;\n            }\n            visible_up_global[i][j] = up_bound;\n\n            // Vertical visibility (down)\n            int down_bound = i;\n            while (down_bound < N_global - 1 && is_road_global[down_bound + 1][j]) {\n                down_bound++;\n            }\n            visible_down_global[i][j] = down_bound;\n        }\n    }\n}\n\n// Update the global coverage status based on visiting (r, c) (O(N))\n// This marks all squares visible from (r,c) as covered, and increments current_covered_count_global\nvoid update_coverage(int r, int c) {\n    // Horizontal line of sight\n    for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n        if (is_road_global[r][k] && !covered_status_global[r][k]) {\n            covered_status_global[r][k] = true;\n            current_covered_count_global++;\n        }\n    }\n    // Vertical line of sight\n    for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n        if (is_road_global[k][c] && !covered_status_global[k][c]) {\n            covered_status_global[k][c] = true;\n            current_covered_count_global++;\n        }\n    }\n}\n\n// Dijkstra from start_r, start_c to find the next best node to visit\n// The \"best\" node maximizes (new coverage gained) / (cost to reach it).\n// Returns {best_r, best_c} and updates path_cost_found with the cost to reach it.\npair<int, int> find_best_next_node(int start_r, int start_c, long long& path_cost_found) {\n    // dist[r][c] stores the minimum cost to reach (r,c) from (start_r, start_c)\n    // Initialize with -1 to indicate unvisited.\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1)); \n    // prev[r][c] stores the previous node in the shortest path to (r,c)\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1}));\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int best_r = -1, best_c = -1;\n    double max_score = -1.0; // Initialize with a very low score\n    long long min_cost_to_best_target = -1;\n\n    // Directions for moving (Up, Down, Left, Right)\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        // If a shorter path to (r,c) has already been found and processed, skip\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        // Calculate coverage gain for current (r,c)\n        int coverage_gain = 0;\n        // Count newly visible squares horizontally\n        for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n            if (is_road_global[r][k] && !covered_status_global[r][k]) coverage_gain++;\n        }\n        // Count newly visible squares vertically\n        for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n            if (is_road_global[k][c] && !covered_status_global[k][c]) coverage_gain++;\n        }\n        \n        // We only consider moves that yield new coverage and are not staying put (cost > 0)\n        // (start_r, start_c) has already been processed for coverage, so it typically won't yield new coverage.\n        // If it does (e.g., initial coverage was somehow incomplete), we'd want to ignore cost 0 for selection.\n        if (coverage_gain > 0) { \n            double score;\n            if (cost == 0) { // If cost is 0, it means current (r,c) is (start_r, start_c).\n                             // We should avoid picking the start node as the next target unless absolutely necessary,\n                             // as it implies no movement. Assign a very low score to discourage.\n                score = -2.0; \n            } else { // Valid target with positive cost and new coverage\n                score = (double)coverage_gain / cost;\n            }\n\n            // Update best target if current node offers a better score.\n            // If scores are equal, prefer the one with lower cost.\n            if (score > max_score || (score == max_score && cost < min_cost_to_best_target)) {\n                max_score = score;\n                best_r = r;\n                best_c = c;\n                min_cost_to_best_target = cost;\n            }\n        }\n\n        // Explore neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            // Check if neighbor is within bounds and is a road square\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc]; // Cost to move to (nr,nc)\n                // If a shorter path to (nr,nc) is found\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c}; // Store previous node for path reconstruction\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // If no suitable target was found (max_score remains -1.0 or only cost=0 was found)\n    if (best_r == -1 || min_cost_to_best_target == 0) {\n        // This signifies that either all reachable squares are already covered by previously visited locations,\n        // or the heuristic failed to find a valid new target providing coverage.\n        // In this case, we return the current position with 0 cost. The main loop will handle termination.\n        path_cost_found = 0;\n        return {start_r, start_c};\n    }\n\n    path_cost_found = min_cost_to_best_target;\n    return {best_r, best_c};\n}\n\n// Reconstruct path segment using Dijkstra's prev array (O(N^2))\n// This function computes the shortest path between start and end and returns it as a string of moves.\nstring reconstruct_path_segment(int start_r, int start_c, int end_r, int end_c) {\n    if (start_r == end_r && start_c == end_c) return \"\"; // No movement needed\n\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1));\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1}));\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int dr[] = {-1, 1, 0, 0}; // U, D, L, R (used for neighbor calculation)\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (r == end_r && c == end_c) break; // Reached the end node, path found\n\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c};\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // Reconstruct path string by backtracking from end_r, end_c to start_r, start_c\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    \n    // If no path was found (end_r, end_c is unreachable)\n    if (dist[end_r][end_c] == -1) {\n        return \"\"; \n    }\n\n    while (curr_r != start_r || curr_c != start_c) {\n        int pr = prev[curr_r][curr_c].first;\n        int pc = prev[curr_r][curr_c].second;\n        \n        // This check guards against logic errors where prev pointers might be invalid\n        if (pr == -1 || pc == -1) { \n            return \"\"; \n        }\n\n        // Determine the move character based on (pr,pc) to (curr_r,curr_c)\n        if (pr == curr_r - 1 && pc == curr_c) path_segment += 'D'; // Previous was up, current is down (move D)\n        else if (pr == curr_r + 1 && pc == curr_c) path_segment += 'U'; // Previous was down, current is up (move U)\n        else if (pr == curr_r && pc == curr_c - 1) path_segment += 'R'; // Previous was left, current is right (move R)\n        else if (pr == curr_r && pc == curr_c + 1) path_segment += 'L'; // Previous was right, current is left (move L)\n        else { // Unexpected path step\n            return \"\"; \n        }\n        curr_r = pr;\n        curr_c = pc;\n    }\n    reverse(path_segment.begin(), path_segment.end()); // Path was built backwards, reverse to get correct order\n    return path_segment;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); // Optimize C++ standard streams for faster I/O\n    cin.tie(NULL);\n\n    cin >> N_global >> SI_global >> SJ_global;\n\n    grid_global.resize(N_global);\n    costs_global.assign(N_global, vector<int>(N_global));\n    is_road_global.assign(N_global, vector<bool>(N_global, false));\n    covered_status_global.assign(N_global, vector<bool>(N_global, false));\n\n    for (int i = 0; i < N_global; ++i) {\n        cin >> grid_global[i];\n        for (int j = 0; j < N_global; ++j) {\n            if (grid_global[i][j] == '#') {\n                is_road_global[i][j] = false;\n            } else {\n                is_road_global[i][j] = true;\n                costs_global[i][j] = grid_global[i][j] - '0'; // Convert char digit to int\n                total_road_squares_global++; // Count total road squares\n            }\n        }\n    }\n\n    // Precompute visibility for all road squares\n    precompute_visibility();\n\n    // Initial coverage from the starting point (si,sj)\n    update_coverage(SI_global, SJ_global);\n\n    int current_r = SI_global;\n    int current_c = SJ_global;\n    string full_path = \"\";\n\n    // Main loop: find next best node until all squares are covered\n    while (current_covered_count_global < total_road_squares_global) {\n        long long path_cost_to_next_node = 0;\n        // Find the next target that maximizes (new coverage / path cost)\n        pair<int, int> next_target = find_best_next_node(current_r, current_c, path_cost_to_next_node);\n\n        // If find_best_next_node returns the current position, it means no new valid target\n        // (with positive coverage gain and positive cost) was found. This should ideally\n        // not happen if there are still uncovered squares in a connected map.\n        if (next_target.first == current_r && next_target.second == current_c) {\n            break; // Break to prevent infinite loop if heuristic gets stuck\n        }\n\n        // Reconstruct path to the chosen target and append to the full path string\n        string segment = reconstruct_path_segment(current_r, current_c, next_target.first, next_target.second);\n        if (segment.empty() && (current_r != next_target.first || current_c != next_target.second)) {\n            // Path reconstruction failed for a non-trivial move. This indicates an issue.\n            break; \n        }\n        full_path += segment;\n        \n        // Move to the new current position and update coverage status\n        current_r = next_target.first;\n        current_c = next_target.second;\n        update_coverage(current_r, current_c);\n    }\n\n    // After all squares are covered (or loop terminates), return to the starting point\n    string return_segment = reconstruct_path_segment(current_r, current_c, SI_global, SJ_global);\n    full_path += return_segment;\n\n    cout << full_path << endl; // Output the final path string\n\n    return 0;\n}\n","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <iomanip>\n#include <map>\n#include <cmath> // For std::round, std::clamp\n\n// Global constants and variables\nconst int MAX_SKILL_VAL = 100; // Upper bound for skills, based on problem generation info\nconst double INITIAL_S_GUESS = 20.0; // Initial guess for skill levels (from s_i,j generation range [20,60])\nconst double LEARNING_RATE_DENOM = 2.0; // Denominator for learning rate. Smaller value means faster learning.\n\nint N, M, K, R;\nstd::vector<std::vector<int>> D; // Task difficulties D[N][K]\nstd::vector<std::vector<int>> adj; // Adjacency list for dependencies: adj[u] lists tasks v that depend on u\nstd::vector<int> in_degree; // Number of prerequisites not yet completed for each task\n\nenum TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint total_tasks_completed = 0;\n\nstruct AssignedTask {\n    int task_id;\n    int start_day;\n};\n\nstd::vector<bool> member_is_free;\nstd::vector<AssignedTask> assigned_task_info; // assigned_task_info[member_idx]\nstd::vector<double> S_sum_D_task_difficulty; // Sum of D values for a task\n\n// Skill estimation\nstd::vector<std::vector<double>> S; // Estimated skill levels S[M][K]\nstd::vector<std::vector<double>> S_lower_bound; // Conservative lower bounds for skills\n\nint current_day = 0;\n\n// Set of ready tasks (in_degree is 0 and NOT_STARTED)\nstd::set<int> ready_tasks_set; // Stores task_id\n\n// Helper functions\ndouble calculate_w_internal(int member_idx, int task_idx) {\n    double w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += std::max(0.0, (double)D[task_idx][k] - S[member_idx][k]);\n    }\n    return w;\n}\n\nint calculate_t_estimated(int member_idx, int task_idx) {\n    double w = calculate_w_internal(member_idx, task_idx);\n    return std::max(1, (int)std::round(w)); // Round to nearest int, minimum 1\n}\n\n// Function to flush standard output\nvoid flush_stdout() {\n    std::cout << std::flush;\n}\n\n// Struct for candidate assignments to sort them\nstruct AssignmentCandidate {\n    int estimated_time;\n    int member_id;\n    int task_id;\n    // For tie-breaking\n    int out_degree; // Number of tasks unlocked by this task\n    double total_task_difficulty; // Sum of D values for the task\n\n    bool operator<(const AssignmentCandidate& other) const {\n        if (estimated_time != other.estimated_time) {\n            return estimated_time < other.estimated_time; // Prioritize shortest estimated time\n        }\n        // Tie-breaking for estimated_time\n        if (out_degree != other.out_degree) {\n            return out_degree > other.out_degree; // Prioritize tasks that unlock more tasks\n        }\n        if (total_task_difficulty != other.total_task_difficulty) {\n            return total_task_difficulty > other.total_task_difficulty; // Prioritize harder tasks\n        }\n        return task_id < other.task_id; // Stable sort by task_id\n    }\n};\n\nint main() {\n    // Faster I/O\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> K >> R;\n\n    D.resize(N, std::vector<int>(K));\n    S_sum_D_task_difficulty.resize(N);\n    for (int i = 0; i < N; ++i) {\n        double current_sum_D = 0;\n        for (int k = 0; k < K; ++k) {\n            std::cin >> D[i][k];\n            current_sum_D += D[i][k];\n        }\n        S_sum_D_task_difficulty[i] = current_sum_D;\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    task_status.resize(N, NOT_STARTED);\n    member_is_free.resize(M, true);\n    assigned_task_info.resize(M);\n\n    S.resize(M, std::vector<double>(K, INITIAL_S_GUESS));\n    S_lower_bound.resize(M, std::vector<double>(K, 0.0));\n\n    // Initialize ready_tasks_set: tasks with no dependencies or all dependencies met\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            ready_tasks_set.insert(i);\n        }\n    }\n\n    while (true) {\n        current_day++;\n\n        // Process daily input (completed tasks)\n        int n_completed;\n        std::cin >> n_completed;\n\n        if (n_completed == -1) {\n            break; // All tasks completed or max days reached, exit program\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_idx;\n            std::cin >> member_idx;\n            --member_idx; // 0-indexed\n\n            int completed_task_id = assigned_task_info[member_idx].task_id;\n            int start_day = assigned_task_info[member_idx].start_day;\n            int actual_t_ij = current_day - start_day + 1; // Actual days taken\n\n            // Update task status\n            task_status[completed_task_id] = COMPLETED;\n            total_tasks_completed++;\n\n            // Skill Estimation Update for member_idx\n            // Infer w_ij from actual_t_ij. If actual_t_ij == 1, assume w_ij=0 (most optimistic).\n            // Otherwise, assume w_ij = actual_t_ij, ignoring small random noise.\n            double observed_w = (actual_t_ij == 1) ? 0.0 : (double)actual_t_ij;\n            double current_predicted_w = calculate_w_internal(member_idx, completed_task_id);\n\n            // Strong evidence for S_lower_bound if task completed in 1 day\n            if (actual_t_ij == 1) { \n                for (int k = 0; k < K; ++k) {\n                    S_lower_bound[member_idx][k] = std::max(S_lower_bound[member_idx][k], (double)D[completed_task_id][k]);\n                }\n            } else { // actual_t_ij > 1, adjust S based on difference between predicted and observed w\n                double error = current_predicted_w - observed_w; // Positive if predicted was too high, negative if too low\n                int active_skills_count = 0; // Count skills where d_ik > S_jk currently\n                for (int k = 0; k < K; ++k) {\n                    if (D[completed_task_id][k] > S[member_idx][k]) {\n                        active_skills_count++;\n                    }\n                }\n\n                if (active_skills_count > 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (D[completed_task_id][k] > S[member_idx][k]) {\n                            // Adjust S[member_idx][k] to reduce the error.\n                            // If error > 0 (predicted w was too high), S[member_idx][k] needs to increase\n                            // If error < 0 (predicted w was too low), S[member_idx][k] needs to decrease\n                            S[member_idx][k] -= error / (active_skills_count * LEARNING_RATE_DENOM);\n                            S[member_idx][k] = std::clamp(S[member_idx][k], 0.0, (double)MAX_SKILL_VAL);\n                        }\n                    }\n                }\n            }\n\n            // Always apply lower bounds after any other adjustments to maintain consistency\n            for (int k = 0; k < K; ++k) {\n                S[member_idx][k] = std::max(S[member_idx][k], S_lower_bound[member_idx][k]);\n            }\n            \n            // Output skill predictions for visualization (round to nearest integer for output)\n            std::cout << \"#s \" << member_idx + 1;\n            for (int k = 0; k < K; ++k) {\n                std::cout << \" \" << static_cast<int>(std::round(S[member_idx][k]));\n            }\n            std::cout << std::endl;\n\n            // Free the member\n            member_is_free[member_idx] = true;\n\n            // Update in_degree for tasks dependent on the completed task\n            for (int dependent_task_id : adj[completed_task_id]) {\n                in_degree[dependent_task_id]--;\n                if (in_degree[dependent_task_id] == 0 && task_status[dependent_task_id] == NOT_STARTED) {\n                    ready_tasks_set.insert(dependent_task_id);\n                }\n            }\n        }\n\n        // Task Assignment Phase\n        std::vector<std::pair<int, int>> assignments_today;\n        std::vector<int> current_free_members;\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            if (member_is_free[m_idx]) {\n                current_free_members.push_back(m_idx);\n            }\n        }\n\n        // Prioritize a subset of ready tasks to consider for efficiency\n        std::vector<int> tasks_to_consider;\n        if (!ready_tasks_set.empty()) {\n            // Priority for selecting tasks to consider:\n            // High out_degree (unlocks more tasks), high average skill difficulty, then lower task_id\n            std::vector<std::pair<int, int>> sorted_ready_tasks; // (priority_score, task_id)\n            for(int tid : ready_tasks_set) {\n                // Heuristic score: combine out_degree (weighted) and average task difficulty\n                // Multiplying by 100 ensures out_degree has significant impact\n                int score = adj[tid].size() * 100 + static_cast<int>(S_sum_D_task_difficulty[tid] / K); \n                sorted_ready_tasks.push_back({score, tid});\n            }\n            std::sort(sorted_ready_tasks.rbegin(), sorted_ready_tasks.rend()); // Sort descending by score\n\n            // Limit the number of tasks considered to avoid O(M * N_ready * K) complexity\n            // Choose M * (some factor) or a fixed max (e.g., 200)\n            int num_to_consider = std::min((int)sorted_ready_tasks.size(), M * 15); \n            for (int i = 0; i < num_to_consider; ++i) {\n                tasks_to_consider.push_back(sorted_ready_tasks[i].second);\n            }\n        }\n\n        std::vector<AssignmentCandidate> candidates;\n        for (int m_idx : current_free_members) {\n            for (int t_idx : tasks_to_consider) {\n                if (task_status[t_idx] == NOT_STARTED) { // Double check task isn't assigned concurrently\n                    candidates.push_back({\n                        calculate_t_estimated(m_idx, t_idx),\n                        m_idx,\n                        t_idx,\n                        (int)adj[t_idx].size(),\n                        S_sum_D_task_difficulty[t_idx]\n                    });\n                }\n            }\n        }\n        std::sort(candidates.begin(), candidates.end());\n\n        // Greedily assign tasks based on sorted candidates\n        for (const auto& candidate : candidates) {\n            int m_idx = candidate.member_id;\n            int t_idx = candidate.task_id;\n\n            if (member_is_free[m_idx] && task_status[t_idx] == NOT_STARTED) {\n                assignments_today.push_back({m_idx + 1, t_idx + 1});\n                member_is_free[m_idx] = false;\n                task_status[t_idx] = IN_PROGRESS;\n                assigned_task_info[m_idx] = {t_idx, current_day}; // Store start day and task ID\n                ready_tasks_set.erase(t_idx); // Remove from ready set as it's now in progress\n            }\n            \n            // Break conditions: if all free members have been assigned OR all remaining tasks are assigned\n            if (assignments_today.size() == current_free_members.size() || \n                total_tasks_completed + assignments_today.size() == N) {\n                break; \n            }\n        }\n\n        // Output assignments for the day\n        std::cout << assignments_today.size();\n        for (const auto& p : assignments_today) {\n            std::cout << \" \" << p.first << \" \" << p.second;\n        }\n        std::cout << std::endl;\n        flush_stdout(); // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc006":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <set>\n#include <unordered_set>\n\n// --- Structs ---\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id; // 1-indexed original ID\n    Point p; // pickup\n    Point d; // delivery\n};\n\nenum NodeType {\n    PICKUP_TYPE = 0,\n    DELIVERY_TYPE = 1\n};\n\nstruct RouteNode {\n    int order_id;\n    NodeType type;\n    Point coord;\n};\n\n// --- Global Constants ---\nconst Point OFFICE = {400, 400};\nconst int NUM_TOTAL_ORDERS = 1000;\nconst int NUM_DELIVERIES_QUOTA = 50;\n\n// --- Random Number Generator ---\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\nlong long manhattan_dist(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\n// Calculate total distance for a route represented by a sequence of RouteNodes\nlong long calculate_total_route_distance(const std::vector<RouteNode>& route_nodes) {\n    long long total_dist = 0;\n    if (route_nodes.empty()) {\n        return manhattan_dist(OFFICE, OFFICE); // If no deliveries, just go to office and back (0 dist)\n    }\n\n    total_dist += manhattan_dist(OFFICE, route_nodes[0].coord);\n    for (size_t i = 0; i < route_nodes.size() - 1; ++i) {\n        total_dist += manhattan_dist(route_nodes[i].coord, route_nodes[i+1].coord);\n    }\n    total_dist += manhattan_dist(route_nodes.back().coord, OFFICE);\n    return total_dist;\n}\n\n// Generates an initial route using a greedy Nearest Neighbor heuristic.\n// `selected_order_ids` is a vector of 1-indexed original order IDs.\n// `all_orders_map` provides access to order details by ID.\nstd::vector<RouteNode> generate_nearest_neighbor_route(const std::vector<int>& selected_order_ids, \n                                                       const std::map<int, Order>& all_orders_map) {\n    std::vector<RouteNode> route;\n    std::unordered_set<int> unpicked_order_ids(selected_order_ids.begin(), selected_order_ids.end());\n    std::unordered_set<int> un_delivered_order_ids;\n\n    Point current_pos = OFFICE;\n\n    while (!unpicked_order_ids.empty() || !un_delivered_order_ids.empty()) {\n        std::vector<std::pair<long long, RouteNode>> candidates; \n\n        // Consider pickup points\n        for (int order_id : unpicked_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            long long d = manhattan_dist(current_pos, order.p);\n            candidates.push_back({d, {order_id, PICKUP_TYPE, order.p}});\n        }\n\n        // Consider delivery points\n        for (int order_id : un_delivered_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            long long d = manhattan_dist(current_pos, order.d);\n            candidates.push_back({d, {order_id, DELIVERY_TYPE, order.d}});\n        }\n\n        if (candidates.empty()) break; // Should not happen if logic is correct\n\n        // Find minimum distance among candidates\n        long long min_dist = candidates[0].first;\n        for (size_t i = 1; i < candidates.size(); ++i) {\n            if (candidates[i].first < min_dist) {\n                min_dist = candidates[i].first;\n            }\n        }\n\n        // Collect all candidates that achieve the minimum distance\n        std::vector<RouteNode> best_candidates_nodes;\n        for (const auto& cand : candidates) {\n            if (cand.first == min_dist) {\n                best_candidates_nodes.push_back(cand.second);\n            }\n        }\n        \n        // Randomly pick one of the best candidates (tie-breaking)\n        std::uniform_int_distribution<int> dist_cand_idx(0, best_candidates_nodes.size() - 1);\n        RouteNode chosen_node = best_candidates_nodes[dist_cand_idx(rng)];\n\n        route.push_back(chosen_node);\n        current_pos = chosen_node.coord;\n\n        if (chosen_node.type == PICKUP_TYPE) {\n            unpicked_order_ids.erase(chosen_node.order_id);\n            un_delivered_order_ids.insert(chosen_node.order_id);\n        } else { // DELIVERY_TYPE\n            un_delivered_order_ids.erase(chosen_node.order_id);\n        }\n    }\n    return route;\n}\n\n// Applies a node relocation local search operator.\n// Moves a randomly chosen node to a new random valid position in the route, respecting precedence.\nstd::vector<RouteNode> relocate_node(const std::vector<RouteNode>& current_route,\n                                     const std::map<int, Order>& all_selected_orders_map) {\n    if (current_route.size() < 2) return current_route; // Need at least 2 nodes to meaningfully relocate\n\n    std::uniform_int_distribution<int> dist_move_idx(0, current_route.size() - 1);\n    int move_idx = dist_move_idx(rng);\n    RouteNode node_to_move = current_route[move_idx];\n\n    std::vector<RouteNode> new_route_temp;\n    new_route_temp.reserve(current_route.size() - 1);\n    for (size_t i = 0; i < current_route.size(); ++i) {\n        if (i == (size_t)move_idx) continue;\n        new_route_temp.push_back(current_route[i]);\n    }\n    \n    int min_insert_idx = 0; // The first possible insertion point (after the virtual office start)\n    int max_insert_idx = new_route_temp.size(); // The last possible insertion point (before the virtual office end)\n\n    if (node_to_move.type == PICKUP_TYPE) {\n        // P_k must be inserted before D_k. Find D_k's current position.\n        int Di_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == DELIVERY_TYPE) {\n                Di_pos = i;\n                break;\n            }\n        }\n        if (Di_pos != -1) { \n            max_insert_idx = Di_pos;\n        }\n    } else { // DELIVERY_TYPE\n        // D_k must be inserted after P_k. Find P_k's current position.\n        int Pi_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == PICKUP_TYPE) {\n                Pi_pos = i;\n                break;\n            }\n        }\n        if (Pi_pos != -1) { \n            min_insert_idx = Pi_pos + 1;\n        }\n    }\n    \n    // Ensure min_insert_idx <= max_insert_idx. This should hold if the original route was valid.\n    // In edge cases where the list of remaining nodes is empty, min/max_insert_idx will be 0.\n    if (min_insert_idx > max_insert_idx) { // Should not happen for a valid route\n         min_insert_idx = 0;\n         max_insert_idx = new_route_temp.size();\n    }\n    \n    std::uniform_int_distribution<int> dist_insert_pos(min_insert_idx, max_insert_idx);\n    int insert_pos = dist_insert_pos(rng); \n    \n    new_route_temp.insert(new_route_temp.begin() + insert_pos, node_to_move);\n    return new_route_temp;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // --- Input Reading ---\n    std::vector<Order> all_orders(NUM_TOTAL_ORDERS);\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        all_orders[i].id = i + 1; // 1-indexed\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 Selection (Greedy based on standalone cost) ---\n    std::vector<std::pair<long long, int>> order_costs(NUM_TOTAL_ORDERS); // {cost, original_id}\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        long long cost = manhattan_dist(OFFICE, all_orders[i].p) +\n                         manhattan_dist(all_orders[i].p, all_orders[i].d) +\n                         manhattan_dist(all_orders[i].d, OFFICE);\n        order_costs[i] = {cost, all_orders[i].id};\n    }\n    std::sort(order_costs.begin(), order_costs.end());\n\n    std::vector<int> current_selected_order_ids_vec;\n    std::map<int, Order> current_selected_orders_map;\n    std::unordered_set<int> selected_order_set; // For quick lookup\n    std::vector<int> unselected_order_ids_vec;\n\n    for (int i = 0; i < NUM_DELIVERIES_QUOTA; ++i) {\n        int order_id = order_costs[i].second;\n        current_selected_order_ids_vec.push_back(order_id);\n        current_selected_orders_map[order_id] = all_orders[order_id - 1]; // Store 1-indexed\n        selected_order_set.insert(order_id);\n    }\n    for (int i = NUM_DELIVERIES_QUOTA; i < NUM_TOTAL_ORDERS; ++i) {\n        unselected_order_ids_vec.push_back(order_costs[i].second);\n    }\n\n    // --- Initial Route Generation ---\n    std::vector<RouteNode> current_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n    long long current_total_dist = calculate_total_route_distance(current_route_nodes);\n\n    // --- Best Solution Tracking ---\n    long long best_total_dist = current_total_dist;\n    std::vector<RouteNode> best_route_nodes = current_route_nodes;\n    std::vector<int> best_selected_order_ids = current_selected_order_ids_vec;\n\n    // --- Simulated Annealing Parameters ---\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SEC = 1.9; // Time limit for SA loop\n    const double T_START = 5000.0; // Initial temperature\n    const double T_END = 1.0;     // Final temperature\n    const double PROB_ORDER_SWAP = 0.05; // Probability of performing an order swap\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_selected_idx(0, NUM_DELIVERIES_QUOTA - 1);\n    std::uniform_int_distribution<int> dist_unselected_idx(0, NUM_TOTAL_ORDERS - NUM_DELIVERIES_QUOTA - 1);\n    \n    // --- Simulated Annealing Loop ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_sec = std::chrono::duration<double>(current_time - start_time).count();\n\n        if (elapsed_sec >= TIME_LIMIT_SEC) {\n            break;\n        }\n\n        double progress = elapsed_sec / TIME_LIMIT_SEC;\n        double current_T = T_START * std::pow(T_END / T_START, progress);\n\n        long long new_total_dist;\n        std::vector<RouteNode> new_route_nodes;\n        bool orders_swapped_this_iter = false; // Flag to revert if swap is rejected\n\n        if (dist_0_1(rng) < PROB_ORDER_SWAP && !unselected_order_ids_vec.empty()) {\n            // --- Order Swap Operation ---\n            int out_vec_idx = dist_selected_idx(rng);\n            int order_out_id = current_selected_order_ids_vec[out_vec_idx];\n\n            int in_vec_idx = dist_unselected_idx(rng);\n            int order_in_id = unselected_order_ids_vec[in_vec_idx];\n\n            // Perform the swap temporarily\n            current_selected_order_ids_vec[out_vec_idx] = order_in_id;\n            unselected_order_ids_vec[in_vec_idx] = order_out_id;\n            \n            selected_order_set.erase(order_out_id);\n            selected_order_set.insert(order_in_id);\n\n            current_selected_orders_map.erase(order_out_id);\n            current_selected_orders_map[order_in_id] = all_orders[order_in_id - 1];\n\n            // Re-generate route for the new set of orders\n            new_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n            new_total_dist = calculate_total_route_distance(new_route_nodes);\n            orders_swapped_this_iter = true;\n        } else {\n            // --- Route Relocation Operation ---\n            new_route_nodes = relocate_node(current_route_nodes, current_selected_orders_map);\n            new_total_dist = calculate_total_route_distance(new_route_nodes);\n        }\n\n        // --- Acceptance Criteria ---\n        if (new_total_dist < current_total_dist) {\n            current_total_dist = new_total_dist;\n            current_route_nodes = new_route_nodes;\n        } else {\n            double prob_acceptance = std::exp((current_total_dist - new_total_dist) / current_T);\n            if (dist_0_1(rng) < prob_acceptance) {\n                current_total_dist = new_total_dist;\n                current_route_nodes = new_route_nodes;\n            } else {\n                // Reject: if orders were swapped, revert them\n                if (orders_swapped_this_iter) {\n                    // Revert the last swap\n                    int order_in_id = current_selected_order_ids_vec[out_vec_idx];\n                    int order_out_id = unselected_order_ids_vec[in_vec_idx];\n\n                    current_selected_order_ids_vec[out_vec_idx] = order_out_id;\n                    unselected_order_ids_vec[in_vec_idx] = order_in_id;\n                    \n                    selected_order_set.erase(order_in_id);\n                    selected_order_set.insert(order_out_id);\n\n                    current_selected_orders_map.erase(order_in_id);\n                    current_selected_orders_map[order_out_id] = all_orders[order_out_id - 1];\n                }\n            }\n        }\n\n        // --- Update Best Solution ---\n        if (current_total_dist < best_total_dist) {\n            best_total_dist = current_total_dist;\n            best_route_nodes = current_route_nodes;\n            best_selected_order_ids = current_selected_order_ids_vec;\n        }\n    }\n\n    // --- Output ---\n    std::cout << NUM_DELIVERIES_QUOTA;\n    for (int id : best_selected_order_ids) {\n        std::cout << \" \" << id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_route_nodes.size() + 2; // +2 for start and end office points\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (const auto& node : best_route_nodes) {\n        std::cout << \" \" << node.coord.x << \" \" << node.coord.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric> // For std::iota (used by DSU internally or for basic DSU setup)\n#include <iomanip> // For std::fixed, std::setprecision, if needed for debugging\n#include <algorithm> // For std::min/max, etc.\n\n// AC Library DSU\n// Make sure to include this in your project or copy it if not using a judge that provides it.\n// Example: if using local library, it might be #include \"atcoder/dsu.hpp\"\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    long long d; // Precomputed rounded Euclidean distance\n};\n\n// Function to calculate rounded Euclidean distance\nlong long calculate_d(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    // dx*dx + dy*dy can be up to 800^2 + 800^2 = 1,280,000. Fits in long long.\n    // sqrt of 1,280,000 is approx 1131.\n    return std::round(std::sqrt(static_cast<double>(dx * dx + dy * dy)));\n}\n\n// Global constants for problem size\nconst int N_NODES = 400;\nconst int M_EDGES = 1995;\n\n// Heuristic parameters for tuning\n// TAU_MIN: Initial strictness for cost ratio l_i / d_i\n// TAU_MAX: Final leniency for cost ratio l_i / d_i when close to connecting all nodes\n// URGENCY_BUFFER: How many \"extra\" remaining edges we can afford to reject before becoming desperate.\n// These values are based on typical performance for similar online MST heuristics.\nconst double TAU_MIN = 1.3;\nconst double TAU_MAX = 2.2;\nconst int URGENCY_BUFFER = 15;\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    // Read vertex coordinates\n    std::vector<Point> vertices(N_NODES);\n    for (int i = 0; i < N_NODES; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    // Read edge endpoints and precompute d_i (rounded Euclidean distance)\n    std::vector<EdgeInfo> edges(M_EDGES);\n    for (int i = 0; i < M_EDGES; ++i) {\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].d = calculate_d(vertices[edges[i].u], vertices[edges[i].v]);\n    }\n\n    // Initialize DSU for N_NODES vertices\n    atcoder::dsu dsu(N_NODES);\n    int edges_taken_count = 0; // Keep track of how many edges we have adopted\n\n    // Process edges one by one\n    for (int i = 0; i < M_EDGES; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        long long d_val = edges[i].d;\n\n        // Read the actual length l_i for the current edge\n        long long l_val;\n        std::cin >> l_val;\n\n        int decision = 0; // Default decision: 0 (reject)\n\n        // Check if u and v are already connected\n        if (!dsu.same(u, v)) {\n            // u and v are in different components, this edge could connect them.\n            \n            // Get current number of connected components\n            int current_components = dsu.groups().size();\n            // Number of additional edges (merges) needed to connect all components\n            // (N_NODES - 1) total edges for MST, (N_NODES - current_components) edges already taken to reduce components.\n            // So, (N_NODES - 1) - (N_NODES - current_components) = current_components - 1 more edges are needed.\n            int needed_to_connect = current_components - 1; \n\n            // Number of candidate edges remaining to be revealed (excluding the current one)\n            int remaining_candidates = M_EDGES - (i + 1);\n\n            // Calculate the cost ratio l_i / d_i.\n            // d_val is guaranteed to be >= 6 based on problem constraints (min distance > 5).\n            double cost_ratio = static_cast<double>(l_val) / d_val;\n\n            // --- Urgency Check ---\n            // If we're running low on candidate edges relative to what's needed,\n            // we must take this edge to ensure connectivity.\n            // URGENCY_BUFFER provides a safety margin; if needed_to_connect is roughly\n            // equal to or greater than remaining_candidates minus the buffer, we become urgent.\n            if (needed_to_connect >= remaining_candidates - URGENCY_BUFFER) {\n                decision = 1; // Adopt this edge to ensure connectivity\n            } else {\n                // --- Adaptive Threshold Check ---\n                // If not urgent, be selective based on the cost ratio and progress.\n                // The threshold for accepting an edge adapts based on how many edges\n                // we've already adopted relative to the total N-1 needed for an MST.\n                double progress_ratio_taken = static_cast<double>(edges_taken_count) / (N_NODES - 1.0);\n                // current_tau interpolates between TAU_MIN (when edges_taken_count is 0)\n                // and TAU_MAX (when edges_taken_count is N_NODES-1).\n                double current_tau = TAU_MIN + (TAU_MAX - TAU_MIN) * progress_ratio_taken;\n\n                if (cost_ratio <= current_tau) {\n                    decision = 1; // Adopt if its cost is within the current acceptable threshold\n                }\n            }\n        }\n\n        // Apply the decision: merge components if adopted\n        if (decision == 1) {\n            dsu.merge(u, v);\n            edges_taken_count++;\n        }\n\n        // Output the decision (0 or 1) and flush stdout\n        std::cout << decision << std::endl;\n    }\n\n    return 0;\n}\n","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <set>\n#include <algorithm>\n#include <tuple> // For std::tie\n#include <map>   // For BFS path reconstruction\n\nusing namespace std;\n\n// Global constants\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: U, D, L, R\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    // Overload operators for use in sets/maps and comparisons\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    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// Game state variables\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type; // Not used for movement prediction in this solution\nvector<Point> human_pos;\n\n// Board state: 0=passable, 1=impassable (wall)\nvector<vector<int>> board(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n\n// Global BFS data structures (re-used each time BFS is called)\nvector<vector<int>> dist_bfs;\nvector<vector<Point>> parent_bfs;\n\n// Function to check if a point is within grid boundaries\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// BFS to find shortest path distance from start to target_neighbor.\n// Also stores parent pointers to reconstruct the first step of the path.\n// `start`: The starting point for BFS (human's current position).\n// `target_neighbor`: The specific cell the human wants to reach (adjacent to a block goal).\n// `current_blocked_this_turn`: Set of cells that will become walls this turn by other humans.\n// `current_moved_to_this_turn_targets`: Set of cells that other humans are planning to move to this turn.\n// `all_human_current_pos`: Current positions of all humans (to avoid pathfinding through other humans' current spots).\n// `self_idx`: Index of the human for whom BFS is being run (to allow passing through its own start cell).\nint bfs(Point start, Point target_neighbor, const set<Point>& current_blocked_this_turn,\n        const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    dist_bfs.assign(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    parent_bfs.assign(GRID_SIZE, vector<Point>(GRID_SIZE, {-1, -1}));\n    queue<Point> q;\n\n    // Check if the starting position itself is invalid/impassable\n    if (!is_valid(start.r, start.c) || board[start.r][start.c] == 1 ||\n        current_blocked_this_turn.count(start)) {\n        return -1;\n    }\n\n    q.push(start);\n    dist_bfs[start.r][start.c] = 0;\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        if (curr == target_neighbor) {\n            return dist_bfs[curr.r][curr.c]; // Target reached\n        }\n\n        // Explore 4 cardinal neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.r + DR[i];\n            int nc = curr.c + DC[i];\n            Point next = {nr, nc};\n\n            // Basic checks: within bounds, not visited yet\n            if (!is_valid(nr, nc) || dist_bfs[nr][nc] != -1) continue;\n\n            // Check if 'next' cell is impassable due to existing walls or planned blocks\n            if (board[nr][nc] == 1) continue; // Existing wall\n            if (current_blocked_this_turn.count(next)) continue; // Blocked by another human this turn\n\n            // Check if 'next' cell is a target for another human's move this turn\n            if (current_moved_to_this_turn_targets.count(next)) continue;\n            \n            // Check if 'next' cell is currently occupied by another human (who isn't moving out of it)\n            bool is_other_human_current_pos = false;\n            for(int h_idx_other = 0; h_idx_other < M; ++h_idx_other) {\n                if (h_idx_other == self_idx) continue; // Current human can pass through its own start\n                if (all_human_current_pos[h_idx_other] == next) {\n                    is_other_human_current_pos = true;\n                    break;\n                }\n            }\n            if (is_other_human_current_pos) continue; // Impassable if another human is currently there\n\n            // If all checks pass, 'next' is a valid step\n            dist_bfs[nr][nc] = dist_bfs[curr.r][curr.c] + 1;\n            parent_bfs[nr][nc] = curr;\n            q.push(next);\n        }\n    }\n    return -1; // Target not reachable\n}\n\n// Reconstructs the character for the first move from 'start' to 'target_neighbor' based on BFS path.\nchar get_move_char(Point start, Point target_neighbor, const set<Point>& current_blocked_this_turn,\n                   const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    if (bfs(start, target_neighbor, current_blocked_this_turn, current_moved_to_this_turn_targets, all_human_current_pos, self_idx) == -1) {\n        return '.'; // No path found\n    }\n\n    Point curr = target_neighbor;\n    Point prev = parent_bfs[curr.r][curr.c];\n    \n    // Trace back the parent pointers to find the first step from 'start'\n    while (prev != start) {\n        curr = prev;\n        prev = parent_bfs[curr.r][curr.c];\n    }\n\n    // 'curr' is now the first step from 'start'\n    for (int i = 0; i < 4; ++i) {\n        if (start.r + DR[i] == curr.r && start.c + DC[i] == curr.c) {\n            return MOVE_CHARS[i]; // Return corresponding move character\n        }\n    }\n    return '.'; // Should not be reached if BFS found a path\n}\n\n// Structure to represent a rectangle (inclusive coordinates, 0-indexed)\nstruct Rect {\n    int r1, c1, r2, c2;\n    int area() const { return (r2 - r1 + 1) * (c2 - c1 + 1); }\n    // Check if a point is inside the rectangle\n    bool contains(Point p) const {\n        return p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2;\n    }\n    // Get all cells on the perimeter of the rectangle\n    vector<Point> get_perimeter_cells() const {\n        vector<Point> perimeter;\n        // Top and bottom sides\n        for (int c = c1; c <= c2; ++c) {\n            perimeter.push_back({r1, c});\n            if (r1 != r2) perimeter.push_back({r2, c});\n        }\n        // Left and right sides (avoid double counting corners by adjusting loop range)\n        for (int r = r1 + 1; r < r2; ++r) {\n            perimeter.push_back({r, c1});\n            if (c1 != c2) perimeter.push_back({r, c2});\n        }\n        return perimeter;\n    }\n};\n\nRect target_rect = {0, 0, 0, 0}; // The main region humans will try to enclose\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read initial pet information\n    cin >> N;\n    pet_pos.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i];\n        pet_pos[i].r--; // Convert to 0-indexed\n        pet_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // Read initial human information\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].r >> human_pos[i].c;\n        human_pos[i].r--; // Convert to 0-indexed\n        human_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // --- Initialization Phase: Find the best target rectangle ---\n    long long max_heuristic_score = -1; \n    Rect best_initial_rect = {0, 0, 0, 0}; // Default to an invalid rectangle\n\n    // Brute force search for the best pet-free rectangle\n    for (int r1 = 0; r1 < GRID_SIZE; ++r1) {\n        for (int c1 = 0; c1 < GRID_SIZE; ++c1) {\n            for (int r2 = r1; r2 < GRID_SIZE; ++r2) {\n                for (int c2 = c1; c2 < GRID_SIZE; ++c2) {\n                    Rect current_rect = {r1, c1, r2, c2};\n                    bool is_pet_free = true;\n                    // Check if any pet is inside the current rectangle\n                    for (int i = 0; i < N; ++i) {\n                        if (current_rect.contains(pet_pos[i])) {\n                            is_pet_free = false;\n                            break;\n                        }\n                    }\n\n                    if (is_pet_free) {\n                        long long current_area = current_rect.area();\n                        if (current_area == 0) continue; // Skip 0-area rectangles\n                        \n                        long long dist_sum = 0;\n                        vector<Point> perimeter = current_rect.get_perimeter_cells();\n\n                        // Calculate sum of Manhattan distances from humans to their closest perimeter cell\n                        for (int i = 0; i < M; ++i) {\n                            int min_dist_to_perimeter = 100000; // Initialize with a large value\n                            for (const auto& p_cell : perimeter) {\n                                min_dist_to_perimeter = min(min_dist_to_perimeter, abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c));\n                            }\n                            dist_sum += min_dist_to_perimeter;\n                        }\n\n                        // Heuristic score: (Area) - (Weight * Sum_of_Distances)\n                        // A weight of 1 is chosen to balance area against human travel time.\n                        long long current_heuristic_score = current_area - dist_sum * 1; \n\n                        if (current_heuristic_score > max_heuristic_score) {\n                            max_heuristic_score = current_heuristic_score;\n                            best_initial_rect = current_rect;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    target_rect = best_initial_rect;\n    \n    // Fallback: If the chosen rectangle is too small or initial conditions are poor,\n    // default to a central 20x20 square.\n    if (target_rect.area() < M * 5) { // Arbitrary threshold for \"too small\"\n        target_rect = {5, 5, 24, 24}; // Default to 20x20 central square (0-indexed)\n    }\n\n    // Get all cells on the perimeter of the chosen target_rect once\n    vector<Point> target_perimeter_cells = target_rect.get_perimeter_cells();\n    \n    // `human_target_wall_goals[i]` stores the specific perimeter cell that human 'i' is trying to block.\n    vector<Point> human_target_wall_goals(M, {-1,-1}); \n\n    // --- Main Loop: 300 turns of human actions and pet movements ---\n    for (int turn = 0; turn < MAX_TURNS; ++turn) {\n        // 1. Determine `can_block_grid`: which cells are valid to block this turn.\n        vector<vector<bool>> can_block_grid(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n        // Pets make cells unblockable\n        for (int i = 0; i < N; ++i) {\n            Point p = pet_pos[i];\n            can_block_grid[p.r][p.c] = false; // Rule 1: Cannot block pet's square\n            for (int d = 0; d < 4; ++d) { // Rule 2: Cannot block squares adjacent to a pet\n                int nr = p.r + DR[d];\n                int nc = p.c + DC[d];\n                if (is_valid(nr, nc)) {\n                    can_block_grid[nr][nc] = false;\n                }\n            }\n        }\n        // Humans make cells unblockable\n        for (int i = 0; i < M; ++i) {\n            Point h = human_pos[i];\n            can_block_grid[h.r][h.c] = false; // Rule 1: Cannot block human's square\n        }\n\n        // 2. Human Action Planning\n        vector<char> actions_output(M, '.'); // Stores the final action character for each human\n        vector<Point> next_human_pos_candidates(M); // Stores each human's position AFTER actions\n        set<Point> current_blocked_this_turn;       // Cells chosen to be blocked by humans THIS turn\n        set<Point> current_moved_to_this_turn_targets; // Cells chosen to be moved into by humans THIS turn\n\n        // 2.1. Update each human's block goal\n        // Humans greedily pick the closest, unblocked, blockable perimeter cell that is not already assigned to another human.\n        for (int i = 0; i < M; ++i) {\n            // Re-assign goal if current goal is completed, invalid, or already blocked\n            if (human_target_wall_goals[i].r == -1 || \n                !is_valid(human_target_wall_goals[i].r, human_target_wall_goals[i].c) ||\n                board[human_target_wall_goals[i].r][human_target_wall_goals[i].c] == 1) { \n                \n                Point best_goal = {-1,-1};\n                int min_dist = 100000;\n\n                // Temporarily track goals assigned to other humans (within this turn's assignment phase)\n                set<Point> temp_assigned_goals;\n                for(int j=0; j<M; ++j) {\n                    if (j != i && human_target_wall_goals[j].r != -1) {\n                        temp_assigned_goals.insert(human_target_wall_goals[j]);\n                    }\n                }\n\n                for (const auto& p_cell : target_perimeter_cells) {\n                    // Check if the perimeter cell is currently:\n                    //   1. Passable (not already a wall)\n                    //   2. Blockable (no pets nearby)\n                    //   3. Not already being blocked by another human this turn (from previous phase 1 decision)\n                    //   4. Not already assigned as a goal to another human (for current goal assignment phase)\n                    if (board[p_cell.r][p_cell.c] == 0 && can_block_grid[p_cell.r][p_cell.c] && \n                        !current_blocked_this_turn.count(p_cell) && !temp_assigned_goals.count(p_cell)) {\n                        \n                        int dist = abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c); // Manhattan distance\n                        if (dist < min_dist) {\n                            min_dist = dist;\n                            best_goal = p_cell;\n                        }\n                    }\n                }\n                human_target_wall_goals[i] = best_goal; // Assign the new best goal\n            }\n        }\n        \n        // 2.2. Phase 1: Determine BLOCK actions\n        // Humans who are adjacent to their block goal perform the block action.\n        for (int i = 0; i < M; ++i) {\n            next_human_pos_candidates[i] = human_pos[i]; // Default: stay put\n            if (human_target_wall_goals[i].r != -1) {\n                Point goal = human_target_wall_goals[i];\n                for (int d = 0; d < 4; ++d) { // Check adjacent cells\n                    if (human_pos[i].r + DR[d] == goal.r && human_pos[i].c + DC[d] == goal.c) { // Human is adjacent to goal\n                        // Confirm blockable conditions before blocking\n                        if (board[goal.r][goal.c] == 0 && can_block_grid[goal.r][goal.c] && !current_blocked_this_turn.count(goal)) {\n                            actions_output[i] = BLOCK_CHARS[d]; // Set block action\n                            current_blocked_this_turn.insert(goal); // Mark as blocked for this turn\n                            board[goal.r][goal.c] = 1; // Temporarily update board for pathfinding in Phase 2\n                            human_target_wall_goals[i] = {-1,-1}; // Goal achieved, reset\n                        }\n                        break; // A human can only perform one action (block or move)\n                    }\n                }\n            }\n        }\n        \n        // 2.3. Phase 2: Determine MOVE actions for humans who did not block.\n        // Use a priority queue to resolve conflicts for moving to the same cell.\n        struct MoveCandidate {\n            int human_idx;\n            Point next_pos;\n            char move_char;\n            int priority; // Higher priority (e.g., closer to goal) is better\n            bool operator<(const MoveCandidate& other) const {\n                return priority < other.priority; // Min-priority queue for default, so this makes it max-priority.\n            }\n        };\n        priority_queue<MoveCandidate> move_queue;\n\n        for (int i = 0; i < M; ++i) {\n            if (actions_output[i] == '.') { // Only if human didn't block in Phase 1\n                Point goal = human_target_wall_goals[i];\n                if (goal.r != -1) { // If there's still a block goal to move towards\n                    // Find the closest adjacent cell to the goal that the human can move to\n                    Point target_neighbor_to_move_towards = {-1,-1};\n                    int min_dist_to_goal_adj = 100000;\n                    for(int d=0; d<4; ++d) {\n                        Point adj_to_goal = {goal.r + DR[d], goal.c + DC[d]};\n                        if (is_valid(adj_to_goal.r, adj_to_goal.c)) {\n                            // Ensure the target neighbor is not an existing wall or a cell being blocked this turn\n                            if (board[adj_to_goal.r][adj_to_goal.c] == 0 && !current_blocked_this_turn.count(adj_to_goal)) {\n                                int dist = abs(human_pos[i].r - adj_to_goal.r) + abs(human_pos[i].c - adj_to_goal.c); // Manhattan distance\n                                if (dist < min_dist_to_goal_adj) {\n                                    min_dist_to_goal_adj = dist;\n                                    target_neighbor_to_move_towards = adj_to_goal;\n                                }\n                            }\n                        }\n                    }\n\n                    if (target_neighbor_to_move_towards.r != -1) { // Found a valid neighbor to move towards\n                        // Use BFS to get the first move character\n                        char move_c = get_move_char(human_pos[i], target_neighbor_to_move_towards, \n                                                    current_blocked_this_turn, current_moved_to_this_turn_targets, \n                                                    human_pos, i); \n                        if (move_c != '.') { // If a path was found\n                            Point first_step = human_pos[i]; \n                            for (int d = 0; d < 4; ++d) {\n                                if (MOVE_CHARS[d] == move_c) {\n                                    first_step = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                                    break;\n                                }\n                            }\n                            // Priority is based on negative distance to goal, so smaller distance means higher priority\n                            move_queue.push({i, first_step, move_c, -min_dist_to_goal_adj}); \n                        }\n                    }\n                }\n            }\n        }\n\n        // Process the move_queue to resolve conflicts (multiple humans wanting to move to the same cell)\n        while (!move_queue.empty()) {\n            MoveCandidate mc = move_queue.top();\n            move_queue.pop();\n\n            if (actions_output[mc.human_idx] == '.') { // If human hasn't been assigned an action yet\n                // Check if the target cell for this move is free (not blocked or targeted by another human)\n                if (!current_blocked_this_turn.count(mc.next_pos) && !current_moved_to_this_turn_targets.count(mc.next_pos)) {\n                    actions_output[mc.human_idx] = mc.move_char; // Assign the move action\n                    next_human_pos_candidates[mc.human_idx] = mc.next_pos; // Update planned position\n                    current_moved_to_this_turn_targets.insert(mc.next_pos); // Mark as targeted\n                }\n                // Else: Conflict occurred, the human stays put (action remains '.')\n            }\n        }\n\n        // 3. Output actions for all humans\n        for (int i = 0; i < M; ++i) {\n            cout << actions_output[i];\n        }\n        cout << endl; // Newline after all actions\n        fflush(stdout); // Crucial for interactive problems\n\n        // 4. Update game state (board and human_pos) based on actions\n        for (int i = 0; i < M; ++i) {\n            // If the action was a block, update the board state permanently\n            // Check if it's not a '.' and not one of the move characters ('U', 'D', 'L', 'R')\n            if (actions_output[i] != '.' && string(MOVE_CHARS).find(actions_output[i]) == string::npos) {\n                Point blocked_cell = human_pos[i]; // Initialize with human's position\n                char block_char = actions_output[i];\n                for(int d=0; d<4; ++d) {\n                    if (BLOCK_CHARS[d] == block_char) {\n                        blocked_cell = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                        break;\n                    }\n                }\n                board[blocked_cell.r][blocked_cell.c] = 1; // Mark cell as impassable\n            }\n            human_pos[i] = next_human_pos_candidates[i]; // Update human positions\n        }\n\n        // 5. Read pet movements and update pet positions\n        string pet_moves_str;\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves_str;\n            if (pet_moves_str == \".\") continue; // Pet did not move\n            \n            for (char move_char : pet_moves_str) {\n                for (int d = 0; d < 4; ++d) {\n                    if (MOVE_CHARS[d] == move_char) {\n                        pet_pos[i].r += DR[d];\n                        pet_pos[i].c += DC[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int H = 20;\nconst int W = 20;\nconst int MAX_PATH_LENGTH = 200;\n\n// Global variables for problem input\nint start_r, start_c, target_r, target_c;\ndouble p_forget_val;\nbool has_wall_right[H][W - 1]; // wall between (r,c) and (r,c+1)\nbool has_wall_down[H - 1][W];  // wall between (r,c) and (r+1,c)\n\n// Directions for movement\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar move_chars[] = {'U', 'D', 'L', 'R'};\n\n// Helper function to calculate next position, staying if wall or boundary\npair<int, int> get_next_pos(int r, int c, char move_char) {\n    int nr = r, nc = c; // Default to staying\n    if (move_char == 'U') {\n        if (r > 0 && !has_wall_down[r - 1][c]) {\n            nr = r - 1;\n        }\n    } else if (move_char == 'D') {\n        if (r < H - 1 && !has_wall_down[r][c]) {\n            nr = r + 1;\n        }\n    } else if (move_char == 'L') {\n        if (c > 0 && !has_wall_right[r][c - 1]) {\n            nc = c - 1;\n        }\n    } else if (move_char == 'R') {\n        if (c < W - 1 && !has_wall_right[r][c]) {\n            nc = c + 1;\n        }\n    }\n    return {nr, nc};\n}\n\n// DP states (declared globally to avoid reallocations and for performance)\nvector<vector<double>> current_dp_state(H, vector<double>(W));\nvector<vector<double>> next_dp_state(H, vector<double>(W));\n\n// Evaluates a given path string\ndouble evaluate(const string& path) {\n    // Reset initial state for a new path evaluation\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_dp_state[i][j] = 0.0;\n        }\n    }\n    current_dp_state[start_r][start_c] = 1.0;\n\n    double total_expected_score = 0.0;\n\n    for (int k = 0; k < path.length(); ++k) {\n        // Clear next_dp_state for this turn's calculations\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                next_dp_state[i][j] = 0.0;\n            }\n        }\n\n        double prob_reach_this_turn = 0.0;\n        char move_char = path[k];\n\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (current_dp_state[r][c] == 0.0) continue; // No probability mass\n\n                // Option 1: Forgets char (prob p_forget_val), stays at (r,c)\n                // current_dp_state[r][c] is prob of being at (r,c) AND NOT AT TARGET.\n                // So (r,c) cannot be (target_r, target_c).\n                // Thus, staying at (r,c) does not make him reach the target.\n                next_dp_state[r][c] += current_dp_state[r][c] * p_forget_val;\n\n                // Option 2: Remembers char (prob 1-p_forget_val), moves according to move_char\n                pair<int, int> next_pos = get_next_pos(r, c, move_char);\n                int nr = next_pos.first;\n                int nc = next_pos.second;\n\n                if (nr == target_r && nc == target_c) {\n                    // Reached target at turn k+1\n                    prob_reach_this_turn += current_dp_state[r][c] * (1.0 - p_forget_val);\n                } else {\n                    // Did not reach target\n                    next_dp_state[nr][nc] += current_dp_state[r][c] * (1.0 - p_forget_val);\n                }\n            }\n        }\n\n        total_expected_score += prob_reach_this_turn * (401.0 - (k + 1));\n        current_dp_state.swap(next_dp_state); // Efficiently update current_dp_state\n    }\n    return total_expected_score;\n}\n\n// BFS to find the shortest path\nstring get_bfs_path() {\n    vector<vector<int>> dist(H, vector<int>(W, -1));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> move_to_parent(H, vector<char>(W, ' '));\n    queue<pair<int, int>> q;\n\n    q.push({start_r, start_c});\n    dist[start_r][start_c] = 0;\n\n    // Using std::queue for simplicity, it's efficient enough for 400 cells\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        if (r == target_r && c == target_c) break; // Found target\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            char move_char = move_chars[i];\n\n            // Check boundaries and walls (using consistent logic with get_next_pos)\n            bool can_move = true;\n            if (move_char == 'U') {\n                if (r == 0 || has_wall_down[r - 1][c]) can_move = false;\n            } else if (move_char == 'D') {\n                if (r == H - 1 || has_wall_down[r][c]) can_move = false;\n            } else if (move_char == 'L') {\n                if (c == 0 || has_wall_right[r][c - 1]) can_move = false;\n            } else if (move_char == 'R') {\n                if (c == W - 1 || has_wall_right[r][c]) can_move = false;\n            }\n\n            if (!can_move) continue;\n            \n            // If can_move, the next position is (nr, nc)\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                parent[nr][nc] = {r, c};\n                move_to_parent[nr][nc] = move_char;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path_str = \"\";\n    int curr_r = target_r;\n    int curr_c = target_c;\n    \n    // According to problem statement, start and target are guaranteed to be different\n    // and all squares are reachable. So dist[target_r][target_c] should not be -1.\n    while (curr_r != start_r || curr_c != start_c) {\n        path_str += move_to_parent[curr_r][curr_c];\n        pair<int, int> p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read input\n    cin >> start_r >> start_c >> target_r >> target_c >> p_forget_val;\n\n    for (int i = 0; i < H; ++i) {\n        string row_h;\n        cin >> row_h;\n        for (int j = 0; j < W - 1; ++j) {\n            has_wall_right[i][j] = (row_h[j] == '1');\n        }\n    }\n    for (int i = 0; i < H - 1; ++i) {\n        string row_v;\n        cin >> row_v;\n        for (int j = 0; j < W; ++j) {\n            has_wall_down[i][j] = (row_v[j] == '1');\n        }\n    }\n\n    // Timer setup\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0; // Use 1.95 seconds to be safe\n\n    // Initial path (BFS shortest path)\n    string best_path_str = get_bfs_path();\n    double best_score = evaluate(best_path_str);\n    string current_path_str = best_path_str;\n    double current_score = best_score;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    // SA parameters\n    double T_start = 2000.0; // Starting temperature\n    double T_end = 1.0;     // Ending temperature\n\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) break;\n\n        double T = T_start * pow(T_end / T_start, elapsed_ms / TIME_LIMIT_MS);\n        \n        string new_path_str = current_path_str;\n        \n        // Adaptive operation selection probabilities\n        double current_len = current_path_str.length();\n        double insert_prob, delete_prob, change_prob;\n\n        // Tune probabilities based on current path length\n        if (current_len < MAX_PATH_LENGTH * 0.5) { // If path is very short\n            insert_prob = 0.5; delete_prob = 0.1; change_prob = 0.4;\n        } else if (current_len < MAX_PATH_LENGTH * 0.8) { // If path is moderately short\n            insert_prob = 0.4; delete_prob = 0.2; change_prob = 0.4;\n        } else if (current_len > MAX_PATH_LENGTH * 0.95) { // If path is very long\n            insert_prob = 0.05; delete_prob = 0.5; change_prob = 0.45;\n        } else { // Default or moderate length\n            insert_prob = 0.25; delete_prob = 0.25; change_prob = 0.5;\n        }\n        \n        double op_choice_rand = prob_dist(rng);\n\n        // --- Operation 1: Change character ---\n        if (op_choice_rand < change_prob) { \n            if (new_path_str.empty()) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            char original_char = new_path_str[idx];\n            \n            char new_char;\n            do {\n                uniform_int_distribution<int> char_dist(0, 3);\n                new_char = move_chars[char_dist(rng)];\n            } while (new_char == original_char);\n            \n            new_path_str[idx] = new_char;\n        } \n        // --- Operation 2: Insert character ---\n        else if (op_choice_rand < change_prob + insert_prob) {\n            if (new_path_str.length() >= MAX_PATH_LENGTH) continue;\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length()); \n            int idx = idx_dist(rng);\n            uniform_int_distribution<int> char_dist(0, 3);\n            char char_to_insert = move_chars[char_dist(rng)];\n            \n            new_path_str.insert(idx, 1, char_to_insert);\n        } \n        // --- Operation 3: Delete character ---\n        else { \n            if (new_path_str.empty()) continue; // Path cannot be empty\n            if (new_path_str.length() == 1 && (start_r == target_r && start_c == target_c)) continue; // Don't make path empty if start=target\n\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            \n            new_path_str.erase(idx, 1);\n        }\n\n        // Evaluate new path\n        double new_score = evaluate(new_path_str);\n\n        // SA acceptance criterion\n        if (new_score > current_score || prob_dist(rng) < exp((new_score - current_score) / T)) {\n            current_score = new_score;\n            current_path_str = new_path_str;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path_str = current_path_str;\n            }\n        }\n    }\n\n    cout << best_path_str << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple> // For std::tuple\n\n// Define grid dimensions\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0=Left, 1=Up, 2=Right, 3=Down\n// di, dj: changes in row and column for each direction\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// initial_to[tile_type][entry_direction] -> exit_direction\n// Provided by problem statement\nconst int initial_to[8][4] = {\n    {1, 0, -1, -1}, // Type 0: L-U curve (0-1)\n    {-1, 2, 1, -1}, // Type 1: U-R curve (1-2)\n    {-1, -1, 3, 2}, // Type 2: R-D curve (2-3)\n    {3, -1, -1, 0}, // Type 3: D-L curve (3-0)\n    {1, 0, 3, 2},   // Type 4: L-U and R-D (0-1, 2-3)\n    {3, 2, 1, 0},   // Type 5: U-R and D-L (1-2, 3-0)\n    {2, -1, 0, -1}, // Type 6: horizontal straight (0-2)\n    {-1, 3, -1, 1}  // Type 7: vertical straight (1-3)\n};\n\n// Stores the initial tile types read from input\nstd::vector<std::vector<int>> initial_tiles(H, std::vector<int>(W));\n// Stores the current rotation for each tile (0-3)\nstd::vector<std::vector<int>> current_rotations(H, std::vector<int>(W));\n\n// Precompute effective_to table for faster lookup\n// effective_to[initial_tile_type][rotation_count][entry_direction] -> exit_direction\nint effective_to[8][4][4];\n\nvoid precompute_effective_to() {\n    for (int t_initial = 0; t_initial < 8; ++t_initial) {\n        for (int r_rot = 0; r_rot < 4; ++r_rot) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // 1. Convert absolute entry direction to tile's original orientation\n                int d_base = (d_entry - r_rot + 4) % 4;\n                \n                // 2. Find exit direction in tile's original orientation\n                int exit_base = initial_to[t_initial][d_base];\n                \n                // 3. If broken, mark as -1\n                if (exit_base == -1) {\n                    effective_to[t_initial][r_rot][d_entry] = -1;\n                } else {\n                    // 4. Convert exit direction back to absolute orientation\n                    effective_to[t_initial][r_rot][d_entry] = (exit_base + r_rot) % 4;\n                }\n            }\n        }\n    }\n}\n\n// Function to calculate the exit direction for a given tile and entry\ninline int get_exit_dir(int r, int c, int d_entry) {\n    return effective_to[initial_tiles[r][c]][current_rotations[r][c]][d_entry];\n}\n\nstruct VisitedState {\n    int id;  // Unique ID for the current calculate_score() call or active path\n    int len; // Path length when this state was first visited in current active path\n};\n// Use static to initialize once to {0,0} for all entries\nstatic VisitedState visited_tracking[H][W][4];\nstatic int current_search_id = 0; // Incremented for each calculate_score() call\n\nlong long calculate_score() {\n    std::vector<long long> loop_lengths;\n    current_search_id++; // New unique ID for this score calculation\n\n    // `active_path_id` is used to mark nodes *currently in the path exploration*.\n    // `current_search_id` is used to mark nodes that have been *fully processed*\n    // (either part of a completed cycle or a path that dead-ended/merged).\n    int active_path_id = current_search_id + 1;\n\n    for (int r = 0; r < H; ++r) {\n        for (int c = 0; c < W; ++c) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                if (visited_tracking[r][c][d_entry].id == current_search_id ||\n                    visited_tracking[r][c][d_entry].id == active_path_id) {\n                    continue; // Already processed or currently being explored\n                }\n\n                int curr_r = r;\n                int curr_c = c;\n                int curr_d_entry = d_entry;\n                long long path_len = 0;\n                \n                // Store nodes in current path for later global marking\n                std::vector<std::tuple<int, int, int>> nodes_in_current_path_segment;\n\n                while (true) {\n                    // Check if current node is out of bounds\n                    if (curr_r < 0 || curr_r >= H || curr_c < 0 || curr_c >= W) {\n                        break; // Out of bounds\n                    }\n                    \n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == active_path_id) {\n                        // Cycle detected! Current node was visited in this active path.\n                        long long cycle_start_len = visited_tracking[curr_r][curr_c][curr_d_entry].len;\n                        loop_lengths.push_back(path_len - cycle_start_len);\n                        break;\n                    }\n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == current_search_id) {\n                        // Merged into an already processed path/cycle (from an earlier exploration in this `calculate_score` call)\n                        break;\n                    }\n\n                    // Mark current node as 'in active path' and record its length\n                    visited_tracking[curr_r][curr_c][curr_d_entry] = {active_path_id, (int)path_len};\n                    nodes_in_current_path_segment.emplace_back(curr_r, curr_c, curr_d_entry); // Store nodes for later global marking\n\n                    int d_exit = get_exit_dir(curr_r, curr_c, curr_d_entry);\n                    if (d_exit == -1) {\n                        break; // Broken line\n                    }\n\n                    int next_r = curr_r + di[d_exit];\n                    int next_c = curr_c + dj[d_exit];\n                    int next_d_entry = (d_exit + 2) % 4; // Direction into the next tile\n                    path_len++;\n\n                    curr_r = next_r;\n                    curr_c = next_c;\n                    curr_d_entry = next_d_entry;\n                }\n\n                // After path ends (break from loop), mark all nodes visited in `nodes_in_current_path_segment`\n                // as 'processed for current_search_id'. This includes nodes part of detected cycles.\n                for (const auto& node : nodes_in_current_path_segment) {\n                    visited_tracking[std::get<0>(node)][std::get<1>(node)][std::get<2>(node)].id = current_search_id;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) {\n        return 0;\n    }\n\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend()); // Sort descending\n    return loop_lengths[0] * loop_lengths[1];\n}\n\n// Random number generator\nstd::mt19937 mt;\n\nvoid solve() {\n    auto start_time = std::chrono::high_resolution_clock::now();\n\n    // Read initial tile types\n    for (int i = 0; i < H; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < W; ++j) {\n            initial_tiles[i][j] = row_str[j] - '0';\n        }\n    }\n\n    precompute_effective_to();\n\n    // Initialize random number generator\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\n    mt.seed(seed);\n\n    // Initial solution: random rotations\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_rotations[i][j] = mt() % 4;\n        }\n    }\n\n    std::vector<std::vector<int>> best_rotations = current_rotations;\n    long long current_score = calculate_score();\n    long long best_score = current_score;\n\n    // Simulated Annealing parameters\n    // T_START chosen to be large enough given potential max score ~3.24 * 10^6\n    double T_START = 200000.0; \n    double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds out of 2.0s\n    \n    long long iteration_count = 0;\n\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) { \n            break;\n        }\n\n        // Linear cooling schedule\n        double T = T_START * (1.0 - elapsed_ms / TIME_LIMIT_MS);\n        if (T < 0.1) T = 0.1; // Prevent T from becoming zero or negative too early\n\n        // Generate neighbor: pick one random tile and change its rotation\n        int r_idx = mt() % H;\n        int c_idx = mt() % W;\n        int old_rot = current_rotations[r_idx][c_idx];\n        int new_rot = (old_rot + (mt() % 3) + 1) % 4; // Ensures new_rot is different from old_rot\n\n        current_rotations[r_idx][c_idx] = new_rot;\n        long long neighbor_score = calculate_score();\n        \n        long long delta_score = neighbor_score - current_score;\n\n        if (delta_score > 0 || std::uniform_real_distribution<double>(0.0, 1.0)(mt) < std::exp(delta_score / T)) {\n            current_score = neighbor_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations;\n            }\n        } else {\n            // Revert to old rotation\n            current_rotations[r_idx][c_idx] = old_rot;\n        }\n        iteration_count++;\n    }\n\n    // Output best rotations\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++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}\n","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n\n// Standard library includes\n// Not using AC Library or Boost for this problem, as DSU is simple to implement.\n\nusing namespace std;\n\n// --- Constants and Global Variables ---\nconst long long TIME_LIMIT_MS = 2800; // 2.8 seconds for computation\nconst double T_START = 200.0;        // Initial temperature for Simulated Annealing\nconst double T_END = 0.01;           // Final temperature for Simulated Annealing\n\nint N;               // Board size\nint MAX_S_VALUE;     // Maximum possible S value (N*N - 1)\nlong long MAX_MOVES; // Maximum allowed operations (T = 2 * N^3)\nint W_S;             // Weight for (MAX_S_VALUE - S) in energy function\nint W_K = 1;         // Weight for K (number of operations) in energy function\n\n// Directions for empty square movement\n// 0: U (empty moves up, tile from (er-1, ec) slides D into (er, ec))\n// 1: D (empty moves down, tile from (er+1, ec) slides U into (er, ec))\n// 2: L (empty moves left, tile from (er, ec-1) slides R into (er, ec))\n// 3: R (empty moves right, tile from (er, ec+1) slides L into (er, ec))\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_char[] = {'U', 'D', 'L', 'R'};\nint opposite_dir[] = {1, 0, 3, 2}; // e.g., opposite of U(0) is D(1)\n\n// Global random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- DSU Structure for Score Calculation ---\nstruct DSU {\n    vector<int> parent;\n    vector<int> comp_size;\n    vector<int> num_edges;\n    vector<bool> has_cycle;\n    int num_cells;\n\n    DSU(int n_squared) : num_cells(n_squared) {\n        parent.resize(num_cells);\n        iota(parent.begin(), parent.end(), 0); // Initialize parent[i] = i\n        comp_size.assign(num_cells, 1);        // Each cell starts as a component of size 1\n        num_edges.assign(num_cells, 0);        // Each component starts with 0 edges\n        has_cycle.assign(num_cells, false);    // No cycles initially\n    }\n\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\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            // Union by size/rank: attach smaller tree to larger tree\n            if (comp_size[root_i] < comp_size[root_j])\n                swap(root_i, root_j);\n            parent[root_j] = root_i;\n            comp_size[root_i] += comp_size[root_j];\n            num_edges[root_i] += num_edges[root_j]; // Add edges from merged component\n            num_edges[root_i]++;                     // Add the new edge\n            has_cycle[root_i] = has_cycle[root_i] || has_cycle[root_j]; // Propagate cycle info\n        } else {\n            num_edges[root_i]++;         // Edge added within the same component\n            has_cycle[root_i] = true;    // This implies a cycle\n        }\n    }\n};\n\n// --- BoardState Structure ---\nstruct BoardState {\n    vector<vector<int>> board;\n    int empty_r, empty_c;\n    string moves;\n    int last_move_idx; // Index of the last move (0:U, 1:D, 2:L, 3:R), -1 if no previous move\n\n    BoardState(int n_val) : board(n_val, vector<int>(n_val)), empty_r(-1), empty_c(-1), last_move_idx(-1) {}\n\n    // Calculate the score S for the current board configuration\n    // S is the number of vertices in the largest tree component (connected and acyclic)\n    int calculate_S() const {\n        DSU dsu(N * N);\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // The empty cell is not part of the graph formed by tiles\n                if (r == empty_r && c == empty_c) continue;\n\n                int current_tile = board[r][c];\n                int current_idx = r * N + c;\n\n                // Check downward connection with (r+1, c)\n                if (r + 1 < N) {\n                    // Ensure the neighbor cell (r+1,c) is not the empty square\n                    if (!(r + 1 == empty_r && c == empty_c)) { \n                        int neighbor_tile = board[r+1][c];\n                        int neighbor_idx = (r+1) * N + c;\n                        // An edge exists if (r,c) has a downward line (bit 8) AND (r+1,c) has an upward line (bit 2)\n                        if ((current_tile & 8) && (neighbor_tile & 2)) {\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n                // Check rightward connection with (r, c+1)\n                if (c + 1 < N) {\n                    // Ensure the neighbor cell (r,c+1) is not the empty square\n                    if (!(r == empty_r && c + 1 == empty_c)) {\n                        int neighbor_tile = board[r][c+1];\n                        int neighbor_idx = r * N + (c+1);\n                        // An edge exists if (r,c) has a rightward line (bit 4) AND (r,c+1) has a leftward line (bit 1)\n                        if ((current_tile & 4) && (neighbor_tile & 1)) {\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n            }\n        }\n\n        int max_S = 0;\n        for (int i = 0; i < N * N; ++i) {\n            // Skip the empty square when evaluating components\n            if (i == empty_r * N + empty_c) continue;\n\n            if (dsu.parent[i] == i) { // If 'i' is the root of a component\n                // A component is considered a \"tree\" for scoring if it has no cycles\n                // and has (num_vertices - 1) edges. The DSU logic ensures that\n                // if has_cycle[root] is false, then num_edges[root] == comp_size[root] - 1.\n                if (!dsu.has_cycle[i]) {\n                    max_S = max(max_S, dsu.comp_size[i]);\n                }\n            }\n        }\n        return max_S;\n    }\n};\n\n// --- Main Function ---\nint main() {\n    ios_base::sync_with_stdio(false); // Faster I/O\n    cin.tie(NULL);\n\n    cin >> N >> MAX_MOVES;\n\n    MAX_S_VALUE = N * N - 1; // Total number of tiles, excluding the empty one\n    W_S = 2 * N;             // Set W_S based on N, W_K is 1\n\n    BoardState current_state(N);\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            current_state.board[i][j] = stoi(string(1, row_str[j]), nullptr, 16);\n            if (current_state.board[i][j] == 0) { // Found the empty square\n                current_state.empty_r = i;\n                current_state.empty_c = j;\n            }\n        }\n    }\n\n    // Initialize best state with the initial state\n    BoardState best_state = current_state;\n    int current_S = current_state.calculate_S();\n    int current_K = 0; // Number of operations starts at 0\n\n    int best_S = current_S;\n    int best_K = current_K;\n\n    // Calculate initial energy\n    long double current_energy = (long double)(MAX_S_VALUE - current_S) * W_S + current_K * W_K;\n    long double best_energy = current_energy;\n\n    auto start_time = chrono::steady_clock::now();\n    long long iter_count = 0;\n\n    uniform_real_distribution<long double> dist_prob(0.0, 1.0); // For acceptance probability\n\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() < TIME_LIMIT_MS) {\n        iter_count++;\n\n        // Calculate current temperature based on elapsed time\n        long double progress = (long double)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / TIME_LIMIT_MS;\n        long double temp = T_START * pow(T_END / T_START, progress);\n\n        // Determine possible moves\n        vector<int> possible_moves_indices;\n        for (int i = 0; i < 4; ++i) { // Iterate through U, D, L, R directions\n            int next_empty_r = current_state.empty_r + dr[i];\n            int next_empty_c = current_state.empty_c + dc[i];\n\n            // Check if move is within board boundaries\n            if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                // If there was a previous move, avoid immediately reversing it\n                if (current_state.last_move_idx == -1 || i != opposite_dir[current_state.last_move_idx]) {\n                    possible_moves_indices.push_back(i);\n                }\n            }\n        }\n        \n        // Fallback: If no non-reverting moves are possible (unlikely for N >= 6),\n        // then consider all valid moves, including reversing. This prevents getting stuck.\n        if (possible_moves_indices.empty()) {\n            for (int i = 0; i < 4; ++i) {\n                int next_empty_r = current_state.empty_r + dr[i];\n                int next_empty_c = current_state.empty_c + dc[i];\n                if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                     possible_moves_indices.push_back(i);\n                }\n            }\n            if (possible_moves_indices.empty()) { // Still empty? This means N<2 or invalid board, just continue.\n                 continue;\n            }\n        }\n\n        // Pick a random move from the possible options\n        uniform_int_distribution<int> dist_valid_dir(0, possible_moves_indices.size() - 1);\n        int move_idx = possible_moves_indices[dist_valid_dir(rng)];\n\n        int next_empty_r = current_state.empty_r + dr[move_idx];\n        int next_empty_c = current_state.empty_c + dc[move_idx];\n        \n        // Create the next state by performing the chosen move\n        BoardState next_state = current_state;\n        // The tile at (next_empty_r, next_empty_c) moves into the current empty spot\n        // The current empty spot (current_state.empty_r, current_state.empty_c) becomes the new tile's value\n        // And (next_empty_r, next_empty_c) becomes the new empty spot\n        next_state.board[current_state.empty_r][current_state.empty_c] = next_state.board[next_empty_r][next_empty_c];\n        next_state.board[next_empty_r][next_empty_c] = 0; // The tile that moved leaves an empty square\n        next_state.empty_r = next_empty_r;\n        next_state.empty_c = next_empty_c;\n        next_state.moves += dir_char[move_idx]; // Record the move\n        next_state.last_move_idx = move_idx;     // Update last move index\n\n        int next_K = next_state.moves.length();\n        if (next_K > MAX_MOVES) {\n            // If this move exceeds the maximum allowed operations, reject it.\n            continue; \n        }\n\n        // Calculate S and energy for the next state\n        int next_S = next_state.calculate_S();\n        long double next_energy = (long double)(MAX_S_VALUE - next_S) * W_S + next_K * W_K;\n\n        long double delta_E = next_energy - current_energy;\n\n        // Simulated Annealing acceptance criteria\n        if (delta_E < 0 || dist_prob(rng) < exp(-delta_E / temp)) {\n            // Accept the new state\n            current_state = next_state;\n            current_S = next_S;\n            current_K = next_K;\n            current_energy = next_energy;\n            \n            // Update the best solution found so far\n            if (current_S > best_S) {\n                best_S = current_S;\n                best_K = current_K;\n                best_state = current_state;\n                best_energy = current_energy;\n            } else if (current_S == best_S && current_K < best_K) { // If S is same, prefer fewer moves\n                best_K = current_K;\n                best_state = current_state;\n                best_energy = current_energy;\n            }\n        }\n    }\n\n    // Output debug information to stderr\n    cerr << \"Iterations: \" << iter_count << endl;\n    cerr << \"Best S: \" << best_S << endl;\n    cerr << \"Best K: \" << best_K << endl;\n    \n    // Output the sequence of moves to stdout\n    cout << best_state.moves << endl;\n\n    return 0;\n}\n","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <algorithm>\n#include <unordered_map>\n\n// Using long long for coordinates and intermediate calculations for lines\n// Max value for Ax + By + C is ~2*10^18, fits in long long.\n\nusing namespace std;\n\n// --- Time and Random Number Generator ---\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nuniform_int_distribution<long long> dist_line_coord(-1000000000LL, 1000000000LL); // Line point coordinates\nuniform_int_distribution<int> dist_k_idx(0, 99); // For picking which line to perturb, K is fixed at 100\nuniform_int_distribution<int> dist_coord_choice(0, 3); // For picking px, py, qx, qy to perturb\nuniform_real_distribution<double> dist_01(0.0, 1.0);\n\n// --- Global variables ---\nint N_strawberries;\nint K_max_cuts; \nvector<int> a_attendees(11); // a_d for d=1 to 10. a_attendees[0] unused.\nlong long total_attendees_demand = 0; // Sum of a_d\n\nstruct Strawberry {\n    long long x, y;\n};\nvector<Strawberry> strawberries;\n\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C; // Line equation Ax + By + C = 0\n\n    Line(long long p1x, long long p1y, long long p2x, long long p2y) :\n        px(p1x), py(p1y), qx(p2x), qy(p2y) {\n        // Ensure distinct points; if identical, slightly move one to make it distinct.\n        if (p1x == p2x && p1y == p2y) { \n            p2x++; // Move qx by 1 unit to make it distinct. Within bounds if p2x is not max.\n            if (p2x > 1000000000LL) p2x -= 2; // If max, move other way.\n        }\n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n        \n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        // Normalize such that A is positive, or if A is 0, B is positive.\n        // This ensures a canonical representation for the line.\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n    Line() : px(0), py(0), qx(1), qy(0), A(0), B(-1), C(0) {} // Default horizontal line y=0\n\n    void perturb(double temp_ratio) {\n        long long perturb_magnitude = (long long)(2e8 * temp_ratio) + 1; // Range decreases with temp_ratio (0 to 1)\n        if (perturb_magnitude < 10) perturb_magnitude = 10;\n        \n        long long old_px = px, old_py = py, old_qx = qx, old_qy = qy; // Store all old values for potential revert\n        \n        long long *coord_ptr;\n        switch (dist_coord_choice(rng)) {\n            case 0: coord_ptr = &px; break;\n            case 1: coord_ptr = &py; break;\n            case 2: coord_ptr = &qx; break;\n            default: coord_ptr = &qy; break;\n        }\n        long long new_coord_val = *coord_ptr + uniform_int_distribution<long long>(-perturb_magnitude, perturb_magnitude)(rng);\n        *coord_ptr = max(-1000000000LL, min(1000000000LL, new_coord_val));\n\n        // After perturbing, ensure points are distinct. If not, revert to original.\n        if (px == qx && py == qy) {\n            px = old_px; py = old_py; qx = old_qx; qy = old_qy;\n        }\n        \n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n\n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n};\n\n// Custom hash for vector<char> for unordered_map\nstruct VecCharHash {\n    std::size_t operator()(const std::vector<char>& v) const {\n        std::size_t seed = v.size();\n        for (char i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\n// State variables for Simulated Annealing\nvector<vector<char>> strawberry_line_sides_current; // strawberry_line_sides_current[j][i] is sign for strawberry j w.r.t line i\nvector<bool> strawberry_is_lost_current; // strawberry_is_lost_current[j] is true if strawberry j is on any line\nunordered_map<vector<char>, int, VecCharHash> piece_strawberry_counts_current; // Counts of strawberries for each unique line side vector\nvector<long long> b_d_current(11, 0); // Current counts of pieces with d strawberries\nlong long current_score = 0;\nvector<Line> current_lines;\n\n\n// Function to calculate score based on a given b_d vector\nlong long calculate_score(const vector<long long>& b_d_vec) {\n    long long actual_distributed = 0;\n    for (int d = 1; d <= 10; ++d) {\n        actual_distributed += min(a_attendees[d], (int)b_d_vec[d]);\n    }\n    // Score formula: round(10^6 * sum(min(a_d,b_d)) / sum(a_d))\n    if (total_attendees_demand == 0) return 0; // Avoid division by zero\n    return round(1e6 * (double)actual_distributed / total_attendees_demand);\n}\n\n// Function to generate a random line (for initial solution or full replacement)\nLine generate_random_line() {\n    long long p1x, p1y, p2x, p2y;\n    do {\n        p1x = dist_line_coord(rng);\n        p1y = dist_line_coord(rng);\n        p2x = dist_line_coord(rng);\n        p2y = dist_line_coord(rng);\n    } while (p1x == p2x && p1y == p2y); // Loop until distinct points are generated\n    return Line(p1x, p1y, p2x, p2y);\n}\n\n\n// Performs a full evaluation of the given set of lines.\n// Populates strawberry_line_sides_current, strawberry_is_lost_current, \n// piece_strawberry_counts_current, b_d_current, and current_score.\nvoid full_evaluate(const vector<Line>& lines) {\n    strawberry_line_sides_current.assign(N_strawberries, vector<char>(K_max_cuts));\n    strawberry_is_lost_current.assign(N_strawberries, false);\n    piece_strawberry_counts_current.clear();\n    fill(b_d_current.begin(), b_d_current.end(), 0);\n\n    for (int j = 0; j < N_strawberries; ++j) {\n        for (int i = 0; i < K_max_cuts; ++i) {\n            long long val = lines[i].A * strawberries[j].x + lines[i].B * strawberries[j].y + lines[i].C;\n            if (val == 0) {\n                strawberry_is_lost_current[j] = true;\n                break; // This strawberry is lost, no need to check other lines\n            }\n            strawberry_line_sides_current[j][i] = (val > 0 ? 1 : -1);\n        }\n        if (!strawberry_is_lost_current[j]) {\n            piece_strawberry_counts_current[strawberry_line_sides_current[j]]++;\n        }\n    }\n\n    for (const auto& pair : piece_strawberry_counts_current) {\n        if (pair.second > 0 && pair.second <= 10) { \n            b_d_current[pair.second]++;\n        }\n    }\n    current_score = calculate_score(b_d_current);\n}\n\nvoid solve() {\n    cin >> N_strawberries >> K_max_cuts;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a_attendees[d];\n        total_attendees_demand += a_attendees[d];\n    }\n    strawberries.resize(N_strawberries);\n    for (int i = 0; i < N_strawberries; ++i) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n\n    // Initial solution: K_max_cuts random lines\n    current_lines.resize(K_max_cuts);\n    for (int i = 0; i < K_max_cuts; ++i) {\n        current_lines[i] = generate_random_line();\n    }\n    \n    // Perform initial full evaluation\n    full_evaluate(current_lines);\n\n    vector<Line> best_lines = current_lines;\n    long long best_score = current_score;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.95; // seconds\n\n    double T_start = 1e7; \n    double T_end = 1e-1;   // Final temperature, low enough to accept only very good changes towards the end\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double temp_ratio = elapsed_time / TIME_LIMIT; // Goes from 0.0 to 1.0\n        double T = T_start * pow(T_end / T_start, temp_ratio); // Exponential cooling schedule\n\n        // Choose a line to perturb\n        int line_idx_to_perturb = dist_k_idx(rng);\n        Line original_line_at_idx = current_lines[line_idx_to_perturb];\n        Line candidate_line = original_line_at_idx;\n        candidate_line.perturb(1.0 - temp_ratio); // Perturb range decreases as temp_ratio approaches 1.0\n\n        // --- Simulate changes and calculate new_score ---\n        // Temporary state for the candidate solution. These are copies.\n        vector<long long> temp_b_d = b_d_current;\n        unordered_map<vector<char>, int, VecCharHash> temp_piece_strawberry_counts = piece_strawberry_counts_current;\n\n        // Vectors to store changes needed to commit if accepted.\n        // These store the *new* state for 'line_idx_to_perturb' or 'is_lost'.\n        vector<char> next_signs_at_idx(N_strawberries);\n        vector<bool> next_is_lost_status(N_strawberries);\n\n        // Iterate through all strawberries to simulate changes\n        for (int j = 0; j < N_strawberries; ++j) {\n            bool was_lost_j = strawberry_is_lost_current[j];\n            char old_sign_at_idx_j = was_lost_j ? 0 : strawberry_line_sides_current[j][line_idx_to_perturb];\n\n            long long val = candidate_line.A * strawberries[j].x + candidate_line.B * strawberries[j].y + candidate_line.C;\n            char new_sign_at_idx_j = (val == 0) ? 0 : (val > 0 ? 1 : -1);\n\n            // Store proposed new state for this strawberry in temporary commit vectors\n            next_signs_at_idx[j] = new_sign_at_idx_j;\n            next_is_lost_status[j] = (new_sign_at_idx_j == 0);\n\n            // Check if this strawberry's *overall piece status* changes.\n            // Case 1: Was lost, remains lost. No change to any piece count for this strawberry.\n            if (was_lost_j && (new_sign_at_idx_j == 0)) {\n                continue;\n            }\n            // Case 2: Was not lost, remains not lost, and sign for line_idx doesn't change. No change.\n            if (!was_lost_j && !(new_sign_at_idx_j == 0) && (old_sign_at_idx_j == new_sign_at_idx_j)) {\n                continue;\n            }\n            \n            // This strawberry's effective piece status changes, so update temp_b_d and temp_piece_strawberry_counts\n            \n            // If it was in a piece, remove it from old piece (before its modification)\n            if (!was_lost_j) { \n                int old_count = temp_piece_strawberry_counts[strawberry_line_sides_current[j]];\n                if (old_count >= 1 && old_count <= 10) {\n                    temp_b_d[old_count]--;\n                }\n                temp_piece_strawberry_counts[strawberry_line_sides_current[j]]--;\n            }\n\n            // If it now belongs to a piece, add it to the new piece\n            if (!(new_sign_at_idx_j == 0)) { // If it is not lost\n                // Construct the new key by taking the old key and changing sign for line_idx_to_perturb\n                vector<char> new_key_j = strawberry_line_sides_current[j]; \n                new_key_j[line_idx_to_perturb] = new_sign_at_idx_j; \n                \n                temp_piece_strawberry_counts[new_key_j]++;\n                int new_count = temp_piece_strawberry_counts[new_key_j];\n\n                if (new_count >= 1 && new_count <= 10) {\n                    temp_b_d[new_count]++;\n                }\n            }\n        }\n        \n        long long new_score = calculate_score(temp_b_d);\n\n        if (new_score > current_score || dist_01(rng) < exp((double)(new_score - current_score) / T)) {\n            // Accept the change\n            current_lines[line_idx_to_perturb] = candidate_line;\n            b_d_current = temp_b_d;\n            piece_strawberry_counts_current = temp_piece_strawberry_counts;\n            current_score = new_score;\n\n            // Commit changes to strawberry_line_sides_current and strawberry_is_lost_current for all strawberries\n            for (int j = 0; j < N_strawberries; ++j) {\n                strawberry_is_lost_current[j] = next_is_lost_status[j];\n                if (!strawberry_is_lost_current[j]) {\n                    strawberry_line_sides_current[j][line_idx_to_perturb] = next_signs_at_idx[j];\n                }\n            }\n\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_lines = current_lines;\n            }\n        } else {\n            // Reject: no changes to `current_lines`, `b_d_current`, `piece_strawberry_counts_current`.\n            // `strawberry_line_sides_current` and `strawberry_is_lost_current` were not modified globally in the loop,\n            // so no revert needed for them.\n        }\n    }\n\n    // Output best solution found\n    cout << K_max_cuts << endl;\n    for (const auto& line : best_lines) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << endl;\n    }\n}\n\n// Main function to run the solution\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <chrono>\n\n// To manage execution time\nstd::chrono::high_resolution_clock::time_point start_time;\ndouble time_limit_ms = 4900.0; // 4.9 seconds to be safe\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        return !(*this == other);\n    }\n    // For sorting in set/map, etc.\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\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\nstruct RectangleOp {\n    Point p1, p2, p3, p4;\n};\n\nint N_global;\ndouble center_coord;\nstd::vector<std::vector<bool>> has_dot;\n\n// For condition 3: tracking drawn segments\n// horizontal_drawn[y][x]: segment (x,y)-(x+1,y)\nstd::vector<std::vector<bool>> horizontal_drawn;\n// vertical_drawn[x][y]: segment (x,y)-(x,y+1)\nstd::vector<std::vector<bool>> vertical_drawn;\n// diag_up_drawn[x][y]: segment (x,y)-(x+1,y+1) (slope +1)\nstd::vector<std::vector<bool>> diag_up_drawn;\n// diag_down_drawn[x][y]: segment (x,y+1)-(x+1,y) (slope -1)\nstd::vector<std::vector<bool>> diag_down_drawn;\n\n// Weights precomputation\nstd::vector<std::vector<double>> point_weights;\n\n// Precompute weights for all points\nvoid precompute_weights() {\n    point_weights.resize(N_global, std::vector<double>(N_global));\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            point_weights[i][j] = pow(i - center_coord, 2) + pow(j - center_coord, 2) + 1.0;\n        }\n    }\n}\n\ndouble get_weight(Point p) {\n    if (p.x < 0 || p.x >= N_global || p.y < 0 || p.y >= N_global) return -1.0; // Invalid point\n    return point_weights[p.x][p.y];\n}\n\nbool is_in_bounds(Point p) {\n    return p.x >= 0 && p.x < N_global && p.y >= 0 && p.y < N_global;\n}\n\n// Helper to check if a point on perimeter is an allowed dot (one of p2,p3,p4)\nbool is_allowed_dot(Point p, Point p2, Point p3, Point p4) {\n    return p == p2 || p == p3 || p == p4;\n}\n\n// Function to check condition 2 (no other dots on perimeter)\n// Iterates grid points on each segment.\nbool check_perimeter_dots(Point p1, Point p2, Point p3, Point p4) {\n    auto check_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        int steps = std::max(std::abs(dx), std::abs(dy));\n\n        if (steps == 0) return true; // Degenerate segment\n\n        for (int i = 1; i < steps; ++i) { // Exclude endpoints\n            Point p = {start.x + dx * i / steps, start.y + dy * i / steps};\n            if (p.x * steps != start.x * steps + dx * i || p.y * steps != start.y * steps + dy * i) continue; // Only check integer points\n\n            if (has_dot[p.x][p.y] && !is_allowed_dot(p, p2, p3, p4)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    if (!check_segment(p1, p2)) return false;\n    if (!check_segment(p2, p3)) return false;\n    if (!check_segment(p3, p4)) return false;\n    if (!check_segment(p4, p1)) return false;\n    return true;\n}\n\n// Function to check condition 3 (no shared segment with positive length)\nbool check_shared_segments(Point p1, Point p2, Point p3, Point p4) {\n    auto check_and_mark_segment = [&](Point start, Point end, bool dry_run) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                if (vertical_drawn[x][y]) return false;\n                if (!dry_run) vertical_drawn[x][y] = true;\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                if (horizontal_drawn[y][x]) return false;\n                if (!dry_run) horizontal_drawn[y][x] = true;\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                if (diag_up_drawn[min_x + i][min_y + i]) return false;\n                if (!dry_run) diag_up_drawn[min_x + i][min_y + i] = true;\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            int x_inc = (dx > 0) ? 1 : -1;\n            int y_inc = (dy > 0) ? 1 : -1; // dx=-dy means x_inc = -y_inc\n            \n            // Normalize start and end points for consistent indexing.\n            // A segment (x, y+1) -> (x+1, y) is defined by (x,y) for diag_down_drawn\n            // This maps the segment's \"top-left\" corner of its bounding box.\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end); // Ensure start.x <= end.x\n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                // Determine the correct (x,y) for diag_down_drawn[x][y] for (x, y+1)-(x+1, y)\n                // If the segment is (current_start.x, current_start.y) to (current_start.x+1, current_start.y-1)\n                // The index for diag_down_drawn is (current_start.x, current_start.y-1)\n                int current_x = current_start.x + i;\n                int current_y = current_start.y - i -1; // y-coord of lower-left corner\n\n                if (diag_down_drawn[current_x][current_y]) return false;\n                if (!dry_run) diag_down_drawn[current_x][current_y] = true;\n            }\n        }\n        return true;\n    };\n\n    if (!check_and_mark_segment(p1, p2, true)) return false;\n    if (!check_and_mark_segment(p2, p3, true)) return false;\n    if (!check_and_mark_segment(p3, p4, true)) return false;\n    if (!check_and_mark_segment(p4, p1, true)) return false;\n\n    return true; // All checks passed for dry run\n}\n\nvoid mark_segments_drawn(Point p1, Point p2, Point p3, Point p4) {\n    auto mark_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                vertical_drawn[x][y] = true;\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                horizontal_drawn[y][x] = true;\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                diag_up_drawn[min_x + i][min_y + i] = true;\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end);\n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                int current_x = current_start.x + i;\n                int current_y = current_start.y - i -1; // This is the y-coord of the lower left corner (x,y) where the segment is (x,y+1)-(x+1,y)\n                diag_down_drawn[current_x][current_y] = true;\n            }\n        }\n    };\n\n    mark_segment(p1, p2);\n    mark_segment(p2, p3);\n    mark_segment(p3, p4);\n    mark_segment(p4, p1);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    start_time = std::chrono::high_resolution_clock::now();\n\n    int M;\n    std::cin >> N_global >> M;\n\n    center_coord = (N_global - 1) / 2.0;\n\n    has_dot.resize(N_global, std::vector<bool>(N_global, false));\n    horizontal_drawn.resize(N_global, std::vector<bool>(N_global - 1, false));\n    vertical_drawn.resize(N_global - 1, std::vector<bool>(N_global, false));\n    diag_up_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n    diag_down_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n\n\n    std::vector<Point> current_dots_list;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        std::cin >> x >> y;\n        current_dots_list.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    precompute_weights();\n\n    std::vector<RectangleOp> operations;\n    int loop_count = 0;\n    const int max_loops = 5000; // Cap the total main loop iterations to avoid TLE for extreme cases\n\n    while (loop_count < max_loops) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n\n        double best_P1_weight = -1.0;\n        RectangleOp best_op;\n        bool found_op = false;\n\n        // Iterate over all pairs of existing dots P2 and P4\n        for (int i = 0; i < current_dots_list.size(); ++i) {\n            Point p2 = current_dots_list[i];\n            for (int j = 0; j < current_dots_list.size(); ++j) {\n                if (i == j) continue;\n                Point p4 = current_dots_list[j];\n\n                // --- Try Axis-aligned rectangle ---\n                Point p1_aa = {p2.x, p4.y};\n                Point p3_aa = {p4.x, p2.y};\n\n                if (is_in_bounds(p1_aa) && !has_dot[p1_aa.x][p1_aa.y] &&\n                    is_in_bounds(p3_aa) && has_dot[p3_aa.x][p3_aa.y] &&\n                    p1_aa != p2 && p1_aa != p3_aa && p1_aa != p4) // Ensure non-degenerate rectangle\n                {\n                    if (check_perimeter_dots(p1_aa, p2, p3_aa, p4) &&\n                        check_shared_segments(p1_aa, p2, p3_aa, p4)) {\n                        double current_weight = get_weight(p1_aa);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_aa, p2, p3_aa, p4};\n                            found_op = true;\n                        }\n                    }\n                }\n\n                // --- Try 45-degree inclined rectangle ---\n                // P1.x = (P2.x + P4.x - (P2.y - P4.y)) / 2\n                // P1.y = (P2.y + P4.y + (P2.x - P4.x)) / 2\n                // P3.x = (P2.x + P4.x + (P2.y - P4.y)) / 2\n                // P3.y = (P2.y + P4.y - (P2.x - P4.x)) / 2\n                int sum_x = p2.x + p4.x;\n                int sum_y = p2.y + p4.y;\n                int diff_x = p2.x - p4.x;\n                int diff_y = p2.y - p4.y;\n\n                // Check for integer coordinates after transformation\n                if ((sum_x - diff_y) % 2 == 0 && (sum_y + diff_x) % 2 == 0 &&\n                    (sum_x + diff_y) % 2 == 0 && (sum_y - diff_x) % 2 == 0) {\n                    Point p1_45 = {(sum_x - diff_y) / 2, (sum_y + diff_x) / 2};\n                    Point p3_45 = {(sum_x + diff_y) / 2, (sum_y - diff_x) / 2};\n\n                    if (is_in_bounds(p1_45) && !has_dot[p1_45.x][p1_45.y] &&\n                        is_in_bounds(p3_45) && has_dot[p3_45.x][p3_45.y] &&\n                        p1_45 != p2 && p1_45 != p3_45 && p1_45 != p4) { // non-degenerate\n                        if (check_perimeter_dots(p1_45, p2, p3_45, p4) &&\n                            check_shared_segments(p1_45, p2, p3_45, p4)) {\n                            double current_weight = get_weight(p1_45);\n                            if (current_weight > best_P1_weight) {\n                                best_P1_weight = current_weight;\n                                best_op = {p1_45, p2, p3_45, p4};\n                                found_op = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found_op) {\n            break; // No more valid operations\n        }\n\n        // Perform the best operation\n        operations.push_back(best_op);\n        has_dot[best_op.p1.x][best_op.p1.y] = true;\n        current_dots_list.push_back(best_op.p1); // Add new dot to list for future operations\n        mark_segments_drawn(best_op.p1, best_op.p2, best_op.p3, best_op.p4);\n        loop_count++;\n    }\n\n    std::cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        std::cout << op.p1.x << \" \" << op.p1.y << \" \"\n                  << op.p2.x << \" \" << op.p2.y << \" \"\n                  << op.p3.x << \" \" << op.p3.y << \" \"\n                  << op.p4.x << \" \" << op.p4.y << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath> // For round\n\n// Using std namespace for convenience in competitive programming context\nusing namespace std;\n\n// Constants for board size\nconst int N = 10; \n\n// Global board state\nvector<vector<int>> board(N, vector<int>(N, 0)); // 0: empty, 1,2,3: flavors\n\n// Stores the flavors of candies in the order they are received (f_1 to f_100)\nvector<int> flavors_data(100);\n\n// Maps original flavor index (1,2,3) to its assigned region index (0,1,2)\nmap<int, int> flavor_to_region_idx;\n// Maps assigned region index (0,1,2) back to its original flavor index (1,2,3)\nvector<int> region_idx_to_flavor(3);\n\n// Stores start and end rows for each assigned region (0,1,2)\nvector<int> region_rows_start(3);\nvector<int> region_rows_end(3);\n\n// Function to find the (r, c) coordinates of the p-th empty cell\npair<int, int> get_coords_from_p_idx(int p_idx) {\n    int count = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) {\n                count++;\n                if (count == p_idx) {\n                    return {r, c};\n                }\n            }\n        }\n    }\n    return {-1, -1}; // Should not happen in a valid problem scenario\n}\n\n// Function to apply a tilt operation to a given board\nvoid apply_tilt(vector<vector<int>>& current_board, char dir) {\n    if (dir == 'F') { // Forward (up, towards row 0)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = 0; r < N; ++r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = 0; r < N; ++r) {\n                if (r < candies_in_col.size()) {\n                    current_board[r][c] = candies_in_col[r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'B') { // Backward (down, towards row N-1)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = N - 1; r >= 0; --r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = N - 1; r >= 0; --r) {\n                if ((N - 1 - r) < candies_in_col.size()) { // Fill from bottom up\n                    current_board[r][c] = candies_in_col[N - 1 - r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'L') { // Left (towards col 0)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = 0; c < N; ++c) {\n                if (c < candies_in_row.size()) {\n                    current_board[r][c] = candies_in_row[c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'R') { // Right (towards col N-1)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = N - 1; c >= 0; --c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = N - 1; c >= 0; --c) {\n                if ((N - 1 - c) < candies_in_row.size()) { // Fill from right to left\n                    current_board[r][c] = candies_in_row[N - 1 - c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    }\n}\n\n// Function to get the target flavor for a given cell (r, c) based on region partitioning\nint get_target_flavor_for_pos(int r, int c) {\n    int assigned_region_idx;\n    if (r >= region_rows_start[0] && r <= region_rows_end[0]) {\n        assigned_region_idx = 0;\n    } else if (r >= region_rows_start[1] && r <= region_rows_end[1]) {\n        assigned_region_idx = 1;\n    } else { // r must be in region 2\n        assigned_region_idx = 2;\n    }\n    return region_idx_to_flavor[assigned_region_idx];\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // 1. Read all candy flavors (f_1 to f_100)\n    vector<int> d_counts(4, 0); // d_counts[0] unused, d_counts[1,2,3] for flavors 1,2,3\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors_data[i];\n        d_counts[flavors_data[i]]++;\n    }\n\n    // 2. Determine region assignment based on flavor counts\n    // Store pairs of {count, flavor_idx}\n    vector<pair<int, int>> flavor_data_sorted; \n    flavor_data_sorted.push_back({d_counts[1], 1});\n    flavor_data_sorted.push_back({d_counts[2], 2});\n    flavor_data_sorted.push_back({d_counts[3], 3});\n\n    // Sort flavors by their counts in descending order\n    sort(flavor_data_sorted.rbegin(), flavor_data_sorted.rend()); \n\n    // Assign region_idx 0, 1, 2 to flavors based on sorted order (largest count gets region 0, etc.)\n    for (int i = 0; i < 3; ++i) {\n        flavor_to_region_idx[flavor_data_sorted[i].second] = i;\n        region_idx_to_flavor[i] = flavor_data_sorted[i].second;\n    }\n\n    // Calculate initial row counts for each region\n    vector<int> row_counts(3);\n    int assigned_total_rows = 0;\n    for (int i = 0; i < 2; ++i) { // Assign rows for the first two flavors\n        // Calculate proportional rows, ensure at least 1 row\n        row_counts[i] = round(flavor_data_sorted[i].first * static_cast<double>(N) / 100.0);\n        row_counts[i] = max(1, row_counts[i]); \n        assigned_total_rows += row_counts[i];\n    }\n    // The last region takes all remaining rows, ensuring total is N\n    row_counts[2] = max(1, N - assigned_total_rows); \n\n    // Adjust row counts if their sum exceeds N due to rounding and minimum 1 row per region.\n    // This ensures total rows is N while keeping each region at least 1 row.\n    int current_sum_row_counts = row_counts[0] + row_counts[1] + row_counts[2];\n    int diff = current_sum_row_counts - N;\n    if (diff > 0) { // If sum is too high, decrement from largest regions first (index 0, then 1, then 2)\n        for (int i = 0; i < 3 && diff > 0; ++i) {\n            // Only decrement if row count is greater than 1 to maintain the minimum of 1 row\n            if (row_counts[i] > 1) { \n                int decrement_val = min(diff, row_counts[i] - 1);\n                row_counts[i] -= decrement_val;\n                diff -= decrement_val;\n            }\n        }\n    }\n    // No need to adjust for diff < 0 as row_counts[2] calculation handles making the sum exactly N,\n    // unless current_sum_row_counts was already > N when calculating row_counts[2],\n    // which is then caught by the diff > 0 logic above.\n\n    // Calculate actual row start/end for each region based on the final row counts\n    int current_row_idx = 0;\n    for (int i = 0; i < 3; ++i) {\n        region_rows_start[i] = current_row_idx;\n        region_rows_end[i] = current_row_idx + row_counts[i] - 1;\n        current_row_idx += row_counts[i];\n    }\n    \n    // Main loop: process each candy one by one\n    char directions[] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p_t;\n        cin >> p_t; // Read the index of the empty cell for the current candy\n\n        // Find coordinates for the new candy\n        pair<int, int> new_candy_coords = get_coords_from_p_idx(p_t);\n        int r_new = new_candy_coords.first;\n        int c_new = new_candy_coords.second;\n\n        // Place the new candy on the board\n        board[r_new][c_new] = flavors_data[t];\n\n        double best_tilt_score = -1e18; // Initialize with a very small number\n        char best_dir = ' ';\n\n        // Evaluate each of the four possible tilt directions\n        for (char dir : directions) {\n            vector<vector<int>> temp_board = board; // Create a copy of the board for simulation\n            apply_tilt(temp_board, dir); // Simulate the tilt\n\n            double current_tilt_score = 0.0;\n            // Calculate heuristic score for the simulated board state\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (temp_board[r][c] != 0) { // If there's a candy in this cell\n                        int candy_flavor = temp_board[r][c];\n                        int target_flavor = get_target_flavor_for_pos(r, c); // Get the flavor intended for this region\n                        if (candy_flavor == target_flavor) {\n                            current_tilt_score += 1.0; // Reward for being in the correct region\n                        } else {\n                            current_tilt_score -= 1.0; // Penalty for being in the wrong region\n                        }\n                    }\n                }\n            }\n\n            // Update best direction if current tilt yields a higher score\n            if (current_tilt_score > best_tilt_score) {\n                best_tilt_score = current_tilt_score;\n                best_dir = dir;\n            }\n        }\n\n        // Apply the chosen best tilt to the actual board\n        apply_tilt(board, best_dir);\n\n        // Output the chosen direction and flush stdout\n        cout << best_dir << endl;\n    }\n\n    return 0;\n}\n","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <map>\n#include <iomanip>\n#include <chrono> // For timing (not used in final solution, but helpful for debugging)\n\n// Adjacency matrix representation\nusing AdjMatrix = std::vector<std::vector<bool>>;\n\n// Function to convert adjacency matrix to string representation\n// N is number of vertices\nstd::string graph_to_string(const AdjMatrix& adj, int N) {\n    std::string s = \"\";\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Function to convert string representation to adjacency matrix\n// N is number of vertices\nAdjMatrix string_to_graph(const std::string& s, int N) {\n    AdjMatrix adj(N, std::vector<bool>(N, false));\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                adj[i][j] = adj[j][i] = true;\n            }\n            k++;\n        }\n    }\n    return adj;\n}\n\n// Computes WL refinement color histogram (fingerprint) of a graph\n// N is number of vertices\n// wl_iters is the number of Weisfeiler-Lehman iterations\nstd::map<int, int> compute_wl_fingerprint(const AdjMatrix& adj, int N, int wl_iters) {\n    std::vector<int> colors(N);\n    // Initial colors based on degrees\n    for (int i = 0; i < N; ++i) {\n        int degree = 0;\n        for (int j = 0; j < N; ++j) {\n            if (adj[i][j]) {\n                degree++;\n            }\n        }\n        colors[i] = degree;\n    }\n\n    std::map<std::vector<int>, int> color_map; // Maps unique (current_color, sorted_neighbor_colors) to a new integer color\n    int next_color_idx = 0; // Counter for assigning new unique colors\n\n    for (int iter = 0; iter < wl_iters; ++iter) {\n        std::vector<int> new_colors(N);\n        for (int i = 0; i < N; ++i) {\n            std::vector<int> neighbor_colors;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    neighbor_colors.push_back(colors[j]);\n                }\n            }\n            std::sort(neighbor_colors.begin(), neighbor_colors.end());\n\n            // Construct key for color_map: current color + sorted list of neighbor colors\n            std::vector<int> current_key = {colors[i]};\n            current_key.insert(current_key.end(), neighbor_colors.begin(), neighbor_colors.end());\n            \n            // Assign a new unique color if this key hasn't been seen before\n            if (color_map.find(current_key) == color_map.end()) {\n                color_map[current_key] = next_color_idx++;\n            }\n            new_colors[i] = color_map[current_key];\n        }\n        colors = new_colors; // Update colors for the next iteration\n    }\n\n    // Compute histogram of final colors\n    std::map<int, int> histogram;\n    for (int c : colors) {\n        histogram[c]++;\n    }\n    return histogram;\n}\n\n// Calculates squared Euclidean distance between two color histograms\n// Using squared distance is faster as it avoids sqrt and maintains ordering\ndouble histogram_distance(const std::map<int, int>& h1, const std::map<int, int>& h2) {\n    double dist_sq = 0;\n    \n    // Iterate over all colors present in either histogram\n    // To do this efficiently, collect all unique colors first\n    std::vector<int> all_colors;\n    for(const auto& pair : h1) all_colors.push_back(pair.first);\n    for(const auto& pair : h2) all_colors.push_back(pair.first);\n    std::sort(all_colors.begin(), all_colors.end());\n    all_colors.erase(std::unique(all_colors.begin(), all_colors.end()), all_colors.end());\n\n    for (int color : all_colors) {\n        int count1 = h1.count(color) ? h1.at(color) : 0;\n        int count2 = h2.count(color) ? h2.at(color) : 0;\n        dist_sq += (double)(count1 - count2) * (count1 - count2);\n    }\n    return dist_sq;\n}\n\n// Global variables for problem parameters and generated graphs\nint M_param;\ndouble EPSILON_param;\nint N_chosen;\nstd::vector<AdjMatrix> G_graphs;\nstd::vector<std::map<int, int>> G_fingerprints; // Precomputed fingerprints for G_graphs\nint WL_ITERS_chosen; // Number of WL iterations to use\n\n// Function to precompute N and all M graphs G_k\nvoid precompute_graphs() {\n    // Determine N based on M and epsilon. Heuristic choice.\n    // Tries to balance the need for more distinct graphs (larger M, epsilon) with score penalty (larger N).\n    N_chosen = std::min(100, std::max(4, (int)(M_param * 0.4 + 20 + EPSILON_param * 50)));\n\n    // Determine WL_ITERS based on epsilon. Heuristic choice.\n    // Fewer iterations for higher epsilon to prevent noise from propagating too much.\n    WL_ITERS_chosen = std::max(1, 3 - (int)(EPSILON_param * 5));\n\n    int E_total = N_chosen * (N_chosen - 1) / 2; // Total possible edges\n    \n    G_graphs.resize(M_param);\n    G_fingerprints.resize(M_param);\n\n    // List all possible edges to facilitate random selection\n    std::vector<std::pair<int, int>> all_possible_edges;\n    for (int i = 0; i < N_chosen; ++i) {\n        for (int j = i + 1; j < N_chosen; ++j) {\n            all_possible_edges.push_back({i, j});\n        }\n    }\n\n    for (int k = 0; k < M_param; ++k) {\n        AdjMatrix current_G(N_chosen, std::vector<bool>(N_chosen, false));\n        \n        // Target number of edges for G_k.\n        // Distributed from 0 to E_total across M graphs.\n        int target_edges_count = std::round((double)k / (M_param - 1) * E_total);\n        if (M_param == 1) target_edges_count = 0; // Special case for M=1 to avoid division by zero\n        \n        // Generate edges using a pseudo-random approach.\n        // A fixed seed 'k' ensures G_k is deterministic and distinct for each k.\n        std::mt19937 rng(k); \n        std::vector<std::pair<int, int>> shuffled_edges = all_possible_edges;\n        std::shuffle(shuffled_edges.begin(), shuffled_edges.end(), rng);\n\n        // Add the target number of edges\n        for (int i = 0; i < target_edges_count; ++i) {\n            auto edge = shuffled_edges[i];\n            current_G[edge.first][edge.second] = true;\n            current_G[edge.second][edge.first] = true;\n        }\n        G_graphs[k] = current_G;\n        // Precompute fingerprint for efficiency\n        G_fingerprints[k] = compute_wl_fingerprint(current_G, N_chosen, WL_ITERS_chosen);\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read M and epsilon\n    std::cin >> M_param >> EPSILON_param;\n\n    // Perform precomputation (determine N, generate G_k graphs and their fingerprints)\n    precompute_graphs();\n\n    // Output N and the M generated graphs\n    std::cout << N_chosen << std::endl;\n    for (int k = 0; k < M_param; ++k) {\n        std::cout << graph_to_string(G_graphs[k], N_chosen) << std::endl;\n    }\n    std::cout << std::flush; // Crucial for interactive problems\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str; // Read the received graph H_k\n        AdjMatrix H_adj = string_to_graph(H_str, N_chosen);\n\n        // Compute fingerprint for H_k\n        std::map<int, int> H_fingerprint = compute_wl_fingerprint(H_adj, N_chosen, WL_ITERS_chosen);\n\n        double min_dist = -1.0;\n        int best_t = -1;\n\n        // Compare H_k's fingerprint with all precomputed G_t fingerprints\n        for (int t = 0; t < M_param; ++t) {\n            double current_dist = histogram_distance(H_fingerprint, G_fingerprints[t]);\n            if (best_t == -1 || current_dist < min_dist) {\n                min_dist = current_dist;\n                best_t = t;\n            }\n        }\n        std::cout << best_t << std::endl; // Output the prediction\n        std::cout << std::flush; // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <limits>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <map>\n#include <iomanip> // For setprecision\n#include <random>\n\nusing namespace std;\n\n// Using long long for distances to avoid overflow for sums\nconst long long INF = numeric_limits<long long>::max() / 2; // A sufficiently large value that avoids overflow when added to\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Node {\n    long long dist;\n    int u;\n    bool operator>(const Node& other) const {\n        return dist > other.dist;\n    }\n};\n\nstruct EdgeInfo {\n    int u, v, w, id;\n    long double val; // combined importance score: extra_dist * edge_betweenness\n};\n\nvector<vector<pair<int, int>>> adj; // adj[u] = list of {v, edge_id}\nvector<Edge> edges_data;\nint N_global, M_global, D_global, K_global;\n\n// Dijkstra's algorithm to find shortest paths from a source s\n// Optionally excludes a specific edge for extra_dist calculation\n// Returns a vector of distances from s to all other vertices.\nvector<long long> dijkstra(int s, const vector<vector<pair<int, int>>>& current_adj, int excluded_edge_id = -1) {\n    vector<long long> dist(N_global, INF);\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n    dist[s] = 0;\n    pq.push({0, s});\n\n    while (!pq.empty()) {\n        long long d = pq.top().dist;\n        int u = pq.top().u;\n        pq.pop();\n\n        if (d > dist[u]) continue; // Already found a shorter path\n\n        for (auto& edge_pair : current_adj[u]) {\n            int v = edge_pair.first;\n            int edge_id = edge_pair.second;\n\n            if (edge_id == excluded_edge_id) continue;\n\n            long long weight = edges_data[edge_id].w;\n            if (dist[u] != INF && dist[u] + weight < dist[v]) { // dist[u] != INF check to prevent overflow\n                dist[v] = dist[u] + weight;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Brandes' algorithm for Edge Betweenness Centrality\n// Returns a vector where element i is the betweenness centrality of edge_data[i]\nvector<long double> calculate_edge_betweenness() {\n    vector<long double> edge_betweenness(M_global, 0.0);\n\n    for (int s = 0; s < N_global; ++s) {\n        vector<long long> dist(N_global, INF);\n        vector<long long> num_shortest_paths(N_global, 0); // Count of shortest paths from s to v\n        vector<vector<int>> predecessors(N_global); // For each v, a list of vertices u that precede v on shortest paths from s\n        vector<int> stack; // To process vertices in decreasing order of distance\n\n        priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n        dist[s] = 0;\n        num_shortest_paths[s] = 1;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            long long d = pq.top().dist;\n            int u = pq.top().u;\n            pq.pop();\n\n            if (d > dist[u]) continue; \n            \n            stack.push_back(u); // Add to stack for processing in reverse order of distance\n\n            for (auto& edge_pair : adj[u]) {\n                int v = edge_pair.first;\n                int edge_id = edge_pair.second;\n                long long weight = edges_data[edge_id].w;\n\n                if (dist[u] != INF) { // Only consider paths from reachable u\n                    if (dist[u] + weight < dist[v]) {\n                        dist[v] = dist[u] + weight;\n                        num_shortest_paths[v] = num_shortest_paths[u];\n                        predecessors[v].clear();\n                        predecessors[v].push_back(u);\n                        pq.push({dist[v], v});\n                    } else if (dist[u] + weight == dist[v]) {\n                        num_shortest_paths[v] += num_shortest_paths[u];\n                        predecessors[v].push_back(u);\n                    }\n                }\n            }\n        }\n\n        vector<long double> delta(N_global, 0.0); // Dependency of s on v\n        while (!stack.empty()) {\n            int v = stack.back();\n            stack.pop_back();\n\n            for (int u_pred : predecessors[v]) {\n                // Fraction of shortest paths from s to v that pass through u_pred\n                // num_shortest_paths[v] must be > 0 here, because v is reachable from s\n                long double path_fraction = (long double)num_shortest_paths[u_pred] / num_shortest_paths[v];\n                long double contribution = path_fraction * (1.0 + delta[v]);\n                \n                // Find edge_id for (u_pred, v)\n                int found_edge_id = -1;\n                for(const auto& edge_pair : adj[u_pred]) {\n                    if (edge_pair.first == v) {\n                        found_edge_id = edge_pair.second;\n                        break; \n                    }\n                }\n                \n                if (found_edge_id != -1) { // Should always be found for edges on shortest paths\n                    edge_betweenness[found_edge_id] += contribution;\n                }\n                delta[u_pred] += contribution;\n            }\n        }\n    }\n    return edge_betweenness;\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    cin >> N_global >> M_global >> D_global >> K_global;\n\n    adj.resize(N_global);\n    edges_data.resize(M_global);\n\n    for (int i = 0; i < M_global; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v; // 0-indexed\n        edges_data[i] = {u, v, w, i};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i}); // Add edge for both directions\n    }\n\n    // Skip coordinates input as they are not used in this solution\n    for (int i = 0; i < N_global; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge betweenness centrality for each edge\n    vector<long double> edge_betweenness = calculate_edge_betweenness();\n\n    // 2. Precompute extra_dist for each edge (d'(u,v) - w when edge (u,v) is removed)\n    vector<long long> extra_dist(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        int u = edges_data[i].u;\n        int v = edges_data[i].v;\n        int w = edges_data[i].w;\n        vector<long long> dist_from_u_without_edge = dijkstra(u, adj, i);\n        // If u and v become disconnected, consider the path effectively infinite (10^9 from problem)\n        // Ensure extra_dist is non-negative\n        extra_dist[i] = (dist_from_u_without_edge[v] == INF) ? (1000000000LL - w) : (dist_from_u_without_edge[v] - w);\n        if (extra_dist[i] < 0) extra_dist[i] = 0; \n    }\n    \n    // 3. Combine scores: val[e_idx] = extra_dist[e_idx] * edge_betweenness[e_idx]\n    vector<EdgeInfo> edge_infos(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        edge_infos[i] = {edges_data[i].u, edges_data[i].v, edges_data[i].w, i, (long double)extra_dist[i] * edge_betweenness[i]};\n    }\n    \n    // 4. Initial assignment (r[M]): Sort edges by combined importance (val) and assign round-robin\n    sort(edge_infos.begin(), edge_infos.end(), [](const EdgeInfo& a, const EdgeInfo& b) {\n        return a.val > b.val;\n    });\n\n    vector<int> r(M_global); // repair day for each edge (1-indexed)\n    vector<int> day_load(D_global + 1, 0); // Number of edges assigned to each day\n    vector<long double> current_sum_val(D_global + 1, 0.0); // Sum of val for edges assigned to each day\n\n    for (int i = 0; i < M_global; ++i) {\n        int edge_id = edge_infos[i].id;\n        int day = (i % D_global) + 1; // Round-robin assignment based on sorted importance\n        r[edge_id] = day;\n        day_load[day]++;\n        current_sum_val[day] += edge_infos[i].val;\n    }\n    \n    // Calculate initial estimated frustration score (sum of average vals per day)\n    long double current_total_approx_score = 0.0;\n    for (int k = 1; k <= D_global; ++k) {\n        if (day_load[k] > 0) {\n            current_total_approx_score += current_sum_val[k] / day_load[k];\n        }\n    }\n\n    vector<int> best_r = r;\n    long double best_total_approx_score = current_total_approx_score;\n\n    // Simulated Annealing parameters\n    double time_limit_sec = 5.9; // Allocate 5.9 seconds for SA\n    long double T_start = 1e12; // Starting temperature\n    long double T_end = 1e-4;   // Ending temperature\n    \n    // Random number generation setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_edge(0, M_global - 1);\n    uniform_int_distribution<int> dist_day(1, D_global);\n    uniform_real_distribution<long double> dist_01(0.0, 1.0);\n\n    // SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time_sec = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time_sec > time_limit_sec) {\n            break;\n        }\n\n        // Linear cooling schedule\n        long double current_T = T_start * (1.0 - elapsed_time_sec / time_limit_sec);\n        if (current_T < T_end) current_T = T_end;\n\n        int edge_idx = dist_edge(rng); // Randomly pick an edge to move\n        int day_from = r[edge_idx];\n        int day_to = dist_day(rng); // Randomly pick a target day\n\n        // Check feasibility and efficiency constraints\n        if (day_from == day_to || day_load[day_to] >= K_global) {\n            continue; // Cannot move to same day or to an already full day\n        }\n\n        long double val_e = edge_infos[edge_idx].val; // Importance value of the edge being moved\n\n        // Calculate old average frustration for affected days\n        long double old_f_from = current_sum_val[day_from] / day_load[day_from];\n        long double old_f_to = (day_load[day_to] > 0) ? (current_sum_val[day_to] / day_load[day_to]) : 0.0; // If day_to is empty, old frustration is 0\n\n        // Calculate new average frustration if move is accepted\n        long double new_f_from = (day_load[day_from] > 1) ? ((current_sum_val[day_from] - val_e) / (day_load[day_from] - 1.0)) : 0.0; // If day_from becomes empty, new frustration is 0\n        long double new_f_to = (current_sum_val[day_to] + val_e) / (day_load[day_to] + 1.0);\n        \n        long double delta_score = (new_f_from - old_f_from) + (new_f_to - old_f_to);\n\n        // Acceptance criteria for Simulated Annealing\n        if (delta_score < 0 || dist_01(rng) < exp(-delta_score / current_T)) {\n            // Accept the move\n            r[edge_idx] = day_to;\n            day_load[day_from]--;\n            day_load[day_to]++;\n            current_sum_val[day_from] -= val_e;\n            current_sum_val[day_to] += val_e;\n            current_total_approx_score += delta_score;\n\n            // Update best solution found so far\n            if (current_total_approx_score < best_total_approx_score) {\n                best_total_approx_score = current_total_approx_score;\n                best_r = r;\n            }\n        }\n    }\n\n    // Output the best assignment found\n    for (int i = 0; i < M_global; ++i) {\n        cout << best_r[i] << (i == M_global - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}\n","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <queue>\n#include <chrono>\n\nusing namespace std;\n\n// Global D for convenience\nint D;\n\n// Struct for 3D point\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& 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 Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\n// Represents a polycube shape as a vector of relative points\nusing Shape = vector<Point>;\n\n// Function to apply a rotation to a point relative to its origin (0,0,0)\nPoint rotate_point(const Point& p, int rot_idx) {\n    // This defines the 24 unique rotations\n    // The specific order is somewhat arbitrary but covers all possibilities.\n    // Each case maps (x,y,z) to a permutation of (+/-x, +/-y, +/-z)\n    switch (rot_idx) {\n        case 0: return {p.x, p.y, p.z}; // +X+Y+Z\n        case 1: return {p.x, p.z, -p.y}; // +X+Z-Y\n        case 2: return {p.x, -p.y, -p.z}; // +X-Y-Z\n        case 3: return {p.x, -p.z, p.y}; // +X-Z+Y\n        \n        case 4: return {-p.x, -p.y, p.z}; // -X-Y+Z\n        case 5: return {-p.x, -p.z, -p.y}; // -X-Z-Y\n        case 6: return {-p.x, p.y, -p.z}; // -X+Y-Z\n        case 7: return {-p.x, p.z, p.y}; // -X+Z+Y\n\n        case 8: return {p.y, p.x, -p.z}; // +Y+X-Z\n        case 9: return {p.y, p.z, p.x}; // +Y+Z+X\n        case 10: return {p.y, -p.x, p.z}; // +Y-X+Z\n        case 11: return {p.y, -p.z, -p.x}; // +Y-Z-X\n\n        case 12: return {-p.y, p.x, p.z}; // -Y+X+Z\n        case 13: return {-p.y, p.z, -p.x}; // -Y+Z-X\n        case 14: return {-p.y, -p.x, -p.z}; // -Y-X-Z\n        case 15: return {-p.y, -p.z, p.x}; // -Y-Z+X\n        \n        case 16: return {p.z, p.x, p.y}; // +Z+X+Y\n        case 17: return {p.z, p.y, -p.x}; // +Z+Y-X\n        case 18: return {p.z, -p.x, -p.y}; // +Z-X-Y\n        case 19: return {p.z, -p.y, p.x}; // +Z-Y+X\n        \n        case 20: return {-p.z, p.x, p.y}; // -Z+X+Y\n        case 21: return {-p.z, p.y, -p.x}; // -Z+Y-X\n        case 22: return {-p.z, -p.x, -p.y}; // -Z-X-Y\n        case 23: return {-p.z, -p.y, p.x}; // -Z-Y+X\n    }\n    return p; // Should not be reached\n}\n\n// Function to canonicalize a shape (vector of relative points)\nShape get_canonical_form(const Shape& shape) {\n    if (shape.empty()) return {};\n\n    Shape canonical_shape = shape;\n    // Initial sort to have a baseline for comparison\n    sort(canonical_shape.begin(), canonical_shape.end());\n\n    for (int rot_idx = 0; rot_idx < 24; ++rot_idx) {\n        Shape rotated_shape_temp;\n        for (const auto& p : shape) {\n            rotated_shape_temp.push_back(rotate_point(p, rot_idx));\n        }\n\n        // Translate to (0,0,0) origin\n        int min_x = D, min_y = D, min_z = D;\n        for (const auto& p : rotated_shape_temp) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated_shape_temp) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n\n        sort(rotated_shape_temp.begin(), rotated_shape_temp.end());\n        if (rotated_shape_temp < canonical_shape) {\n            canonical_shape = rotated_shape_temp;\n        }\n    }\n    return canonical_shape;\n}\n\n// Data structures for block management\nmap<Shape, int> canonical_shape_to_assigned_id;\nvector<Shape> block_definitions; // Stores the actual canonical shape for each ID (1-indexed)\nvector<int> block_volumes;       // Stores volume for each ID\nvector<bool> block_used_in_1;    // True if block ID is used in obj 1\nvector<bool> block_used_in_2;    // True if block ID is used in obj 2\nint current_b_id = 1;            // Next available block ID. Block IDs are 1-indexed.\n\n// Gets a block ID for a given shape, assigning a new one if not seen\n// The shape_points_relative must be relative to its own minimal bounding box corner (0,0,0)\nint get_or_assign_block_id(const Shape& shape_points_relative, int volume) {\n    Shape canonical_shape = get_canonical_form(shape_points_relative);\n    if (canonical_shape_to_assigned_id.count(canonical_shape)) {\n        return canonical_shape_to_assigned_id[canonical_shape];\n    } else {\n        int new_id = current_b_id++;\n        canonical_shape_to_assigned_id[canonical_shape] = new_id;\n        block_definitions.push_back(canonical_shape); // Store canonical form\n        block_volumes.push_back(volume);\n        block_used_in_1.push_back(false); // Initialize usage flags\n        block_used_in_2.push_back(false);\n        return new_id;\n    }\n}\n\n// BFS to find a connected component and return its absolute points.\n// Also modifies `grid_to_search` by setting visited cells to 0.\n// Returns a pair: {vector of absolute points, relative shape}\npair<vector<Point>, Shape> find_and_extract_component(vector<vector<vector<int>>>& grid_to_search, int start_x, int start_y, int start_z) {\n    vector<Point> absolute_points;\n    Shape relative_shape;\n\n    if (start_x < 0 || start_x >= D || start_y < 0 || start_y >= D || start_z < 0 || start_z >= D || grid_to_search[start_x][start_y][start_z] == 0) {\n        return {absolute_points, relative_shape};\n    }\n\n    queue<Point> q;\n    q.push({start_x, start_y, start_z});\n    grid_to_search[start_x][start_y][start_z] = 0; // Mark as visited and remove from current grid\n    absolute_points.push_back({start_x, start_y, start_z});\n\n    int dx[] = {0, 0, 0, 0, 1, -1};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {1, -1, 0, 0, 0, 0};\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            int nz = curr.z + dz[i];\n\n            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D && grid_to_search[nx][ny][nz] == 1) {\n                grid_to_search[nx][ny][nz] = 0; // Mark as visited\n                q.push({nx, ny, nz});\n                absolute_points.push_back({nx, ny, nz});\n            }\n        }\n    }\n    \n    // Translate the component points to be relative to their bounding box min corner\n    if (absolute_points.empty()) return {absolute_points, relative_shape};\n\n    int min_x = D, min_y = D, min_z = D;\n    for (const auto& p : absolute_points) {\n        min_x = min(min_x, p.x);\n        min_y = min(min_y, p.y);\n        min_z = min(min_z, p.z);\n    }\n    \n    for (const auto& p : absolute_points) {\n        relative_shape.push_back({p.x - min_x, p.y - min_y, p.z - min_z});\n    }\n    sort(relative_shape.begin(), relative_shape.end());\n    \n    return {absolute_points, relative_shape};\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D;\n\n    vector<string> f1_str(D), r1_str(D), f2_str(D), r2_str(D);\n    for (int i = 0; i < D; ++i) cin >> f1_str[i];\n    for (int i = 0; i < D; ++i) cin >> r1_str[i];\n    for (int i = 0; i < D; ++i) cin >> f2_str[i];\n    for (int i = 0; i < D; ++i) cin >> r2_str[i];\n\n    // U_i_grid[x][y][z] == 1 if (x,y,z) can be occupied based on silhouettes\n    vector<vector<vector<int>>> U1_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U2_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U_intersect_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                bool in_u1 = (f1_str[z][x] == '1' && r1_str[z][y] == '1');\n                bool in_u2 = (f2_str[z][x] == '1' && r2_str[z][y] == '1');\n                \n                if (in_u1) U1_grid_mutable[x][y][z] = 1;\n                if (in_u2) U2_grid_mutable[x][y][z] = 1;\n                if (in_u1 && in_u2) U_intersect_grid_mutable[x][y][z] = 1;\n            }\n        }\n    }\n\n    vector<vector<vector<int>>> b1_final(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_final(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Create dummy entries for 0-indexed vectors, as block IDs are 1-indexed\n    block_definitions.push_back({}); // Placeholder for block ID 0\n    block_volumes.push_back(0);\n    block_used_in_1.push_back(false);\n    block_used_in_2.push_back(false);\n\n    // 1. Fill shared space (U_intersect_grid_mutable) with large components\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U_intersect_grid_mutable[x][y][z] == 1) { // If cell is available and not yet processed\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U_intersect_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n\n                    if (!absolute_points.empty()) { // Should always be true if grid_to_search[x][y][z] was 1\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_1[block_id] = true; \n                        block_used_in_2[block_id] = true;\n                        \n                        for (const auto& p_abs : absolute_points) {\n                            b1_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                            b2_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                            // Also mark in U1_grid_mutable and U2_grid_mutable as used, so they aren't re-processed\n                            U1_grid_mutable[p_abs.x][p_abs.y][p_abs.z] = 0;\n                            U2_grid_mutable[p_abs.x][p_abs.y][p_abs.z] = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // 2. Fill remaining U1_grid_mutable (object 1 specific blocks)\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U1_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U1_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_1[block_id] = true;\n\n                        for (const auto& p_abs : absolute_points) {\n                            b1_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Fill remaining U2_grid_mutable (object 2 specific blocks)\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U2_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U2_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_2[block_id] = true;\n\n                        for (const auto& p_abs : absolute_points) {\n                            b2_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    // The current `current_b_id - 1` is the total number of unique block shapes.\n    // Each of these blocks is guaranteed to be used in at least one object due to the placement logic.\n    cout << current_b_id - 1 << endl;\n\n    // Output b1\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b1_final[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    // Output b2\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b2_final[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\nconst long long INF_LL = 4e18; // Sufficiently large infinity for long long\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\nstruct Edge {\n    int id; // original edge index (0 to M-1)\n    int u, v;\n    long long w;\n};\n\nstruct EdgeInfo { // For adjacency list\n    int to_node;\n    long long weight;\n    int original_edge_idx;\n};\n\n// For Dijkstra\nstruct State {\n    long long cost;\n    int u;\n\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\nint N, M, K;\nvector<Point> nodes;\nvector<Edge> edges_data;\nvector<Point> residents;\nvector<vector<EdgeInfo>> adj; // adjacency list for graph\n\n// Precomputed distances\nvector<vector<long long>> dist_res_node_sq; // dist_res_node_sq[k][i] = squared Euclidean distance from resident k to node i\nvector<long long> dist_from_1; // Shortest path cost from node 1 to node i\nvector<int> parent_on_spt_node; // parent_on_spt_node[i] = parent node in SPT from node 1\nvector<int> parent_on_spt_edge_idx; // parent_on_spt_edge_idx[i] = original edge index of (parent[i], i)\n\n// Global random generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to calculate squared Euclidean distance\nlong long distSq(Point p1, 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\n// Calculate rounded Euclidean distance\nint round_dist_val(long long dist_sq) {\n    return static_cast<int>(round(sqrt((long double)dist_sq))); // Cast to long double for sqrt for precision\n}\n\n// Dijkstra from node 1\nvoid run_dijkstra() {\n    dist_from_1.assign(N + 1, INF_LL);\n    parent_on_spt_node.assign(N + 1, -1);\n    parent_on_spt_edge_idx.assign(N + 1, -1);\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist_from_1[1] = 0;\n    pq.push({0, 1});\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        long long d = current.cost;\n        int u = current.u;\n\n        if (d > dist_from_1[u]) continue;\n\n        for (auto& edge_info : adj[u]) {\n            int v = edge_info.to_node;\n            long long weight = edge_info.weight;\n            int edge_idx = edge_info.original_edge_idx;\n\n            if (dist_from_1[u] + weight < dist_from_1[v]) {\n                dist_from_1[v] = dist_from_1[u] + weight;\n                parent_on_spt_node[v] = u;\n                parent_on_spt_edge_idx[v] = edge_idx;\n                pq.push({dist_from_1[v], v});\n            }\n        }\n    }\n}\n\n// Recalculates edge cost for a given set of active stations\nlong long calculate_edge_cost_from_active_stations(const set<int>& active_stations, vector<int>& B_output_temp) {\n    set<int> edges_on_idx_set;\n    long long current_edge_cost = 0;\n\n    for (int u : active_stations) {\n        if (dist_from_1[u] == INF_LL) { \n            return INF_LL; // Should not happen if `active_stations` are already filtered or cost is set to INF_LL\n        }\n        if (u == 1) continue; \n        \n        int curr = u;\n        while (curr != 1 && parent_on_spt_node[curr] != -1) {\n            int edge_idx = parent_on_spt_edge_idx[curr];\n            if (edges_on_idx_set.find(edge_idx) == edges_on_idx_set.end()) {\n                edges_on_idx_set.insert(edge_idx);\n                current_edge_cost += edges_data[edge_idx].w;\n            }\n            curr = parent_on_spt_node[curr];\n        }\n    }\n    \n    // Populate B_output_temp\n    B_output_temp.assign(M, 0);\n    for (int j = 0; j < M; ++j) {\n        if (edges_on_idx_set.count(j)) {\n            B_output_temp[j] = 1;\n        }\n    }\n\n    return current_edge_cost;\n}\n\n\nvoid solve() {\n    // Precomputation (read input, run Dijkstra, calculate resident-node distances)\n    nodes.resize(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        cin >> nodes[i].x >> nodes[i].y;\n        nodes[i].id = i;\n    }\n\n    adj.resize(N + 1);\n    edges_data.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges_data[j].u >> edges_data[j].v >> edges_data[j].w;\n        edges_data[j].id = j;\n        adj[edges_data[j].u].push_back({edges_data[j].v, edges_data[j].w, j});\n        adj[edges_data[j].v].push_back({edges_data[j].u, edges_data[j].w, j});\n    }\n\n    residents.resize(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n\n    run_dijkstra();\n\n    dist_res_node_sq.resize(K, vector<long long>(N + 1));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            dist_res_node_sq[k][i] = distSq(residents[k], nodes[i]);\n        }\n    }\n    \n    // Initial solution (Greedy approach)\n    vector<int> P_current(N + 1, 0);\n    \n    // For each resident, assign it to its closest reachable station (within 5000 radius).\n    // Then combine P values for stations.\n    for (int k = 0; k < K; ++k) {\n        int best_station_for_k = -1;\n        long long min_dist_sq_for_k = (long long)5001 * 5001; // Max guaranteed distance is 5000\n        for (int i = 1; i <= N; ++i) {\n            if (dist_from_1[i] == INF_LL) continue; // Station must be reachable from 1\n            if (dist_res_node_sq[k][i] <= (long long)5000 * 5000) {\n                if (dist_res_node_sq[k][i] < min_dist_sq_for_k) {\n                    min_dist_sq_for_k = dist_res_node_sq[k][i];\n                    best_station_for_k = i;\n                }\n            }\n        }\n        if (best_station_for_k != -1) {\n            P_current[best_station_for_k] = max(P_current[best_station_for_k], round_dist_val(min_dist_sq_for_k));\n        } else {\n             // This indicates a problem as per problem statement guarantee. Should not happen.\n        }\n    }\n    // Cap all P values at 5000\n    for(int i=1; i<=N; ++i) {\n        P_current[i] = min(P_current[i], 5000);\n    }\n    \n    vector<int> B_best(M);\n    long long best_S = INF_LL;\n    vector<int> P_best = P_current;\n\n    // State variables for SA (to allow incremental updates)\n    long long current_P_cost_SA = 0;\n    set<int> active_stations_SA;\n    vector<int> num_covering_stations_for_resident(K, 0);\n    int num_residents_fully_covered = 0;\n\n    // Initialize SA state variables from P_current\n    for (int i = 1; i <= N; ++i) {\n        if (P_current[i] > 0 && dist_from_1[i] == INF_LL) { // If an initially active station is unreachable\n            current_P_cost_SA = INF_LL; // Mark initial state as invalid\n            break;\n        }\n        current_P_cost_SA += (long long)P_current[i] * P_current[i];\n        if (P_current[i] > 0) {\n            active_stations_SA.insert(i);\n        }\n    }\n    if (current_P_cost_SA != INF_LL) { // If initial P cost is valid (all active stations reachable)\n        for (int k = 0; k < K; ++k) {\n            for (int i = 1; i <= N; ++i) {\n                if (P_current[i] > 0) {\n                    if (dist_res_node_sq[k][i] <= (long long)P_current[i] * P_current[i]) {\n                        num_covering_stations_for_resident[k]++;\n                    }\n                }\n            }\n            if (num_covering_stations_for_resident[k] > 0) {\n                num_residents_fully_covered++;\n            }\n        }\n    }\n    \n    long long current_edge_cost_SA = 0;\n    if (current_P_cost_SA != INF_LL && num_residents_fully_covered == K) {\n        vector<int> temp_B(M); // Placeholder for calculate_edge_cost_from_active_stations\n        current_edge_cost_SA = calculate_edge_cost_from_active_stations(active_stations_SA, temp_B);\n        best_S = current_P_cost_SA + current_edge_cost_SA;\n        P_best = P_current;\n    }\n\n\n    // Simulated Annealing\n    chrono::high_resolution_clock::time_point start_time = chrono::high_resolution_clock::now();\n    long double current_temp;\n    if (best_S == INF_LL) { \n        current_temp = 1e9; \n    } else {\n        current_temp = (long double)best_S / 100.0; // Dynamic initial temperature\n    }\n    long double end_temp = 1.0;\n    long double time_limit = 1.95; // seconds\n    \n    // Parameters for SA moves\n    const int P_ADJUST_RANGE = 500; \n    \n    long long iter_count = 0;\n    while (true) {\n        chrono::high_resolution_clock::time_point current_time = chrono::high_resolution_clock::now();\n        long double elapsed_time = chrono::duration_cast<chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        if (elapsed_time > time_limit) {\n            break;\n        }\n        \n        current_temp = end_temp + (current_temp - end_temp) * (1.0 - elapsed_time / time_limit);\n        \n        vector<int> P_next = P_current; // P_next is a copy for perturbation\n        long long next_P_cost = current_P_cost_SA;\n        set<int> next_active_stations = active_stations_SA;\n        vector<int> next_num_covering_stations = num_covering_stations_for_resident;\n        int next_num_residents_fully_covered = num_residents_fully_covered;\n\n        int target_node = rng() % N + 1;\n        int old_P_val = P_current[target_node]; // Use P_current for old P value\n\n        if (dist_from_1[target_node] == INF_LL) { // Don't bother with unreachable nodes\n            continue;\n        }\n\n        int move_type = rng() % 100;\n\n        if (move_type < 60) { // Type 0: Adjust P_i for a random station i (60% chance)\n            int rand_delta = (rng() % (2 * P_ADJUST_RANGE + 1)) - P_ADJUST_RANGE;\n            int new_P_val = old_P_val + rand_delta;\n            new_P_val = max(0, min(5000, new_P_val));\n            P_next[target_node] = new_P_val;\n\n            // Update incremental costs\n            next_P_cost -= (long long)old_P_val * old_P_val;\n            next_P_cost += (long long)new_P_val * new_P_val;\n\n            if (old_P_val == 0 && new_P_val > 0) { // Station became active\n                next_active_stations.insert(target_node);\n            } else if (old_P_val > 0 && new_P_val == 0) { // Station became inactive\n                next_active_stations.erase(target_node);\n            }\n\n            // Update coverage counts incrementally for O(K) complexity\n            for (int k = 0; k < K; ++k) {\n                bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                if (old_covered_by_target && !new_covered_by_target) {\n                    next_num_covering_stations[k]--;\n                    if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                } else if (!old_covered_by_target && new_covered_by_target) {\n                    next_num_covering_stations[k]++;\n                    if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                }\n            }\n\n        } else { // Type 1: Try to turn off a station and re-assign coverage (40% chance)\n            \n            // If target_node is currently OFF, try turning it ON (random P)\n            if (old_P_val == 0) { \n                int new_P_val = rng() % 5001; // Random P between 0 and 5000\n                P_next[target_node] = new_P_val;\n\n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_P_cost += (long long)new_P_val * new_P_val;\n\n                if (new_P_val > 0) {\n                    next_active_stations.insert(target_node);\n                }\n\n                // Update coverage counts incrementally\n                for (int k = 0; k < K; ++k) {\n                    bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                    bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                    if (old_covered_by_target && !new_covered_by_target) {\n                        next_num_covering_stations[k]--;\n                        if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                    } else if (!old_covered_by_target && new_covered_by_target) {\n                        next_num_covering_stations[k]++;\n                        if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                    }\n                }\n\n            } else { // If target_node is currently ON, try turning it OFF and re-assign\n                // Temporarily remove target_node's coverage from next_num_covering_stations\n                // This makes it easy to find truly uncovered residents for re-assignment\n                for(int k=0; k<K; ++k){\n                    if(dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val){\n                        next_num_covering_stations[k]--;\n                        if(next_num_covering_stations[k] == 0){\n                            next_num_residents_fully_covered--;\n                        }\n                    }\n                }\n\n                P_next[target_node] = 0; \n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_active_stations.erase(target_node);\n\n                // For each resident that became uncovered, find the best station to cover it\n                for(int k=0; k<K; ++k){\n                    if(next_num_covering_stations[k] == 0){ // This resident is now uncovered\n                        int best_alt_station = -1;\n                        long long min_dist_sq = INF_LL; \n                        for(int i=1; i<=N; ++i){ \n                            if(dist_from_1[i] == INF_LL) continue; // Only consider reachable stations\n                            if(dist_res_node_sq[k][i] < min_dist_sq){\n                                min_dist_sq = dist_res_node_sq[k][i];\n                                best_alt_station = i;\n                            }\n                        }\n                        if(best_alt_station != -1){\n                            int old_alt_P = P_next[best_alt_station]; // Use P_next (which might already be updated)\n                            long long required_P_sq = min_dist_sq;\n                            int required_P = round_dist_val(required_P_sq);\n                            int new_alt_P = max(old_alt_P, min(5000, required_P));\n                            \n                            // Apply change to P_next and update costs incrementally\n                            P_next[best_alt_station] = new_alt_P;\n                            next_P_cost -= (long long)old_alt_P * old_alt_P;\n                            next_P_cost += (long long)new_alt_P * new_alt_P;\n                            if (old_alt_P == 0 && new_alt_P > 0) {\n                                next_active_stations.insert(best_alt_station);\n                            }\n                            // Update coverage for this resident 'k' by best_alt_station\n                            // (Only for k, not all residents affected by best_alt_station's P change)\n                            if (dist_res_node_sq[k][best_alt_station] <= (long long)new_alt_P * new_alt_P) {\n                                next_num_covering_stations[k]++;\n                                if(next_num_covering_stations[k] == 1) { // It just became covered again\n                                    next_num_residents_fully_covered++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        long long S_current_val = current_P_cost_SA + current_edge_cost_SA;\n        long long S_next = INF_LL;\n\n        if (next_num_residents_fully_covered == K) {\n            vector<int> B_temp(M);\n            long long next_edge_cost = calculate_edge_cost_from_active_stations(next_active_stations, B_temp);\n            S_next = next_P_cost + next_edge_cost;\n        }\n\n        if (S_next < best_S) {\n            P_current = P_next;\n            current_P_cost_SA = next_P_cost;\n            active_stations_SA = next_active_stations;\n            num_covering_stations_for_resident = next_num_covering_stations;\n            num_residents_fully_covered = next_num_residents_fully_covered;\n            current_edge_cost_SA = S_next - current_P_cost_SA; // derive edge cost from S_next and P_cost\n            best_S = S_next;\n            P_best = P_next;\n        } else if (S_next != INF_LL) {\n            long double prob = exp((S_current_val - S_next) / current_temp);\n            if (uniform_real_distribution<long double>(0.0, 1.0)(rng) < prob) {\n                P_current = P_next;\n                current_P_cost_SA = next_P_cost;\n                active_stations_SA = next_active_stations;\n                num_covering_stations_for_resident = next_num_covering_stations;\n                num_residents_fully_covered = next_num_residents_fully_covered;\n                current_edge_cost_SA = S_next - current_P_cost_SA;\n            }\n        }\n        \n        iter_count++;\n    }\n\n    // Final calculation for output\n    vector<int> B_final(M);\n    calculate_edge_cost_from_active_stations(active_stations_SA, B_final); \n\n    // Output\n    for (int i = 1; i <= N; ++i) {\n        cout << P_best[i] << (i == N ? \"\" : \" \");\n    }\n    cout << endl;\n    for (int j = 0; j < M; ++j) {\n        cout << B_final[j] << (j == M - 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 >> K;\n    solve();\n\n    return 0;\n}\n","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <tuple>   // For std::tuple\n\n// N is fixed to 30 for all inputs.\n// The problem defines N as the number of tiers.\n// Tiers are 0-indexed from 0 to N-1.\n// Ball coordinates are (x,y) where 0 <= x <= N-1 and 0 <= y <= x.\nconst int N = 30;\n\n// Global data structures for the pyramid state and operations.\n// The pyramid itself, storing the ball numbers.\nstd::vector<std::vector<int>> pyramid(N);\n\n// To quickly find the coordinates of a ball given its number.\n// `current_pos_of_value[ball_number]` stores `{x, y}`.\nstd::vector<std::pair<int, int>> current_pos_of_value(N * (N + 1) / 2);\n\n// Stores the sequence of swap operations.\n// Each operation is a tuple `{x1, y1, x2, y2}`.\nstd::vector<std::tuple<int, int, int, int>> operations;\n\n/**\n * @brief Performs a swap between two balls at given coordinates and records the operation.\n *\n * This function updates the `pyramid` and `current_pos_of_value` data structures\n * to reflect the swap, and adds the operation to the `operations` list.\n * The coordinates (r1, c1) and (r2, c2) must refer to adjacent balls.\n *\n * @param r1 Row coordinate of the first ball.\n * @param c1 Column coordinate of the first ball.\n * @param r2 Row coordinate of the second ball.\n * @param c2 Column coordinate of the second ball.\n */\nvoid perform_swap(int r1, int c1, int r2, int c2) {\n    int val1 = pyramid[r1][c1];\n    int val2 = pyramid[r2][c2];\n\n    // Swap values in the pyramid grid\n    pyramid[r1][c1] = val2;\n    pyramid[r2][c2] = val1;\n\n    // Update the mapping from value to its current position\n    current_pos_of_value[val1] = {r2, c2};\n    current_pos_of_value[val2] = {r1, c1};\n\n    // Record the swap operation\n    operations.emplace_back(r1, c1, r2, c2);\n}\n\n/**\n * @brief Sifts down an element at (r, c) to satisfy the min-pyramid property.\n *\n * This function repeatedly compares the ball at (r, c) with its two children\n * ((r+1, c) and (r+1, c+1)). If the parent ball is larger than either child,\n * it swaps the parent with the smallest child. This process continues until\n * the parent ball is smaller than or equal to both its children, or it reaches\n * the bottom tier.\n * This is an iterative implementation of the sift-down (or heapify-down) process.\n *\n * @param r Row coordinate of the ball to sift down.\n * @param c Column coordinate of the ball to sift down.\n */\nvoid sift_down(int r, int c) {\n    while (true) {\n        int parent_val = pyramid[r][c];\n        int min_val = parent_val; // Initialize min_val with parent's value\n        int target_r = r;         // Initialize target_r and target_c to parent's position\n        int target_c = c;\n\n        // Check left child: (r+1, c)\n        // Ensure that (r,c) is not in the last tier (N-1)\n        if (r + 1 < N) {\n            int child1_val = pyramid[r+1][c];\n            if (child1_val < min_val) {\n                min_val = child1_val;\n                target_r = r + 1;\n                target_c = c;\n            }\n        }\n\n        // Check right child: (r+1, c+1)\n        // Ensure (r,c) is not in the last tier AND (r+1, c+1) is a valid coordinate.\n        // For a tier x, valid column indices are from 0 to x.\n        // So for tier r+1, column c+1 must satisfy c+1 <= r+1.\n        if (r + 1 < N && c + 1 <= r + 1) {\n            int child2_val = pyramid[r+1][c+1];\n            // Crucially, compare against `min_val` (which might be child1_val already),\n            // not directly `parent_val`, to find the smallest among parent and both children.\n            if (child2_val < min_val) {\n                min_val = child2_val;\n                target_r = r + 1;\n                target_c = c + 1;\n            }\n        }\n\n        // If no child was smaller than the parent (or if it's a leaf node),\n        // the element is in its correct position relative to its children.\n        if (target_r == r && target_c == c) {\n            break; // Sifting process complete for this element\n        } else {\n            // Swap the current ball with the smallest child\n            perform_swap(r, c, target_r, target_c);\n\n            // Continue sifting down from the new position of the swapped element\n            r = target_r;\n            c = target_c;\n        }\n    }\n}\n\n\nint main() {\n    // Optimize C++ standard streams for competitive programming.\n    // This unties cin from cout and disables synchronization with C stdio,\n    // speeding up input/output operations.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read the initial state of the pyramid from standard input.\n    // Each row 'i' has 'i+1' balls.\n    for (int i = 0; i < N; ++i) {\n        pyramid[i].resize(i + 1); // Allocate space for balls in tier 'i'\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> pyramid[i][j];\n            // Store the initial position of each ball number.\n            current_pos_of_value[pyramid[i][j]] = {i, j};\n        }\n    }\n\n    // Apply the bottom-up heapify algorithm to satisfy the min-pyramid property.\n    // We iterate from the second-to-last tier (N-2) up to the top tier (0).\n    // For each ball in these tiers, we call sift_down to ensure it's smaller\n    // than its children. Since we process tiers bottom-up, when we sift down\n    // an element, its children's sub-pyramids are already correctly heapified.\n    for (int r = N - 2; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            sift_down(r, c);\n        }\n    }\n\n    // Output the total number of operations performed.\n    std::cout << operations.size() << std::endl;\n    // Output each swap operation in the specified format.\n    for (const auto& op : operations) {\n        std::cout << std::get<0>(op) << \" \"\n                  << std::get<1>(op) << \" \"\n                  << std::get<2>(op) << \" \"\n                  << std::get<3>(op) << std::endl;\n    }\n\n    return 0;\n}\n","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::abs\n\n// Global constants\nconst int D = 9;\nconst int DR[] = {-1, 1, 0, 0}; // delta row for neighbors (up, down, left, right)\nconst int DC[] = {0, 0, -1, 1}; // delta col for neighbors\n\n// Grid cell states\nconst int EMPTY = -1;\nconst int OBSTACLE = -2;\nconst int ENTRANCE_CELL = -3; // Renamed to avoid conflict with function entrance_r/c\nconst int UNVISITED = -1; // For BFS distance arrays\n\n// Global variables for the warehouse state\nint grid[D][D]; // Stores container ID (0 to M-1), or EMPTY/OBSTACLE/ENTRANCE_CELL\nbool is_obstacle[D][D];\nint static_dist[D][D]; // BFS distance from entrance on an empty grid\nstd::vector<std::pair<int, int>> static_ranked_squares; // Sorted by static_dist\nstd::map<std::pair<int, int>, int> square_to_static_rank; // Maps (r,c) to its rank in static_ranked_squares\n\nstd::pair<int, int> container_pos[D * D]; // Maps container ID to its (r,c) location\nint M; // Total number of containers\n\n// Coordinates of the entrance\nint entrance_r, entrance_c;\n\n// BFS utility function\n// Returns a vector of reachable empty squares (for placement phase)\n// Also populates reachable_container_ids_ptr if provided (for transport-out phase)\nstd::vector<std::pair<int, int>> bfs_reachable_info(\n    int (&current_grid)[D][D],\n    int (&current_dist)[D][D], // Output: distances from entrance\n    const bool* extracted_containers_mask_ptr, // Pointer to mask for extracted containers (nullptr for placement)\n    std::set<int>* reachable_container_ids_ptr // Output: reachable container IDs (nullptr for placement)\n) {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            current_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    current_dist[entrance_r][entrance_c] = 0;\n\n    std::vector<std::pair<int, int>> reachable_empty_squares_candidates;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue; // Out of bounds\n            if (is_obstacle[nr][nc]) continue; // Obstacle\n\n            if (current_dist[nr][nc] == UNVISITED) { // Not visited yet\n                if (current_grid[nr][nc] == EMPTY) {\n                    current_dist[nr][nc] = current_dist[r][c] + 1;\n                    q.push({nr, nc});\n                    reachable_empty_squares_candidates.push_back({nr, nc});\n                } else if (current_grid[nr][nc] == ENTRANCE_CELL) { \n                    // Entrance is traversable and starting point, already visited at dist 0.\n                    // No need to push again or add to reachable_empty_squares_candidates.\n                } else if (current_grid[nr][nc] >= 0) { // Contains a container\n                    int container_id = current_grid[nr][nc];\n                    if (extracted_containers_mask_ptr && extracted_containers_mask_ptr[container_id]) { \n                        // Container already extracted, treat as empty and traversable\n                        current_dist[nr][nc] = current_dist[r][c] + 1;\n                        q.push({nr, nc});\n                        reachable_empty_squares_candidates.push_back({nr, nc}); // Add as an available \"empty\" path square\n                    } else { \n                        // Container still present, cannot traverse, but is reachable for extraction\n                        if (reachable_container_ids_ptr) {\n                            reachable_container_ids_ptr->insert(container_id);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return reachable_empty_squares_candidates;\n}\n\n// Precomputes static distances from the entrance on an empty grid\nvoid precompute_static_distances() {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            static_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    static_dist[entrance_r][entrance_c] = 0;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (is_obstacle[nr][nc]) continue;\n\n            if (static_dist[nr][nc] == UNVISITED) {\n                static_dist[nr][nc] = static_dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Collect all valid container squares and sort them by static distance\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (!is_obstacle[i][j] && (i != entrance_r || j != entrance_c)) {\n                static_ranked_squares.push_back({i, j});\n            }\n        }\n    }\n\n    // Sort by static_dist, then row, then column for consistent ranking\n    std::sort(static_ranked_squares.begin(), static_ranked_squares.end(), [](const auto& a, const auto& b) {\n        if (static_dist[a.first][a.second] != static_dist[b.first][b.second]) {\n            return static_dist[a.first][a.second] < static_dist[b.first][b.second];\n        }\n        if (a.first != b.first) {\n            return a.first < b.first;\n        }\n        return a.second < b.second;\n    });\n\n    for (int i = 0; i < static_ranked_squares.size(); ++i) {\n        square_to_static_rank[static_ranked_squares[i]] = i;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_obstacles;\n    std::cin >> D >> N_obstacles; // D is fixed at 9, but read for generality\n\n    entrance_r = 0;\n    entrance_c = (D - 1) / 2;\n\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            grid[i][j] = EMPTY;\n            is_obstacle[i][j] = false;\n        }\n    }\n    grid[entrance_r][entrance_c] = ENTRANCE_CELL;\n\n    for (int k = 0; k < N_obstacles; ++k) {\n        int r_obs, c_obs;\n        std::cin >> r_obs >> c_obs;\n        is_obstacle[r_obs][c_obs] = true;\n        grid[r_obs][c_obs] = OBSTACLE;\n    }\n\n    M = D * D - 1 - N_obstacles; // Total number of containers\n\n    precompute_static_distances();\n\n    // Placement Phase\n    int current_dist[D][D]; // Temporary array for BFS distances in current state\n    bool dummy_extracted_mask[D*D] = {false}; // Placeholder, not used in placement phase BFS\n\n    for (int d = 0; d < M; ++d) {\n        int t_d; // Container ID\n        std::cin >> t_d;\n\n        std::vector<std::pair<int, int>> reachable_empty_squares =\n            bfs_reachable_info(grid, current_dist, dummy_extracted_mask, nullptr); // Nullptr for transport-out specific parameters\n\n        int best_score_diff = M + 1; // Max possible diff is M-1, so M+1 is a safe initial high value\n        std::pair<int, int> best_pos = {-1, -1};\n\n        for (const auto& p : reachable_empty_squares) {\n            int r = p.first;\n            int c = p.second;\n            int static_rank = square_to_static_rank[p];\n            int score_diff = std::abs(t_d - static_rank);\n\n            if (score_diff < best_score_diff) {\n                best_score_diff = score_diff;\n                best_pos = p;\n            } else if (score_diff == best_score_diff) {\n                // Tie-breaking rules for placement:\n                // 1. Prefer smaller current_dist (currently closer to entrance)\n                if (current_dist[r][c] < current_dist[best_pos.first][best_pos.second]) {\n                    best_pos = p;\n                }\n                // 2. If current_dist is also tied, prefer smaller static_dist (inherently closer)\n                else if (current_dist[r][c] == current_dist[best_pos.first][best_pos.second]) {\n                    if (static_dist[r][c] < static_dist[best_pos.first][best_pos.second]) {\n                        best_pos = p;\n                    }\n                    // 3. If static_dist is also tied, prefer smaller row, then smaller column (lexicographical)\n                    else if (static_dist[r][c] == static_dist[best_pos.first][best_pos.second]) {\n                        if (r < best_pos.first) {\n                            best_pos = p;\n                        } else if (r == best_pos.first) {\n                            if (c < best_pos.second) {\n                                best_pos = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        grid[best_pos.first][best_pos.second] = t_d;\n        container_pos[t_d] = best_pos;\n\n        std::cout << best_pos.first << \" \" << best_pos.second << std::endl;\n    }\n\n    // Transport-Out Phase\n    std::vector<int> b_sequence(M);\n    bool extracted_containers_mask[D*D]; // Tracks which containers have been extracted\n    for(int i = 0; i < D*D; ++i) extracted_containers_mask[i] = false;\n\n    for (int k = 0; k < M; ++k) {\n        std::set<int> reachable_containers;\n        // BFS to find all reachable containers given current grid state and extracted_containers_mask\n        bfs_reachable_info(grid, current_dist, extracted_containers_mask, &reachable_containers);\n\n        int min_reachable_id = -1;\n        if (!reachable_containers.empty()) {\n            min_reachable_id = *reachable_containers.begin(); // std::set keeps elements sorted, so begin() is the smallest\n        } else {\n            // This case should ideally not be reached if the problem guarantees connectivity\n            // and we always place containers in reachable spots.\n            // As a fallback, this would mean searching for the smallest unextracted ID,\n            // but this indicates a problem with logic or problem constraints.\n            // For now, assume a container is always reachable.\n            for (int id = 0; id < M; ++id) {\n                if (!extracted_containers_mask[id]) {\n                    min_reachable_id = id;\n                    break;\n                }\n            }\n        }\n\n        b_sequence[k] = min_reachable_id;\n        extracted_containers_mask[min_reachable_id] = true; // Mark container as extracted\n    }\n\n    for (int k = 0; k < M; ++k) {\n        std::pair<int, int> pos = container_pos[b_sequence[k]];\n        std::cout << pos.first << \" \" << pos.second << std::endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set> // For tracking affected pairs in adjacency check\n\nusing namespace std;\n\n// Fixed grid size and number of wards\nconst int N = 50;\nconst int M = 100;\n\n// Original map from input\nint c[N][N]; \n// Created map (modified during SA)\nint d[N][N]; \n\n// Required adjacencies: adj_req[u][v] is true if u and v must be adjacent\nbool adj_req[M + 1][M + 1];\n\n// Current adjacencies in 'd' map: adj_count[u][v] stores number of edges between color u and color v\nint adj_count[M + 1][M + 1];\n\n// Number of cells for each color in 'd' map\nint num_cells[M + 1];\n\n// Stores coordinates of cells for each color (used to find start point for BFS)\nvector<pair<int, int>> ward_cells[M + 1];\n\n// Directions for neighbors (up, down, left, right)\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\n\n// Check if coordinates (r, c_val) are within the grid bounds\ninline bool is_valid_coord(int r, int c_val) {\n    return r >= 0 && r < N && c_val >= 0 && c_val < N;\n}\n\n// Check if a color 'k' is connected in the 'd' map.\n// If (excluded_r, excluded_c) is specified, that cell is temporarily ignored for connectivity.\nbool check_color_connectivity(int k, int excluded_r = -1, int excluded_c = -1) {\n    int current_num_k_cells = num_cells[k];\n    if (excluded_r != -1 && d[excluded_r][excluded_c] == k) {\n        current_num_k_cells--; // If the excluded cell has color k, reduce the count\n    }\n\n    if (current_num_k_cells == 0) return true; // Empty ward is trivially connected\n\n    // Find a starting point for BFS for color k\n    int start_r = -1, start_c = -1;\n    for (auto p : ward_cells[k]) {\n        if (p.first == excluded_r && p.second == excluded_c) continue;\n        start_r = p.first;\n        start_c = p.second;\n        break;\n    }\n    \n    if (start_r == -1) { // No cells of color k left after exclusion\n        return current_num_k_cells == 0;\n    }\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_count = 0;\n\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    reachable_count++;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == k && !visited[nr][nc]) {\n                if (nr == excluded_r && nc == excluded_c) continue; // Skip the excluded cell\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_count++;\n            }\n        }\n    }\n    return reachable_count == current_num_k_cells;\n}\n\n// Check if color 0 is connected (to the outside) in the 'd' map\nbool check_zero_connectivity() {\n    int current_zero_count = num_cells[0];\n    if (current_zero_count == 0) return true; // No 0s, trivially connected\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_zeros = 0;\n\n    // Add all boundary cells that are color 0 to the queue\n    for (int r = 0; r < N; ++r) {\n        if (d[r][0] == 0 && !visited[r][0]) { q.push({r, 0}); visited[r][0] = true; reachable_zeros++; }\n        if (d[r][N - 1] == 0 && !visited[r][N - 1]) { q.push({r, N - 1}); visited[r][N - 1] = true; reachable_zeros++; }\n    }\n    for (int c_val = 1; c_val < N - 1; ++c_val) { // Avoid double counting corners\n        if (d[0][c_val] == 0 && !visited[0][c_val]) { q.push({0, c_val}); visited[0][c_val] = true; reachable_zeros++; }\n        if (d[N - 1][c_val] == 0 && !visited[N - 1][c_val]) { q.push({N - 1, c_val}); visited[N - 1][c_val] = true; reachable_zeros++; }\n    }\n\n    // If no boundary '0' cells, but there are other '0' cells, they are disconnected.\n    // If current_zero_count > 0 and reachable_zeros == 0 (no boundary 0s), then it's disconnected\n    if (current_zero_count > 0 && reachable_zeros == 0) return false;\n\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == 0 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_zeros++;\n            }\n        }\n    }\n    return reachable_zeros == current_zero_count;\n}\n\n\nvoid solve() {\n    // Read input\n    int n_val, m_val;\n    cin >> n_val >> m_val; // N, M are fixed, but read them\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> c[i][j];\n        }\n    }\n\n    // Initialize d with c, and calculate initial state metrics\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            d[i][j] = c[i][j];\n            num_cells[d[i][j]]++;\n            ward_cells[d[i][j]].push_back({i, j});\n        }\n    }\n\n    // Precompute required adjacencies (adj_req) from original map 'c'\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = c[r][c_val];\n            \n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_req[curr_color][0] = adj_req[0][curr_color] = true;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = c[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_req[curr_color][neighbor_color] = adj_req[neighbor_color][curr_color] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initialize current adjacencies (adj_count) from 'd' (which is initially 'c')\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = d[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_count[min(curr_color, 0)][max(curr_color, 0)]++;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = d[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_count[min(curr_color, neighbor_color)][max(curr_color, neighbor_color)]++;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Each edge is counted twice (e.g., (u,v) and (v,u)), so divide by 2 for unique adjacencies.\n    // However, adj_count stores number of shared boundaries, not unique pairs. So (u,v) count for u-v edge, not u-v / v-u.\n    // (u,v) -> adj_count[min(u,v)][max(u,v)] is the correct way to count unique adjacencies.\n    // The current loop structure counts (u,v) edge once when processing u and once when processing v if (u,v) is in c[r][c_val] == u, c[nr][nc] == v.\n    // So, we divide by 2 to get the actual number of connecting edges.\n    for(int u = 0; u <= M; ++u) {\n        for (int v = u; v <= M; ++v) { // v = u to v = M ensures each pair is processed once\n            adj_count[u][v] /= 2;\n        }\n    }\n\n\n    // Store best map and score. Score is number of non-zero cells (maximize this).\n    vector<vector<int>> best_d(N, vector<int>(N));\n    int current_score = N * N - num_cells[0]; \n    int best_score = current_score;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            best_d[i][j] = d[i][j];\n        }\n    }\n\n    // --- Simulated Annealing parameters ---\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95; // seconds (slightly less than 2s to allow for output)\n    double T_start = 2000.0;        // Initial temperature\n    double T_end = 1.0;             // Final temperature\n    long long iter_count = 0;       // Iteration counter\n\n    // Distributions for random selection\n    uniform_int_distribution<int> dist_rc(0, N - 1); // For random row/col\n    uniform_int_distribution<int> dist_color_m(1, M); // For random ward color (1 to M)\n    uniform_real_distribution<double> dist_real(0.0, 1.0); // For acceptance probability\n\n    // Main SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int r = dist_rc(rng);       // Random row\n        int c_val = dist_rc(rng);   // Random column\n        int old_color = d[r][c_val]; // Current color of the cell\n        int new_color;              // Proposed new color\n\n        // Strategy to pick new_color:\n        // Prioritize reducing 0s, then explore other moves\n        if (old_color == 0) {\n            // Try to fill this 0 cell with a neighboring ward's color\n            vector<int> non_zero_neighbors;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] != 0) {\n                    non_zero_neighbors.push_back(d[nr][nc]);\n                }\n            }\n\n            if (!non_zero_neighbors.empty()) {\n                // Pick a random non-zero neighbor's color\n                uniform_int_distribution<int> dist_neighbor_idx(0, non_zero_neighbors.size() - 1);\n                new_color = non_zero_neighbors[dist_neighbor_idx(rng)];\n            } else {\n                // If no non-zero neighbors, pick a random ward color (less effective, might create isolated components)\n                new_color = dist_color_m(rng); \n            }\n        } else { // Current cell is a ward color (1 to M)\n            // Option 1: Change to 0 (might fix forbidden adjacencies, but increases 0s)\n            // Option 2: Change to another non-zero color (assimilation/swap with neighbor)\n            if (dist_real(rng) < 0.5) { // 50% chance to try changing to 0\n                new_color = 0;\n            } else { // 50% chance to try changing to a neighbor's color\n                vector<int> neighbor_colors;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc)) {\n                        neighbor_colors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!neighbor_colors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, neighbor_colors.size() - 1);\n                    new_color = neighbor_colors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); // Random if no neighbors, fallback\n                }\n            }\n        }\n\n        if (new_color == old_color) continue; // No effective change, skip\n\n        // --- Prepare for tentative move and checks ---\n        // Store original state to revert if move is invalid/rejected\n        // Temporarily modify d[r][c_val]\n        d[r][c_val] = new_color;\n\n        // Collect changes to adj_count for efficient reversion\n        vector<tuple<int, int, int>> temp_adj_count_deltas; // {u, v, delta}\n        set<pair<int,int>> affected_adj_pairs; // Track unique (u,v) pairs affected\n\n        // Update adj_count based on (r,c_val) -> (new_color)\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c_val + DC[i];\n            if (is_valid_coord(nr, nc)) {\n                int neighbor_color = d[nr][nc]; // Use d's value, which is potentially new_color\n                                                  // but for its neighbor, it's the current color of neighbor\n                \n                // Remove old_color's adjacency with neighbor_color\n                if (old_color != neighbor_color) {\n                    int u = min(old_color, neighbor_color);\n                    int v = max(old_color, neighbor_color);\n                    adj_count[u][v]--;\n                    temp_adj_count_deltas.emplace_back(u, v, 1); // For reverting: add 1\n                    affected_adj_pairs.insert({u,v});\n                }\n                // Add new_color's adjacency with neighbor_color\n                if (new_color != neighbor_color) {\n                    int u = min(new_color, neighbor_color);\n                    int v = max(new_color, neighbor_color);\n                    adj_count[u][v]++;\n                    temp_adj_count_deltas.emplace_back(u, v, -1); // For reverting: subtract 1\n                    affected_adj_pairs.insert({u,v});\n                }\n            }\n        }\n        // Handle boundary adjacencies with color 0\n        if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n            if (old_color != 0) {\n                int u = min(old_color, 0); int v = max(old_color, 0);\n                adj_count[u][v]--;\n                temp_adj_count_deltas.emplace_back(u, v, 1);\n                affected_adj_pairs.insert({u,v});\n            }\n            if (new_color != 0) {\n                int u = min(new_color, 0); int v = max(new_color, 0);\n                adj_count[u][v]++;\n                temp_adj_count_deltas.emplace_back(u, v, -1);\n                affected_adj_pairs.insert({u,v});\n            }\n        }\n        \n        // --- Perform validity checks ---\n        bool move_is_valid = true;\n\n        // 1. Local Adjacency Check: No required adjacencies broken, no forbidden ones created\n        for(auto p : affected_adj_pairs) {\n            int u = p.first;\n            int v = p.second;\n            bool current_adj_exists = (adj_count[u][v] > 0);\n            if (current_adj_exists != adj_req[u][v]) {\n                move_is_valid = false;\n                break;\n            }\n        }\n        if (!move_is_valid) goto revert_move; // Jump to revert if adjacency is violated\n\n        // 2. Connectivity check for old_color (if it's not 0 and shrinking)\n        if (old_color != 0 && num_cells[old_color] > 1) { // Only check if old_color will still exist\n            // Heuristic: If (r,c_val) had 0 or 1 neighbor of old_color, connectivity is likely fine.\n            // Only perform BFS if (r,c_val) was connected to multiple old_color cells\n            int old_color_neighbors_count = 0;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == old_color) {\n                    old_color_neighbors_count++;\n                }\n            }\n            // If it had multiple connections, removal might split the component\n            if (old_color_neighbors_count >= 2) { \n                if (!check_color_connectivity(old_color, r, c_val)) {\n                    move_is_valid = false;\n                }\n            }\n        }\n        if (!move_is_valid) goto revert_move;\n\n        // 3. Connectivity check for new_color (if it's not 0 and expanding/connecting)\n        if (new_color != 0 && old_color != new_color && num_cells[new_color] > 0) { \n            // If the cell (r,c) becomes new_color, it must connect to an existing new_color region\n            bool connected_to_new_color_region = false;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == new_color) {\n                    connected_to_new_color_region = true;\n                    break;\n                }\n            }\n            if (!connected_to_new_color_region) {\n                // If no new_color neighbors, it forms an isolated component, which is invalid\n                move_is_valid = false;\n            }\n        }\n        if (!move_is_valid) goto revert_move;\n\n        // 4. Connectivity check for color 0 (expensive but crucial)\n        if (!check_zero_connectivity()) {\n            move_is_valid = false;\n        }\n        if (!move_is_valid) goto revert_move;\n\n        // --- Move is valid, now decide on acceptance ---\n        // Update num_cells and ward_cells for score calculation\n        num_cells[old_color]--;\n        num_cells[new_color]++;\n        \n        int new_score = N * N - num_cells[0]; // Score is number of non-zero cells\n\n        // Simulated Annealing acceptance logic\n        if (new_score > current_score || dist_real(rng) < exp((new_score - current_score) / T)) {\n            // Accept the move: update ward_cells permanently\n            auto& old_ward_vec = ward_cells[old_color];\n            for (size_t i = 0; i < old_ward_vec.size(); ++i) {\n                if (old_ward_vec[i].first == r && old_ward_vec[i].second == c_val) {\n                    old_ward_vec.erase(old_ward_vec.begin() + i);\n                    break;\n                }\n            }\n            ward_cells[new_color].push_back({r, c_val});\n            current_score = new_score;\n\n            if (new_score > best_score) {\n                best_score = new_score;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        best_d[i][j] = d[i][j];\n                    }\n                }\n            }\n        } else {\n            // Reject the move: revert changes to d, adj_count, num_cells\n            num_cells[old_color]++;\n            num_cells[new_color]--;\nrevert_move: // Label for goto statement\n            d[r][c_val] = old_color;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u, v, val;\n                tie(u, v, val) = delta;\n                adj_count[u][v] += val;\n            }\n        }\n    } // End of SA loop\n\n    // Output the best map found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_d[i][j] << (j == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n#include <map>\n\n// DSU structure\nstruct DSU {\n    std::vector<int> parent;\n    std::vector<int> sz; // Stores size of component for root\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    // Returns true if i and j were in different sets and are now united.\n    // comp_estimated_weight must be provided to update the new root's estimated weight.\n    bool unite(int i, int j, std::vector<double>& comp_estimated_weight) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            // Union by size\n            if (sz[root_i] < sz[root_j]) std::swap(root_i, root_j);\n            \n            // Weighted average for the new component's estimated weight\n            double new_weight = (comp_estimated_weight[root_i] * sz[root_i] + comp_estimated_weight[root_j] * sz[root_j]) / (sz[root_i] + sz[root_j]);\n\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            comp_estimated_weight[root_i] = new_weight;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global random number generator\nstd::mt19937 mt;\n\n// Function to perform a query\nstd::string query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int item_idx : L) {\n        std::cout << \" \" << item_idx;\n    }\n    for (int item_idx : R) {\n        std::cout << \" \" << item_idx;\n    }\n    std::cout << std::endl; // Flush output\n    \n    std::string result;\n    std::cin >> result;\n    return result;\n}\n\n// Function to calculate variance for the partitioning\ndouble calculate_variance(int D, const std::vector<double>& group_sums) {\n    if (D == 0) return 0.0;\n    double sum_t = 0.0;\n    for (double t : group_sums) {\n        sum_t += t;\n    }\n    double mean_t = sum_t / D;\n    double variance = 0.0;\n    for (double t : group_sums) {\n        variance += (t - mean_t) * (t - mean_t);\n    }\n    return variance / D;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Use current time as seed for random number generator\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N, D, Q;\n    std::cin >> N >> D >> Q;\n\n    DSU dsu(N);\n    std::vector<double> comp_estimated_weight(N);\n    for (int i = 0; i < N; ++i) {\n        comp_estimated_weight[i] = 1.0; // Initial estimated weight for each component root\n    }\n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    // Query parameters\n    const double initial_learning_rate = 0.05;\n    const double final_learning_rate = 0.001;\n    const int max_group_query_size = 5;\n\n    for (int q_idx = 0; q_idx < Q; ++q_idx) {\n        double current_learning_rate = initial_learning_rate - (initial_learning_rate - final_learning_rate) * q_idx / Q;\n\n        std::vector<int> active_roots;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.parent[i] == i) { // Check if 'i' is a root\n                active_roots.push_back(i);\n            }\n        }\n\n        std::vector<int> L_items, R_items;\n        int root_L_comp = -1, root_R_comp = -1; // Roots of components chosen for L and R\n\n        if (active_roots.size() < 2) { \n            // All items in one component, or only one item left. \n            // If N is sufficiently large (>= 2), we can still pick two distinct items.\n            int item1 = mt() % N;\n            int item2 = mt() % N;\n            while (item1 == item2) {\n                item2 = mt() % N;\n            }\n            L_items.push_back(item1);\n            R_items.push_back(item2);\n            root_L_comp = dsu.find(item1);\n            root_R_comp = dsu.find(item2);\n        } else {\n            // Pick two distinct random roots\n            std::shuffle(active_roots.begin(), active_roots.end(), mt);\n            root_L_comp = active_roots[0];\n            root_R_comp = active_roots[1];\n\n            // Get items belonging to these components\n            std::vector<int> items_in_root1_comp;\n            std::vector<int> items_in_root2_comp;\n            for (int i = 0; i < N; ++i) {\n                if (dsu.find(i) == root_L_comp) items_in_root1_comp.push_back(i);\n                if (dsu.find(i) == root_R_comp) items_in_root2_comp.push_back(i);\n            }\n            \n            // Randomly select L_size and R_size\n            int L_size = 1 + mt() % max_group_query_size;\n            int R_size = 1 + mt() % max_group_query_size;\n\n            L_size = std::min((int)items_in_root1_comp.size(), L_size);\n            R_size = std::min((int)items_in_root2_comp.size(), R_size);\n\n            // Ensure L_size and R_size are at least 1, unless component is empty (should not happen for active roots)\n            if (L_size == 0 && !items_in_root1_comp.empty()) L_size = 1;\n            if (R_size == 0 && !items_in_root2_comp.empty()) R_size = 1;\n\n            std::shuffle(items_in_root1_comp.begin(), items_in_root1_comp.end(), mt);\n            std::shuffle(items_in_root2_comp.begin(), items_in_root2_comp.end(), mt);\n\n            for (int k = 0; k < L_size; ++k) L_items.push_back(items_in_root1_comp[k]);\n            for (int k = 0; k < R_size; ++k) R_items.push_back(items_in_root2_comp[k]);\n        }\n        \n        // Safety check, although should be covered by logic above\n        if (L_items.empty() || R_items.empty()) {\n            if (N > 1) { // If N is large enough for two distinct items\n                 L_items.clear(); R_items.clear();\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else { // N=1, cannot make a query, but N >= 30, so this won't happen.\n                continue; // Skip query.\n            }\n        }\n\n        std::string result = query(L_items, R_items);\n\n        // Calculate current estimated sums based on component representatives\n        double sum_L_est = 0.0;\n        for (int item_idx : L_items) sum_L_est += comp_estimated_weight[dsu.find(item_idx)];\n        double sum_R_est = 0.0;\n        for (int item_idx : R_items) sum_R_est += comp_estimated_weight[dsu.find(item_idx)];\n\n        if (result == \"=\") {\n            // For 1-1 comparison of different components: merge\n            if (L_items.size() == 1 && R_items.size() == 1 && root_L_comp != root_R_comp) {\n                dsu.unite(L_items[0], R_items[0], comp_estimated_weight);\n            } else if (root_L_comp != root_R_comp) { // Group equality for different components\n                // Adjust component weights to make their estimated sums equal\n                // New weight for root_L_comp s.t. current_sum_L becomes (current_sum_L + current_sum_R)/2\n                double target_sum = (sum_L_est + sum_R_est) / 2.0;\n                if (sum_L_est > 1e-9) comp_estimated_weight[root_L_comp] *= (target_sum / sum_L_est);\n                if (sum_R_est > 1e-9) comp_estimated_weight[root_R_comp] *= (target_sum / sum_R_est);\n            }\n            // If roots are the same, equality doesn't give new relative information between them.\n        } else { // Inequality: L is lighter (<) or heavier (>) than R\n            if (result == \"<\") { // Actual L < Actual R\n                // Our estimates should decrease L's component weight, increase R's\n                comp_estimated_weight[root_L_comp] *= (1.0 - current_learning_rate);\n                comp_estimated_weight[root_R_comp] *= (1.0 + current_learning_rate);\n            } else { // Actual L > Actual R (result == \">\")\n                // Our estimates should increase L's component weight, decrease R's\n                comp_estimated_weight[root_L_comp] *= (1.0 + current_learning_rate);\n                comp_estimated_weight[root_R_comp] *= (1.0 - current_learning_rate);\n            }\n        }\n\n        // Ensure weights are positive. Minimum weight is 1 as per problem constraints on w_i.\n        comp_estimated_weight[root_L_comp] = std::max(1.0, comp_estimated_weight[root_L_comp]);\n        comp_estimated_weight[root_R_comp] = std::max(1.0, comp_estimated_weight[root_R_comp]);\n    }\n\n    // Phase 2: Partitioning using Simulated Annealing\n    std::vector<double> final_weights(N);\n    for (int i = 0; i < N; ++i) {\n        final_weights[i] = comp_estimated_weight[dsu.find(i)];\n    }\n\n    std::vector<int> item_to_group(N);\n    std::vector<int> item_indices(N);\n    std::iota(item_indices.begin(), item_indices.end(), 0);\n\n    // Initial greedy assignment: sort items by estimated weight descending\n    std::sort(item_indices.begin(), item_indices.end(), [&](int a, int b) {\n        return final_weights[a] > final_weights[b];\n    });\n\n    std::vector<double> group_sums(D, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int item_idx = item_indices[i];\n        int min_group = 0;\n        for (int d = 1; d < D; ++d) {\n            if (group_sums[d] < group_sums[min_group]) {\n                min_group = d;\n            }\n        }\n        item_to_group[item_idx] = min_group;\n        group_sums[min_group] += final_weights[item_idx];\n    }\n\n    // Simulated Annealing parameters\n    double T_start = 1000.0; // Starting temperature\n    double T_end = 1.0;      // Ending temperature (small but not zero)\n\n    auto current_time = std::chrono::high_resolution_clock::now();\n    double elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n\n    long long iter_count = 0;\n    while (elapsed_time < TIME_LIMIT) {\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int item_to_move_idx = mt() % N;\n        int current_group = item_to_group[item_to_move_idx];\n        int new_group = mt() % D;\n        \n        if (new_group == current_group) {\n            // No actual move, just update time and continue\n            current_time = std::chrono::high_resolution_clock::now();\n            elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n            continue; \n        }\n\n        // Calculate potential new variance without actually changing state yet\n        std::vector<double> next_group_sums = group_sums;\n        next_group_sums[current_group] -= final_weights[item_to_move_idx];\n        next_group_sums[new_group] += final_weights[item_to_move_idx];\n        \n        double next_variance = calculate_variance(D, next_group_sums);\n        double current_variance = calculate_variance(D, group_sums); // Re-calculate to ensure it's up to date with any previous changes\n\n        if (next_variance < current_variance) {\n            // Always accept better solution\n            current_variance = next_variance;\n            group_sums = next_group_sums;\n            item_to_group[item_to_move_idx] = new_group;\n        } else {\n            // Accept worse solution with probability\n            double prob = std::exp((current_variance - next_variance) / T);\n            if (std::uniform_real_distribution<double>(0.0, 1.0)(mt) < prob) {\n                current_variance = next_variance;\n                group_sums = next_group_sums;\n                item_to_group[item_to_move_idx] = new_group;\n            }\n        }\n        \n        current_time = std::chrono::high_resolution_clock::now();\n        elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        std::cout << item_to_group[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <algorithm> // For std::max or other utilities if needed\n\n// Fixed constants for N and M as per problem statement\nconst int N_BOXES = 200;\nconst int M_STACKS = 10;\n\n// Structure to hold the state of a box\nstruct BoxInfo {\n    int stack_idx;  // 0-indexed stack number (0 to M_STACKS-1)\n    int height_idx; // 0-indexed height from bottom (0 to stack.size()-1)\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n_input, m_input; // Read N and M, though they are fixed\n    std::cin >> n_input >> m_input;\n\n    // stacks[i] is a deque representing stack i, from bottom to top\n    std::vector<std::deque<int>> stacks(M_STACKS);\n    // box_location[v] stores BoxInfo for box v (1-indexed box_id)\n    std::vector<BoxInfo> box_location(N_BOXES + 1);\n\n    // Initialize stacks and box_location from input\n    for (int i = 0; i < M_STACKS; ++i) {\n        for (int j = 0; j < N_BOXES / M_STACKS; ++j) {\n            int box_id;\n            std::cin >> box_id;\n            stacks[i].push_back(box_id);\n            box_location[box_id] = {i, j};\n        }\n    }\n\n    std::vector<std::pair<int, int>> operations;\n    // long long total_energy_expended = 0; // For debugging/local testing, not required for output\n\n    // Iterate for each box from 1 to N_BOXES in ascending order\n    for (int v = 1; v <= N_BOXES; ++v) {\n        int current_stack_idx = box_location[v].stack_idx;\n        int current_height_idx = box_location[v].height_idx;\n\n        // If box v is already carried out, skip (e.g., if problem logic was different, or error)\n        // With current strict 1..N order, this check mainly guards against logical errors.\n        if (current_stack_idx == -1) {\n            continue;\n        }\n\n        // Check if box v is at the top of its stack\n        if (current_height_idx == stacks[current_stack_idx].size() - 1) {\n            // Box v is at the top, can be carried out\n            operations.push_back({v, 0}); // Operation 2: (v, 0)\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n        } else {\n            // Box v is not at the top, need to move boxes above it\n\n            // Identify the bottom-most box of the block to be moved\n            int block_bottom_box_id = stacks[current_stack_idx][current_height_idx + 1];\n            // Calculate number of boxes to move (k in problem statement)\n            int num_boxes_to_move = stacks[current_stack_idx].size() - (current_height_idx + 1);\n            // total_energy_expended += (long long)num_boxes_to_move + 1; // Add cost (k+1)\n\n            // Choose destination stack for Operation 1\n            int dest_stack_idx = -1;\n            int max_top_box_val = -1; // For heuristic: pick stack with highest top box value\n\n            // Strategy 1: Prioritize empty stacks\n            for (int d = 0; d < M_STACKS; ++d) {\n                if (d == current_stack_idx) continue; // Cannot move to the same stack\n                if (stacks[d].empty()) {\n                    dest_stack_idx = d;\n                    break; // Found an empty stack, use it\n                }\n            }\n\n            // Strategy 2: If no empty stack, choose stack with the highest value at its top\n            if (dest_stack_idx == -1) {\n                for (int d = 0; d < M_STACKS; ++d) {\n                    if (d == current_stack_idx) continue;\n                    // At this point, stacks[d] is guaranteed not empty\n                    if (stacks[d].back() > max_top_box_val) {\n                        max_top_box_val = stacks[d].back();\n                        dest_stack_idx = d;\n                    }\n                }\n            }\n\n            // Perform Operation 1: move block_bottom_box_id and boxes above it to dest_stack_idx\n            // Output stack_idx as 1-indexed, so dest_stack_idx + 1\n            operations.push_back({block_bottom_box_id, dest_stack_idx + 1});\n\n            // Temporarily store boxes that will be moved\n            std::vector<int> boxes_to_move;\n            for (size_t i = current_height_idx + 1; i < stacks[current_stack_idx].size(); ++i) {\n                boxes_to_move.push_back(stacks[current_stack_idx][i]);\n            }\n            \n            // Resize the original stack to remove the moved boxes\n            stacks[current_stack_idx].resize(current_height_idx + 1);\n\n            // Add the moved boxes to the destination stack and update their locations\n            for (int box_id : boxes_to_move) {\n                box_location[box_id] = {dest_stack_idx, (int)stacks[dest_stack_idx].size()};\n                stacks[dest_stack_idx].push_back(box_id);\n            }\n            \n            // After moving, box v is now at the top of its original stack.\n            // Update v's height_idx to reflect its new top position\n            box_location[v].height_idx = stacks[current_stack_idx].size() - 1;\n\n            // Perform Operation 2: carry out box v\n            operations.push_back({v, 0});\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n        }\n    }\n\n    // Output the sequence of operations\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip> // For setprecision\n#include <functional> // For std::function\n\nusing namespace std;\n\nint N;\nvector<string> H_walls; // h[i][j] wall between (i,j) and (i+1,j)\nvector<string> V_walls; // v[i][j] wall between (i,j) and (i,j+1)\nvector<vector<int>> D_values; // d[i][j] dirt susceptibility\n\n// Directions: D, R, U, L\nint DR[] = {1, 0, -1, 0};\nint DC[] = {0, 1, 0, -1};\nchar DIR_CHARS[] = {'D', 'R', 'U', 'L'};\nchar REV_DIR_CHARS[] = {'U', 'L', 'D', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Get next position after moving in a given direction\nPos get_next_pos(Pos current, int dir_idx) {\n    return {current.r + DR[dir_idx], current.c + DC[dir_idx]};\n}\n\n// Check if move is valid (within bounds and no wall)\nbool is_valid_move(Pos current, int dir_idx) {\n    int nr = current.r + DR[dir_idx];\n    int nc = current.c + DC[dir_idx];\n\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n        return false; // Out of bounds\n    }\n\n    // Check for walls\n    if (dir_idx == 0) { // Down (DR[0]=1, DC[0]=0) from (current.r, current.c) to (current.r+1, current.c)\n        return H_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 1) { // Right (DR[1]=0, DC[1]=1) from (current.r, current.c) to (current.r, current.c+1)\n        return V_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 2) { // Up (DR[2]=-1, DC[2]=0) from (current.r, current.c) to (current.r-1, current.c)\n        return H_walls[nr][nc] == '0'; // Wall between (nr,nc) and (nr+1,nc) which is (current.r-1,current.c) and (current.r,current.c)\n    } else if (dir_idx == 3) { // Left (DR[3]=0, DC[3]=-1) from (current.r, current.c) to (current.r, current.c-1)\n        return V_walls[nr][nc] == '0'; // Wall between (nr,nc) and (nr,nc+1) which is (current.r,current.c-1) and (current.r,current.c)\n    }\n    return false; // Should not happen\n}\n\n// Calculate exact score based on path_moves and visits\ndouble calculate_exact_score(int L, const vector<vector<int>>& visits_data, const vector<vector<int>>& d_values) {\n    double total_S_sum_terms = 0.0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int sq_idx = i * N + j;\n            const auto& cell_visits = visits_data[sq_idx];\n\n            if (cell_visits.empty()) {\n                // This means an illegal path (square not visited)\n                return 1e18; // Very high penalty\n            }\n\n            double sum_term_for_cell = 0.0;\n            int N_ij = cell_visits.size();\n\n            for (int k = 0; k < N_ij - 1; ++k) {\n                long long T = cell_visits[k+1] - cell_visits[k];\n                sum_term_for_cell += (double)T * (T - 1) / 2.0;\n            }\n            // For the last interval that wraps around\n            long long T_last = L - cell_visits[N_ij-1] + cell_visits[0];\n            sum_term_for_cell += (double)T_last * (T_last - 1) / 2.0;\n\n            total_S_sum_terms += d_values[i][j] * sum_term_for_cell;\n        }\n    }\n    return total_S_sum_terms / L;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    H_walls.resize(N - 1);\n    V_walls.resize(N);\n    D_values.resize(N, vector<int>(N));\n\n    for (int i = 0; i < N - 1; ++i) cin >> H_walls[i];\n    for (int i = 0; i < N; ++i) cin >> V_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D_values[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    string current_path_moves;\n    \n    // Initial DFS path generation\n    vector<bool> dfs_visited_cells(N * N, false);\n    \n    // Lambda function for DFS path building\n    function<void(Pos)> build_dfs_path = \n        [&](Pos current) {\n        int current_idx = current.r * N + current.c;\n        dfs_visited_cells[current_idx] = true;\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            int next_idx = next.r * N + next.c;\n\n            if (next.r < 0 || next.r >= N || next.c < 0 || next.c >= N) continue; // Out of bounds check\n            if (!is_valid_move(current, dir_idx)) continue; // Wall check\n            if (dfs_visited_cells[next_idx]) continue; // Already visited\n\n            current_path_moves += DIR_CHARS[dir_idx];\n            build_dfs_path(next);\n            current_path_moves += REV_DIR_CHARS[dir_idx];\n        }\n    };\n    \n    build_dfs_path({0,0});\n    int current_L = current_path_moves.length();\n\n    // Build visits list from the initial DFS path\n    vector<vector<int>> current_visits(N * N);\n    Pos temp_pos = {0,0};\n    for (int t = 0; t < current_L; ++t) {\n        char move_char = current_path_moves[t];\n        int dir_idx = -1;\n        for(int i=0; i<4; ++i) if(DIR_CHARS[i] == move_char) dir_idx = i;\n        temp_pos = get_next_pos(temp_pos, dir_idx);\n        current_visits[temp_pos.r * N + temp_pos.c].push_back(t + 1); // t+1 because 1-indexed time\n    }\n\n    double current_score = calculate_exact_score(current_L, current_visits, D_values);\n    double best_score = current_score;\n    string best_path_moves = current_path_moves;\n\n    // Set up random number generators for Simulated Annealing\n    mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double T_start = 1000.0; // Initial temperature (can be related to max D_value)\n    double T_end = 1.0;     // Final temperature\n    long long max_iterations_for_temp = 200000; // A reference for cooling schedule progression\n\n    int iter_count = 0;\n    // Iterate for a maximum of 1.9 seconds (leaving some margin for output/cleanup)\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1900) {\n        iter_count++;\n        // Linear cooling schedule\n        double T = T_start + (T_end - T_start) * ((double)iter_count / max_iterations_for_temp);\n        if (T < T_end) T = T_end; // Ensure temp doesn't drop below T_end\n\n        // Try adding a 2-move loop from (0,0) to an adjacent cell and back\n        Pos zero_zero_pos = {0,0};\n        \n        int dir_idx = rng() % 4; // Random direction for neighbor of (0,0)\n        Pos next_loop_pos = get_next_pos(zero_zero_pos, dir_idx);\n        \n        // Check if the loop is valid (within bounds, no walls for both moves)\n        if (next_loop_pos.r < 0 || next_loop_pos.r >= N || next_loop_pos.c < 0 || next_loop_pos.c >= N) continue;\n        if (!is_valid_move(zero_zero_pos, dir_idx)) continue;\n        int rev_dir_idx = (dir_idx + 2) % 4; // Direction to move back to (0,0)\n        if (!is_valid_move(next_loop_pos, rev_dir_idx)) continue;\n\n        string added_moves = string(1, DIR_CHARS[dir_idx]) + string(1, REV_DIR_CHARS[rev_dir_idx]);\n        string temp_path_moves = current_path_moves + added_moves;\n        int temp_L = current_L + 2;\n        \n        if (temp_L > 100000) continue; // Path length limit\n\n        vector<vector<int>> temp_visits = current_visits; // Create a copy of current visits data\n        \n        // Add new visit times for the two cells involved in the loop\n        // The first new visit is for `next_loop_pos` at `current_L + 1`\n        // The second new visit is for `zero_zero_pos` at `current_L + 2`\n        int next_loop_idx = next_loop_pos.r * N + next_loop_pos.c;\n        int zero_zero_idx = zero_zero_pos.r * N + zero_zero_pos.c;\n\n        // Use lower_bound and insert to maintain sorted order efficiently (O(k) where k is vector size)\n        auto it_next = lower_bound(temp_visits[next_loop_idx].begin(), temp_visits[next_loop_idx].end(), current_L + 1);\n        temp_visits[next_loop_idx].insert(it_next, current_L + 1);\n\n        auto it_zero = lower_bound(temp_visits[zero_zero_idx].begin(), temp_visits[zero_zero_idx].end(), current_L + 2);\n        temp_visits[zero_zero_idx].insert(it_zero, current_L + 2);\n        \n        double temp_score = calculate_exact_score(temp_L, temp_visits, D_values);\n        \n        double delta_score = temp_score - current_score;\n\n        if (delta_score < 0 || (T > 0 && dist_real(rng) < exp(-delta_score / T))) {\n            current_path_moves = temp_path_moves;\n            current_L = temp_L;\n            current_visits = temp_visits;\n            current_score = temp_score;\n\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_path_moves = current_path_moves;\n            }\n        }\n    }\n\n    cout << best_path_moves << endl;\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <tuple> // For std::tuple comparison\n#include <cmath> // For std::abs\n\n// Aho-Corasick Node definition\nstruct ACNode {\n    std::array<int, 26> go; // Transition links for characters 'A'-'Z'\n    int fail; // Failure link\n    std::vector<int> pattern_indices; // Indices of patterns ending at this node (or via failure links)\n    int depth; // Length of string represented by this node\n\n    ACNode() : fail(0), depth(0) {\n        go.fill(0); // Initialize all transitions to 0 (root node)\n    }\n};\n\nstd::vector<ACNode> ac_trie; // The Aho-Corasick automaton trie\nstd::vector<bool> global_found_tks; // Tracks which of the M patterns have been found\nint M_val; // Stores the total number of patterns (M)\n\n// Builds the Aho-Corasick automaton from the given patterns\nvoid build_ac(const std::vector<std::string>& patterns) {\n    ac_trie.clear();\n    ac_trie.emplace_back(); // Root node (node 0)\n    M_val = patterns.size();\n    global_found_tks.assign(M_val, false); // Initialize all patterns as not found\n\n    // 1. Build Trie structure: Insert all patterns into the trie\n    for (int p_idx = 0; p_idx < M_val; ++p_idx) {\n        int curr = 0; // Start from the root\n        for (char ch : patterns[p_idx]) {\n            int c_idx = ch - 'A';\n            if (ac_trie[curr].go[c_idx] == 0) { // If transition doesn't exist, create a new node\n                ac_trie[curr].go[c_idx] = ac_trie.size(); // Assign new node ID\n                ac_trie.emplace_back(); // Add new node to the trie\n                ac_trie.back().depth = ac_trie[curr].depth + 1; // Set its depth\n            }\n            curr = ac_trie[curr].go[c_idx]; // Move to the next node\n        }\n        ac_trie[curr].pattern_indices.push_back(p_idx); // Mark this node as an end point for pattern p_idx\n    }\n\n    // 2. Build Failure Links and propagate output patterns using BFS\n    std::queue<int> q;\n    // For all direct children of the root, their failure link points to the root (0)\n    for (int i = 0; i < 26; ++i) {\n        if (ac_trie[0].go[i] != 0) {\n            ac_trie[ac_trie[0].go[i]].fail = 0; // Set fail link\n            q.push(ac_trie[0].go[i]); // Add to BFS queue\n        }\n    }\n\n    while (!q.empty()) {\n        int u = q.front(); // Current node\n        q.pop();\n\n        // Propagate pattern_indices from the failure link:\n        // Any patterns found via `u`'s failure link are also considered found when at `u`\n        int f = ac_trie[u].fail;\n        for (int p_idx : ac_trie[f].pattern_indices) {\n            ac_trie[u].pattern_indices.push_back(p_idx);\n        }\n        // Note: For distinct patterns, `pattern_indices` won't usually have duplicates this way.\n        // If necessary, `std::sort` and `std::unique` could be used here for robustness.\n\n        // For each character in the alphabet\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            if (ac_trie[u].go[c_idx] != 0) { // If a direct child `v` exists for char `c_idx`\n                int v = ac_trie[u].go[c_idx];\n                // The fail link of `v` is found by following `u`'s fail link, then trying to match `c_idx`\n                ac_trie[v].fail = ac_trie[ac_trie[u].fail].go[c_idx];\n                q.push(v); // Add `v` to the BFS queue\n            } else { // If no direct child `v` for char `c_idx`, create a \"shortcut\"\n                // This makes `go[c_idx]` from `u` behave as if it's `go[c_idx]` from `u`'s failure link\n                ac_trie[u].go[c_idx] = ac_trie[ac_trie[u].fail].go[c_idx];\n            }\n        }\n    }\n}\n\n// Get the next state in the Aho-Corasick automaton.\n// This function relies on the precomputed 'go' links which already include fail link shortcuts.\nint get_next_ac_state(int current_node, char ch) {\n    int c_idx = ch - 'A';\n    return ac_trie[current_node].go[c_idx];\n}\n\n// Checks for newly found patterns at the given node and updates the global_found_tks array.\nvoid check_and_update_patterns(int node_id) {\n    for (int p_idx : ac_trie[node_id].pattern_indices) {\n        if (!global_found_tks[p_idx]) { // If this pattern hasn't been marked as found yet\n            global_found_tks[p_idx] = true; // Mark it as found\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_grid, M_patterns;\n    std::cin >> N_grid >> M_patterns;\n\n    int s_i, s_j; // Initial finger position\n    std::cin >> s_i >> s_j;\n\n    std::vector<std::string> A_grid(N_grid);\n    // Precompute coordinates for each character on the grid for efficient lookup\n    std::vector<std::vector<std::pair<int, int>>> char_to_coords(26);\n    for (int i = 0; i < N_grid; ++i) {\n        std::cin >> A_grid[i];\n        for (int j = 0; j < N_grid; ++j) {\n            char_to_coords[A_grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    std::vector<std::string> t_patterns(M_patterns);\n    for (int k = 0; k < M_patterns; ++k) {\n        std::cin >> t_patterns[k];\n    }\n\n    build_ac(t_patterns); // Build the Aho-Corasick automaton\n\n    std::pair<int, int> current_pos = {s_i, s_j}; // Current finger position\n    int current_ac_node = 0; // Current state in the Aho-Corasick automaton (starts at root)\n    std::vector<std::pair<int, int>> operations; // List to store the sequence of operations\n\n    // Check if any patterns are found by the empty string (root node).\n    // This is typically not the case for non-empty patterns but ensures correctness for any edge cases.\n    check_and_update_patterns(0);\n\n    // Main greedy loop: continue until all patterns are found or the operation limit is reached\n    while (true) {\n        int found_count = 0;\n        for(bool b : global_found_tks) {\n            if (b) found_count++;\n        }\n\n        if (found_count == M_patterns) {\n            break; // All patterns found, goal achieved\n        }\n        if (operations.size() >= 5000) {\n            break; // Operation limit reached, cannot perform more actions\n        }\n\n        int best_nr = -1, best_nc = -1; // Coordinates for the best next move\n        char best_char_to_append = ' '; // Character for the best next move\n        \n        // Metric for choosing the best next operation:\n        // Using a tuple for lexicographical comparison:\n        // 1. Maximize newly found patterns (`temp_new_tks_count`).\n        // 2. Minimize typing cost (`-current_move_cost` because tuple comparison is maximizing).\n        // 3. Maximize Aho-Corasick node depth (`ac_trie[next_node].depth`).\n        std::tuple<int, int, int> best_metric = {-1, 1, -1}; // Initialize with values any valid choice will beat\n\n        // Iterate through all possible next characters and their positions on the keyboard\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            char c = 'A' + c_idx;\n            for (auto [nr, nc] : char_to_coords[c_idx]) { // Iterate through all physical locations of character 'c'\n                int current_move_cost = std::abs(nr - current_pos.first) + std::abs(nc - current_pos.second) + 1;\n                int next_node = get_next_ac_state(current_ac_node, c); // Get the AC state after appending 'c'\n\n                // Temporarily count how many *new* patterns would be found by this specific choice\n                int temp_new_tks_count = 0;\n                for (int p_idx : ac_trie[next_node].pattern_indices) {\n                    if (!global_found_tks[p_idx]) { // If this pattern hasn't been found yet\n                        temp_new_tks_count++;\n                    }\n                }\n                \n                std::tuple<int, int, int> current_metric = {temp_new_tks_count, -current_move_cost, ac_trie[next_node].depth};\n\n                if (current_metric > best_metric) { // Compare using tuple's lexicographical order\n                    best_metric = current_metric;\n                    best_nr = nr;\n                    best_nc = nc;\n                    best_char_to_append = c;\n                }\n            }\n        }\n\n        // If no valid character choice was found, it implies that no move improves the score\n        // (which usually means all patterns are found, or we've hit a state where no further progress is possible\n        // under the greedy heuristic). This should ideally not happen if M_patterns are not all found and ops < 5000.\n        if (best_nr == -1) {\n            break; \n        }\n\n        // Perform the chosen best operation\n        operations.push_back({best_nr, best_nc});\n        current_pos = {best_nr, best_nc}; // Update finger position\n        current_ac_node = get_next_ac_state(current_ac_node, best_char_to_append); // Update AC state\n        check_and_update_patterns(current_ac_node); // Update the global set of found patterns\n    }\n\n    // Output the sequence of operations as required by the problem statement\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc030":"","ahc031":"long long calculate_delta_cost(int d, const Rect& old_r, const Rect& new_r, int k_id,\n                                 const bool H_prev_day[W+1][W], const bool V_prev_day[W][W+1],\n                                 GridManager& gm, long long current_total_cost) {\n    // 1. Calculate delta area cost:\n    long long delta_area_cost = 0;\n    // Remove old_r's contribution\n    if (old_r.area() < a_global[d][k_id]) delta_area_cost -= 100LL * (a_global[d][k_id] - old_r.area());\n    // Add new_r's contribution\n    if (new_r.area() < a_global[d][k_id]) delta_area_cost += 100LL * (a_global[d][k_id] - new_r.area());\n\n    // 2. Calculate delta partition cost:\n    long long delta_partition_cost = 0;\n    \n    // Temporarily revert the placed_rects entry for k_id to old_r\n    // (since gm.place(new_r, k_id) was already called for validation)\n    // We need the state *before* gm.place(new_r, k_id) to figure out diffs.\n    // The safest way is to manage `H_curr` and `V_curr` arrays incrementally.\n    \n    // Instead of directly calculating delta, calculate new total cost based on `gm.placed_rects`\n    // (which now includes new_r) and then subtract `current_total_cost`.\n    // This implies `calculate_day_cost` is called directly, but its performance needs to be improved\n    // beyond `O(W^2)`.\n\n    // Optimized `calculate_day_cost` for incremental SA updates:\n    // Store `H_current_sum` and `V_current_sum` (total active partitions)\n    // When `is_occupied[r][c]` changes, it affects 4 segments.\n    // For each affected segment `s = (i,j)-(i',j')`:\n    //  `old_H_curr_s = is_segment_a_border_before_change(s)`\n    //  `new_H_curr_s = is_segment_a_border_after_change(s)`\n    //  If `(old_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    //  If `(new_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    // This is the $O(Area)$ bottleneck.\n    // To implement `is_segment_a_border`, you need `is_occupied` state.\n\n    // A simpler way:\n    // Copy `is_occupied` state to a temporary `is_occupied_temp`\n    // Then `gm.remove(k_id, from_is_occupied_temp)`\n    // Compute `old_local_partition_status` using `is_occupied_temp` within `old_r`'s perimeter + 1 cell buffer.\n    // `gm.place(new_r, to_is_occupied_temp)`\n    // Compute `new_local_partition_status` using `is_occupied_temp` within `new_r`'s perimeter + 1 cell buffer.\n    // Then calculate the `delta_partition_cost` within these local affected regions.\n\n    // For simplicity of implementation (and hoping that AvgArea is small enough on average)\n    // just call the full `calculate_day_cost` after updating `gm.placed_rects`.\n    // With `SA_ITERATIONS` around 1000 per day, total $5 \\times 10^7$ iterations for `calculate_day_cost`.\n    // AvgArea $20000 \\approx 0.02 W^2$.\n    // If average $W^2$ operations is $2 \\times 10^4$, then $5 \\times 10^7 \\times 2 \\times 10^4 = 10^{12}$. Still too much.\n    // This is why `calculate_day_cost` *must* be O(Perimeter) in SA.\n    \n    // Let's go with the O(Perimeter) approach for SA iterations.\n    // Need to precompute `H_curr` and `V_curr` from `is_occupied` once per day.\n    // Then when a rectangle `R_k` changes, we update only the segments around its perimeter.\n    // This implies `H_curr_global[W+1][W]` and `V_curr_global[W][W+1]` must be updated incrementally.\n    \n    // `current_H_states[W+1][W]` and `current_V_states[W][W+1]` (booleans)\n    // `current_H_count`, `current_V_count` (total partition lengths)\n    // On a move:\n    //  `old_r_perimeter_segs = get_perimeter_segments(old_r)`\n    //  `new_r_perimeter_segs = get_perimeter_segments(new_r)`\n    //  For `s` in `old_r_perimeter_segs` and `new_r_perimeter_segs` (union):\n    //    `was_border = is_segment_a_border(s, is_occupied_before_change)`\n    //    `is_border = is_segment_a_border(s, is_occupied_after_change)`\n    //    If `was_border != is_border`:\n    //      if `was_border != global_H_prev[s]`: `delta_cost--`\n    //      if `is_border != global_H_prev[s]`: `delta_cost++`\n    // This `is_segment_a_border` checks `is_occupied` for neighbors of `s`, which means `O(1)` per segment.\n    // Total `O(Perimeter)` for partition cost delta. Area update is $O(Area)$.\n    // So the move is $O(Area + Perimeter)$, which becomes $O(Area)$ in worst case.\n    // Let's assume avg Area is small enough on average for $N=50$ given $W=1000$.\n    // If $W^2/N = 20000$, $Area \\sim 20000$. This is the largest factor.\n    // $50 \\times 1000 \\times 20000 = 10^9$. Maybe SA_ITERATIONS must be smaller, say 1000.\n    // $50 \\times 1000 \\times 20000 = 10^9$. This would be close to 1 second.\n    // $SA\\_ITERATIONS=1000$ per day. Total $50000$ iterations.\n    // Each is $O(Area)$, `20000`. So $50000 \\times 20000 = 10^9$. This will be slow for 3s.\n    // The input generation suggests `a_d,k` sum is around $W^2-E$. Smallest $E$ is $W^2 \\times 0.0025 = 2500$.\n    // So average desired area is typically $W^2/N \\approx 20000$.\n    // Maybe `Area` updates are sparse?\n}\n\nFinal decision: I will implement `calculate_day_cost` with `O(W^2)` per call, and reduce `SA_ITERATIONS` to a very small number (e.g., 50 per day). This makes total operations $D \\times SA\\_ITERATIONS \\times W^2 = 50 \\times 50 \\times 10^6 = 2.5 \\times 10^9$. This might barely pass, or be too slow. A hybrid: `O(Area)` based delta computation during SA, and full `O(W^2)` only once at the end of each day for `global_H_prev` update.\n","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric> // Required for std::accumulate, though not used in final code. Keep for general utility sense.\n#include <algorithm> // Required for std::max, though manual check is used.\n#include <limits>    // Required for std::numeric_limits\n\n// Define MOD constant\nconst int MOD = 998244353;\n\n// Structure to store an performed operation\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N, M, K;\n    std::cin >> N >> M >> K;\n\n    // Initialize the board with initial values `a_i,j`.\n    // We store values modulo MOD, so `int` is sufficient as MOD fits in int.\n    std::vector<std::vector<int>> current_board(N, std::vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> current_board[i][j]; // a_i,j are guaranteed to be < MOD\n        }\n    }\n\n    // Read all stamp configurations `s_m,i,j`.\n    std::vector<std::vector<std::vector<int>>> s(M, std::vector<std::vector<int>>(3, std::vector<int>(3)));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> s[m][i][j]; // s_m,i,j are guaranteed to be < MOD\n            }\n        }\n    }\n\n    // Vector to store the sequence of operations chosen.\n    std::vector<Operation> operations_performed;\n\n    // Perform up to K operations.\n    for (int k_idx = 0; k_idx < K; ++k_idx) {\n        long long max_gain = std::numeric_limits<long long>::min(); // Initialize with the smallest possible long long value.\n                                                                     // This ensures any valid gain, positive or negative, will replace it.\n        int best_m = -1, best_p = -1, best_q = -1; // Variables to store the best operation found in the current step.\n\n        // Iterate through all possible stamps.\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            // Iterate through all possible top-left positions (p, q) for the stamp.\n            // A 3x3 stamp starting at (p,q) covers (p..p+2, q..q+2).\n            // For N=9, p and q can range from 0 to N-3 (i.e., 0 to 6).\n            for (int p_idx = 0; p_idx <= N - 3; ++p_idx) {\n                for (int q_idx = 0; q_idx <= N - 3; ++q_idx) {\n                    long long current_gain = 0; // Accumulated gain for the current stamp application.\n\n                    // Calculate the score change if this stamp is applied.\n                    for (int i_s = 0; i_s < 3; ++i_s) {\n                        for (int j_s = 0; j_s < 3; ++j_s) {\n                            int r = p_idx + i_s; // Row on the board\n                            int c = q_idx + j_s; // Column on the board\n\n                            int old_val_mod = current_board[r][c]; // Current value modulo MOD\n                            \n                            // Calculate new value modulo MOD.\n                            // Cast to long long before addition to prevent potential overflow\n                            // if old_val_mod + s[m_idx][i_s][j_s] were to exceed INT_MAX,\n                            // although for current constraints, int would likely be fine.\n                            long long new_val_mod_calc = (long long)old_val_mod + s[m_idx][i_s][j_s];\n                            int new_val_mod = new_val_mod_calc % MOD;\n                            \n                            // Add the change in score for this cell to current_gain.\n                            // If new_val_mod is smaller than old_val_mod (due to wrap-around),\n                            // this subtraction correctly yields a negative gain (loss).\n                            current_gain += (new_val_mod - old_val_mod);\n                        }\n                    }\n\n                    // If this operation yields a better total gain, record it as the best.\n                    if (current_gain > max_gain) {\n                        max_gain = current_gain;\n                        best_m = m_idx;\n                        best_p = p_idx;\n                        best_q = q_idx;\n                    }\n                }\n            }\n        }\n\n        // If the best possible operation does not provide a positive gain,\n        // it means we cannot increase the total score further. So, we stop.\n        // `max_gain <= 0` covers cases where the gain is negative (score decreases)\n        // or zero (score remains same). Both are not desirable.\n        if (max_gain <= 0) { \n            break; \n        }\n\n        // Apply the chosen best operation to update the board state.\n        for (int i_s = 0; i_s < 3; ++i_s) {\n            for (int j_s = 0; j_s < 3; ++j_s) {\n                int r = best_p + i_s;\n                int c = best_q + j_s;\n                current_board[r][c] = ((long long)current_board[r][c] + s[best_m][i_s][j_s]) % MOD;\n            }\n        }\n        // Record the operation.\n        operations_performed.push_back({best_m, best_p, best_q});\n    }\n\n    // Output the number of operations performed.\n    std::cout << operations_performed.size() << std::endl;\n    // Output each operation's details.\n    for (const auto& op : operations_performed) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n\n    return 0;\n}\n","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\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 { // For map keys\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint DR[] = {-1, 1, 0, 0}; // U, D, L, R\nint DC[] = {0, 0, -1, 1};\n\n// Correct way to get char from dr,dc\nchar get_dir_char(int dr, int dc) {\n    if (dr == -1 && dc == 0) return 'U';\n    if (dr == 1 && dc == 0) return 'D';\n    if (dr == 0 && dc == -1) return 'L';\n    if (dr == 0 && dc == 1) return 'R';\n    return '.'; // Should not happen for a valid move\n}\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int holding_container_id; // -1 if not holding\n    bool is_large;\n    bool is_bombed;\n};\n\nstruct State {\n    vector<vector<int>> board; // container ID, -1 if empty\n    vector<Crane> cranes;\n    vector<int> incoming_idx; // next container index for each receiving gate (row)\n    vector<int> next_dispatch_val; // next container ID expected at each dispatch gate (row)\n    vector<vector<int>> A; // initial incoming container sequence\n    map<int, Pos> container_locations; // Map container_id to its (r,c) position or {-1,-1} if in crane's hand or not on board\n};\n\n// BFS to find the next step (dr, dc) and path cost\n// Returns {dr, dc} for the next step. {0,0} if no path or already at target.\n// path_cost_out will be set to the cost of the path, or -1 if no path.\nPos get_next_step(const State& current_state, int crane_id, Pos start_pos, Pos target_pos,\n                  bool is_holding_container, bool is_large_crane,\n                  const vector<Pos>& other_crane_current_pos_snapshot, // Snapshot of all crane positions before planning\n                  const vector<Pos>& other_crane_target_next_pos_planned, // Planned next positions for higher priority cranes (j < crane_id)\n                  int& path_cost_out) {\n\n    if (start_pos == target_pos) {\n        path_cost_out = 0;\n        return {0,0};\n    }\n\n    queue<pair<Pos, vector<Pos>>> q; // Pos, path_to_Pos\n    map<Pos, int> dist; // Using map for visited/distance because Pos is not easily hashable for unordered_map\n\n    vector<Pos> initial_path;\n    initial_path.push_back(start_pos);\n\n    q.push({start_pos, initial_path});\n    dist[start_pos] = 0;\n\n    Pos next_step_dir = {0,0};\n    path_cost_out = -1; // Default to no path found\n\n    while (!q.empty()) {\n        Pos u = q.front().first;\n        vector<Pos> path = q.front().second;\n        int d = dist[u];\n        q.pop();\n\n        if (u == target_pos) {\n            // Path found. The first step is path[1] - path[0]\n            path_cost_out = d;\n            if (path.size() > 1) { // If path length > 0, there is a next step\n                next_step_dir = {path[1].r - start_pos.r, path[1].c - start_pos.c};\n            }\n            return next_step_dir;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos v = {u.r + DR[i], u.c + DC[i]};\n\n            if (v.r < 0 || v.r >= N || v.c < 0 || v.c >= N) continue; // Out of bounds\n\n            // Check for container on destination square (for small cranes holding cargo)\n            if (!is_large_crane && is_holding_container && current_state.board[v.r][v.c] != -1) {\n                continue; // Small crane carrying a container cannot move into occupied square\n            }\n\n            bool collision = false;\n            for (int j = 0; j < N; ++j) {\n                if (j == crane_id || current_state.cranes[j].is_bombed) continue; // Skip self or bombed cranes\n\n                Pos other_curr_j = other_crane_current_pos_snapshot[j]; // The actual current position of crane j\n                Pos other_next_j_planned = other_crane_target_next_pos_planned[j]; // The *planned* next position of crane j (if j < crane_id)\n\n                if (j < crane_id) { // Higher priority crane, its next position is already planned\n                    if (v == other_next_j_planned) { // Check if target cell v is taken by a higher priority crane's planned move\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == other_next_j_planned) { // Check for swap collision with higher priority crane\n                        collision = true; break;\n                    }\n                } else { // Lower priority crane, it hasn't planned its move yet, so use its current position\n                    if (v == other_curr_j) { // Check if target cell v is currently occupied by a lower priority crane\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == current_state.cranes[j].pos) { // Check for swap collision with lower priority crane\n                        collision = true; break;\n                    }\n                }\n            }\n            if (collision) continue;\n\n            // Check if already visited or found a shorter path\n            if (dist.find(v) == dist.end() || dist[v] > d + 1) {\n                dist[v] = d + 1;\n                vector<Pos> new_path = path;\n                new_path.push_back(v);\n                q.push({v, new_path});\n            }\n        }\n    }\n    return {0,0}; // No path found, return (0,0) direction\n}\n\n\nvoid solve() {\n    State current_state;\n    current_state.board.assign(N, vector<int>(N, -1));\n    current_state.A.assign(N, vector<int>(N));\n    current_state.incoming_idx.assign(N, 0);\n    current_state.next_dispatch_val.assign(N, 0);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> current_state.A[i][j];\n        }\n    }\n\n    current_state.cranes.resize(N);\n    for (int i = 0; i < N; ++i) {\n        current_state.cranes[i].id = i;\n        current_state.cranes[i].pos = {i, 0};\n        current_state.cranes[i].holding_container_id = -1;\n        current_state.cranes[i].is_large = (i == 0);\n        current_state.cranes[i].is_bombed = false;\n        current_state.container_locations[-1] = {-1,-1}; // Dummy entry\n    }\n\n    int turns = 0;\n    int dispatched_count = 0;\n\n    vector<string> all_crane_actions(N, \"\");\n\n    while (dispatched_count < N*N && turns < MAX_TURNS) {\n        turns++;\n        \n        // 0. Store current crane positions for BFS collision detection\n        vector<Pos> other_crane_current_pos_snapshot(N);\n        for(int i=0; i<N; ++i) other_crane_current_pos_snapshot[i] = current_state.cranes[i].pos;\n\n        // 1. Incoming containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.incoming_idx[i] < N) {\n                bool gate_has_container = (current_state.board[i][0] != -1);\n                bool gate_has_crane = false;\n                for(int k=0; k<N; ++k) {\n                    if (!current_state.cranes[k].is_bombed && current_state.cranes[k].pos.r == i && current_state.cranes[k].pos.c == 0) {\n                        gate_has_crane = true;\n                        break;\n                    }\n                }\n                if (!gate_has_container && !gate_has_crane) {\n                    int container_id = current_state.A[i][current_state.incoming_idx[i]];\n                    current_state.board[i][0] = container_id;\n                    current_state.container_locations[container_id] = {i,0};\n                    current_state.incoming_idx[i]++;\n                }\n            }\n        }\n\n        // 2. Crane actions planning\n        vector<char> current_turn_actions_char(N, '.');\n        vector<Pos> target_next_crane_pos_planned(N); // For prioritized collision detection, stores planned next pos for cranes j < k\n        vector<int> target_next_crane_holding_planned(N); // For P/Q updates\n\n        // Initialize planned positions and holding status to current state\n        for (int k = 0; k < N; ++k) {\n            target_next_crane_pos_planned[k] = current_state.cranes[k].pos;\n            target_next_crane_holding_planned[k] = current_state.cranes[k].holding_container_id;\n        }\n\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) {\n                current_turn_actions_char[k] = '.';\n                continue;\n            }\n\n            Pos crane_curr_pos = current_state.cranes[k].pos;\n            int holding_id = current_state.cranes[k].holding_container_id;\n\n            // Priority 1: Deliver if holding the correct container at the dispatch gate\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                if (is_next_dispatch && crane_curr_pos.r == target_row && crane_curr_pos.c == N - 1) {\n                    current_turn_actions_char[k] = 'Q';\n                    target_next_crane_holding_planned[k] = -1; // Released\n                    // Container will be removed from board in step 3\n                    continue;\n                }\n            }\n\n            // If holding a container, move it towards its destination\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                Pos actual_target_dest = {target_row, (is_next_dispatch ? N - 1 : N - 2)};\n                \n                // Small crane handling for cross-row moves with cargo (drop at N/2 column)\n                if (!current_state.cranes[k].is_large && crane_curr_pos.r != target_row) {\n                    Pos release_mid_pos = {crane_curr_pos.r, N/2};\n                    if (crane_curr_pos == release_mid_pos) {\n                        current_turn_actions_char[k] = 'Q';\n                        target_next_crane_holding_planned[k] = -1; // Released\n                        current_state.container_locations[holding_id] = release_mid_pos; // Mark container's new location\n                    } else {\n                        // Move towards release_mid_pos\n                        int cost;\n                        Pos dir = get_next_step(current_state, k, crane_curr_pos, release_mid_pos, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                        if (cost != -1) {\n                            current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                            target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                        } else {\n                            current_turn_actions_char[k] = '.';\n                        }\n                    }\n                } else { // Large crane, or small crane already in correct row, or small crane not needing cross-row (i.e. only moving along row)\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, actual_target_dest, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n                continue; // Crane has a container, its action is determined\n            }\n\n            // If not holding a container, find a task\n            int best_cost = MAX_TURNS + 1; // High value\n            Pos best_pick_pos = {-1,-1};\n            int best_item_id = -1;\n            Pos best_release_pos = {-1,-1};\n            \n            // Helper for pathfinding cost\n            auto calculate_cost = [&](Pos target_for_pickup) {\n                int cost;\n                get_next_step(current_state, k, crane_curr_pos, target_for_pickup, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                return cost;\n            };\n            \n            // Check if a container is already targeted by a higher-priority crane or held\n            auto is_container_busy = [&](int container_id) {\n                if (container_id == -1) return true;\n                for (int j = 0; j < N; ++j) {\n                    if (current_state.cranes[j].id != k && current_state.cranes[j].holding_container_id == container_id) return true;\n                }\n                return false;\n            };\n\n            // Task search priorities (high to low):\n\n            // Option 1: Pick up 'next_dispatch_val'\n            for (int i = 0; i < N; ++i) {\n                int C = current_state.next_dispatch_val[i];\n                if (current_state.container_locations.count(C) && current_state.container_locations[C].r != -1) { // Container exists on board\n                    Pos c_pos = current_state.container_locations[C];\n                    if (is_container_busy(C)) continue;\n                    \n                    // Small crane can only pick up if container is in its row or large crane.\n                    if (!current_state.cranes[k].is_large && c_pos.r != k) continue;\n\n                    int cost = calculate_cost(c_pos);\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = c_pos;\n                        best_item_id = C;\n                        best_release_pos = {i, N-1}; // Ultimate destination\n                    }\n                }\n            }\n            \n            // Option 2: Clear receiving gate (row i, col 0)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.incoming_idx[i] < N && current_state.board[i][0] != -1) {\n                    int C = current_state.board[i][0];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,0});\n                    if (cost != -1 && cost < best_cost) { \n                        best_cost = cost;\n                        best_pick_pos = {i,0};\n                        best_item_id = C;\n                        // Determine temp release pos based on container's target row\n                        if (C/N == i) best_release_pos = {i,1}; // Stay in row, move right one cell\n                        else best_release_pos = {i, N/2}; // Move to middle column, large crane will pick up (handled by option 5 for large crane)\n                    }\n                }\n            }\n\n            // Option 3: Clear dispatch gate (row i, col N-1)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != current_state.next_dispatch_val[i]) {\n                    int C = current_state.board[i][N-1];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,N-1});\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = {i,N-1};\n                        best_item_id = C;\n                        // Determine temp release pos based on container's target row\n                        if (C/N == i) best_release_pos = {i,N-2}; // Stay in row, move left one cell\n                        else best_release_pos = {i, N/2}; // Move to middle column, large crane will pick up\n                    }\n                }\n            }\n            \n            // Option 4: Move container to its staging area (row, N-2) if in correct row but too far left\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N-2; ++c) { // Check cells to the left of N-2\n                    int C = current_state.board[r][c];\n                    if (C != -1 && C/N == r && C != current_state.next_dispatch_val[r]) {\n                        if (is_container_busy(C)) continue;\n\n                        // Small crane can only pick up if container is in its row\n                        if (!current_state.cranes[k].is_large && r != k) continue;\n\n                        int cost = calculate_cost({r,c});\n                        if (cost != -1 && cost < best_cost) {\n                            best_cost = cost;\n                            best_pick_pos = {r,c};\n                            best_item_id = C;\n                            best_release_pos = {r,N-2}; // Staging area for its own row\n                        }\n                    }\n                }\n            }\n\n            // Option 5: Move container to its row's middle column (C/N, N/2) - for cross-row moves (Large crane only).\n            if (current_state.cranes[k].is_large) { // Only large crane handles cross-row pickups\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        int C = current_state.board[r][c];\n                        if (C != -1 && C/N != r) { // Container in wrong row\n                            if (is_container_busy(C)) continue;\n                            int cost = calculate_cost({r,c});\n                            if (cost != -1 && cost < best_cost) {\n                                best_cost = cost;\n                                best_pick_pos = {r,c};\n                                best_item_id = C;\n                                best_release_pos = {C/N,N/2}; // Release in its target row's middle column\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Execute the chosen task\n            if (best_cost != MAX_TURNS + 1) { // A task was found\n                if (crane_curr_pos == best_pick_pos) {\n                    current_turn_actions_char[k] = 'P';\n                    target_next_crane_holding_planned[k] = best_item_id;\n                    current_state.container_locations[best_item_id] = {-1,-1}; // In crane's hand (not on board)\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, best_pick_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.'; // Should ideally not happen if best_cost was valid\n                    }\n                }\n            } else { // No urgent task, move to a parking spot\n                Pos parking_pos = current_state.cranes[k].is_large ? Pos{0, N/2} : Pos{k, 1}; // Large crane at center-top, small cranes at their row's column 1\n                if (crane_curr_pos == parking_pos) {\n                    current_turn_actions_char[k] = '.';\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, parking_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n            }\n        }\n\n        // Apply all planned actions\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) continue;\n\n            char action = current_turn_actions_char[k];\n            all_crane_actions[k] += action;\n\n            if (action == 'P') {\n                int container_id = current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c];\n                current_state.cranes[k].holding_container_id = container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = -1;\n            } else if (action == 'Q') {\n                int container_id = current_state.cranes[k].holding_container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = container_id;\n                current_state.cranes[k].holding_container_id = -1;\n                current_state.container_locations[container_id] = current_state.cranes[k].pos; // Container back on board\n            } else if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n                current_state.cranes[k].pos = target_next_crane_pos_planned[k];\n            }\n        }\n        \n        // 3. Dispatch containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] == current_state.next_dispatch_val[i]) {\n                int dispatched_id = current_state.board[i][N-1];\n                current_state.board[i][N-1] = -1;\n                current_state.container_locations.erase(dispatched_id); // Container removed from the game\n                current_state.next_dispatch_val[i]++;\n                dispatched_count++;\n            }\n        }\n    }\n\n    // Output results\n    for (int i = 0; i < N; ++i) {\n        cout << all_crane_actions[i] << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\n// N is fixed at 20 for this problem\nconst int N = 20;\n\n// Global variables to store the current state\nint H[N][N]; // Current heights of the grid cells\nint current_r = 0; // Current row of the dump truck\nint current_c = 0; // Current column of the dump truck\nlong long truck_load = 0; // Current amount of soil loaded on the truck\nstd::vector<std::string> ops; // Stores the sequence of operations\n\n// Calculates Manhattan distance between two cells\nlong long manhattan_dist(int r1, int c1, int r2, int c2) {\n    return std::abs(r1 - r2) + std::abs(c1 - c2);\n}\n\n// Moves the truck to the target coordinates and records the movement operations\nvoid move_truck_to(int target_r, int target_c) {\n    while (current_r < target_r) {\n        ops.push_back(\"D\");\n        current_r++;\n    }\n    while (current_r > target_r) {\n        ops.push_back(\"U\");\n        current_r--;\n    }\n    while (current_c < target_c) {\n        ops.push_back(\"R\");\n        current_c++;\n    }\n    while (current_c > target_c) {\n        ops.push_back(\"L\");\n        current_c--;\n    }\n}\n\n// Structure to hold cell coordinates and a calculated distance, used for sorting candidates\nstruct CandidateCell {\n    int r, c;\n    long long dist;\n\n    bool operator<(const CandidateCell& other) const {\n        return dist < other.dist;\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int dummy_N; // Read N, but it's fixed at 20\n    std::cin >> dummy_N;\n\n    long long total_initial_positive_soil = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> H[i][j];\n            if (H[i][j] > 0) {\n                total_initial_positive_soil += H[i][j];\n            }\n        }\n    }\n\n    long long soil_moved_to_level_sinks = 0; // Tracks the total soil moved to fulfill negative heights\n    const int K_CANDIDATES = 10; // Number of closest sources/sinks to consider for efficiency\n\n    // Timer for execution time limit\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds to be safe (total limit is 2.0 sec)\n\n    // Main loop: continues until all soil is leveled or operation/time limits are reached\n    while (soil_moved_to_level_sinks < total_initial_positive_soil) {\n        if (ops.size() >= 99000) { // Max 100000 turns, stop early to avoid exceeding\n            break;\n        }\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) {\n            break;\n        }\n\n        std::vector<CandidateCell> all_sources; // List of all cells with H > 0\n        std::vector<CandidateCell> all_sinks;   // List of all cells with H < 0\n\n        // Populate sources and sinks lists\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (H[i][j] > 0) {\n                    // For sources, calculate distance from current truck position\n                    all_sources.push_back({i, j, manhattan_dist(current_r, current_c, i, j)});\n                } else if (H[i][j] < 0) {\n                    // For sinks, distance will be calculated later from a potential source\n                    all_sinks.push_back({i, j, 0}); \n                }\n            }\n        }\n\n        // If no sources or sinks remain, the leveling is complete (or stuck)\n        if (all_sources.empty() || all_sinks.empty()) {\n            break;\n        }\n\n        // Sort sources by their distance from the current truck position\n        std::sort(all_sources.begin(), all_sources.end());\n\n        long long min_cost = -1; // Stores the minimum cost found for a transfer\n        int best_sr = -1, best_sc = -1, best_dr = -1, best_dc = -1; // Coordinates of the best source/sink\n        long long best_D = 0; // Amount of soil for the best transfer\n\n        // Iterate through a limited number of closest source candidates\n        int num_source_candidates = std::min((int)all_sources.size(), K_CANDIDATES);\n        for (int i = 0; i < num_source_candidates; ++i) {\n            int sr = all_sources[i].r;\n            int sc = all_sources[i].c;\n\n            // Create a temporary list of sinks, calculating their distance from the current source candidate\n            std::vector<CandidateCell> current_sink_candidates;\n            for (const auto& sink : all_sinks) {\n                current_sink_candidates.push_back({sink.r, sink.c, manhattan_dist(sr, sc, sink.r, sink.c)});\n            }\n            // Sort these sinks by their distance from the current source candidate\n            std::sort(current_sink_candidates.begin(), current_sink_candidates.end());\n\n            // Iterate through a limited number of closest sink candidates for this source\n            int num_sink_candidates = std::min((int)current_sink_candidates.size(), K_CANDIDATES);\n            for (int j = 0; j < num_sink_candidates; ++j) {\n                int dr = current_sink_candidates[j].r;\n                int dc = current_sink_candidates[j].c;\n\n                // Calculate the amount of soil to transfer: min of available at source and needed at sink\n                long long D = std::min((long long)H[sr][sc], -(long long)H[dr][dc]);\n                if (D <= 0) continue; // No actual transfer possible\n\n                // Calculate the total cost for this specific (source, sink, amount) transfer\n                long long cost_to_source = manhattan_dist(current_r, current_c, sr, sc) * 100LL;\n                long long cost_source_to_sink = manhattan_dist(sr, sc, dr, dc) * (100LL + D);\n                long long current_total_cost = cost_to_source + cost_source_to_sink + 2LL * D;\n\n                // Update if this transfer is cheaper than previously found ones\n                if (min_cost == -1 || current_total_cost < min_cost) {\n                    min_cost = current_total_cost;\n                    best_sr = sr; best_sc = sc;\n                    best_dr = dr; best_dc = dc;\n                    best_D = D;\n                }\n            }\n        }\n\n        // If no valid transfer was found in this iteration (min_cost still -1), break the loop\n        if (min_cost == -1) {\n            break;\n        }\n\n        // Execute the operations for the chosen best transfer\n        \n        // 1. Move truck to the best source\n        move_truck_to(best_sr, best_sc);\n        \n        // 2. Load soil\n        ops.push_back(\"+\" + std::to_string(best_D));\n        truck_load += best_D;\n        H[best_sr][best_sc] -= best_D; // Update source cell's height\n        \n        // 3. Move truck to the best sink\n        move_truck_to(best_dr, best_dc);\n        \n        // 4. Unload soil\n        ops.push_back(\"-\" + std::to_string(best_D));\n        truck_load -= best_D;\n        H[best_dr][best_dc] += best_D; // Update sink cell's height\n        soil_moved_to_level_sinks += best_D; // Increment total soil leveled\n    }\n\n    // Output all recorded operations\n    for (const std::string& op : ops) {\n        std::cout << op << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <cmath>   // For std::exp\n\n// --- Global variables for N, M, T and X_seeds ---\nint N_global, M_global, T_global;\nstd::vector<std::vector<int>> X_seeds_global; // Current seeds available for planting\n\n// --- RNG ---\n// Use std::mt19937_64 for potentially better randomness and larger range.\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper function to calculate potential for a pair ---\n// Returns the sum of max values for each criterion between two seeds.\n// seed_idx1 and seed_idx2 are indices into X_seeds_global.\nlong long calculate_pair_potential(int seed_idx1, int seed_idx2) {\n    long long potential = 0;\n    for (int l = 0; l < M_global; ++l) {\n        potential += std::max(X_seeds_global[seed_idx1][l], X_seeds_global[seed_idx2][l]);\n    }\n    return potential;\n}\n\n// --- Helper function to get adjacent coordinates ---\n// Returns a vector of {row, col} pairs for direct neighbors of (r, c).\nstd::vector<std::pair<int, int>> get_adjacent_coords(int r, int c) {\n    std::vector<std::pair<int, int>> adj;\n    int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n    int dc[] = {0, 0, -1, 1};\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_global && nc >= 0 && nc < N_global) {\n            adj.push_back({nr, nc});\n        }\n    }\n    return adj;\n}\n\n// --- Function to calculate total score for a grid configuration ---\n// Sum of potential values for all adjacent pairs in the grid.\nlong long calculate_grid_score(const std::vector<std::vector<int>>& A) {\n    long long total_score = 0;\n    // Horizontal adjacencies\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global - 1; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i][j+1]);\n        }\n    }\n    // Vertical adjacencies\n    for (int i = 0; i < N_global - 1; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i+1][j]);\n        }\n    }\n    return total_score;\n}\n\nvoid solve() {\n    std::cin >> N_global >> M_global >> T_global;\n\n    int seed_count = 2 * N_global * (N_global - 1);\n    X_seeds_global.resize(seed_count, std::vector<int>(M_global));\n\n    // Read initial seeds\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M_global; ++j) {\n            std::cin >> X_seeds_global[i][j];\n        }\n    }\n\n    // Main simulation loop for T turns\n    for (int turn = 0; turn < T_global; ++turn) {\n        // 1. Select seeds for planting:\n        // Calculate V_k for all current seeds and pick the top N*N.\n        std::vector<std::pair<long long, int>> seed_values(seed_count); // {V_k, seed_idx}\n        for (int i = 0; i < seed_count; ++i) {\n            long long current_Vk = 0;\n            for (int l = 0; l < M_global; ++l) {\n                current_Vk += X_seeds_global[i][l];\n            }\n            seed_values[i] = {current_Vk, i};\n        }\n        std::sort(seed_values.rbegin(), seed_values.rend()); // Sort descending by V_k\n\n        std::vector<int> selected_seeds_indices(N_global * N_global);\n        for (int i = 0; i < N_global * N_global; ++i) {\n            selected_seeds_indices[i] = seed_values[i].second;\n        }\n\n        // 2. Determine placement using Simulated Annealing\n        std::vector<std::vector<int>> current_A(N_global, std::vector<int>(N_global));\n        \n        // Initial placement for SA: random permutation of selected seeds\n        std::shuffle(selected_seeds_indices.begin(), selected_seeds_indices.end(), rng);\n        int k_idx = 0;\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                current_A[i][j] = selected_seeds_indices[k_idx++];\n            }\n        }\n\n        long long current_score = calculate_grid_score(current_A);\n        std::vector<std::vector<int>> best_A = current_A;\n        long long best_score = current_score;\n\n        // SA parameters (tuned for AHC035 constraints)\n        double start_temp = 20000.0; \n        double end_temp = 100.0;    \n        long long max_iterations = 200000; // Total iterations if no time limit hit\n        \n        // Time budget for SA loop (e.g., 180ms per turn to stay within 2s total)\n        auto start_time = std::chrono::high_resolution_clock::now();\n        std::chrono::milliseconds time_budget(180); \n\n        std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        std::uniform_int_distribution<int> dist_rc(0, N_global - 1); // For random row/col\n\n        for (long long iter = 0; iter < max_iterations; ++iter) {\n            // Check time budget\n            auto current_time = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time) > time_budget) {\n                break; \n            }\n\n            // Calculate current temperature\n            double temp = start_temp + (end_temp - start_temp) * iter / max_iterations;\n\n            // Pick two random distinct cells to swap\n            int r1 = dist_rc(rng);\n            int c1 = dist_rc(rng);\n            int r2 = dist_rc(rng);\n            int c2 = dist_rc(rng);\n            while (r1 == r2 && c1 == c2) { // Ensure distinct cells\n                r2 = dist_rc(rng);\n                c2 = dist_rc(rng);\n            }\n\n            int seed1_idx = current_A[r1][c1]; // Original seed at (r1,c1)\n            int seed2_idx = current_A[r2][c2]; // Original seed at (r2,c2)\n\n            // Calculate change in score (delta_score)\n            // We only need to consider neighbors not directly part of the (r1,c1)-(r2,c2) edge,\n            // as the potential value for that direct edge doesn't change due to a swap\n            // (calculate_pair_potential is symmetric).\n            long long old_adj_contrib = 0;\n            std::vector<std::pair<int, int>> neighbors_r1c1 = get_adjacent_coords(r1, c1);\n            std::vector<std::pair<int, int>> neighbors_r2c2 = get_adjacent_coords(r2, c2);\n\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { // Exclude (r2,c2) if it's a neighbor\n                    old_adj_contrib += calculate_pair_potential(seed1_idx, current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { // Exclude (r1,c1) if it's a neighbor\n                    old_adj_contrib += calculate_pair_potential(seed2_idx, current_A[p.first][p.second]);\n                }\n            }\n\n            // Temporarily perform the swap\n            current_A[r1][c1] = seed2_idx;\n            current_A[r2][c2] = seed1_idx;\n\n            long long new_adj_contrib = 0;\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { // Exclude (r2,c2) if it's a neighbor\n                    new_adj_contrib += calculate_pair_potential(current_A[r1][c1], current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { // Exclude (r1,c1) if it's a neighbor\n                    new_adj_contrib += calculate_pair_potential(current_A[r2][c2], current_A[p.first][p.second]);\n                }\n            }\n            \n            long long delta_score = new_adj_contrib - old_adj_contrib;\n            long long new_score = current_score + delta_score;\n\n            // Metropolis criterion for acceptance\n            if (new_score > current_score || dist_prob(rng) < std::exp(static_cast<double>(new_score - current_score) / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_A = current_A;\n                }\n            } else {\n                // Revert the swap if not accepted\n                current_A[r1][c1] = seed1_idx;\n                current_A[r2][c2] = seed2_idx;\n            }\n        }\n        \n        // Output the best placement found for this turn\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                std::cout << best_A[i][j];\n                if (j < N_global - 1) {\n                    std::cout << \" \";\n                } else {\n                    std::cout << std::endl;\n                }\n            }\n        }\n        std::cout.flush(); // Flush output to interactive judge\n\n        // 3. Read the new seeds for the next turn\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M_global; ++j) {\n                std::cin >> X_seeds_global[i][j];\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    solve();\n    \n    return 0;\n}\n","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for grid and problem parameters\nint N, M, V_MAX;\n\n// Current state of takoyaki (sources and targets)\nset<pair<int, int>> current_s_takoyaki; // Takoyaki that need to be picked up\nset<pair<int, int>> current_t_empty;    // Target squares that need takoyaki\n\n// Robotic arm state\nstruct Vec2 {\n    int x, y;\n    Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }\n    Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }\n    long long dist_sq(const Vec2& other) const { return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y); }\n};\n\nVec2 root_pos;\nvector<Vec2> rel_vecs; // relative position of vertex u to its parent p_u\nvector<int> orient_idx; // 0:right, 1:down, 2:left, 3:up (problem's definition)\n\n// For positions calculation\nvector<Vec2> abs_pos;\nvector<bool> is_fingertip;\nvector<int> parent_map; // parent_map[u] gives parent of u\nvector<int> L_map; // L_map[u] gives length of (parent[u], u)\n\nvector<bool> fingertip_holding; // Whether each fingertip is holding a takoyaki\n\n// PROBLEM_REL_DX, PROBLEM_REL_DY for cardinal directions (0:R, 1:D, 2:L, 3:U)\n// These define the (row_diff, col_diff) for a segment pointing in that direction.\n// R: (0,1)\n// D: (1,0)\n// L: (0,-1)\n// U: (-1,0)\nconst int PROBLEM_REL_DX[] = {0, 1, 0, -1}; \nconst int PROBLEM_REL_DY[] = {1, 0, -1, 0};\n\n// Rotate a vector (dx, dy) 90 degrees clockwise according to problem example: (L,0) -> (0,L)\nVec2 rotate_cw_problem(const Vec2& v) { return {v.y, v.x}; }\n// Rotate a vector (dx, dy) 90 degrees counter-clockwise according to problem example: (L,0) -> (0,-L)\nVec2 rotate_ccw_problem(const Vec2& v) { return {-v.y, -v.x}; }\n\n// Update absolute positions of all vertices\nvoid update_abs_pos() {\n    abs_pos[0] = root_pos;\n    for (size_t i = 1; i < abs_pos.size(); ++i) {\n        abs_pos[i] = abs_pos[parent_map[i]] + rel_vecs[i];\n    }\n}\n\n// Calculate centroid of a set of points\nVec2 calculate_centroid(const set<pair<int, int>>& points) {\n    if (points.empty()) {\n        return {-1, -1}; // Invalid centroid\n    }\n    long long sum_x = 0, sum_y = 0;\n    for (const auto& p : points) {\n        sum_x += p.first;\n        sum_y += p.second;\n    }\n    return {(int)round((double)sum_x / points.size()), (int)round((double)sum_y / points.size())};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> V_MAX;\n\n    set<pair<int, int>> initial_sources_raw; // To store original sources\n    set<pair<int, int>> target_goals_raw; // To store original targets\n\n    // Read initial takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                initial_sources_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Read target takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                target_goals_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Initialize current_s_takoyaki and current_t_empty by removing already satisfied takoyaki\n    current_s_takoyaki = initial_sources_raw;\n    current_t_empty = target_goals_raw;\n\n    for (auto it = current_t_empty.begin(); it != current_t_empty.end(); ) {\n        if (current_s_takoyaki.count(*it)) {\n            current_s_takoyaki.erase(*it);\n            it = current_t_empty.erase(it);\n        } else {\n            ++it;\n        }\n    }\n\n    // Design the robotic arm (V' = V_MAX, star graph, all edges length 1)\n    int V_prime = V_MAX; // Number of vertices in the arm\n    cout << V_prime << endl;\n\n    parent_map.resize(V_prime);\n    L_map.resize(V_prime);\n    is_fingertip.resize(V_prime, false);\n    \n    // Root is 0. Children 1 to V_prime-1 are fingertips.\n    for (int u = 1; u < V_prime; ++u) {\n        // Parent of u is 0, length 1\n        cout << 0 << \" \" << 1 << endl;\n        parent_map[u] = 0;\n        L_map[u] = 1; // All fingertips are length 1 away from root\n        is_fingertip[u] = true;\n    }\n\n    // Initial root position (center of the grid)\n    root_pos = {N / 2, N / 2};\n    cout << root_pos.x << \" \" << root_pos.y << endl;\n\n    // Initialize arm state\n    abs_pos.resize(V_prime);\n    rel_vecs.resize(V_prime);\n    orient_idx.resize(V_prime, 0); // All edges initially point right (direction 0)\n\n    for (int u = 1; u < V_prime; ++u) {\n        rel_vecs[u] = {L_map[u] * PROBLEM_REL_DX[0], L_map[u] * PROBLEM_REL_DY[0]}; // (L,0) for parent-child edge\n    }\n\n    fingertip_holding.resize(V_prime, false); // No fingertip holds takoyaki initially\n\n    // Operation loop\n    for (int turn = 0; turn < 100000; ++turn) {\n        if (current_t_empty.empty()) {\n            break; // All takoyaki delivered\n        }\n\n        // 1. Calculate absolute positions based on current root_pos and relative vectors\n        update_abs_pos();\n\n        // 2. Determine root movement\n        string command_root_move = \".\";\n        Vec2 target_centroid = {-1, -1};\n\n        int holding_count = 0;\n        for(int i=0; i<V_prime; ++i) if(is_fingertip[i] && fingertip_holding[i]) holding_count++;\n\n        if (holding_count > 0) { // If holding takoyaki, prioritize moving to target empty spots\n            target_centroid = calculate_centroid(current_t_empty);\n        } else { // If no takoyaki held, prioritize moving to source takoyaki\n            target_centroid = calculate_centroid(current_s_takoyaki);\n        }\n        \n        // If no target or source left, break or idle\n        if (target_centroid.x == -1) { \n            break; \n        }\n\n        int next_rx = root_pos.x;\n        int next_ry = root_pos.y;\n\n        int dx_diff = target_centroid.x - root_pos.x;\n        int dy_diff = target_centroid.y - root_pos.y;\n\n        // Prioritize moving along the larger difference axis\n        if (abs(dx_diff) >= abs(dy_diff)) {\n            if (dx_diff > 0) { // Move Down (increase row index)\n                if (root_pos.x + 1 < N) {\n                    next_rx = root_pos.x + 1;\n                    command_root_move = \"D\";\n                }\n            } else if (dx_diff < 0) { // Move Up (decrease row index)\n                if (root_pos.x - 1 >= 0) {\n                    next_rx = root_pos.x - 1;\n                    command_root_move = \"U\";\n                }\n            }\n        } \n        \n        // If no movement determined yet, try the other axis\n        if (command_root_move == \".\") { \n            if (dy_diff > 0) { // Move Right (increase col index)\n                if (root_pos.y + 1 < N) {\n                    next_ry = root_pos.y + 1;\n                    command_root_move = \"R\";\n                }\n            } else if (dy_diff < 0) { // Move Left (decrease col index)\n                if (root_pos.y - 1 >= 0) {\n                    next_ry = root_pos.y - 1;\n                    command_root_move = \"L\";\n                }\n            }\n        }\n\n        // Apply root movement\n        root_pos.x = next_rx;\n        root_pos.y = next_ry;\n        \n        // Update positions after root move (needed for rotation logic)\n        update_abs_pos();\n\n        // 3. Determine rotations\n        string command_rotations_str(V_prime - 1, '.'); // For non-root vertices (1 to V_prime-1)\n        vector<int> desired_orient_idx(V_prime, -1); // -1 means no specific rotation desired for this turn\n\n        // Prioritize placing takoyaki\n        // Try to assign holding fingertips to target squares\n        for (int d = 0; d < 4; ++d) { // For each cardinal direction (0:R, 1:D, 2:L, 3:U)\n            // Target cell one unit away from root in direction d\n            Vec2 target_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (target_cell.x >= 0 && target_cell.x < N && target_cell.y >= 0 && target_cell.y < N &&\n                current_t_empty.count({target_cell.x, target_cell.y})) {\n                \n                // Find a holding fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n\n        // Then assign empty fingertips to source squares\n        for (int d = 0; d < 4; ++d) {\n            // Source cell one unit away from root in direction d\n            Vec2 source_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (source_cell.x >= 0 && source_cell.x < N && source_cell.y >= 0 && source_cell.y < N &&\n                current_s_takoyaki.count({source_cell.x, source_cell.y})) {\n                \n                // Find an empty fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && !fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n        \n        // Apply rotations based on desired_orient_idx\n        for (int u = 1; u < V_prime; ++u) { // Only non-root vertices can rotate (fingertips in this design)\n            if (desired_orient_idx[u] != -1) {\n                int current_d = orient_idx[u];\n                int target_d = desired_orient_idx[u];\n\n                if (current_d == target_d) {\n                    command_rotations_str[u - 1] = '.'; // No rotation needed\n                } else {\n                    // Calculate shortest rotation path (1 step CW vs 1 step CCW)\n                    int cw_diff = (target_d - current_d + 4) % 4;\n                    int ccw_diff = (current_d - target_d + 4) % 4;\n\n                    if (cw_diff == 1) { // 90 deg CW\n                        command_rotations_str[u - 1] = 'R';\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else if (ccw_diff == 1) { // 90 deg CCW\n                        command_rotations_str[u - 1] = 'L';\n                        orient_idx[u] = (orient_idx[u] + 3) % 4;\n                        rel_vecs[u] = rotate_ccw_problem(rel_vecs[u]);\n                    } else if (cw_diff == 2) { // 180 deg, takes 2 turns. Pick one direction.\n                        command_rotations_str[u - 1] = 'R'; // Arbitrarily choose CW\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else { // Should not happen with 0-3 directions, but for safety\n                         command_rotations_str[u - 1] = '.';\n                    }\n                }\n            } else {\n                command_rotations_str[u - 1] = '.'; // No specific target, no rotation\n            }\n        }\n        \n        // Update positions after rotations\n        update_abs_pos();\n\n        // 4. Determine grab/release actions\n        string command_P_str(V_prime, '.'); // For all vertices, 0 to V_prime-1\n        \n        // Process fingertips in order of ID (1 to V_prime-1)\n        for (int u = 1; u < V_prime; ++u) { \n            // Vertex 0 (root) is not a fingertip, so its action is always '.'\n            // command_P_str[0] will remain '.'\n\n            Vec2 current_tip_pos = abs_pos[u];\n\n            // Check if fingertip is within grid boundaries\n            if (current_tip_pos.x < 0 || current_tip_pos.x >= N || current_tip_pos.y < 0 || current_tip_pos.y >= N) {\n                continue; // Fingertip outside grid, cannot act\n            }\n\n            if (fingertip_holding[u]) { // If currently holding a takoyaki\n                if (current_t_empty.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Place takoyaki on target square\n                    command_P_str[V_prime + u] = 'P'; // Action for vertex 'u' is at index V_prime + u\n                    current_t_empty.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = false;\n                }\n            } else { // If not holding a takoyaki\n                if (current_s_takoyaki.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Pick up takoyaki from source square\n                    command_P_str[V_prime + u] = 'P';\n                    current_s_takoyaki.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = true;\n                }\n            }\n        }\n        \n        // Output combined command string\n        // Format: [root_move_char][V_prime-1 rotation_chars][V_prime P_chars]\n        cout << command_root_move << command_rotations_str;\n        // The problem expects V' characters for P_actions, where index 0 is root, 1 to V'-1 are others.\n        // And the example shows command_P_str with V_prime-1 for non-root, and '.' for root.\n        // \"The (V' + i)-th character (0 <= i <= V'-1) represents the action of vertex i.\"\n        // This implies: S[V'] for vertex 0, S[V'+1] for vertex 1, etc.\n        cout << command_P_str[V_prime]; // Action for root (always '.')\n        for (int u = 1; u < V_prime; ++u) {\n            cout << command_P_str[V_prime + u]; // Actions for vertices 1 to V_prime-1\n        }\n        cout << endl;\n    }\n\n    return 0;\n}\n","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <set>\n#include <optional>\n\nusing namespace std;\n\n// Timer utility\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    double time_limit_ms;\n\n    Timer(double limit_ms) : time_limit_ms(limit_ms) {\n        start_time = chrono::high_resolution_clock::now();\n    }\n\n    bool is_time_up() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() >= time_limit_ms;\n    }\n\n    double get_elapsed_time_ms() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n    }\n};\n\n// Point structure\nstruct Point {\n    int x, y;\n};\n\n// Rectangle structure\nstruct Rect {\n    int x_min, y_min, x_max, y_max;\n    long long length() const {\n        if (x_min > x_max || y_min > y_max) return 0; // Degenerate rectangle has 0 length\n        return 2LL * (x_max - x_min) + 2LL * (y_max - y_min);\n    }\n};\n\n// Fenwick Tree (BIT) for 2D range sum queries\ntemplate <typename T>\nstruct FenwickTree2D {\n    int max_x_idx, max_y_idx;\n    vector<vector<T>> bit;\n\n    FenwickTree2D(int mx_idx, int my_idx) : max_x_idx(mx_idx), max_y_idx(my_idx) {\n        bit.assign(max_x_idx + 1, vector<T>(max_y_idx + 1, 0));\n    }\n\n    void update(int x, int y, T delta) {\n        for (int i = x + 1; i <= max_x_idx; i += i & -i) {\n            for (int j = y + 1; j <= max_y_idx; j += j & -j) {\n                bit[i][j] += delta;\n            }\n        }\n    }\n\n    T query(int x, int y) { // query sum from (0,0) to (x,y) inclusive\n        T sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i) {\n            for (int j = y + 1; j > 0; j -= j & -j) {\n                sum += bit[i][j];\n            }\n        }\n        return sum;\n    }\n\n    T query_rect_sum(int x1, int y1, int x2, int y2) { // query sum for [x1, x2] x [y1, y2] (compressed indices)\n        T sum = query(x2, y2);\n        if (x1 > 0) sum -= query(x1 - 1, y2);\n        if (y1 > 0) sum -= query(x2, y1 - 1);\n        if (x1 > 0 && y1 > 0) sum += query(x1 - 1, y1 - 1);\n        return sum;\n    }\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nvector<int> unique_xs, unique_ys;\nmap<int, int> x_to_idx, y_to_idx;\nFenwickTree2D<int>* ft_ptr = nullptr; // Pointer to FenwickTree2D\n\n// Score calculation wrapper for real coordinates using compressed FT\nlong long calculate_rect_score(const Rect& rect) {\n    if (rect.x_min >= rect.x_max || rect.y_min >= rect.y_max) return 0; // Degenerate or invalid rectangle (e.g., x_min=x_max)\n\n    auto it_x1 = lower_bound(unique_xs.begin(), unique_xs.end(), rect.x_min);\n    if (it_x1 == unique_xs.end()) return 0; \n    int x1_idx = distance(unique_xs.begin(), it_x1);\n\n    auto it_x2 = upper_bound(unique_xs.begin(), unique_xs.end(), rect.x_max);\n    if (it_x2 == unique_xs.begin()) return 0; \n    int x2_idx = distance(unique_xs.begin(), it_x2) - 1;\n\n    auto it_y1 = lower_bound(unique_ys.begin(), unique_ys.end(), rect.y_min);\n    if (it_y1 == unique_ys.end()) return 0; \n    int y1_idx = distance(unique_ys.begin(), it_y1);\n\n    auto it_y2 = upper_bound(unique_ys.begin(), unique_ys.end(), rect.y_max);\n    if (it_y2 == unique_ys.begin()) return 0; \n    int y2_idx = distance(unique_ys.begin(), it_y2) - 1;\n\n    if (x1_idx > x2_idx || y1_idx > y2_idx) return 0; \n\n    return ft_ptr->query_rect_sum(x1_idx, y1_idx, x2_idx, y2_idx);\n}\n\n// Polygon state for SA: a rectangle with an optional hole\nstruct PolygonState {\n    Rect outer;\n    optional<Rect> hole;\n    long long value; // Score (mackerels - sardines)\n    long long total_len; // Total length of edges\n    vector<Point> vertices; // Actual vertices for output\n\n    PolygonState() : value(0), total_len(0), outer({0,0,0,0}) {} // Default empty state\n\n    void calculate_polygon_data() {\n        if (outer.x_min >= outer.x_max || outer.y_min >= outer.y_max) { // Outer rect is invalid or degenerate\n            value = -1; // Indicate invalid state\n            total_len = 0;\n            vertices.clear();\n            return;\n        }\n        \n        long long outer_score = calculate_rect_score(outer);\n        long long hole_score = 0;\n\n        if (hole.has_value()) {\n            // Hole must be strictly inside outer rectangle\n            if (!(hole.value().x_min > outer.x_min && hole.value().x_max < outer.x_max &&\n                  hole.value().y_min > outer.y_min && hole.value().y_max < outer.y_max)) {\n                value = -1; // Invalid hole position\n                total_len = 0;\n                vertices.clear();\n                return;\n            }\n            hole_score = calculate_rect_score(hole.value());\n        }\n        \n        value = outer_score - hole_score;\n        total_len = outer.length() + (hole.has_value() ? hole.value().length() : 0);\n\n        // Generate vertices for output if valid and non-negative score (for initial output)\n        vertices.clear();\n        if (value >= 0) { // Only generate vertices if score is non-negative\n            // Outer rectangle vertices (CW)\n            vertices.push_back({outer.x_min, outer.y_min});\n            vertices.push_back({outer.x_max, outer.y_min});\n            vertices.push_back({outer.x_max, outer.y_max});\n            vertices.push_back({outer.x_min, outer.y_max});\n\n            if (hole.has_value()) {\n                // Hole rectangle vertices (CCW to define a hole, relative to outer CW)\n                vertices.push_back({hole.value().x_min, hole.value().y_min});\n                vertices.push_back({hole.value().x_min, hole.value().y_max});\n                vertices.push_back({hole.value().x_max, hole.value().y_max});\n                vertices.push_back({hole.value().x_max, hole.value().y_min});\n            }\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer(1900); // 1.9 seconds time limit\n\n    cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    set<int> x_coords_set, y_coords_set;\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        x_coords_set.insert(mackerels[i].x);\n        y_coords_set.insert(mackerels[i].y);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        x_coords_set.insert(sardines[i].x);\n        y_coords_set.insert(sardines[i].y);\n    }\n\n    // Coordinate compression\n    unique_xs.assign(x_coords_set.begin(), x_coords_set.end());\n    unique_ys.assign(y_coords_set.begin(), y_coords_set.end());\n\n    // Ensure 0 and 100000 are in unique_xs/ys as potential boundaries\n    if (unique_xs.empty() || unique_xs.front() != 0) { unique_xs.insert(unique_xs.begin(), 0); }\n    if (unique_xs.back() != 100000) { unique_xs.push_back(100000); }\n    if (unique_ys.empty() || unique_ys.front() != 0) { unique_ys.insert(unique_ys.begin(), 0); }\n    if (unique_ys.back() != 100000) { unique_ys.push_back(100000); }\n\n\n    for (int i = 0; i < unique_xs.size(); ++i) x_to_idx[unique_xs[i]] = i;\n    for (int i = 0; i < unique_ys.size(); ++i) y_to_idx[unique_ys[i]] = i;\n\n    // Initialize 2D Fenwick Tree\n    FenwickTree2D<int> ft(unique_xs.size(), unique_ys.size());\n    ft_ptr = &ft;\n\n    for (int i = 0; i < N; ++i) { // Mackerels\n        ft.update(x_to_idx[mackerels[i].x], y_to_idx[mackerels[i].y], 1);\n    }\n    for (int i = 0; i < N; ++i) { // Sardines\n        ft.update(x_to_idx[sardines[i].x], y_to_idx[sardines[i].y], -1);\n    }\n\n    // Initialize random number generator\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_idx_x(0, unique_xs.size() - 1);\n    uniform_int_distribution<int> rand_idx_y(0, unique_ys.size() - 1);\n    uniform_real_distribution<double> rand_prob(0.0, 1.0);\n    \n    // Initial solution: full map rectangle\n    PolygonState best_polygon;\n    best_polygon.outer = {0, 0, 100000, 100000};\n    best_polygon.calculate_polygon_data();\n    \n    // If full map rect is invalid or negative score, initialize with a tiny valid rect\n    if (best_polygon.value < 0 || best_polygon.total_len > 400000) {\n        best_polygon.outer = {0,0,1,1};\n        best_polygon.hole.reset();\n        best_polygon.calculate_polygon_data();\n    }\n\n    PolygonState current_polygon = best_polygon;\n\n    double T_start = 2000.0; // Initial temperature, roughly max expected value\n    double T_end = 1.0;     // Final temperature\n    long long iter_count = 0;\n    long long max_iterations = 200000; // Heuristic for average case\n\n    while (!timer.is_time_up() && iter_count < max_iterations) {\n        iter_count++;\n        PolygonState next_polygon = current_polygon;\n\n        // Randomly choose a move type\n        // 0: Modify outer, 1: Modify hole, 2: Remove hole, 3: Add hole\n        int move_type = uniform_int_distribution<int>(0, (current_polygon.hole.has_value() ? 3 : 2))(rng);\n        \n        if (move_type == 0) { // Modify outer rectangle\n            int dim_to_change = uniform_int_distribution<int>(0, 3)(rng);\n            int new_val_idx;\n            if (dim_to_change == 0) { // x_min\n                new_val_idx = rand_idx_x(rng);\n                next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max);\n            } else if (dim_to_change == 1) { // y_min\n                new_val_idx = rand_idx_y(rng);\n                next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max);\n            } else if (dim_to_change == 2) { // x_max\n                new_val_idx = rand_idx_x(rng);\n                next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min);\n            } else { // y_max\n                new_val_idx = rand_idx_y(rng);\n                next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min);\n            }\n        } else if (move_type == 1 && current_polygon.hole.has_value()) { // Modify inner hole\n            int dim_to_change = uniform_int_distribution<int>(0, 3)(rng);\n            int new_val_idx;\n            if (dim_to_change == 0) { // x_min\n                new_val_idx = rand_idx_x(rng);\n                next_polygon.hole.value().x_min = min(unique_xs[new_val_idx], next_polygon.hole.value().x_max);\n            } else if (dim_to_change == 1) { // y_min\n                new_val_idx = rand_idx_y(rng);\n                next_polygon.hole.value().y_min = min(unique_ys[new_val_idx], next_polygon.hole.value().y_max);\n            } else if (dim_to_change == 2) { // x_max\n                new_val_idx = rand_idx_x(rng);\n                next_polygon.hole.value().x_max = max(unique_xs[new_val_idx], next_polygon.hole.value().x_min);\n            } else { // y_max\n                new_val_idx = rand_idx_y(rng);\n                next_polygon.hole.value().y_max = max(unique_ys[new_val_idx], next_polygon.hole.value().y_min);\n            }\n        } else if (move_type == 2 && current_polygon.hole.has_value()) { // Remove hole\n            next_polygon.hole.reset();\n        } else { // Add hole (or try again to modify outer if no hole to remove)\n            if (!current_polygon.hole.has_value()) {\n                // Generate a random hole within current outer boundaries\n                int hx_min_idx = rand_idx_x(rng);\n                int hx_max_idx = rand_idx_x(rng);\n                int hy_min_idx = rand_idx_y(rng);\n                int hy_max_idx = rand_idx_y(rng);\n                \n                int hx_min = min(unique_xs[hx_min_idx], unique_xs[hx_max_idx]);\n                int hx_max = max(unique_xs[hx_min_idx], unique_xs[hx_max_idx]);\n                int hy_min = min(unique_ys[hy_min_idx], unique_ys[hy_max_idx]);\n                int hy_max = max(unique_ys[hy_min_idx], unique_ys[hy_max_idx]);\n                \n                // Ensure strictly inside outer polygon and valid size\n                hx_min = max(hx_min, next_polygon.outer.x_min + 1);\n                hx_max = min(hx_max, next_polygon.outer.x_max - 1);\n                hy_min = max(hy_min, next_polygon.outer.y_min + 1);\n                hy_max = min(hy_max, next_polygon.outer.y_max - 1);\n\n                if (hx_min < hx_max && hy_min < hy_max) {\n                    next_polygon.hole = Rect{hx_min, hy_min, hx_max, hy_max};\n                } else {\n                    // Invalid hole attempt, fallback to modify outer rectangle\n                    int dim_to_change = uniform_int_distribution<int>(0, 3)(rng);\n                    int new_val_idx;\n                    if (dim_to_change == 0) { // x_min\n                        new_val_idx = rand_idx_x(rng);\n                        next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max);\n                    } else if (dim_to_change == 1) { // y_min\n                        new_val_idx = rand_idx_y(rng);\n                        next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max);\n                    } else if (dim_to_change == 2) { // x_max\n                        new_val_idx = rand_idx_x(rng);\n                        next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min);\n                    } else { // y_max\n                        new_val_idx = rand_idx_y(rng);\n                        next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min);\n                    }\n                }\n            } else { // move_type was 3, but already has a hole. Fallback to modify outer.\n                int dim_to_change = uniform_int_distribution<int>(0, 3)(rng);\n                int new_val_idx;\n                if (dim_to_change == 0) { // x_min\n                    new_val_idx = rand_idx_x(rng);\n                    next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max);\n                } else if (dim_to_change == 1) { // y_min\n                    new_val_idx = rand_idx_y(rng);\n                    next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max);\n                } else if (dim_to_change == 2) { // x_max\n                    new_val_idx = rand_idx_x(rng);\n                    next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min);\n                } else { // y_max\n                    new_val_idx = rand_idx_y(rng);\n                    next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min);\n                }\n            }\n        }\n        \n        next_polygon.calculate_polygon_data();\n        \n        // Check validity: must have non-negative value and total length <= 4e5\n        if (next_polygon.value < 0 || next_polygon.total_len > 400000) {\n            continue; // Invalid move, try again\n        }\n\n        // Annealing acceptance probability\n        double current_temp = T_start * pow(T_end / T_start, timer.get_elapsed_time_ms() / timer.time_limit_ms);\n        double prob = 1.0;\n        if (next_polygon.value < current_polygon.value) {\n            prob = exp((double)(next_polygon.value - current_polygon.value) / current_temp);\n        }\n\n        if (rand_prob(rng) < prob) {\n            current_polygon = next_polygon;\n            if (current_polygon.value > best_polygon.value) {\n                best_polygon = current_polygon;\n            }\n        }\n    }\n\n    // Output the best polygon found\n    // If best_polygon.value is negative, problem's score will be max(0, -val + 1) = 1.\n    // In this case, output a default 1x1 polygon for safety and guaranteed distinct vertices.\n    if (best_polygon.value < 0) {\n        cout << 4 << endl;\n        cout << \"0 0\" << endl;\n        cout << \"1 0\" << endl;\n        cout << \"1 1\" << endl;\n        cout << \"0 1\" << endl;\n    } else {\n        cout << best_polygon.vertices.size() << endl;\n        for (const auto& v : best_polygon.vertices) {\n            cout << v.x << \" \" << v.y << endl;\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <map>\n#include <iomanip> // For std::fixed, std::setprecision\n#include <chrono> // For timing\n\n// Random number generator\nstd::mt19937 rng;\n\n// Global parameters from input\nint N_GLOBAL;\nint T_TOTAL_GLOBAL;\nlong long SIGMA_GLOBAL;\nstd::vector<long long> W_PRIME_GLOBAL, H_PRIME_GLOBAL; // Initial observed dimensions\n\n// Current estimates for true widths and heights, using double for precision\nstd::vector<double> current_estimated_w, current_estimated_h;\n\n// Struct to represent a single placement operation\nstruct Operation {\n    int p;     // Rectangle index (0 to N-1)\n    int r;     // Rotation (0: no, 1: 90-deg)\n    char d;    // Direction ('U' or 'L')\n    int b;     // Reference rectangle index (-1 for origin or 0 to p-1)\n};\n\n// Struct to store details of a rectangle after it's been placed\nstruct PlacedRectInfo {\n    long long x, y, w, h; // Coordinates and dimensions\n    int p_idx;             // Original index of the rectangle\n    bool rotated;          // True if rotated\n};\n\n// Helper function for random integer generation\nint random_int(int min, int max) {\n    std::uniform_int_distribution<int> dist(min, max);\n    return dist(rng);\n}\n\n// Helper function for random char selection\nchar random_char(char c1, char c2) {\n    return (random_int(0, 1) == 0) ? c1 : c2;\n}\n\n// Simulates the placement of rectangles given a set of operations and current dimension estimates.\n// Returns the predicted bounding box (W, H) and the detailed info of placed rectangles.\nstd::pair<std::pair<long long, long long>, std::vector<PlacedRectInfo>>\nsimulate_placement(const std::vector<Operation>& ops,\n                   const std::vector<double>& est_w,\n                   const std::vector<double>& est_h) {\n    \n    std::vector<PlacedRectInfo> placed_rect_infos;\n    std::map<int, PlacedRectInfo> p_idx_to_info; // Map from original rectangle index to its PlacedRectInfo\n\n    long long max_X = 0;\n    long long max_Y = 0;\n\n    for (const auto& op : ops) {\n        // Get estimated dimensions and apply rotation\n        long long current_w = static_cast<long long>(est_w[op.p]);\n        long long current_h = static_cast<long long>(est_h[op.p]);\n        \n        if (op.r == 1) { // Rotate 90 degrees\n            std::swap(current_w, current_h);\n        }\n\n        // Clamp dimensions to problem constraints [1, 10^9]\n        current_w = std::max(1LL, std::min(1000000000LL, current_w));\n        current_h = std::max(1LL, std::min(1000000000LL, current_h));\n\n        long long new_x = 0;\n        long long new_y = 0;\n\n        if (op.d == 'U') {\n            // Determine the x-coordinate of the left edge\n            long long target_x_left = 0;\n            if (op.b != -1) {\n                target_x_left = p_idx_to_info[op.b].x + p_idx_to_info[op.b].w;\n            }\n            new_x = target_x_left;\n\n            // Find the highest point (max y + h) that the new rectangle would sit on\n            long long y_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for horizontal overlap with placed_r\n                if (placed_r.x < new_x + current_w && placed_r.x + placed_r.w > new_x) {\n                    y_stop_level = std::max(y_stop_level, placed_r.y + placed_r.h);\n                }\n            }\n            new_y = y_stop_level;\n\n        } else { // op.d == 'L'\n            // Determine the y-coordinate of the top edge\n            long long target_y_top = 0;\n            if (op.b != -1) {\n                target_y_top = p_idx_to_info[op.b].y + p_idx_to_info[op.b].h;\n            }\n            new_y = target_y_top;\n\n            // Find the rightmost point (max x + w) that the new rectangle would push against\n            long long x_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for vertical overlap with placed_r\n                if (placed_r.y < new_y + current_h && placed_r.y + placed_r.h > new_y) {\n                    x_stop_level = std::max(x_stop_level, placed_r.x + placed_r.w);\n                }\n            }\n            new_x = x_stop_level;\n        }\n\n        // Store info for the newly placed rectangle\n        PlacedRectInfo info = {new_x, new_y, current_w, current_h, op.p, (op.r == 1)};\n        placed_rect_infos.push_back(info); // For tracking order of placement\n        p_idx_to_info[op.p] = info;      // For quick lookup by original index\n\n        // Update overall bounding box dimensions\n        max_X = std::max(max_X, new_x + current_w);\n        max_Y = std::max(max_Y, new_y + current_h);\n    }\n\n    return {{max_X, max_Y}, placed_rect_infos};\n}\n\n// Generates an initial random placement strategy\nstd::vector<Operation> generate_random_strategy(int N) {\n    std::vector<Operation> ops(N);\n    for (int i = 0; i < N; ++i) {\n        ops[i].p = i; // Always place rectangles in ascending order of their original indices\n        ops[i].r = random_int(0, 1);\n        ops[i].d = random_char('U', 'L');\n        ops[i].b = random_int(-1, i - 1); // Reference rectangle must be -1 or a previously placed index\n    }\n    return ops;\n}\n\n// Main solution function\nvoid solve() {\n    // Read initial N, T, sigma and rectangle measurements\n    std::cin >> N_GLOBAL >> T_TOTAL_GLOBAL >> SIGMA_GLOBAL;\n\n    W_PRIME_GLOBAL.resize(N_GLOBAL);\n    H_PRIME_GLOBAL.resize(N_GLOBAL);\n    current_estimated_w.resize(N_GLOBAL);\n    current_estimated_h.resize(N_GLOBAL);\n\n    for (int i = 0; i < N_GLOBAL; ++i) {\n        std::cin >> W_PRIME_GLOBAL[i] >> H_PRIME_GLOBAL[i];\n        current_estimated_w[i] = static_cast<double>(W_PRIME_GLOBAL[i]);\n        current_estimated_h[i] = static_cast<double>(H_PRIME_GLOBAL[i]);\n    }\n\n    // Initialize the best strategy found so far across all turns\n    std::vector<Operation> overall_best_ops = generate_random_strategy(N_GLOBAL);\n    auto initial_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n    long long overall_best_score_predicted = initial_sim_result.first.first + initial_sim_result.first.second;\n\n    // Time management for local search\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 2.9; // Allow some buffer for I/O and final calculations\n\n    for (int turn = 0; turn < T_TOTAL_GLOBAL; ++turn) {\n        // Current best strategy for this specific turn, initialized from overall best\n        std::vector<Operation> current_best_ops_this_turn = overall_best_ops;\n        long long current_best_score_this_turn = overall_best_score_predicted;\n\n        // Perform local search (hill climbing) for a fixed number of attempts\n        // This number is carefully chosen based on time limit and N^2 complexity of simulation.\n        const int NUM_LOCAL_SEARCH_ATTEMPTS = 50; \n\n        for (int iter = 0; iter < NUM_LOCAL_SEARCH_ATTEMPTS; ++iter) {\n            std::vector<Operation> candidate_ops = current_best_ops_this_turn; // Start from current best of this turn\n            int p_idx_to_change = random_int(0, N_GLOBAL - 1); // Pick a random rectangle to perturb\n\n            // Randomly choose one parameter to mutate\n            int mutate_type = random_int(0, 2); // 0: r (rotation), 1: d (direction), 2: b (reference)\n\n            if (mutate_type == 0) { // Mutate rotation\n                candidate_ops[p_idx_to_change].r = 1 - candidate_ops[p_idx_to_change].r;\n            } else if (mutate_type == 1) { // Mutate direction\n                candidate_ops[p_idx_to_change].d = (candidate_ops[p_idx_to_change].d == 'U' ? 'L' : 'U');\n            } else { // Mutate reference rectangle (b_i)\n                candidate_ops[p_idx_to_change].b = random_int(-1, p_idx_to_change - 1);\n            }\n\n            // Simulate the candidate strategy and evaluate its score\n            auto sim_result = simulate_placement(candidate_ops, current_estimated_w, current_estimated_h);\n            long long current_score = sim_result.first.first + sim_result.first.second;\n\n            // If the candidate is better, update the best for this turn\n            if (current_score < current_best_score_this_turn) {\n                current_best_ops_this_turn = candidate_ops;\n                current_best_score_this_turn = current_score;\n            }\n        }\n        \n        // After local search, if a better strategy was found for this turn, update the overall best\n        if (current_best_score_this_turn < overall_best_score_predicted) {\n            overall_best_ops = current_best_ops_this_turn;\n            overall_best_score_predicted = current_best_score_this_turn;\n        }\n\n        // Output the chosen (overall best) strategy for this turn\n        std::cout << N_GLOBAL << std::endl;\n        for (const auto& op : overall_best_ops) {\n            std::cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << std::endl;\n        }\n        std::cout << std::flush; // Crucial for interactive problems\n\n        // Read observed W' and H' from the judge\n        long long W_observed, H_observed;\n        std::cin >> W_observed >> H_observed;\n\n        // --- Update dimension estimates based on feedback ---\n        auto sim_result_for_update = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        long long W_predicted = sim_result_for_update.first.first;\n        long long H_predicted = sim_result_for_update.first.second;\n\n        // Calculate scaling ratios. Predicted W/H should not be zero since min_w/h is 1.\n        double W_ratio = static_cast<double>(W_observed) / W_predicted;\n        double H_ratio = static_cast<double>(H_observed) / H_predicted;\n\n        // Learning rate decreases over turns to stabilize estimates\n        double learn_rate = 0.05 / std::sqrt(turn + 1.0); \n        // Regularization rate to pull estimates back towards initial observations\n        double initial_reversion_rate = 0.01 / std::sqrt(turn + 1.0); \n\n        for (int i = 0; i < N_GLOBAL; ++i) {\n            // Adjust estimates based on observed vs. predicted global dimensions\n            current_estimated_w[i] += learn_rate * (W_ratio - 1.0) * current_estimated_w[i];\n            current_estimated_h[i] += learn_rate * (H_ratio - 1.0) * current_estimated_h[i];\n\n            // Regularize towards the initial noisy measurements w'_i, h'_i\n            current_estimated_w[i] = (1.0 - initial_reversion_rate) * current_estimated_w[i] + initial_reversion_rate * W_PRIME_GLOBAL[i];\n            current_estimated_h[i] = (1.0 - initial_reversion_rate) * current_estimated_h[i] + initial_reversion_rate * H_PRIME_GLOBAL[i];\n\n            // Clamp estimates within reasonable bounds (problem implies these max values)\n            current_estimated_w[i] = std::max(1.0, std::min(1000000000.0, current_estimated_w[i]));\n            current_estimated_h[i] = std::max(1.0, std::min(1000000000.0, current_estimated_h[i]));\n        }\n\n        // Re-calculate the overall best predicted score with the new estimates\n        overall_best_score_predicted = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.first + \n                                       simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.second;\n\n        // Check if remaining time is too low to continue effectively\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT_SECONDS) {\n            break; \n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for speed\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Seed the random number generator\n    // For local testing, a fixed seed like 0 is useful for reproducibility.\n    // For submission, using system time is standard to get different results for different test cases.\n    rng.seed(std::chrono::system_clock::now().time_since_epoch().count());\n\n    // Call the solver function\n    solve();\n\n    return 0;\n}\n","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <queue>\n#include <chrono>\n#include <random>\n// #include <map> // Not strictly needed, but included in thinking process\n\n// Global random number generator\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Structure to hold graph and problem data\nstruct ProblemData {\n    int N, M, H_limit;\n    std::vector<int> A;\n    std::vector<std::vector<int>> adj; // Adjacency list for the original graph\n    // Edges and coords are not used by the SA algorithm, but kept for completeness\n    std::vector<std::pair<int, int>> edges;\n    std::vector<std::pair<int, int>> coords;\n};\n\n// Structure to hold a solution candidate (parent array, score, heights)\nstruct Solution {\n    std::vector<int> parent;\n    long long score;\n    std::vector<int> heights; // Heights for current parent configuration\n\n    Solution(int N_val) : parent(N_val, -1), score(0), heights(N_val, -1) {}\n};\n\n// Function to evaluate a given parent array and compute heights\n// Returns score, and populates heights_out. Returns -1 for invalid states.\n// Invalid states include cycles or height constraint violations.\nlong long eval_score(const ProblemData& pd, const std::vector<int>& p, std::vector<int>& heights_out) {\n    int N = pd.N;\n    int H_limit = pd.H_limit;\n    const std::vector<int>& A = pd.A;\n\n    std::vector<std::vector<int>> children_lists(N);\n    std::vector<bool> is_root(N, true);\n    for (int v = 0; v < N; ++v) {\n        if (p[v] != -1) {\n            // Basic parent validity check (within bounds, not self)\n            // This is a safety check; forms_cycle and problem constraints should handle most of this.\n            if (p[v] < 0 || p[v] >= N || p[v] == v) { \n                return -1; // Invalid parent reference\n            }\n            children_lists[p[v]].push_back(v);\n            is_root[v] = false;\n        }\n    }\n\n    std::fill(heights_out.begin(), heights_out.end(), -1);\n    long long current_total_score = 0;\n    \n    // Use a queue for BFS\n    std::queue<int> q;\n\n    for (int r = 0; r < N; ++r) {\n        // If 'r' is a root and has not been processed yet (i.e., not part of another tree)\n        if (is_root[r] && heights_out[r] == -1) { \n            q.push(r);\n            heights_out[r] = 0;\n            current_total_score += (1LL * (heights_out[r] + 1) * A[r]);\n\n            while (!q.empty()) {\n                int u = q.front();\n                q.pop();\n\n                if (heights_out[u] > H_limit) { // Height constraint violation for this tree\n                    return -1;\n                }\n\n                for (int v_child : children_lists[u]) {\n                    if (heights_out[v_child] == -1) { // If not yet visited in this tree\n                        heights_out[v_child] = heights_out[u] + 1;\n                        if (heights_out[v_child] > H_limit) { // Height constraint violation\n                            return -1;\n                        }\n                        current_total_score += (1LL * (heights_out[v_child] + 1) * A[v_child]);\n                        q.push(v_child);\n                    } else {\n                        // This case implies a cycle or a structural inconsistency in the parent array.\n                        // The forms_cycle check should catch most ancestor-descendant cycles.\n                        // Any remaining detected cycle would make this an invalid forest.\n                        return -1; \n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure all nodes have been assigned a height (i.e., are part of some tree).\n    // If any node remains with heights_out[v] == -1, it means the parent array 'p'\n    // does not form a spanning forest. This shouldn't happen for a valid set of parents.\n    for(int v = 0; v < N; ++v){\n        if(heights_out[v] == -1){\n            return -1; // Indicates a disjoint node/subgraph not correctly rooted or parented\n        }\n    }\n\n    return current_total_score;\n}\n\n// Function to check for cycles efficiently during a proposed parent change\n// Returns true if new_p is an ancestor of v (which means setting parent[v] = new_p forms a cycle)\nbool forms_cycle(int v, int new_p, const std::vector<int>& current_p, const ProblemData& pd) {\n    if (new_p == -1) return false;\n\n    // Traverse up from new_p using current parent pointers\n    int curr = new_p;\n    for(int i = 0; i <= pd.H_limit + 1 && curr != -1; ++i) { \n        if (curr == v) {\n            return true; // Found v, so v is an ancestor of new_p, forms a cycle\n        }\n        curr = current_p[curr];\n    }\n    return false; // No cycle detected within the typical height limit\n}\n\nvoid solve() {\n    ProblemData pd;\n    std::cin >> pd.N >> pd.M >> pd.H_limit;\n    pd.A.resize(pd.N);\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.A[i];\n    pd.adj.resize(pd.N);\n    pd.edges.resize(pd.M); // Not strictly used by this SA approach, but might be useful for other heuristics\n    for (int i = 0; i < pd.M; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        pd.adj[u].push_back(v);\n        pd.adj[v].push_back(u);\n        pd.edges[i] = {u, v}; \n    }\n    pd.coords.resize(pd.N); // Not used by this SA approach\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.coords[i].first >> pd.coords[i].second;\n\n    // Initial solution: all nodes are roots\n    Solution current_sol(pd.N);\n    current_sol.score = eval_score(pd, current_sol.parent, current_sol.heights);\n    if (current_sol.score == -1) { // This should ideally not happen for the initial \"all roots\" state if N > 0\n                                   // But if N=0 or other weird inputs, better handle it.\n                                   // For N > 0, an initial state of all roots is always valid.\n        current_sol.score = std::accumulate(pd.A.begin(), pd.A.end(), 0LL); // Min score (all roots, h=0)\n        std::fill(current_sol.heights.begin(), current_sol.heights.end(), 0);\n    }\n\n    Solution best_sol = current_sol;\n\n    // Simulated Annealing parameters\n    // Using time-based annealing\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Slightly less than 2 seconds to be safe\n    double start_temp = 500.0;           // Initial temperature (adjust based on problem scale)\n    double end_temp = 1.0;               // Final temperature\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n\n    // Main Simulated Annealing loop\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration<double, std::milli>(current_time - start_time).count();\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            break;\n        }\n\n        double progress = elapsed_ms / TIME_LIMIT_MS;\n        double temp = start_temp * (1.0 - progress) + end_temp * progress; // Linear cooling\n\n        // Choose a random vertex to modify\n        int v = rng() % pd.N;\n\n        // Store original parent of v, so we can revert if the move is rejected\n        int original_p_v = current_sol.parent[v];\n        \n        // Generate candidate parents: -1 (make root) and all neighbors of v\n        std::vector<int> candidate_parents;\n        candidate_parents.push_back(-1); // Option to make v a root\n        for (int neighbor : pd.adj[v]) {\n            // Ensure neighbor is not v itself (shouldn't happen for simple graphs, but safe check)\n            if (neighbor != v) { \n                candidate_parents.push_back(neighbor);\n            }\n        }\n\n        // Pick a random candidate parent\n        int new_p = candidate_parents[rng() % candidate_parents.size()];\n        \n        // Temporarily apply the move\n        current_sol.parent[v] = new_p;\n\n        // Check for cycles *before* full evaluation to save time\n        if (forms_cycle(v, new_p, current_sol.parent, pd)) {\n             current_sol.parent[v] = original_p_v; // Revert\n             continue; // Invalid move due to cycle, try next iteration\n        }\n        \n        // Evaluate the new state\n        std::vector<int> new_heights(pd.N);\n        long long new_score = eval_score(pd, current_sol.parent, new_heights);\n\n        if (new_score != -1) { // Valid move (no height limit violation or structural error)\n            if (new_score > best_sol.score) {\n                best_sol.score = new_score;\n                best_sol.parent = current_sol.parent;\n                best_sol.heights = new_heights; // Store heights (optional, for analysis)\n            }\n\n            // Simulated Annealing acceptance condition\n            if (new_score > current_sol.score || \n                dist_0_1(rng) < std::exp((double)(new_score - current_sol.score) / temp)) {\n                \n                current_sol.score = new_score;\n                current_sol.heights = new_heights;\n            } else {\n                // Revert the change (move rejected)\n                current_sol.parent[v] = original_p_v;\n            }\n        } else {\n            // Revert the change (invalid move due to height limit or structural error)\n            current_sol.parent[v] = original_p_v;\n        }\n    }\n\n    // Output the best solution found\n    for (int i = 0; i < pd.N; ++i) {\n        std::cout << best_sol.parent[i] << (i == pd.N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <utility> // For std::pair\n\n// Structure to store an operation\nstruct Operation {\n    char direction;\n    int index;\n\n    Operation(char d, int i) : direction(d), index(i) {}\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N;\n    std::cin >> N;\n\n    // Store initial Fukunokami positions for constant lookup, as they never move\n    std::set<std::pair<int, int>> fuku_positions_set;\n    // Store current Oni positions. This set will be modified as Oni are removed.\n    std::set<std::pair<int, int>> current_oni_positions_set;\n\n    for (int i = 0; i < N; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                current_oni_positions_set.insert({i, j});\n            } else if (row_str[j] == 'o') {\n                fuku_positions_set.insert({i, j});\n            }\n        }\n    }\n\n    std::vector<Operation> operations;\n\n    // Continue as long as there are Oni on the board\n    while (!current_oni_positions_set.empty()) {\n        int min_moves_overall = 1e9 + 7; // Initialize with a very large number\n        std::pair<int, int> best_oni_to_target = {-1, -1};\n        char chosen_direction = ' ';\n        int chosen_index = -1;\n        \n        // Iterate through all currently present Oni to find the one that can be removed\n        // with the minimum number of operations.\n        for (const auto& oni_pos : current_oni_positions_set) {\n            int r = oni_pos.first;\n            int c = oni_pos.second;\n\n            int min_moves_for_this_oni = 1e9 + 7;\n            char best_direction_for_this_oni = ' ';\n            int best_index_for_this_oni = -1;\n\n            // Check upward path for Fukunokami\n            bool up_clear = true;\n            for (int k = 0; k < r; ++k) {\n                if (fuku_positions_set.count({k, c})) {\n                    up_clear = false;\n                    break;\n                }\n            }\n            if (up_clear) {\n                int moves = 2 * (r + 1);\n                // Use '<' to prioritize U/D/L/R in order if counts are equal (arbitrary tie-breaking)\n                if (moves < min_moves_for_this_oni) { \n                    min_moves_for_this_oni = moves;\n                    best_direction_for_this_oni = 'U';\n                    best_index_for_this_oni = c;\n                }\n            }\n\n            // Check downward path for Fukunokami\n            bool down_clear = true;\n            for (int k = r + 1; k < N; ++k) {\n                if (fuku_positions_set.count({k, c})) {\n                    down_clear = false;\n                    break;\n                }\n            }\n            if (down_clear) {\n                int moves = 2 * (N - r);\n                if (moves < min_moves_for_this_oni) { \n                    min_moves_for_this_oni = moves;\n                    best_direction_for_this_oni = 'D';\n                    best_index_for_this_oni = c;\n                }\n            }\n\n            // Check leftward path for Fukunokami\n            bool left_clear = true;\n            for (int k = 0; k < c; ++k) {\n                if (fuku_positions_set.count({r, k})) {\n                    left_clear = false;\n                    break;\n                }\n            }\n            if (left_clear) {\n                int moves = 2 * (c + 1);\n                if (moves < min_moves_for_this_oni) {\n                    min_moves_for_this_oni = moves;\n                    best_direction_for_this_oni = 'L';\n                    best_index_for_this_oni = r;\n                }\n            }\n\n            // Check rightward path for Fukunokami\n            bool right_clear = true;\n            for (int k = c + 1; k < N; ++k) {\n                if (fuku_positions_set.count({r, k})) {\n                    right_clear = false;\n                    break;\n                }\n            }\n            if (right_clear) {\n                int moves = 2 * (N - c);\n                if (moves < min_moves_for_this_oni) {\n                    min_moves_for_this_oni = moves;\n                    best_direction_for_this_oni = 'R';\n                    best_index_for_this_oni = r;\n                }\n            }\n            \n            // Update overall best Oni to remove\n            if (min_moves_for_this_oni < min_moves_overall) {\n                min_moves_overall = min_moves_for_this_oni;\n                best_oni_to_target = oni_pos;\n                chosen_direction = best_direction_for_this_oni;\n                chosen_index = best_index_for_this_oni;\n            }\n        } // End loop over current_oni_positions_set\n\n        // Now, perform the operations for the chosen Oni and update the set of Oni\n        int r = best_oni_to_target.first;\n        int c = best_oni_to_target.second;\n\n        if (chosen_direction == 'U') {\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('U', chosen_index);\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('D', chosen_index);\n            // Remove Oni in the cleared path (from row 0 up to and including r, in column chosen_index)\n            for(int k_row = 0; k_row <= r; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'D') {\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('D', chosen_index);\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('U', chosen_index);\n            // Remove Oni in the cleared path (from row r down to and including N-1, in column chosen_index)\n            for(int k_row = r; k_row < N; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'L') {\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('L', chosen_index);\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('R', chosen_index);\n            // Remove Oni in the cleared path (from col 0 up to and including c, in row chosen_index)\n            for(int k_col = 0; k_col <= c; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        } else if (chosen_direction == 'R') {\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('R', chosen_index);\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('L', chosen_index);\n            // Remove Oni in the cleared path (from col c down to and including N-1, in row chosen_index)\n            for(int k_col = c; k_col < N; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        }\n        // The problem guarantee ensures that min_moves_for_this_oni will always be updated\n        // and chosen_direction will not remain ' '.\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        std::cout << op.direction << \" \" << op.index << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric> // For std::accumulate\n#include <cmath>   // For std::abs, std::pow, std::exp\n#include <random>  // For std::mt19937, std::uniform_int_distribution, std::uniform_real_distribution\n#include <chrono>  // For high_resolution_clock\n#include <map>     // For cycle detection\n#include <algorithm> // For std::min (though not strictly used, good practice)\n\n// Use a global random number generator for convenience and efficiency\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Function to calculate the error for a given assignment\n// N: Number of employees\n// L: Total number of weeks\n// T: Target cleaning counts for each employee\n// assignments: Vector of pairs (a_i, b_i) for each employee i\nlong long calculate_error(\n    int N, int L, \n    const std::vector<int>& T, \n    const std::vector<std::pair<int, int>>& assignments\n) {\n    std::vector<long long> actual_final_counts(N, 0); // Stores the final cleaning counts for each employee\n\n    int current_cleaner = 0; // The employee who cleans in the current week (starts with employee 0)\n    // counts_in_sim tracks cleaning counts *during this specific simulation run* for cycle detection\n    std::vector<int> counts_in_sim(N, 0); \n    \n    // For cycle detection:\n    // path_cleaners stores the sequence of employees who cleaned, week by week (0-indexed)\n    std::vector<int> path_cleaners; \n    // visited_states_map maps (cleaner_id, count_parity) -> week_idx (the first week_idx this state was observed)\n    std::map<std::pair<int, int>, int> visited_states_map; \n\n    for (int week_idx = 0; week_idx < L; ++week_idx) {\n        int cleaner_for_this_week = current_cleaner;\n        counts_in_sim[cleaner_for_this_week]++; // Increment count for the current cleaner\n        path_cleaners.push_back(cleaner_for_this_week); // Record this week's cleaner\n\n        // A state is defined by (employee who just finished cleaning, their total cleaning count parity)\n        std::pair<int, int> state_after_cleaning = {cleaner_for_this_week, counts_in_sim[cleaner_for_this_week] % 2};\n\n        // Check if this state has been visited before, indicating a cycle\n        if (visited_states_map.count(state_after_cleaning)) {\n            int cycle_start_idx = visited_states_map[state_after_cleaning]; // Index where the cycle began\n            int cycle_length = week_idx - cycle_start_idx + 1;             // Length of the detected cycle\n\n            // Step 1: Accumulate counts for the pre-cycle part (weeks 0 to cycle_start_idx-1)\n            for (int i = 0; i < cycle_start_idx; ++i) {\n                actual_final_counts[path_cleaners[i]]++;\n            }\n\n            // Step 2: Calculate cleaning counts within one full cycle period\n            std::vector<long long> cycle_counts_one_period(N, 0);\n            for (int i = cycle_start_idx; i <= week_idx; ++i) {\n                cycle_counts_one_period[path_cleaners[i]]++;\n            }\n\n            // Step 3: Distribute remaining weeks using the cycle counts\n            // Total weeks that need to be covered by the cycle from cycle_start_idx until L\n            long long remaining_weeks_to_fill_from_cycle_start = L - cycle_start_idx;\n            \n            if (cycle_length > 0) { // Safety check to prevent division by zero, though cycle_length should always be > 0\n                // Add full cycles\n                long long num_full_cycles = remaining_weeks_to_fill_from_cycle_start / cycle_length;\n                for (int i = 0; i < N; ++i) {\n                    actual_final_counts[i] += num_full_cycles * cycle_counts_one_period[i];\n                }\n                // Add remaining part of a partial cycle at the very end\n                long long remaining_in_partial_cycle = remaining_weeks_to_fill_from_cycle_start % cycle_length;\n                for (int i = 0; i < remaining_in_partial_cycle; ++i) {\n                    actual_final_counts[path_cleaners[cycle_start_idx + i]]++;\n                }\n            }\n            \n            // All L weeks have been accounted for, so we can exit the simulation\n            goto end_simulation; \n        }\n        \n        // If no cycle detected yet, record the current state and its week index\n        visited_states_map[state_after_cleaning] = week_idx;\n\n        // Determine the next cleaner based on current cleaner's count parity and assignments\n        if (counts_in_sim[cleaner_for_this_week] % 2 != 0) { // If total count is odd\n            current_cleaner = assignments[cleaner_for_this_week].first;\n        } else { // If total count is even\n            current_cleaner = assignments[cleaner_for_this_week].second;\n        }\n    }\n\n    // This block is reached if the loop completes without finding a cycle.\n    // This happens if L is small enough that no state repeats, or if L happens to be exactly the pre-cycle length.\n    // In this case, 'path_cleaners' contains the cleaners for all L weeks, and their counts\n    // haven't been added to 'actual_final_counts' yet.\n    for (int i = 0; i < L; ++i) {\n        actual_final_counts[path_cleaners[i]]++;\n    }\n\nend_simulation:; // Label for goto\n\n    // Calculate the total absolute error\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += std::abs(actual_final_counts[i] - T[i]);\n    }\n    return error;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_val, L_val; // Use different variable names to avoid potential shadowing\n    std::cin >> N_val >> L_val;\n\n    std::vector<int> T(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        std::cin >> T[i];\n    }\n\n    std::vector<std::pair<int, int>> best_assignments(N_val);\n    std::vector<std::pair<int, int>> current_assignments(N_val);\n\n    // Initial random assignments for a_i and b_i\n    std::uniform_int_distribution<int> dist_N(0, N_val - 1); // For picking employee IDs [0, N-1]\n    for (int i = 0; i < N_val; ++i) {\n        current_assignments[i] = {dist_N(rng), dist_N(rng)};\n    }\n\n    // Calculate initial state error\n    long long current_error = calculate_error(N_val, L_val, T, current_assignments);\n    long long best_error = current_error;\n    best_assignments = current_assignments; // Deep copy the initial best state\n\n    // Simulated Annealing parameters\n    double start_temp = 2000.0; // Initial temperature (can be tuned)\n    double end_temp = 0.01;     // Final temperature (can be tuned)\n    int iteration_limit = 1000000; // Maximum number of SA iterations (will be capped by time)\n    \n    auto start_time = std::chrono::high_resolution_clock::now();\n    long long time_limit_ms = 1900; // Allot 1.9 seconds for computation, leave 0.1s buffer\n\n    for (int iter = 0; iter < iteration_limit; ++iter) {\n        // Check elapsed time to ensure compliance with the time limit\n        auto current_time = std::chrono::high_resolution_clock::now();\n        long long elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break; // Exit SA loop if time limit approached\n        }\n\n        // Geometric cooling schedule for temperature\n        double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / iteration_limit);\n        \n        // Generate a neighbor state by modifying one a_i or b_i\n        int employee_to_change = dist_N(rng); // Randomly pick an employee\n        bool change_first_val = (rng() % 2 == 0); // Randomly decide to change a_i (true) or b_i (false)\n        \n        // Store the original value to allow reverting if the move is not accepted\n        int original_val_to_revert;\n        if (change_first_val) {\n            original_val_to_revert = current_assignments[employee_to_change].first;\n            current_assignments[employee_to_change].first = dist_N(rng); // Propose a new random value\n        } else {\n            original_val_to_revert = current_assignments[employee_to_change].second;\n            current_assignments[employee_to_change].second = dist_N(rng); // Propose a new random value\n        }\n\n        // Calculate the error for the new (modified) assignments\n        long long next_error = calculate_error(N_val, L_val, T, current_assignments);\n\n        if (next_error < current_error) {\n            // If the new solution is better, always accept it\n            current_error = next_error;\n            if (next_error < best_error) {\n                // If it's the best solution found so far, update best_assignments\n                best_error = next_error;\n                best_assignments = current_assignments; // Deep copy\n            }\n        } else {\n            // If the new solution is worse, accept it with a certain probability\n            double probability = std::exp(-(static_cast<double>(next_error - current_error)) / temp);\n            std::uniform_real_distribution<double> dist_real(0.0, 1.0); // For generating a random probability\n            if (dist_real(rng) < probability) {\n                current_error = next_error; // Accept the worse solution\n            } else {\n                // If the worse solution is not accepted, revert the change\n                if (change_first_val) {\n                    current_assignments[employee_to_change].first = original_val_to_revert;\n                } else {\n                    current_assignments[employee_to_change].second = original_val_to_revert;\n                }\n            }\n        }\n    }\n\n    // Output the best assignments found after the SA process\n    for (int i = 0; i < N_val; ++i) {\n        std::cout << best_assignments[i].first << \" \" << best_assignments[i].second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <cmath> // For round, sqrt\n\n// Structure to hold city bounding box\nstruct Rect {\n    int lx, rx, ly, ry;\n};\n\n// Structure to hold city data\nstruct City {\n    int id;\n    int cx, cy; // Center coordinates, using integer division for consistency with sample\n    Rect bounds;\n};\n\n// Disjoint Set Union structure for Kruskal's algorithm\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) return i;\n        return parent[i] = find(parent[i]);\n    }\n    bool 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            return true;\n        }\n        return false;\n    }\n};\n\n// Edge structure for Kruskal's\nstruct Edge {\n    int u, v;\n    std::pair<int, long long> weight; // rank (0=queried, 1=estimated), estimated_dist_sq\n};\n\n// Function to calculate estimated squared distance using center coordinates\nlong long estimated_dist_sq(int u_idx, int v_idx, const std::vector<City>& cities_data) {\n    long long dx = (long long)cities_data[u_idx].cx - cities_data[v_idx].cx;\n    long long dy = (long long)cities_data[u_idx].cy - cities_data[v_idx].cy;\n    return dx * dx + dy * dy;\n}\n\n// Function to make a query to the judge\nstd::vector<std::pair<int, int>> make_query(const std::vector<int>& c_subset) {\n    std::cout << \"? \" << c_subset.size();\n    for (int city_id : c_subset) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl; // Flush!\n\n    std::vector<std::pair<int, int>> result;\n    result.reserve(c_subset.size() - 1);\n    for (size_t i = 0; i < c_subset.size() - 1; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        if (u > v) std::swap(u, v); // Ensure canonical form (u < v)\n        result.push_back({u, v});\n    }\n    return result;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL); // Untie cin and cout for faster I/O, though flushing is still needed for queries\n\n    int N, M, Q, L_actual, W;\n    std::cin >> N >> M >> Q >> L_actual >> 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_data(N);\n    for (int i = 0; i < N; ++i) {\n        cities_data[i].id = i;\n        std::cin >> cities_data[i].bounds.lx >> cities_data[i].bounds.rx >> cities_data[i].bounds.ly >> cities_data[i].bounds.ry;\n        cities_data[i].cx = (cities_data[i].bounds.lx + cities_data[i].bounds.rx) / 2;\n        cities_data[i].cy = (cities_data[i].bounds.ly + cities_data[i].bounds.ry) / 2;\n    }\n\n    // 1. Initial Grouping: Sort by cx, then cy\n    std::vector<int> p(N); // p stores sorted city IDs\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        if (cities_data[i].cx != cities_data[j].cx) return cities_data[i].cx < cities_data[j].cx;\n        return cities_data[i].cy < cities_data[j].cy;\n    });\n\n    std::vector<std::vector<int>> tentative_groups(M);\n    int current_city_idx_p = 0;\n    for (int k = 0; k < M; ++k) {\n        tentative_groups[k].reserve(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            tentative_groups[k].push_back(p[current_city_idx_p++]);\n        }\n    }\n\n    // 2. Query Phase\n    std::set<std::pair<int, int>> queried_edges;\n    int Q_rem = Q;\n\n    // Phase 1: Query small groups entirely\n    for (int k = 0; k < M; ++k) {\n        if (G[k] >= 2 && G[k] <= L_actual && Q_rem > 0) {\n            std::vector<int> current_group = tentative_groups[k];\n            std::vector<std::pair<int, int>> res_edges = make_query(current_group);\n            for (auto edge : res_edges) {\n                queried_edges.insert(edge);\n            }\n            Q_rem--;\n        }\n    }\n\n    // Phase 2: Query large groups with adaptive step_size\n    long long num_chunks_to_query_if_step1 = 0; // Total count of (G_k - L_actual + 1) for large groups\n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual) {\n            num_chunks_to_query_if_step1 += (G[k] - L_actual + 1);\n        }\n    }\n\n    int step_size = 1;\n    if (Q_rem > 0 && num_chunks_to_query_if_step1 > 0) {\n        step_size = (num_chunks_to_query_if_step1 + Q_rem - 1) / Q_rem;\n        step_size = std::max(1, step_size); // Ensure step_size is at least 1\n    } else {\n        step_size = N + 1; // Effectively skip this phase if no queries left or no large groups\n    }\n    \n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k];\n            int last_queried_start = -1; // To track the starting index of the last query made\n            \n            for (int i = 0; i <= (int)current_group.size() - L_actual; i += step_size) {\n                if (Q_rem <= 0) break;\n                \n                std::vector<int> c_subset;\n                c_subset.reserve(L_actual);\n                for (int j = 0; j < L_actual; ++j) {\n                    c_subset.push_back(current_group[i+j]);\n                }\n                \n                std::vector<std::pair<int, int>> res_edges = make_query(c_subset);\n                for (auto edge : res_edges) {\n                    queried_edges.insert(edge);\n                }\n                Q_rem--;\n                last_queried_start = i;\n            }\n\n            // Handle cities at the end of the group that might not have been fully covered\n            // Query the last L_actual cities if the last possible window was not queried\n            if (Q_rem > 0 && current_group.size() >= L_actual) {\n                int ideal_last_start_idx = (int)current_group.size() - L_actual;\n                if (last_queried_start != ideal_last_start_idx) {\n                    std::vector<int> c_subset_end;\n                    c_subset_end.reserve(L_actual);\n                    for(int j = ideal_last_start_idx; j < current_group.size(); ++j) {\n                        c_subset_end.push_back(current_group[j]);\n                    }\n                    std::vector<std::pair<int, int>> res_edges = make_query(c_subset_end);\n                    for (auto edge : res_edges) {\n                        queried_edges.insert(edge);\n                    }\n                    Q_rem--;\n                }\n            }\n        }\n    }\n\n    // 3. Output Phase\n    std::cout << \"!\" << std::endl;\n\n    for (int k = 0; k < M; ++k) {\n        // Output cities in group k\n        for (int i = 0; i < G[k]; ++i) {\n            std::cout << tentative_groups[k][i] << (i == G[k] - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] == 1) { // A single city group needs no roads\n            continue;\n        }\n\n        // Prepare edges for MST\n        std::vector<Edge> edges_for_mst;\n        const std::vector<int>& current_group = tentative_groups[k];\n        \n        // Create all possible edges within the group\n        for (size_t i = 0; i < current_group.size(); ++i) {\n            for (size_t j = i + 1; j < current_group.size(); ++j) {\n                int u = current_group[i];\n                int v = current_group[j];\n                \n                // Ensure u < v for canonical form (matches queried_edges)\n                if (u > v) std::swap(u, v); \n                \n                int rank = 1; // 1 for estimated, 0 for queried\n                if (queried_edges.count({u, v})) {\n                    rank = 0;\n                }\n                \n                long long dist_sq = estimated_dist_sq(u, v, cities_data);\n                edges_for_mst.push_back({u, v, {rank, dist_sq}});\n            }\n        }\n\n        // Sort edges\n        std::sort(edges_for_mst.begin(), edges_for_mst.end(), [](const Edge& a, const Edge& b) {\n            if (a.weight.first != b.weight.first) {\n                return a.weight.first < b.weight.first;\n            }\n            // Tie-break with estimated squared distance\n            if (a.weight.second != b.weight.second) {\n                return a.weight.second < b.weight.second;\n            }\n            // Final tie-break with lexicographical order of cities\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Run Kruskal's\n        // DSU needs to be reset or initialized for each group to ensure connectivity is considered only within the group.\n        // The problem states \"all cities within each group are mutually reachable\".\n        // A DSU of size N is fine, but `unite` operations effectively only work on cities from `current_group`.\n        // To properly use DSU for MST of a subset, we need to map city IDs to `0..G[k]-1` or use a local DSU.\n        // For simplicity and correctness with city IDs, initialize DSU with N and clear its state for each group by creating a new one.\n        DSU dsu(N); \n        std::vector<std::pair<int, int>> mst_output_edges;\n        int edges_count = 0;\n        for (const auto& edge : edges_for_mst) {\n            if (edges_count == G[k] - 1) break; // Found enough edges\n            if (dsu.unite(edge.u, edge.v)) {\n                mst_output_edges.push_back({edge.u, edge.v});\n                edges_count++;\n            }\n        }\n\n        // Output MST edges (lexicographically within group, as required by problem)\n        std::sort(mst_output_edges.begin(), mst_output_edges.end());\n        for (const auto& edge : mst_output_edges) {\n            std::cout << edge.first << \" \" << edge.second << std::endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int N_SIZE = 20;\n\n// Directions for movement and alter actions\n// Corresponding to U, D, L, R\nint DR[] = {-1, 1, 0, 0}; \nint DC[] = {0, 0, -1, 1}; \nchar DIR_CHARS[] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int r, c;\n    int cost;\n\n    // Custom comparator for priority queue (min-heap)\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Enum to categorize the type of action that led to a state\nenum ActionType {\n    MOVE,\n    MOVE_REMOVE_BLOCK, // Move into a square that was blocked, removing the block first\n    SLIDE_WALL,        // Slide, stopping because of an N x N boundary wall\n    SLIDE_ALTER        // Slide, stopping by toggling a block (placing or removing)\n};\n\n// Information to reconstruct the path\nstruct ParentInfo {\n    int pr, pc; // previous row, previous column\n    ActionType type;\n    char dir_char; // direction character for the action (U, D, L, R)\n    int br, bc;   // block row, block column (relevant for SLIDE_ALTER or MOVE_REMOVE_BLOCK)\n};\n\n// Global board state, tracks currently existing blocks\nset<pair<int, int>> current_blocks;\n\n// Helper function to check if coordinates are within grid bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_SIZE && c >= 0 && c < N_SIZE;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M; // N will be 20, M will be 40 as per problem statement\n    cin >> N >> M;\n\n    vector<pair<int, int>> targets(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> targets[k].first >> targets[k].second;\n    }\n\n    vector<pair<char, char>> all_actions; // Stores the final sequence of actions to output\n\n    int current_r = targets[0].first;\n    int current_c = targets[0].second;\n\n    // Iterate through each target segment (from current_pos to next target)\n    for (int k = 0; k < M - 1; ++k) {\n        int start_r = current_r;\n        int start_c = current_c;\n        int target_r = targets[k+1].first;\n        int target_c = targets[k+1].second;\n\n        // Dijkstra's algorithm for shortest path in terms of turns\n        vector<vector<int>> dist(N, vector<int>(N, INF));\n        vector<vector<ParentInfo>> parent(N, vector<ParentInfo>(N));\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[start_r][start_c] = 0;\n        pq.push({start_r, start_c, 0});\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n            int d = current.cost;\n\n            // If we found a shorter path previously, skip this one\n            if (d > dist[r][c]) {\n                continue;\n            }\n            // If we reached the target, we found the shortest path for this segment\n            if (r == target_r && c == target_c) {\n                break; \n            }\n\n            // --- Explore possible Move actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                if (!is_valid(nr, nc)) continue; // Check bounds\n\n                int cost = 0;\n                ActionType type;\n                if (current_blocks.count({nr, nc})) {\n                    // Moving onto a square that currently has a block.\n                    // This costs 1 for Alter (to remove the block) + 1 for Move. Total 2 turns.\n                    cost = 2;\n                    type = MOVE_REMOVE_BLOCK;\n                } else {\n                    // Moving onto an empty square. Costs 1 for Move.\n                    cost = 1;\n                    type = MOVE;\n                }\n\n                if (d + cost < dist[nr][nc]) {\n                    dist[nr][nc] = d + cost;\n                    parent[nr][nc] = {r, c, type, dir_char, nr, nc}; // br, bc store coord of block removed for MOVE_REMOVE_BLOCK\n                    pq.push({nr, nc, d + cost});\n                }\n            }\n\n            // --- Explore possible Slide actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int dr = DR[i];\n                int dc = DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                int current_slide_r = r;\n                int current_slide_c = c;\n                \n                // Iterate through all possible stopping points along the slide path\n                while (true) {\n                    current_slide_r += dr;\n                    current_slide_c += dc;\n                    \n                    // If the next square in slide direction is invalid or blocked by an existing block,\n                    // we cannot slide TO it or PAST it. Break this inner loop for this direction.\n                    if (!is_valid(current_slide_r, current_slide_c) || current_blocks.count({current_slide_r, current_slide_c})) {\n                        break; \n                    }\n\n                    // current_slide_r, current_slide_c is a valid square to stop ON.\n                    int stop_r = current_slide_r;\n                    int stop_c = current_slide_c;\n\n                    // Calculate the coordinates of the square where a stopper block would be placed.\n                    int stopper_block_r = stop_r + dr;\n                    int stopper_block_c = stop_c + dc;\n\n                    int slide_cost = 0;\n                    ActionType type;\n\n                    if (!is_valid(stopper_block_r, stopper_block_c)) {\n                        // Stopping because we hit an N x N boundary wall (stopper block is out of bounds).\n                        // Costs 1 for Slide. No Alter action is needed.\n                        slide_cost = 1; \n                        type = SLIDE_WALL;\n                        // Mark block coords as invalid to indicate no Alter action is tied to it\n                        stopper_block_r = -1; stopper_block_c = -1; \n                    } else {\n                        // Stopping by performing an Alter action on (stopper_block_r, stopper_block_c).\n                        // Costs 1 for Alter + 1 for Slide. Total 2 turns.\n                        slide_cost = 2; \n                        type = SLIDE_ALTER;\n                    }\n\n                    if (d + slide_cost < dist[stop_r][stop_c]) {\n                        dist[stop_r][stop_c] = d + slide_cost;\n                        parent[stop_r][stop_c] = {r, c, type, dir_char, stopper_block_r, stopper_block_c};\n                        pq.push({stop_r, stop_c, d + slide_cost});\n                    }\n                }\n            }\n        }\n\n        // --- Path reconstruction and action recording ---\n        vector<tuple<int,int,ActionType,char,int,int>> path_segments_info;\n        int curr_r = target_r;\n        int curr_c = target_c;\n\n        // Traverse parent pointers backwards from target to start, storing segment info.\n        // This gives actions in reverse order of execution.\n        while (curr_r != start_r || curr_c != start_c) {\n            ParentInfo p = parent[curr_r][curr_c];\n            path_segments_info.emplace_back(p.pr, p.pc, p.type, p.dir_char, p.br, p.bc);\n            curr_r = p.pr;\n            curr_c = p.pc;\n        }\n        // Reverse to get actions in the correct execution order.\n        reverse(path_segments_info.begin(), path_segments_info.end()); \n\n        // Process each action segment in forward order and update global blocks and the action list\n        for (const auto& info : path_segments_info) {\n            int pr, pc, br, bc;\n            ActionType type;\n            char dir_char;\n            tie(pr, pc, type, dir_char, br, bc) = info;\n\n            if (type == MOVE) {\n                all_actions.emplace_back('M', dir_char);\n            } else if (type == MOVE_REMOVE_BLOCK) {\n                all_actions.emplace_back('A', dir_char); // First Alter to remove block at (br,bc)\n                current_blocks.erase({br, bc});           // Update global block state (remove it)\n                all_actions.emplace_back('M', dir_char); // Then Move\n            } else if (type == SLIDE_WALL) {\n                all_actions.emplace_back('S', dir_char);\n            } else if (type == SLIDE_ALTER) {\n                all_actions.emplace_back('A', dir_char); // First Alter to toggle block at (br,bc)\n                // Toggle the block state in the global set\n                if (current_blocks.count({br, bc})) {\n                    current_blocks.erase({br, bc});\n                } else {\n                    current_blocks.insert({br, bc});\n                }\n                all_actions.emplace_back('S', dir_char); // Then Slide\n            }\n        }\n\n        // Update current player position for the next segment\n        current_r = target_r;\n        current_c = target_c;\n    }\n    \n    // Output all recorded actions\n    for (const auto& action : all_actions) {\n        cout << action.first << \" \" << action.second << endl;\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // for std::iota\n\n// Use a custom random number generator for better control and performance\nstd::mt19937_64 mt_rand(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Company data structure\nstruct Company {\n    int id;\n    int x, y, r; // desired location (cell x,y) and desired area\n};\n\n// Rectangle structure\nstruct Rect {\n    int x1, y1, x2, y2; // [x1, x2) x [y1, y2)\n    long long area() const {\n        return (long long)(x2 - x1) * (y2 - y1);\n    }\n    // Check if point (px, py) is contained (for 0.5 offset points, this means cell (px, py) is contained)\n    bool contains(int px, int py) const {\n        return x1 <= px && px < x2 && y1 <= py && py < y2;\n    }\n};\n\n// Node in the D&C tree\nstruct Node {\n    Rect rect; // The bounding box for this node\n    bool is_leaf;\n    int company_id; // Valid if is_leaf is true, stores original company index\n    bool is_vertical_cut; // True for vertical, false for horizontal\n    int cut_coord; // The coordinate of the cut\n    std::vector<int> company_indices; // Indices of companies that fall into this node's rectangle\n    int parent_idx; // Index to parent node\n    int left_child_idx; // Index to left/bottom child\n    int right_child_idx; // Index to right/top child\n\n    // Added fields for SA optimization: min/max coordinates of companies in children subtrees\n    int left_comp_min_x, left_comp_max_x;\n    int left_comp_min_y, left_comp_max_y;\n    int right_comp_min_x, right_comp_max_x;\n    int right_comp_min_y, right_comp_max_y;\n\n    Node(Rect r, bool leaf, int id, const std::vector<int>& indices)\n        : rect(r), is_leaf(leaf), company_id(id), is_vertical_cut(false), cut_coord(-1),\n          company_indices(indices), parent_idx(-1), left_child_idx(-1), right_child_idx(-1),\n          left_comp_min_x(10001), left_comp_max_x(-1), left_comp_min_y(10001), left_comp_max_y(-1),\n          right_comp_min_x(10001), right_comp_max_x(-1), right_comp_min_y(10001), right_comp_max_y(-1) {}\n};\n\nstd::vector<Company> companies_data;\nstd::vector<Rect> final_ad_rects;\nstd::vector<Node> tree_nodes;\nint N_global;\nstd::vector<int> internal_node_indices; // To store indices of internal nodes for SA\n\n// Calculate satisfaction for a single company\ndouble calculate_satisfaction(const Company& company, const Rect& ad_rect) {\n    if (!ad_rect.contains(company.x, company.y)) {\n        return 0.0;\n    }\n    long long s_i = ad_rect.area();\n    long long r_i = company.r;\n    if (s_i == 0) return 0.0; // Area must be positive as per problem statement\n    double ratio = (double)std::min(r_i, s_i) / std::max(r_i, s_i);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Calculate total score for current final_ad_rects\ndouble calculate_total_score() {\n    double total_p = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        total_p += calculate_satisfaction(companies_data[i], final_ad_rects[i]);\n    }\n    return total_p;\n}\n\n// Recursive function to build the D&C tree and determine initial rectangle placements\nvoid build_tree_and_solve(int node_idx, int x1, int y1, int x2, int y2, std::vector<int>&& indices) {\n    tree_nodes[node_idx].rect = {x1, y1, x2, y2};\n    tree_nodes[node_idx].company_indices = indices; // Store indices for SA bounds calculation later\n\n    if (indices.empty()) {\n        tree_nodes[node_idx].is_leaf = true; // Mark as leaf, no company\n        return;\n    }\n    if (indices.size() == 1) {\n        tree_nodes[node_idx].is_leaf = true;\n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n    \n    // This is an internal node\n    internal_node_indices.push_back(node_idx);\n\n    int best_v_cut_coord = -1;\n    long long min_v_area_diff = -1;\n    int best_v_split_point_idx = -1;\n\n    int best_h_cut_coord = -1;\n    long long min_h_area_diff = -1;\n    int best_h_split_point_idx = -1;\n\n    long long total_r_sum = 0;\n    for (int idx : indices) total_r_sum += companies_data[idx].r;\n\n    // Try Vertical Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].x < companies_data[j].x;\n    });\n    long long current_left_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_left_r_sum += companies_data[indices[k]].r;\n        int max_x_left_group = companies_data[indices[k]].x;\n        int min_x_right_group = companies_data[indices[k+1]].x;\n        \n        // The cut coordinate `C` must satisfy: max_x_left_group < C <= min_x_right_group\n        // And also `x1 < C < x2`\n        int candidate_cut_coord = max_x_left_group + 1;\n        \n        if (candidate_cut_coord > min_x_right_group || candidate_cut_coord < x1 + 1 || candidate_cut_coord > x2 - 1) {\n             continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_left_r_sum - (total_r_sum - current_left_r_sum));\n        if (best_v_cut_coord == -1 || diff < min_v_area_diff) {\n            min_v_area_diff = diff;\n            best_v_cut_coord = candidate_cut_coord;\n            best_v_split_point_idx = k + 1;\n        }\n    }\n\n    // Try Horizontal Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].y < companies_data[j].y;\n    });\n    long long current_bottom_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_bottom_r_sum += companies_data[indices[k]].r;\n        int max_y_bottom_group = companies_data[indices[k]].y;\n        int min_y_top_group = companies_data[indices[k+1]].y;\n        \n        int candidate_cut_coord = max_y_bottom_group + 1;\n\n        if (candidate_cut_coord > min_y_top_group || candidate_cut_coord < y1 + 1 || candidate_cut_coord > y2 - 1) {\n            continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_bottom_r_sum - (total_r_sum - current_bottom_r_sum));\n        if (best_h_cut_coord == -1 || diff < min_h_area_diff) {\n            min_h_area_diff = diff;\n            best_h_cut_coord = candidate_cut_coord;\n            best_h_split_point_idx = k + 1;\n        }\n    }\n    \n    // Choose the best cut among vertical and horizontal\n    int final_cut_coord = -1;\n    int final_split_point_idx = -1;\n    bool is_vertical_cut_chosen = false;\n\n    // Prioritize the cut along the longer side if area differences are comparable\n    bool preferred_vertical = (x2 - x1 >= y2 - y1);\n\n    if (best_v_cut_coord != -1 && best_h_cut_coord != -1) {\n        // Deterministic tie-breaking: strictly smaller difference first, then longer side.\n        if (min_v_area_diff < min_h_area_diff) {\n            final_cut_coord = best_v_cut_coord;\n            final_split_point_idx = best_v_split_point_idx;\n            is_vertical_cut_chosen = true;\n        } else if (min_h_area_diff < min_v_area_diff) {\n            final_cut_coord = best_h_cut_coord;\n            final_split_point_idx = best_h_split_point_idx;\n            is_vertical_cut_chosen = false;\n        } else { // min_v_area_diff == min_h_area_diff\n            if (preferred_vertical) {\n                final_cut_coord = best_v_cut_coord;\n                final_split_point_idx = best_v_split_point_idx;\n                is_vertical_cut_chosen = true;\n            } else {\n                final_cut_coord = best_h_cut_coord;\n                final_split_point_idx = best_h_split_point_idx;\n                is_vertical_cut_chosen = false;\n            }\n        }\n    } else if (best_v_cut_coord != -1) {\n        final_cut_coord = best_v_cut_coord;\n        final_split_point_idx = best_v_split_point_idx;\n        is_vertical_cut_chosen = true;\n    } else if (best_h_cut_coord != -1) {\n        final_cut_coord = best_h_cut_coord;\n        final_split_point_idx = best_h_split_point_idx;\n        is_vertical_cut_chosen = false;\n    } else {\n        // Fallback: If no valid cut is found, assign the entire region to the first company.\n        // This should only happen for very small regions or degenerate point distributions\n        // where it's impossible to make a valid cut for multiple companies.\n        tree_nodes[node_idx].is_leaf = true; \n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    tree_nodes[node_idx].cut_coord = final_cut_coord;\n    tree_nodes[node_idx].is_vertical_cut = is_vertical_cut_chosen;\n\n    // Re-sort indices based on the chosen cut dimension for partitioning\n    if (is_vertical_cut_chosen) {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].x < companies_data[j].x;\n        });\n    } else {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].y < companies_data[j].y;\n        });\n    }\n\n    std::vector<int> left_indices(indices.begin(), indices.begin() + final_split_point_idx);\n    std::vector<int> right_indices(indices.begin() + final_split_point_idx, indices.end());\n\n    tree_nodes[node_idx].left_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    tree_nodes[node_idx].right_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    if (is_vertical_cut_chosen) {\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, final_cut_coord, y2, std::move(left_indices));\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, final_cut_coord, y1, x2, y2, std::move(right_indices));\n    } else { // Horizontal cut\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, x2, final_cut_coord, std::move(left_indices)); // 'left' means bottom here\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, x1, final_cut_coord, x2, y2, std::move(right_indices)); // 'right' means top here\n    }\n}\n\n// Function to calculate and store min/max company coordinates for children\nvoid calculate_child_company_bounds_recursive(int node_idx) {\n    Node& node = tree_nodes[node_idx];\n\n    if (node.is_leaf) {\n        return;\n    }\n\n    // Recursively call for children first (post-order traversal)\n    calculate_child_company_bounds_recursive(node.left_child_idx);\n    calculate_child_company_bounds_recursive(node.right_child_idx);\n\n    // Calculate bounds for left child's companies\n    int current_min_x_left = 10001, current_max_x_left = -1;\n    int current_min_y_left = 10001, current_max_y_left = -1;\n    for (int company_idx : tree_nodes[node.left_child_idx].company_indices) {\n        current_min_x_left = std::min(current_min_x_left, companies_data[company_idx].x);\n        current_max_x_left = std::max(current_max_x_left, companies_data[company_idx].x);\n        current_min_y_left = std::min(current_min_y_left, companies_data[company_idx].y);\n        current_max_y_left = std::max(current_max_y_left, companies_data[company_idx].y);\n    }\n    node.left_comp_min_x = current_min_x_left;\n    node.left_comp_max_x = current_max_x_left;\n    node.left_comp_min_y = current_min_y_left;\n    node.left_comp_max_y = current_max_y_left;\n\n    // Calculate bounds for right child's companies\n    int current_min_x_right = 10001, current_max_x_right = -1;\n    int current_min_y_right = 10001, current_max_y_right = -1;\n    for (int company_idx : tree_nodes[node.right_child_idx].company_indices) {\n        current_min_x_right = std::min(current_min_x_right, companies_data[company_idx].x);\n        current_max_x_right = std::max(current_max_x_right, companies_data[company_idx].x);\n        current_min_y_right = std::min(current_min_y_right, companies_data[company_idx].y);\n        current_max_y_right = std::max(current_max_y_right, companies_data[company_idx].y);\n    }\n    node.right_comp_min_x = current_min_x_right;\n    node.right_comp_max_x = current_max_x_right;\n    node.right_comp_min_y = current_min_y_right;\n    node.right_comp_max_y = current_max_y_right;\n}\n\n// Function to update rectangles in a subtree after a cut coordinate changes\nvoid update_subtree_rects(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = tree_nodes[node_idx];\n    node.rect = {x1, y1, x2, y2};\n\n    if (node.is_leaf) {\n        if (node.company_id != -1) { \n            final_ad_rects[node.company_id] = {x1, y1, x2, y2};\n        }\n        return;\n    }\n\n    if (node.is_vertical_cut) {\n        update_subtree_rects(node.left_child_idx, x1, y1, node.cut_coord, y2);\n        update_subtree_rects(node.right_child_idx, node.cut_coord, y1, x2, y2);\n    } else { // Horizontal cut\n        update_subtree_rects(node.left_child_idx, x1, y1, x2, node.cut_coord);\n        update_subtree_rects(node.right_child_idx, x1, node.cut_coord, x2, y2);\n    }\n}\n\nvoid simulated_annealing(double time_limit_ms) {\n    auto start_time = std::chrono::steady_clock::now();\n    \n    // Initial solution and score\n    double current_score = calculate_total_score();\n    double best_score = current_score;\n    std::vector<Rect> best_ad_rects = final_ad_rects;\n\n    // SA parameters (tuned values)\n    double T_start = 0.2; // Adjusted based on typical score delta\n    double T_end = 1e-9;\n    \n    std::uniform_real_distribution<double> dist_01(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_internal_node_idx(0, internal_node_indices.size() - 1);\n\n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms >= time_limit_ms) {\n            break;\n        }\n\n        // Cooling schedule (exponential)\n        double T = T_start * std::pow(T_end / T_start, elapsed_ms / time_limit_ms);\n\n        // Pick a random internal node to modify its cut\n        int node_idx_to_modify = internal_node_indices[dist_internal_node_idx(mt_rand)];\n        Node& node_to_modify = tree_nodes[node_idx_to_modify];\n        \n        // Parent's rect boundaries are stored in node_to_modify.rect\n        int parent_x1 = node_to_modify.rect.x1;\n        int parent_y1 = node_to_modify.rect.y1;\n        int parent_x2 = node_to_modify.rect.x2;\n        int parent_y2 = node_to_modify.rect.y2;\n        \n        int min_cut_coord_bound, max_cut_coord_bound;\n\n        if (node_to_modify.is_vertical_cut) {\n            // Use precomputed bounds\n            int max_x_in_left_subtree = node_to_modify.left_comp_max_x;\n            int min_x_in_right_subtree = node_to_modify.right_comp_min_x;\n            \n            min_cut_coord_bound = std::max(parent_x1 + 1, max_x_in_left_subtree + 1);\n            max_cut_coord_bound = std::min(parent_x2 - 1, min_x_in_right_subtree);\n\n        } else { // Horizontal cut\n            // Use precomputed bounds\n            int max_y_in_bottom_subtree = node_to_modify.left_comp_max_y; // Left child refers to bottom here\n            int min_y_in_top_subtree = node_to_modify.right_comp_min_y;   // Right child refers to top here\n            \n            min_cut_coord_bound = std::max(parent_y1 + 1, max_y_in_bottom_subtree + 1);\n            max_cut_coord_bound = std::min(parent_y2 - 1, min_y_in_top_subtree);\n        }\n\n        if (min_cut_coord_bound > max_cut_coord_bound) {\n            continue; // Cannot move this cut, its position is fixed by point constraints\n        }\n\n        // Store old cut_coord for backtracking\n        int original_cut_coord = node_to_modify.cut_coord;\n        \n        // Generate new cut_coord randomly within valid range\n        std::uniform_int_distribution<int> dist_cut(min_cut_coord_bound, max_cut_coord_bound);\n        node_to_modify.cut_coord = dist_cut(mt_rand);\n        \n        if (original_cut_coord == node_to_modify.cut_coord) { // If random pick same as old, no change\n            continue;\n        }\n\n        // Update rectangles and calculate new score\n        update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        double new_score = calculate_total_score();\n\n        if (new_score > current_score || dist_01(mt_rand) < std::exp((new_score - current_score) / T)) {\n            // Accept new state\n            current_score = new_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ad_rects = final_ad_rects;\n            }\n        } else {\n            // Revert to old state\n            node_to_modify.cut_coord = original_cut_coord;\n            update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        }\n    }\n    \n    final_ad_rects = best_ad_rects;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N_global;\n\n    companies_data.resize(N_global);\n    final_ad_rects.resize(N_global);\n    std::vector<int> initial_company_indices(N_global);\n\n    for (int i = 0; i < N_global; ++i) {\n        companies_data[i].id = i;\n        std::cin >> companies_data[i].x >> companies_data[i].y >> companies_data[i].r;\n        initial_company_indices[i] = i;\n    }\n\n    // Build the initial D&C tree\n    tree_nodes.reserve(2 * N_global); // Max nodes in binary tree is 2N-1\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{}); // Root node\n    \n    build_tree_and_solve(0, 0, 0, 10000, 10000, std::move(initial_company_indices));\n    \n    // Precompute min/max company coordinates for children of each internal node\n    if (!tree_nodes[0].is_leaf) { // Only if there are actual splits\n        calculate_child_company_bounds_recursive(0);\n    }\n    \n    // Simulated Annealing\n    // Using 4.9 seconds out of 5.0s total time limit.\n    // Ensure internal_node_indices is not empty before starting SA\n    if (!internal_node_indices.empty()) {\n        simulated_annealing(4900.0); \n    }\n    \n    // Output the results\n    for (int i = 0; i < N_global; ++i) {\n        std::cout << final_ad_rects[i].x1 << \" \" << final_ad_rects[i].y1 << \" \"\n                  << final_ad_rects[i].x2 << \" \" << final_ad_rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <bitset>\n#include <random>\n#include <numeric> // For iota\n#include <tuple>   // For std::tuple\n\n// Using standard namespace for convenience in competitive programming\nusing namespace std;\n\n// Constants\nconst int GRID_SIZE = 50;\nconst int MAX_TILES = GRID_SIZE * GRID_SIZE; // Max possible number of tiles (all 1x1)\n\n// Global variables to store input data\nint si, sj; // Start row, start column\nint tile_id_grid[GRID_SIZE][GRID_SIZE]; // tile_id_grid[i][j] stores the tile ID for square (i,j)\nint p_grid[GRID_SIZE][GRID_SIZE];       // p_grid[i][j] stores the score value for square (i,j)\n\n// Global variables for best path found so far\nlong long max_score_global = 0;\nstring best_path_string_global = \"\";\n\n// Random number generator. Using std::mt19937 for better randomness than rand().\nmt19937 rng;\n\n// Structure to represent a potential move\nstruct Move {\n    int r, c;           // Next square's row and column\n    char move_char;     // Character representing the move ('U', 'D', 'L', 'R')\n    int score_value;    // Score obtained by moving to (r, c)\n    int tile_id;        // Tile ID of the next square\n};\n\n// Function to get all valid next moves from the current position (r, c)\n// A move is valid if it stays within grid boundaries and leads to an unvisited tile.\nvector<Move> get_valid_moves(int r, int c, const bitset<MAX_TILES>& visited_tiles) {\n    vector<Move> valid_moves;\n    // Possible movements: Up, Down, Left, Right\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1}; \n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n\n        // Check if the next position is within grid boundaries\n        if (nr >= 0 && nr < GRID_SIZE && nc >= 0 && nc < GRID_SIZE) {\n            int next_tile_id = tile_id_grid[nr][nc];\n            // Check if the tile has not been visited yet\n            if (!visited_tiles[next_tile_id]) {\n                valid_moves.push_back({nr, nc, move_chars[k], p_grid[nr][nc], next_tile_id});\n            }\n        }\n    }\n    return valid_moves;\n}\n\n// Function to generate a single path using a randomized greedy approach.\n// It stops when no more valid moves are available or the time limit for this path generation is near.\npair<long long, string> generate_path(chrono::high_resolution_clock::time_point global_start_time, chrono::milliseconds total_time_limit) {\n    long long current_score = p_grid[si][sj]; // Start with score of initial square\n    string current_path_str = \"\";\n    bitset<MAX_TILES> visited_tiles; // Keep track of visited tiles\n    visited_tiles[tile_id_grid[si][sj]] = true; // Mark initial tile as visited\n    int curr_r = si;\n    int curr_c = sj;\n\n    // Use a local random number generator for path generation, seeded by the global one.\n    // This ensures different paths are generated across calls to generate_path.\n    mt19937 local_rng(rng()); \n\n    // Continue extending the path until no more moves or global time limit is approached\n    while (true) {\n        // Periodically check remaining time to avoid exceeding total_time_limit\n        // Stop if less than 10ms remaining to finish current path and update best.\n        // This small buffer helps ensure the program terminates gracefully within the limit.\n        if (chrono::high_resolution_clock::now() - global_start_time >= total_time_limit - chrono::milliseconds(10)) {\n            break; \n        }\n\n        vector<Move> moves = get_valid_moves(curr_r, curr_c, visited_tiles);\n        if (moves.empty()) {\n            break; // No more valid moves from current position\n        }\n\n        // Sort valid moves by their score value in descending order.\n        // This prioritizes moves that give higher immediate scores.\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.score_value > b.score_value;\n        });\n\n        // Heuristic: consider a \"beam\" of top N moves, and pick one randomly.\n        // This balances greedy exploitation (higher scores) with exploration (trying other options).\n        // `effective_beam_width` is set to 5, meaning we consider the top 5 highest-scoring moves.\n        int effective_beam_width = min((int)moves.size(), 5); \n        \n        // Randomly pick an index within the `effective_beam_width`.\n        // This introduces randomness while still preferring high-scoring moves.\n        uniform_int_distribution<int> dist(0, effective_beam_width - 1);\n        int choice_idx = dist(local_rng);\n        \n        const Move& chosen_move = moves[choice_idx];\n\n        // Update current state based on the chosen move\n        curr_r = chosen_move.r;\n        curr_c = chosen_move.c;\n        current_score += chosen_move.score_value;\n        current_path_str += chosen_move.move_char;\n        visited_tiles[chosen_move.tile_id] = true;\n    }\n    return {current_score, current_path_str};\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed the random number generator using the current time.\n    // This provides a different sequence of random numbers for each execution,\n    // which is crucial for iterated randomized algorithms.\n    rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Read input: starting position (si, sj)\n    cin >> si >> sj;\n\n    // Read tile IDs for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> tile_id_grid[i][j];\n        }\n    }\n\n    // Read score values for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> p_grid[i][j];\n        }\n    }\n\n    // Initialize global best score with the score of the starting square.\n    // The path string is initially empty as no moves have been made yet (start square is implicitly visited).\n    max_score_global = p_grid[si][sj];\n    best_path_string_global = \"\"; \n\n    // Record the start time of the entire program execution\n    auto global_start_time = chrono::high_resolution_clock::now();\n    // Set a total time limit slightly less than 2 seconds (e.g., 1950 ms) to ensure output completes.\n    const auto TOTAL_TIME_LIMIT = chrono::milliseconds(1950); \n\n    // Iteratively generate paths and keep the best one found within the time limit.\n    while (chrono::high_resolution_clock::now() - global_start_time < TOTAL_TIME_LIMIT) {\n        // Call generate_path with the global start time and total time limit.\n        // The path generation function itself will manage its internal time checking.\n        pair<long long, string> result = generate_path(global_start_time, TOTAL_TIME_LIMIT);\n        \n        // If the newly generated path has a higher score, update the global best.\n        if (result.first > max_score_global) {\n            max_score_global = result.first;\n            best_path_string_global = result.second;\n        }\n    }\n\n    // Output the sequence of moves for the highest scoring path found.\n    cout << best_path_string_global << endl;\n\n    return 0;\n}\n","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <algorithm> // For std::reverse\n\n// Constants\nconst int GRID_SIZE = 30;\nconst int NUM_VERTICES = GRID_SIZE * GRID_SIZE;\n\n// Parameters for learning and exploration\nconst double INITIAL_EDGE_ESTIMATE = 5000.0; // Average of possible edge lengths\nconst double C_ALPHA = 20.0;                 // Constant for alpha in learning rate: alpha = 1.0 / (usage_count + C_ALPHA)\nconst double EXPLORATION_BONUS = 200.0;      // Bonus for less-used edges in Dijkstra's to encourage exploration\n                                             // Smaller usage_count -> larger bonus -> shorter effective_weight (as it's subtracted)\n\n// Clamping ranges for estimated edge lengths and effective weights\nconst double MIN_CLAMP_ESTIMATE = 900.0;   // Based on problem constraints (min 1000)\nconst double MAX_CLAMP_ESTIMATE = 9100.0;  // Based on problem constraints (max 9000)\nconst double MIN_CLAMP_EFFECTIVE_WEIGHT = 1.0; // To prevent negative effective edge weights in Dijkstra\n\n// Edge structures\n// h_len[i][j] is edge between (i,j) and (i,j+1)\n// v_len[i][j] is edge between (i,j) and (i+1,j)\n// These arrays store estimated lengths and usage counts for each individual edge.\ndouble estimated_h_len[GRID_SIZE][GRID_SIZE - 1];\ndouble estimated_v_len[GRID_SIZE - 1][GRID_SIZE];\n\nlong long usage_h_count[GRID_SIZE][GRID_SIZE - 1];\nlong long usage_v_count[GRID_SIZE - 1][GRID_SIZE];\n\n// Node to index mapping for Dijkstra's\nint node_to_idx(int r, int c) {\n    return r * GRID_SIZE + c;\n}\n\n// Index to node mapping\nstd::pair<int, int> idx_to_node(int idx) {\n    return {idx / GRID_SIZE, idx % GRID_SIZE};\n}\n\n// Function to clamp a double value within a specified range\ndouble clamp(double val, double min_val, double max_val) {\n    if (val < min_val) return min_val;\n    if (val > max_val) return max_val;\n    return val;\n}\n\n// Dijkstra's algorithm to find the shortest path based on current estimates\nstd::string find_path(int start_r, int start_c, int end_r, int end_c, double& path_estimated_len) {\n    int start_idx = node_to_idx(start_r, start_c);\n    int end_idx = node_to_idx(end_r, end_c);\n\n    std::vector<double> dist(NUM_VERTICES, 1e18); // Stores cumulative effective weights\n    std::vector<int> prev_node(NUM_VERTICES, -1);\n    std::vector<char> prev_dir(NUM_VERTICES, ' ');\n\n    std::priority_queue<std::pair<double, int>, std::vector<std::pair<double, int>>, std::greater<std::pair<double, int>>> pq;\n\n    dist[start_idx] = 0;\n    pq.push({0, start_idx});\n\n    while (!pq.empty()) {\n        double d = pq.top().first;\n        int u_idx = pq.top().second;\n        pq.pop();\n\n        if (d > dist[u_idx]) continue;\n        if (u_idx == end_idx) break;\n\n        int ur = idx_to_node(u_idx).first;\n        int uc = idx_to_node(u_idx).second;\n\n        // Explore neighbors (Up, Down, Left, Right)\n        // U: (ur-1, uc) from (ur, uc)\n        if (ur > 0) {\n            int v_idx = node_to_idx(ur - 1, uc);\n            // Edge is v_len[ur-1][uc]\n            double current_estimate = estimated_v_len[ur - 1][uc];\n            long long current_usage = usage_v_count[ur - 1][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE); // Clamp effective weight\n            \n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'U';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // D: (ur+1, uc) from (ur, uc)\n        if (ur < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur + 1, uc);\n            // Edge is v_len[ur][uc]\n            double current_estimate = estimated_v_len[ur][uc];\n            long long current_usage = usage_v_count[ur][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'D';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // L: (ur, uc-1) from (ur, uc)\n        if (uc > 0) {\n            int v_idx = node_to_idx(ur, uc - 1);\n            // Edge is h_len[ur][uc-1]\n            double current_estimate = estimated_h_len[ur][uc - 1];\n            long long current_usage = usage_h_count[ur][uc - 1];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'L';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // R: (ur, uc+1) from (ur, uc)\n        if (uc < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur, uc + 1);\n            // Edge is h_len[ur][uc]\n            double current_estimate = estimated_h_len[ur][uc];\n            long long current_usage = usage_h_count[ur][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'R';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    int curr_idx = end_idx;\n    double actual_path_len_sum = 0.0; // Sum of actual estimated edge lengths (without exploration bonus)\n\n    // Reconstruct path and calculate sum of actual estimated edge lengths\n    while (curr_idx != start_idx && curr_idx != -1) {\n        if (prev_node[curr_idx] == -1) {\n             path_estimated_len = 1e18; \n             return \"\"; // Path not found or error\n        }\n        path_str += prev_dir[curr_idx];\n        \n        int prev_idx = prev_node[curr_idx];\n        int pr = idx_to_node(prev_idx).first;\n        int pc = idx_to_node(prev_idx).second;\n        // int cr = idx_to_node(curr_idx).first; // curr_r, curr_c are from node_to_idx(curr_idx)\n        // int cc = idx_to_node(curr_idx).second;\n\n        // Add the *actual estimated length* of the edge\n        if (prev_dir[curr_idx] == 'U') { // Means we moved from (pr,pc) to (pr-1,pc), so edge is v_len[pr-1][pc]\n            actual_path_len_sum += estimated_v_len[pr-1][pc];\n        } else if (prev_dir[curr_idx] == 'D') { // Means we moved from (pr,pc) to (pr+1,pc), so edge is v_len[pr][pc]\n            actual_path_len_sum += estimated_v_len[pr][pc];\n        } else if (prev_dir[curr_idx] == 'L') { // Means we moved from (pr,pc) to (pr,pc-1), so edge is h_len[pr][pc-1]\n            actual_path_len_sum += estimated_h_len[pr][pc-1];\n        } else { // prev_dir[curr_idx] == 'R' // Means we moved from (pr,pc) to (pr,pc+1), so edge is h_len[pr][pc]\n            actual_path_len_sum += estimated_h_len[pr][pc];\n        }\n        curr_idx = prev_node[curr_idx];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    \n    path_estimated_len = actual_path_len_sum; // This is the total estimated length of the path without exploration bonus\n    return path_str;\n}\n\nvoid solve() {\n    // Initialize estimated edge lengths and usage counts\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            estimated_h_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_h_count[i][j] = 1; \n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            estimated_v_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_v_count[i][j] = 1; \n        }\n    }\n\n    // Main query loop\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        std::cin >> si >> sj >> ti >> tj;\n\n        double current_path_estimated_len; \n        std::string path = find_path(si, sj, ti, tj, current_path_estimated_len);\n        \n        std::cout << path << std::endl;\n        std::cout.flush();\n\n        int observed_path_len_int;\n        std::cin >> observed_path_len_int;\n        double observed_path_len = static_cast<double>(observed_path_len_int);\n\n        // Update edge length estimates\n        // Ensure current_path_estimated_len is not too small to avoid division by zero or extreme scaling.\n        if (current_path_estimated_len < 1.0) current_path_estimated_len = 1.0; \n        double scaling_factor = observed_path_len / current_path_estimated_len;\n        \n        int curr_r = si;\n        int curr_c = sj;\n\n        for (char dir : path) {\n            double* edge_len_ptr;\n            long long* usage_count_ptr;\n            int r_idx, c_idx; // Indices for the specific edge in the respective array\n\n            // Determine which edge was used and its current stats using pre-move coordinates\n            if (dir == 'U') {\n                r_idx = curr_r - 1; // Edge (curr_r-1, curr_c) to (curr_r, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r--; // Move to the new node\n            } else if (dir == 'D') {\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r+1, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r++; // Move to the new node\n            } else if (dir == 'L') {\n                r_idx = curr_r; // Edge (curr_r, curr_c-1) to (curr_r, curr_c)\n                c_idx = curr_c - 1;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c--; // Move to the new node\n            } else { // dir == 'R'\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r, curr_c+1)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c++; // Move to the new node\n            }\n\n            // Apply weighted average update\n            double alpha = 1.0 / (static_cast<double>(*usage_count_ptr) + C_ALPHA);\n            double new_estimate_value = (*edge_len_ptr) * scaling_factor;\n            *edge_len_ptr = clamp((1.0 - alpha) * (*edge_len_ptr) + alpha * new_estimate_value, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            \n            // Increment usage count for the updated edge\n            (*usage_count_ptr)++;\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple> \n\n// Global constants\nconst int N_MATRIX = 20; // N is fixed to 20\nint M;\nstd::vector<std::string> S; // Input strings\n\n// Character to integer mapping for internal use (A=0, ..., H=7, .=8)\nstd::map<char, int> char_to_int_map;\nstd::vector<char> int_to_char_map;\n\n// Simulated Annealing parameters\n// MAX_ITERATIONS is a soft limit; time limit is primary constraint\nlong long MAX_ITERATIONS = 100000000; // Large number, actual iterations depend on TIME_LIMIT\ndouble START_TEMP = 2.0;\ndouble END_TEMP = 1e-9;\n\n// Random number generator\nstd::mt19937 mt;\n\n// Time measurement\nstd::chrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 2.9; // seconds\n\n// --- State Variables for SA ---\nstd::vector<std::string> current_grid;\nint num_dots; // number of '.' in current_grid\nint num_matched_strings; // current 'c' value (number of unique strings found at least once)\n\n// For each string s_idx, how many distinct (start_r, start_c, dir) locations does it currently match?\nstd::vector<int> num_actual_matches_for_string; // size M\n\n// Dynamic list of string indices that are currently unmatched\nstd::vector<int> unmatched_string_indices;\n// Maps s_idx to its position in unmatched_string_indices (-1 if matched)\nstd::vector<int> s_idx_to_unmatched_list_pos; // size M\n\n// --- Precomputed data structures for efficient updates ---\n// Each struct represents a unique \"match window\" (a string starting at a specific cell in a specific direction)\nstruct PotentialMatchInfoBase {\n    int s_idx;\n    int sr, sc; // start row, start col\n    int dir;    // 0 for horizontal, 1 for vertical\n};\n\n// Vector storing all unique PotentialMatchInfoBase instances\nstd::vector<PotentialMatchInfoBase> all_potential_match_info_bases; \n\n// For each grid cell (r_covered, c_covered), this list stores pairs of:\n// <index to all_potential_match_info_bases, p_in_s>\n// `p_in_s` is the position of (r_covered, c_covered) within the string S[s_idx]\nstd::vector<std::pair<int, int>> cell_covers[N_MATRIX][N_MATRIX];\n\n// For each potential match (identified by its index `pm_idx`), the number of mismatches (chars don't match or are '.')\nstd::vector<int> num_mismatches_for_potential_match; \n// For each potential match (identified by `pm_idx`), true if it currently matches the grid perfectly\nstd::vector<bool> is_potential_match_active; \n\n// For each s_idx, a list of pm_idx that correspond to it.\nstd::vector<std::vector<int>> potential_matches_for_string;\n\n// Helper for modulo arithmetic (for negative numbers)\nint mod(int i, int n) {\n    return (i % n + n) % n;\n}\n\nvoid init_char_maps() {\n    char_to_int_map['A'] = 0; char_to_int_map['B'] = 1; char_to_int_map['C'] = 2; char_to_int_map['D'] = 3;\n    char_to_int_map['E'] = 4; char_to_int_map['F'] = 5; char_to_int_map['G'] = 6; char_to_int_map['H'] = 7;\n    char_to_int_map['.'] = 8;\n\n    int_to_char_map.resize(9);\n    int_to_char_map[0] = 'A'; int_to_char_map[1] = 'B'; int_to_char_map[2] = 'C'; int_to_char_map[3] = 'D';\n    int_to_char_map[4] = 'E'; int_to_char_map[5] = 'F'; int_to_char_map[6] = 'G'; int_to_char_map[7] = 'H';\n    int_to_char_map[8] = '.';\n}\n\n// Score calculation: objective function for SA\n// Range for c < M: [0, 1)\n// Range for c = M: [1.0 + 2.0*N*N / (2.0*N*N), 1.0 + 2.0*N*N / (2.0*N*N - (N*N-1))] approx [2.0, 2.995]\ndouble calculate_objective(int c, int d) {\n    if (c < M) {\n        return (double)c / M;\n    } else {\n        return 1.0 + (double)(2.0 * N_MATRIX * N_MATRIX) / (2.0 * N_MATRIX * N_MATRIX - d);\n    }\n}\n\nvoid precompute_potential_matches() {\n    potential_matches_for_string.resize(M);\n    std::map<std::tuple<int, int, int, int>, int> potential_match_key_to_idx; \n    int pm_counter = 0; // Counts unique potential match windows\n\n    for (int s_idx = 0; s_idx < M; ++s_idx) {\n        // For each start position (sr, sc) and direction (0=horiz, 1=vert)\n        for (int sr = 0; sr < N_MATRIX; ++sr) {\n            for (int sc = 0; sc < N_MATRIX; ++sc) {\n                // Horizontal match\n                std::tuple<int, int, int, int> pm_key_h = {s_idx, sr, sc, 0}; \n                if (potential_match_key_to_idx.find(pm_key_h) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_h] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 0});\n                }\n                int pm_idx_h = potential_match_key_to_idx[pm_key_h];\n                potential_matches_for_string[s_idx].push_back(pm_idx_h); \n\n                // Vertical match\n                std::tuple<int, int, int, int> pm_key_v = {s_idx, sr, sc, 1}; \n                if (potential_match_key_to_idx.find(pm_key_v) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_v] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 1});\n                }\n                int pm_idx_v = potential_match_key_to_idx[pm_key_v];\n                potential_matches_for_string[s_idx].push_back(pm_idx_v); \n            }\n        }\n    }\n\n    // Now populate cell_covers using all_potential_match_info_bases\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        int k = S[pm_info_base.s_idx].length();\n        for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n            cell_covers[r][c].push_back({pm_idx, p_in_s});\n        }\n    }\n\n    num_mismatches_for_potential_match.resize(pm_counter);\n    is_potential_match_active.resize(pm_counter, false);\n}\n\nvoid initialize_state() {\n    current_grid.assign(N_MATRIX, std::string(N_MATRIX, '.')); \n    \n    // Initialize with random 'A'-'H' characters (mimics input generation)\n    std::uniform_int_distribution<int> dist_char_AH(0, 7); // A-H only\n    for (int r = 0; r < N_MATRIX; ++r) {\n        for (int c = 0; c < N_MATRIX; ++c) {\n            current_grid[r][c] = int_to_char_map[dist_char_AH(mt)];\n        }\n    }\n    num_dots = 0; // No dots initially\n\n    num_matched_strings = 0;\n    num_actual_matches_for_string.assign(M, 0);\n\n    // Initialize unmatched_string_indices and s_idx_to_unmatched_list_pos\n    unmatched_string_indices.reserve(M); // Pre-allocate memory\n    s_idx_to_unmatched_list_pos.assign(M, -1); // -1 means not in list (i.e., matched)\n    for (int i = 0; i < M; ++i) {\n        unmatched_string_indices.push_back(i);\n        s_idx_to_unmatched_list_pos[i] = i;\n    }\n\n    // Calculate initial mismatch counts for all potential match windows\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        const std::string& s = S[pm_info_base.s_idx];\n        int k = s.length();\n        int mismatches = 0;\n\n        for (int p = 0; p < k; ++p) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n            \n            // A mismatch occurs if the grid character doesn't match the string character OR if it's '.'\n            // With A-H initialization, only the first condition applies initially.\n            if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                mismatches++;\n            }\n        }\n        num_mismatches_for_potential_match[pm_idx] = mismatches;\n\n        if (mismatches == 0) { // This potential match is currently active\n            is_potential_match_active[pm_idx] = true;\n            if (num_actual_matches_for_string[pm_info_base.s_idx] == 0) { // First match for this string\n                num_matched_strings++;\n                // Remove this s_idx from unmatched_string_indices\n                int s_idx = pm_info_base.s_idx;\n                int pos = s_idx_to_unmatched_list_pos[s_idx];\n                if (pos != -1) { \n                    int last_s_idx_in_list = unmatched_string_indices.back();\n                    unmatched_string_indices[pos] = last_s_idx_in_list;\n                    s_idx_to_unmatched_list_pos[last_s_idx_in_list] = pos;\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[s_idx] = -1;\n                }\n            }\n            num_actual_matches_for_string[pm_info_base.s_idx]++;\n        }\n    }\n}\n\nvoid solve() {\n    start_time = std::chrono::high_resolution_clock::now();\n    \n    init_char_maps();\n    precompute_potential_matches();\n    initialize_state();\n\n    std::uniform_int_distribution<int> dist_rc(0, N_MATRIX - 1);\n    std::uniform_int_distribution<int> dist_char_all(0, int_to_char_map.size() - 1); // 9 options: A-H, .\n    std::uniform_int_distribution<int> dist_char_AH(0, 7); // A-H only\n    std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    double best_score = calculate_objective(num_matched_strings, num_dots);\n    std::vector<std::string> best_grid = current_grid;\n\n    // Probability to try to fix a specific mismatch for an unmatched string\n    double p_targeted_fix_attempt = 0.6; \n\n    for (long long iter = 0; iter < MAX_ITERATIONS; ++iter) {\n        double current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            std::chrono::high_resolution_clock::now() - start_time).count() / 1e9;\n        if (current_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = START_TEMP * std::pow(END_TEMP / START_TEMP, (double)iter / MAX_ITERATIONS);\n\n        int r_changed, c_changed;\n        char old_char, new_char;\n\n        bool is_targeted_move_successful = false; // Flag to indicate if a targeted move was generated\n\n        // Strategy 1: Attempt to fix a mismatch for an currently unmatched string\n        if (num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_targeted_fix_attempt) {\n            int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            // Find a potential match window for this string that is currently mismatched\n            std::vector<int> candidates_pm_idx_for_s;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match[pm_idx] > 0) {\n                    candidates_pm_idx_for_s.push_back(pm_idx);\n                }\n            }\n\n            if (!candidates_pm_idx_for_s.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                // Find a cell within this window that is currently mismatched\n                std::vector<std::pair<int, int>> mismatched_cells_in_window; // {r, c}\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    if (current_grid[r_p][c_p] != s_to_fix[p_in_s] || current_grid[r_p][c_p] == '.') {\n                        mismatched_cells_in_window.push_back({r_p, c_p});\n                    }\n                }\n\n                if (!mismatched_cells_in_window.empty()) {\n                    auto target_cell = mismatched_cells_in_window[std::uniform_int_distribution<int>(0, mismatched_cells_in_window.size() - 1)(mt)];\n                    r_changed = target_cell.first;\n                    c_changed = target_cell.second;\n                    old_char = current_grid[r_changed][c_changed];\n                    \n                    int p_in_s_for_target = (pm_info_base.dir == 0) ? \n                                             mod(c_changed - pm_info_base.sc, N_MATRIX) : \n                                             mod(r_changed - pm_info_base.sr, N_MATRIX);\n\n                    new_char = s_to_fix[p_in_s_for_target];\n                    if (new_char != old_char) { // Only proceed if there's an actual change\n                        is_targeted_move_successful = true;\n                    }\n                }\n            }\n        }\n\n        // Strategy 2: General random perturbation (fallback or if selected probabilistically)\n        if (!is_targeted_move_successful) {\n            r_changed = dist_rc(mt);\n            c_changed = dist_rc(mt);\n            old_char = current_grid[r_changed][c_changed];\n            \n            if (num_matched_strings == M) {\n                // If all strings are matched, try to introduce '.' to reduce d\n                if (dist_prob(mt) < 0.8) { // E.g., 80% chance to propose '.'\n                    new_char = '.';\n                } else {\n                    new_char = int_to_char_map[dist_char_all(mt)]; // Random A-H, or .\n                }\n            } else {\n                // If not all strings are matched, prefer filling with A-H (less '.'s)\n                new_char = int_to_char_map[dist_char_AH(mt)]; // A-H only\n            }\n            if (new_char == old_char) continue; // Skip if no effective change\n        }\n\n        // --- Store current state for potential revert ---\n        int prev_num_dots = num_dots;\n        int prev_num_matched_strings_overall = num_matched_strings;\n        \n        // Map to store original match counts and unmatched list positions for affected strings\n        std::map<int, int> s_idx_to_old_actual_match_count_snapshot; \n        std::map<int, int> s_idx_to_old_unmatched_list_pos_snapshot; \n\n        // Temporarily store original mismatch counts and active status for affected potential matches for quick revert\n        std::vector<int> original_mismatches_for_affected_pm;\n        std::vector<bool> original_active_status_for_affected_pm;\n        std::vector<int> affected_pm_indices;\n\n        // --- Apply change and calculate deltas ---\n        // Update num_dots\n        if (old_char == '.' && new_char != '.') { num_dots--; }\n        else if (old_char != '.' && new_char == '.') { num_dots++; }\n        \n        // Iterate through all potential match windows affected by this cell change\n        for (auto const& p : cell_covers[r_changed][c_changed]) {\n            int pm_idx = p.first;\n            int p_in_s = p.second; // Position of (r_changed, c_changed) within S[s_idx]\n\n            affected_pm_indices.push_back(pm_idx);\n            original_mismatches_for_affected_pm.push_back(num_mismatches_for_potential_match[pm_idx]);\n            original_active_status_for_affected_pm.push_back(is_potential_match_active[pm_idx]);\n\n            const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n            int s_idx = pm_info_base.s_idx;\n            char required_char = S[s_idx][p_in_s];\n\n            // Store original match count for this string if not already done in the snapshot\n            if (s_idx_to_old_actual_match_count_snapshot.find(s_idx) == s_idx_to_old_actual_match_count_snapshot.end()) {\n                s_idx_to_old_actual_match_count_snapshot[s_idx] = num_actual_matches_for_string[s_idx];\n                s_idx_to_old_unmatched_list_pos_snapshot[s_idx] = s_idx_to_unmatched_list_pos[s_idx]; \n            }\n\n            // Determine if old/new chars are a mismatch\n            bool old_char_was_bad = (old_char != required_char || old_char == '.');\n            bool new_char_is_bad = (new_char != required_char || new_char == '.');\n\n            // Update mismatch count for this potential match window\n            if (old_char_was_bad && !new_char_is_bad) { // Cell character changed from bad to good for this match\n                num_mismatches_for_potential_match[pm_idx]--;\n            } else if (!old_char_was_bad && new_char_is_bad) { // Cell character changed from good to bad for this match\n                num_mismatches_for_potential_match[pm_idx]++;\n            }\n\n            // Update active status for this potential match window and string's actual match count\n            bool was_match_active = original_active_status_for_affected_pm.back(); \n            bool is_match_active = (num_mismatches_for_potential_match[pm_idx] == 0);\n\n            if (!was_match_active && is_match_active) {\n                is_potential_match_active[pm_idx] = true;\n                num_actual_matches_for_string[s_idx]++;\n            } else if (was_match_active && !is_match_active) {\n                is_potential_match_active[pm_idx] = false;\n                num_actual_matches_for_string[s_idx]--;\n            }\n        }\n\n        // Calculate actual change in num_matched_strings (c) for the proposed state\n        int proposed_num_matched_strings_overall = prev_num_matched_strings_overall;\n        for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n            if (old_count == 0 && num_actual_matches_for_string[s_idx] > 0) proposed_num_matched_strings_overall++;\n            if (old_count > 0 && num_actual_matches_for_string[s_idx] == 0) proposed_num_matched_strings_overall--;\n        }\n\n        // --- Decision (Accept/Revert) ---\n        double current_obj_val = calculate_objective(prev_num_matched_strings_overall, prev_num_dots);\n        double proposed_obj_val = calculate_objective(proposed_num_matched_strings_overall, num_dots);\n\n        if (proposed_obj_val >= current_obj_val || dist_prob(mt) < std::exp((proposed_obj_val - current_obj_val) / T)) {\n            // Accept the change:\n            current_grid[r_changed][c_changed] = new_char;\n            num_matched_strings = proposed_num_matched_strings_overall; \n\n            // Update unmatched_string_indices using the snapshot values\n            for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n                int new_count = num_actual_matches_for_string[s_idx];\n                if (old_count == 0 && new_count > 0) { // String became matched\n                    int pos = s_idx_to_unmatched_list_pos[s_idx]; // Current pos, which is its old pos if it was in list\n                    int last_s_idx_in_list = unmatched_string_indices.back();\n                    unmatched_string_indices[pos] = last_s_idx_in_list;\n                    s_idx_to_unmatched_list_pos[last_s_idx_in_list] = pos;\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[s_idx] = -1;\n                } else if (old_count > 0 && new_count == 0) { // String became unmatched\n                    s_idx_to_unmatched_list_pos[s_idx] = unmatched_string_indices.size();\n                    unmatched_string_indices.push_back(s_idx);\n                }\n            }\n        } else {\n            // Revert the change:\n            num_dots = prev_num_dots; \n\n            // Revert mismatch counts and active status for affected potential matches\n            for (size_t i = 0; i < affected_pm_indices.size(); ++i) {\n                int pm_idx = affected_pm_indices[i];\n                num_mismatches_for_potential_match[pm_idx] = original_mismatches_for_affected_pm[i];\n                is_potential_match_active[pm_idx] = original_active_status_for_affected_pm[i];\n            }\n\n            // Revert num_actual_matches_for_string and s_idx_to_unmatched_list_pos for affected strings\n            for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n                num_actual_matches_for_string[s_idx] = old_count;\n                s_idx_to_unmatched_list_pos[s_idx] = s_idx_to_old_unmatched_list_pos_snapshot[s_idx];\n            }\n            // Rebuild unmatched_string_indices based on the reverted s_idx_to_unmatched_list_pos\n            unmatched_string_indices.clear();\n            for (int i = 0; i < M; ++i) {\n                if (s_idx_to_unmatched_list_pos[i] != -1) { \n                    unmatched_string_indices.push_back(i);\n                }\n            }\n            // After rebuilding `unmatched_string_indices`, its positions for items that are present will likely be different.\n            // Need to update `s_idx_to_unmatched_list_pos` for all those items to reflect their *new* positions.\n            for (size_t i = 0; i < unmatched_string_indices.size(); ++i) {\n                s_idx_to_unmatched_list_pos[unmatched_string_indices[i]] = i;\n            }\n        }\n        \n        // Update best score and grid AFTER all state variables are consistent (either accepted or reverted)\n        double current_final_obj_val = calculate_objective(num_matched_strings, num_dots);\n        if (current_final_obj_val > best_score) {\n            best_score = current_final_obj_val;\n            best_grid = current_grid;\n        }\n    }\n\n    current_grid = best_grid; // Output the best grid found\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N_input; \n    std::cin >> N_input >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> S[i];\n    }\n\n    solve();\n\n    for (int i = 0; i < N_MATRIX; ++i) {\n        std::cout << current_grid[i] << std::endl;\n    }\n\n    return 0;\n}\n","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm> // For std::reverse\n\n// No external libraries other than standard C++ ones are strictly necessary.\n\nusing namespace std;\n\n// Global variables to store map data and current state for convenience\nint N_global;\nint SI_global, SJ_global;\nvector<string> grid_global;\nvector<vector<int>> costs_global; // Stores char '5'-'9' as int\nvector<vector<bool>> is_road_global; // True if square is a road, false if obstacle\n// visible_left/right/up/down store the inclusive boundaries of the visible segment\n// For example, visible_left_global[r][c] is the minimum column index k such that (r,k) is road and on the path to (r,c)\nvector<vector<int>> visible_left_global, visible_right_global, visible_up_global, visible_down_global; \nint total_road_squares_global = 0; // Total count of road squares\nvector<vector<bool>> covered_status_global; // True if the square has been made visible\nint current_covered_count_global = 0; // Count of currently visible road squares\n\n// Structure for Dijkstra's priority queue state\nstruct State {\n    int r, c;\n    long long cost;\n    // For priority queue: min-heap based on cost\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Precompute visible ranges for each road square (O(N^3))\n// This populates visible_left/right/up/down_global arrays.\nvoid precompute_visibility() {\n    visible_left_global.assign(N_global, vector<int>(N_global));\n    visible_right_global.assign(N_global, vector<int>(N_global));\n    visible_up_global.assign(N_global, vector<int>(N_global));\n    visible_down_global.assign(N_global, vector<int>(N_global));\n\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            if (!is_road_global[i][j]) continue; // Only process road squares\n\n            // Horizontal visibility (left)\n            int left_bound = j;\n            while (left_bound > 0 && is_road_global[i][left_bound - 1]) {\n                left_bound--;\n            }\n            visible_left_global[i][j] = left_bound;\n\n            // Horizontal visibility (right)\n            int right_bound = j;\n            while (right_bound < N_global - 1 && is_road_global[i][right_bound + 1]) {\n                right_bound++;\n            }\n            visible_right_global[i][j] = right_bound;\n\n            // Vertical visibility (up)\n            int up_bound = i;\n            while (up_bound > 0 && is_road_global[up_bound - 1][j]) {\n                up_bound--;\n            }\n            visible_up_global[i][j] = up_bound;\n\n            // Vertical visibility (down)\n            int down_bound = i;\n            while (down_bound < N_global - 1 && is_road_global[down_bound + 1][j]) {\n                down_bound++;\n            }\n            visible_down_global[i][j] = down_bound;\n        }\n    }\n}\n\n// Update the global coverage status based on visiting (r, c) (O(N))\n// This marks all squares visible from (r,c) as covered, and increments current_covered_count_global.\nvoid update_coverage(int r, int c) {\n    // Horizontal line of sight\n    for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n        if (is_road_global[r][k] && !covered_status_global[r][k]) {\n            covered_status_global[r][k] = true;\n            current_covered_count_global++;\n        }\n    }\n    // Vertical line of sight\n    for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n        if (is_road_global[k][c] && !covered_status_global[k][c]) {\n            covered_status_global[k][c] = true;\n            current_covered_count_global++;\n        }\n    }\n}\n\n// Dijkstra from start_r, start_c to find the next best node to visit\n// The \"best\" node maximizes (new coverage gained) / (cost to reach it).\n// Returns {best_r, best_c} and updates path_cost_found with the cost to reach it.\npair<int, int> find_best_next_node(int start_r, int start_c, long long& path_cost_found) {\n    // dist[r][c] stores the minimum cost to reach (r,c) from (start_r, start_c)\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1)); \n    // prev[r][c] stores the previous node in the shortest path to (r,c)\n    // This isn't actually used in this function, but would be if path reconstruction happened here.\n    // We recreate it in reconstruct_path_segment to keep functions distinct.\n    // vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1})); \n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int best_r = -1, best_c = -1;\n    double max_score = -1.0; // Initialize with a very low score\n    long long min_cost_to_best_target = -1; // Stores cost of best found target\n    int max_coverage_gain_best = -1; // Stores coverage gain of best found target (for tie-breaking)\n\n    // Directions for moving (Up, Down, Left, Right)\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        // If a shorter path to (r,c) has already been found and processed, skip\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        // Calculate coverage gain for current (r,c)\n        int coverage_gain_current_node = 0;\n        // Count newly visible squares horizontally\n        for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n            if (is_road_global[r][k] && !covered_status_global[r][k]) coverage_gain_current_node++;\n        }\n        // Count newly visible squares vertically\n        for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n            if (is_road_global[k][c] && !covered_status_global[k][c]) coverage_gain_current_node++;\n        }\n        \n        // We only consider moves that yield new coverage AND require movement (cost > 0).\n        // The start node (cost 0) should ideally have 0 coverage_gain after initial update_coverage.\n        if (coverage_gain_current_node > 0 && cost > 0) { \n            double score = (double)coverage_gain_current_node / cost;\n\n            // Tie-breaking:\n            // 1. Higher score (coverage_gain / cost)\n            // 2. If scores are equal, prefer higher coverage_gain\n            // 3. If scores and coverage_gain are equal, prefer lower cost\n            if (score > max_score || \n                (score == max_score && coverage_gain_current_node > max_coverage_gain_best) ||\n                (score == max_score && coverage_gain_current_node == max_coverage_gain_best && cost < min_cost_to_best_target)) \n            {\n                max_score = score;\n                best_r = r;\n                best_c = c;\n                min_cost_to_best_target = cost;\n                max_coverage_gain_best = coverage_gain_current_node;\n            }\n        }\n\n        // Explore neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            // Check if neighbor is within bounds and is a road square\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc]; // Cost to move to (nr,nc)\n                // If a shorter path to (nr,nc) is found\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    // prev[nr][nc] = {r, c}; // Not strictly needed here, recreated for path reconstruction\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // If no suitable target was found (max_score remains -1.0),\n    // it implies either all reachable squares are already covered by previously visited locations,\n    // or the heuristic failed to find a valid new target providing coverage with positive cost.\n    if (best_r == -1) { \n        path_cost_found = 0;\n        return {start_r, start_c}; // Return current position, signaling to main loop to terminate\n    }\n\n    path_cost_found = min_cost_to_best_target;\n    return {best_r, best_c};\n}\n\n// Reconstruct path segment using Dijkstra's prev array (O(N^2))\n// This function computes the shortest path between start and end and returns it as a string of moves.\nstring reconstruct_path_segment(int start_r, int start_c, int end_r, int end_c) {\n    if (start_r == end_r && start_c == end_c) return \"\"; // No movement needed\n\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1));\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1}));\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int dr[] = {-1, 1, 0, 0}; // Relative moves for U, D, L, R\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (r == end_r && c == end_c) break; // Reached the end node, path found\n\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c}; // Store previous node for path reconstruction\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // Reconstruct path string by backtracking from end_r, end_c to start_r, start_c\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    \n    // If no path was found (end_r, end_c is unreachable)\n    if (dist[end_r][end_c] == -1) {\n        return \"\"; \n    }\n\n    while (curr_r != start_r || curr_c != start_c) {\n        int pr = prev[curr_r][curr_c].first;\n        int pc = prev[curr_r][curr_c].second;\n        \n        // This check guards against errors where prev pointers might be invalid (e.g., unreachable start)\n        if (pr == -1 || pc == -1) { \n            return \"\"; \n        }\n\n        // Determine the move character based on (pr,pc) to (curr_r,curr_c)\n        if (pr == curr_r - 1 && pc == curr_c) path_segment += 'D'; // Previous was up, current is down (move D)\n        else if (pr == curr_r + 1 && pc == curr_c) path_segment += 'U'; // Previous was down, current is up (move U)\n        else if (pr == curr_r && pc == curr_c - 1) path_segment += 'R'; // Previous was left, current is right (move R)\n        else if (pr == curr_r && pc == curr_c + 1) path_segment += 'L'; // Previous was right, current is left (move L)\n        // No 'else' for unexpected path step, assuming valid grid traversal guarantees this.\n        curr_r = pr;\n        curr_c = pc;\n    }\n    reverse(path_segment.begin(), path_segment.end()); // Path was built backwards, reverse to get correct order\n    return path_segment;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); // Optimize C++ standard streams for faster I/O\n    cin.tie(NULL);\n\n    cin >> N_global >> SI_global >> SJ_global;\n\n    grid_global.resize(N_global);\n    costs_global.assign(N_global, vector<int>(N_global));\n    is_road_global.assign(N_global, vector<bool>(N_global, false));\n    covered_status_global.assign(N_global, vector<bool>(N_global, false));\n\n    for (int i = 0; i < N_global; ++i) {\n        cin >> grid_global[i];\n        for (int j = 0; j < N_global; ++j) {\n            if (grid_global[i][j] == '#') {\n                is_road_global[i][j] = false;\n            } else {\n                is_road_global[i][j] = true;\n                costs_global[i][j] = grid_global[i][j] - '0'; // Convert char digit to int\n                total_road_squares_global++; // Count total road squares\n            }\n        }\n    }\n\n    // Precompute visibility for all road squares\n    precompute_visibility();\n\n    // Initial coverage from the starting point (si,sj)\n    update_coverage(SI_global, SJ_global);\n\n    int current_r = SI_global;\n    int current_c = SJ_global;\n    string full_path = \"\";\n\n    // Main loop: find next best node until all squares are covered\n    while (current_covered_count_global < total_road_squares_global) {\n        long long path_cost_to_next_node = 0;\n        // Find the next target that maximizes (new coverage / path cost)\n        pair<int, int> next_target = find_best_next_node(current_r, current_c, path_cost_to_next_node);\n\n        // If find_best_next_node returns the current position, it means no new valid target\n        // (with positive coverage gain and positive cost) was found. This should ideally\n        // not happen if there are still uncovered squares in a connected map.\n        // It implies the heuristic got stuck or all remaining squares are unreachable (which contradicts input guarantees).\n        if (next_target.first == current_r && next_target.second == current_c) {\n            break; // Break to prevent infinite loop if heuristic gets stuck\n        }\n\n        // Reconstruct path to the chosen target and append to the full path string\n        string segment = reconstruct_path_segment(current_r, current_c, next_target.first, next_target.second);\n        if (segment.empty() && (current_r != next_target.first || current_c != next_target.second)) {\n            // Path reconstruction failed for a non-trivial move. This indicates a logical issue\n            // (e.g., target chosen was actually unreachable despite Dijkstra finding a cost).\n            // Should not happen with current logic for connected components.\n            break; \n        }\n        full_path += segment;\n        \n        // Move to the new current position and update coverage status\n        current_r = next_target.first;\n        current_c = next_target.second;\n        update_coverage(current_r, current_c);\n    }\n\n    // After all squares are covered (or loop terminates), return to the starting point\n    string return_segment = reconstruct_path_segment(current_r, current_c, SI_global, SJ_global);\n    full_path += return_segment;\n\n    cout << full_path << endl; // Output the final path string\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <iomanip>\n#include <map>\n#include <cmath> // For std::round, std::clamp\n\n// Global constants and variables\nconst int MAX_SKILL_VAL = 100; // Upper bound for skills, based on problem generation info\nconst double INITIAL_S_GUESS = 20.0; // Initial guess for skill levels (from s_i,j generation range [20,60])\nconst double LEARNING_RATE_DENOM = 2.0; // Denominator for learning rate. Smaller value means faster learning.\n\nint N, M, K, R;\nstd::vector<std::vector<int>> D; // Task difficulties D[N][K]\nstd::vector<std::vector<int>> adj; // Adjacency list for dependencies: adj[u] lists tasks v that depend on u\nstd::vector<int> in_degree; // Number of prerequisites not yet completed for each task\n\nenum TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint total_tasks_completed = 0;\n\nstruct AssignedTask {\n    int task_id;\n    int start_day;\n};\n\nstd::vector<bool> member_is_free;\nstd::vector<AssignedTask> assigned_task_info; // assigned_task_info[member_idx]\nstd::vector<double> S_sum_D_task_difficulty; // Sum of D values for a task\n\n// Skill estimation\nstd::vector<std::vector<double>> S; // Estimated skill levels S[M][K]\nstd::vector<std::vector<double>> S_lower_bound; // Conservative lower bounds for skills\n\nint current_day = 0;\n\n// Set of ready tasks (in_degree is 0 and NOT_STARTED)\nstd::set<int> ready_tasks_set; // Stores task_id\n\n// Helper functions\ndouble calculate_w_internal(int member_idx, int task_idx) {\n    double w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += std::max(0.0, (double)D[task_idx][k] - S[member_idx][k]);\n    }\n    return w;\n}\n\nint calculate_t_estimated(int member_idx, int task_idx) {\n    double w = calculate_w_internal(member_idx, task_idx);\n    return std::max(1, (int)std::round(w)); // Round to nearest int, minimum 1\n}\n\n// Function to flush standard output\nvoid flush_stdout() {\n    std::cout << std::flush;\n}\n\n// Struct for candidate assignments to sort them\nstruct AssignmentCandidate {\n    int estimated_time;\n    int member_id;\n    int task_id;\n    // For tie-breaking\n    int out_degree; // Number of tasks unlocked by this task\n    double total_task_difficulty; // Sum of D values for the task\n\n    bool operator<(const AssignmentCandidate& other) const {\n        if (estimated_time != other.estimated_time) {\n            return estimated_time < other.estimated_time; // Prioritize shortest estimated time\n        }\n        // Tie-breaking for estimated_time\n        if (out_degree != other.out_degree) {\n            return out_degree > other.out_degree; // Prioritize tasks that unlock more tasks\n        }\n        if (total_task_difficulty != other.total_task_difficulty) {\n            return total_task_difficulty > other.total_task_difficulty; // Prioritize harder tasks\n        }\n        return task_id < other.task_id; // Stable sort by task_id\n    }\n};\n\nint main() {\n    // Faster I/O\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> K >> R;\n\n    D.resize(N, std::vector<int>(K));\n    S_sum_D_task_difficulty.resize(N);\n    for (int i = 0; i < N; ++i) {\n        double current_sum_D = 0;\n        for (int k = 0; k < K; ++k) {\n            std::cin >> D[i][k];\n            current_sum_D += D[i][k];\n        }\n        S_sum_D_task_difficulty[i] = current_sum_D;\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    task_status.resize(N, NOT_STARTED);\n    member_is_free.resize(M, true);\n    assigned_task_info.resize(M);\n\n    S.resize(M, std::vector<double>(K, INITIAL_S_GUESS));\n    S_lower_bound.resize(M, std::vector<double>(K, 0.0));\n\n    // Initialize ready_tasks_set: tasks with no dependencies or all dependencies met\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            ready_tasks_set.insert(i);\n        }\n    }\n\n    while (true) {\n        current_day++;\n\n        // Process daily input (completed tasks)\n        int n_completed;\n        std::cin >> n_completed;\n\n        if (n_completed == -1) {\n            break; // All tasks completed or max days reached, exit program\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_idx;\n            std::cin >> member_idx;\n            --member_idx; // 0-indexed\n\n            int completed_task_id = assigned_task_info[member_idx].task_id;\n            int start_day = assigned_task_info[member_idx].start_day;\n            int actual_t_ij = current_day - start_day + 1; // Actual days taken\n\n            // Update task status\n            task_status[completed_task_id] = COMPLETED;\n            total_tasks_completed++;\n\n            // Skill Estimation Update for member_idx\n            // Infer w_ij from actual_t_ij. If actual_t_ij == 1, assume w_ij=0 (most optimistic).\n            // Otherwise, assume w_ij = actual_t_ij, ignoring small random noise.\n            double observed_w = (actual_t_ij == 1) ? 0.0 : (double)actual_t_ij;\n            double current_predicted_w = calculate_w_internal(member_idx, completed_task_id);\n\n            // Strong evidence for S_lower_bound if task completed in 1 day\n            if (actual_t_ij == 1) { \n                for (int k = 0; k < K; ++k) {\n                    S_lower_bound[member_idx][k] = std::max(S_lower_bound[member_idx][k], (double)D[completed_task_id][k]);\n                }\n            } else { // actual_t_ij > 1, adjust S based on difference between predicted and observed w\n                double error = current_predicted_w - observed_w; // Positive if predicted was too high, negative if too low\n                int active_skills_count = 0; // Count skills where d_ik > S_jk currently\n                for (int k = 0; k < K; ++k) {\n                    if (D[completed_task_id][k] > S[member_idx][k]) {\n                        active_skills_count++;\n                    }\n                }\n\n                if (active_skills_count > 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (D[completed_task_id][k] > S[member_idx][k]) {\n                            // Adjust S[member_idx][k] to reduce the error.\n                            // If error > 0 (predicted w was too high), S[member_idx][k] needs to increase\n                            // If error < 0 (predicted w was too low), S[member_idx][k] needs to decrease\n                            S[member_idx][k] -= error / (active_skills_count * LEARNING_RATE_DENOM);\n                            S[member_idx][k] = std::clamp(S[member_idx][k], 0.0, (double)MAX_SKILL_VAL);\n                        }\n                    }\n                }\n            }\n\n            // Always apply lower bounds after any other adjustments to maintain consistency\n            for (int k = 0; k < K; ++k) {\n                S[member_idx][k] = std::max(S[member_idx][k], S_lower_bound[member_idx][k]);\n            }\n            \n            // Output skill predictions for visualization (round to nearest integer for output)\n            std::cout << \"#s \" << member_idx + 1;\n            for (int k = 0; k < K; ++k) {\n                std::cout << \" \" << static_cast<int>(std::round(S[member_idx][k]));\n            }\n            std::cout << std::endl;\n\n            // Free the member\n            member_is_free[member_idx] = true;\n\n            // Update in_degree for tasks dependent on the completed task\n            for (int dependent_task_id : adj[completed_task_id]) {\n                in_degree[dependent_task_id]--;\n                if (in_degree[dependent_task_id] == 0 && task_status[dependent_task_id] == NOT_STARTED) {\n                    ready_tasks_set.insert(dependent_task_id);\n                }\n            }\n        }\n\n        // Task Assignment Phase\n        std::vector<std::pair<int, int>> assignments_today;\n        std::vector<int> current_free_members;\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            if (member_is_free[m_idx]) {\n                current_free_members.push_back(m_idx);\n            }\n        }\n\n        // Prioritize a subset of ready tasks to consider for efficiency\n        std::vector<int> tasks_to_consider;\n        if (!ready_tasks_set.empty()) {\n            // Priority for selecting tasks to consider:\n            // High out_degree (unlocks more tasks), high average skill difficulty, then lower task_id\n            std::vector<std::pair<int, int>> sorted_ready_tasks; // (priority_score, task_id)\n            for(int tid : ready_tasks_set) {\n                // Heuristic score: combine out_degree (weighted) and average task difficulty\n                // Multiplying by 100 ensures out_degree has significant impact\n                int score = adj[tid].size() * 100 + static_cast<int>(S_sum_D_task_difficulty[tid] / K); \n                sorted_ready_tasks.push_back({score, tid});\n            }\n            std::sort(sorted_ready_tasks.rbegin(), sorted_ready_tasks.rend()); // Sort descending by score\n\n            // Limit the number of tasks considered to avoid O(M * N_ready * K) complexity\n            // Choose M * (some factor) or a fixed max (e.g., 200)\n            int num_to_consider = std::min((int)sorted_ready_tasks.size(), M * 15); \n            for (int i = 0; i < num_to_consider; ++i) {\n                tasks_to_consider.push_back(sorted_ready_tasks[i].second);\n            }\n        }\n\n        std::vector<AssignmentCandidate> candidates;\n        for (int m_idx : current_free_members) {\n            for (int t_idx : tasks_to_consider) {\n                if (task_status[t_idx] == NOT_STARTED) { // Double check task isn't assigned concurrently\n                    candidates.push_back({\n                        calculate_t_estimated(m_idx, t_idx),\n                        m_idx,\n                        t_idx,\n                        (int)adj[t_idx].size(),\n                        S_sum_D_task_difficulty[t_idx]\n                    });\n                }\n            }\n        }\n        std::sort(candidates.begin(), candidates.end());\n\n        // Greedily assign tasks based on sorted candidates\n        for (const auto& candidate : candidates) {\n            int m_idx = candidate.member_id;\n            int t_idx = candidate.task_id;\n\n            if (member_is_free[m_idx] && task_status[t_idx] == NOT_STARTED) {\n                assignments_today.push_back({m_idx + 1, t_idx + 1});\n                member_is_free[m_idx] = false;\n                task_status[t_idx] = IN_PROGRESS;\n                assigned_task_info[m_idx] = {t_idx, current_day}; // Store start day and task ID\n                ready_tasks_set.erase(t_idx); // Remove from ready set as it's now in progress\n            }\n            \n            // Break conditions: if all free members have been assigned OR all remaining tasks are assigned\n            if (assignments_today.size() == current_free_members.size() || \n                total_tasks_completed + assignments_today.size() == N) {\n                break; \n            }\n        }\n\n        // Output assignments for the day\n        std::cout << assignments_today.size();\n        for (const auto& p : assignments_today) {\n            std::cout << \" \" << p.first << \" \" << p.second;\n        }\n        std::cout << std::endl;\n        flush_stdout(); // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc006":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <set>\n#include <unordered_set>\n\n// --- Structs ---\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id; // 1-indexed original ID\n    Point p; // pickup\n    Point d; // delivery\n};\n\nenum NodeType {\n    PICKUP_TYPE = 0,\n    DELIVERY_TYPE = 1\n};\n\nstruct RouteNode {\n    int order_id;\n    NodeType type;\n    Point coord;\n};\n\n// --- Global Constants ---\nconst Point OFFICE = {400, 400};\nconst int NUM_TOTAL_ORDERS = 1000;\nconst int NUM_DELIVERIES_QUOTA = 50;\n\n// --- Random Number Generator ---\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\nlong long manhattan_dist(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\n// Calculate total distance for a route represented by a sequence of RouteNodes\nlong long calculate_total_route_distance(const std::vector<RouteNode>& route_nodes) {\n    long long total_dist = 0;\n    if (route_nodes.empty()) {\n        return manhattan_dist(OFFICE, OFFICE); // If no deliveries, just go to office and back (0 dist)\n    }\n\n    total_dist += manhattan_dist(OFFICE, route_nodes[0].coord);\n    for (size_t i = 0; i < route_nodes.size() - 1; ++i) {\n        total_dist += manhattan_dist(route_nodes[i].coord, route_nodes[i+1].coord);\n    }\n    total_dist += manhattan_dist(route_nodes.back().coord, OFFICE);\n    return total_dist;\n}\n\n// Generates an initial route using a greedy Nearest Neighbor heuristic.\n// `selected_order_ids` is a vector of 1-indexed original order IDs.\n// `all_orders_map` provides access to order details by ID.\nstd::vector<RouteNode> generate_nearest_neighbor_route(const std::vector<int>& selected_order_ids, \n                                                       const std::map<int, Order>& all_orders_map) {\n    std::vector<RouteNode> route;\n    std::unordered_set<int> unpicked_order_ids(selected_order_ids.begin(), selected_order_ids.end());\n    std::unordered_set<int> un_delivered_order_ids;\n\n    Point current_pos = OFFICE;\n\n    while (!unpicked_order_ids.empty() || !un_delivered_order_ids.empty()) {\n        std::vector<std::pair<long long, RouteNode>> candidates; \n\n        // Consider pickup points\n        for (int order_id : unpicked_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            long long d = manhattan_dist(current_pos, order.p);\n            candidates.push_back({d, {order_id, PICKUP_TYPE, order.p}});\n        }\n\n        // Consider delivery points\n        for (int order_id : un_delivered_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            long long d = manhattan_dist(current_pos, order.d);\n            candidates.push_back({d, {order_id, DELIVERY_TYPE, order.d}});\n        }\n\n        if (candidates.empty()) break; // Should not happen if logic is correct\n\n        // Find minimum distance among candidates\n        long long min_dist = candidates[0].first;\n        for (size_t i = 1; i < candidates.size(); ++i) {\n            if (candidates[i].first < min_dist) {\n                min_dist = candidates[i].first;\n            }\n        }\n\n        // Collect all candidates that achieve the minimum distance\n        std::vector<RouteNode> best_candidates_nodes;\n        for (const auto& cand : candidates) {\n            if (cand.first == min_dist) {\n                best_candidates_nodes.push_back(cand.second);\n            }\n        }\n        \n        // Randomly pick one of the best candidates (tie-breaking)\n        std::uniform_int_distribution<int> dist_cand_idx(0, best_candidates_nodes.size() - 1);\n        RouteNode chosen_node = best_candidates_nodes[dist_cand_idx(rng)];\n\n        route.push_back(chosen_node);\n        current_pos = chosen_node.coord;\n\n        if (chosen_node.type == PICKUP_TYPE) {\n            unpicked_order_ids.erase(chosen_node.order_id);\n            un_delivered_order_ids.insert(chosen_node.order_id);\n        } else { // DELIVERY_TYPE\n            un_delivered_order_ids.erase(chosen_node.order_id);\n        }\n    }\n    return route;\n}\n\n// Applies a node relocation local search operator.\n// Moves a randomly chosen node to a new random valid position in the route, respecting precedence.\n// This function now returns the new route AND the delta in distance from the old route.\nstd::pair<std::vector<RouteNode>, long long> relocate_node_and_calculate_delta(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist) {\n\n    if (current_route.size() < 2) return {current_route, 0}; // Need at least 2 nodes to meaningfully relocate\n\n    std::uniform_int_distribution<int> dist_move_idx(0, current_route.size() - 1);\n    int move_idx = dist_move_idx(rng);\n    RouteNode node_to_move = current_route[move_idx];\n\n    // Calculate distance contribution of node_to_move at its current position\n    Point p_before_old_pos = (move_idx == 0) ? OFFICE : current_route[move_idx - 1].coord;\n    Point p_after_old_pos = (move_idx == current_route.size() - 1) ? OFFICE : current_route[move_idx + 1].coord;\n    long long dist_removed_segment = manhattan_dist(p_before_old_pos, node_to_move.coord) +\n                                     manhattan_dist(node_to_move.coord, p_after_old_pos);\n    long long dist_merged_segment = manhattan_dist(p_before_old_pos, p_after_old_pos);\n    long long delta_from_removal = dist_merged_segment - dist_removed_segment;\n\n    // Create a temporary route with the node removed\n    std::vector<RouteNode> new_route_temp;\n    new_route_temp.reserve(current_route.size() - 1);\n    for (size_t i = 0; i < current_route.size(); ++i) {\n        if (i == (size_t)move_idx) continue;\n        new_route_temp.push_back(current_route[i]);\n    }\n    \n    int min_insert_idx = 0;\n    int max_insert_idx = new_route_temp.size();\n\n    if (node_to_move.type == PICKUP_TYPE) {\n        int Di_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == DELIVERY_TYPE) {\n                Di_pos = i;\n                break;\n            }\n        }\n        if (Di_pos != -1) { \n            max_insert_idx = Di_pos;\n        }\n    } else { // DELIVERY_TYPE\n        int Pi_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == PICKUP_TYPE) {\n                Pi_pos = i;\n                break;\n            }\n        }\n        if (Pi_pos != -1) { \n            min_insert_idx = Pi_pos + 1;\n        }\n    }\n    \n    if (min_insert_idx > max_insert_idx) { \n         // This can happen if, for example, a node is the last pickup and first delivery,\n         // and after removing it, its corresponding partner node is the only one left.\n         // Or if there are no valid positions. Fallback to full range, it might be safer to let the NN re-route.\n         // But for a valid original route, this shouldn't happen for a single relocation.\n         min_insert_idx = 0; \n         max_insert_idx = new_route_temp.size();\n    }\n    // If new_route_temp is empty, min_insert_idx and max_insert_idx should both be 0.\n    // std::uniform_int_distribution must have `a <= b`.\n    if (new_route_temp.empty()) { // Case when current_route has only 1 node and it was removed\n        min_insert_idx = 0;\n        max_insert_idx = 0;\n    }\n\n\n    std::uniform_int_distribution<int> dist_insert_pos(min_insert_idx, max_insert_idx);\n    int insert_pos = dist_insert_pos(rng); \n    \n    // Calculate distance contribution of inserting node_to_move at new_insert_pos\n    Point p_before_new_pos = (insert_pos == 0) ? OFFICE : new_route_temp[insert_pos - 1].coord;\n    Point p_after_new_pos = (insert_pos == new_route_temp.size()) ? OFFICE : new_route_temp[insert_pos].coord;\n    long long dist_new_segment = manhattan_dist(p_before_new_pos, node_to_move.coord) +\n                                 manhattan_dist(node_to_move.coord, p_after_new_pos);\n    long long dist_old_at_insert_point = manhattan_dist(p_before_new_pos, p_after_new_pos);\n    long long delta_from_insertion = dist_new_segment - dist_old_at_insert_point;\n\n    new_route_temp.insert(new_route_temp.begin() + insert_pos, node_to_move);\n\n    long long new_total_dist = current_total_dist + delta_from_removal + delta_from_insertion;\n\n    return {new_route_temp, new_total_dist};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // --- Input Reading ---\n    std::vector<Order> all_orders(NUM_TOTAL_ORDERS);\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        all_orders[i].id = i + 1; // 1-indexed\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 Selection (Greedy based on standalone cost) ---\n    std::vector<std::pair<long long, int>> order_costs(NUM_TOTAL_ORDERS); // {cost, original_id}\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        long long cost = manhattan_dist(OFFICE, all_orders[i].p) +\n                         manhattan_dist(all_orders[i].p, all_orders[i].d) +\n                         manhattan_dist(all_orders[i].d, OFFICE);\n        order_costs[i] = {cost, all_orders[i].id};\n    }\n    std::sort(order_costs.begin(), order_costs.end());\n\n    std::vector<int> current_selected_order_ids_vec;\n    std::map<int, Order> current_selected_orders_map;\n    // std::unordered_set<int> selected_order_set; // Not directly used in the SA loop, removed to simplify\n    std::vector<int> unselected_order_ids_vec;\n\n    for (int i = 0; i < NUM_DELIVERIES_QUOTA; ++i) {\n        int order_id = order_costs[i].second;\n        current_selected_order_ids_vec.push_back(order_id);\n        current_selected_orders_map[order_id] = all_orders[order_id - 1]; // Store 1-indexed\n        // selected_order_set.insert(order_id);\n    }\n    for (int i = NUM_DELIVERIES_QUOTA; i < NUM_TOTAL_ORDERS; ++i) {\n        unselected_order_ids_vec.push_back(order_costs[i].second);\n    }\n\n    // --- Initial Route Generation ---\n    std::vector<RouteNode> current_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n    long long current_total_dist = calculate_total_route_distance(current_route_nodes);\n\n    // --- Best Solution Tracking ---\n    long long best_total_dist = current_total_dist;\n    std::vector<RouteNode> best_route_nodes = current_route_nodes;\n    std::vector<int> best_selected_order_ids = current_selected_order_ids_vec;\n\n    // --- Simulated Annealing Parameters ---\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SEC = 1.95; // Slightly increased time limit\n    const double T_START = 5000.0;     // Initial temperature\n    const double T_END = 1.0;          // Final temperature\n    const double PROB_ORDER_SWAP = 0.05; // Probability of performing an order swap\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_selected_idx(0, NUM_DELIVERIES_QUOTA - 1);\n    \n    // --- Simulated Annealing Loop ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_sec = std::chrono::duration<double>(current_time - start_time).count();\n\n        if (elapsed_sec >= TIME_LIMIT_SEC) {\n            break;\n        }\n\n        double progress = elapsed_sec / TIME_LIMIT_SEC;\n        double current_T = T_START * std::pow(T_END / T_START, progress);\n\n        long long new_total_dist;\n        std::vector<RouteNode> new_route_nodes;\n        bool orders_swapped_this_iter = false; \n\n        // Declare swap related indices outside the if block for scope\n        int out_vec_idx = -1; \n        int in_vec_idx = -1;\n        \n        if (dist_0_1(rng) < PROB_ORDER_SWAP && !unselected_order_ids_vec.empty()) {\n            // --- Order Swap Operation ---\n            out_vec_idx = dist_selected_idx(rng);\n            int order_out_id = current_selected_order_ids_vec[out_vec_idx];\n\n            std::uniform_int_distribution<int> dist_unselected_idx(0, unselected_order_ids_vec.size() - 1);\n            in_vec_idx = dist_unselected_idx(rng);\n            int order_in_id = unselected_order_ids_vec[in_vec_idx];\n\n            // Perform the swap temporarily\n            current_selected_order_ids_vec[out_vec_idx] = order_in_id;\n            unselected_order_ids_vec[in_vec_idx] = order_out_id;\n            \n            // selected_order_set.erase(order_out_id); // Removed selected_order_set to simplify\n            // selected_order_set.insert(order_in_id);\n\n            current_selected_orders_map.erase(order_out_id);\n            current_selected_orders_map[order_in_id] = all_orders[order_in_id - 1];\n\n            // Re-generate route for the new set of orders\n            new_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n            new_total_dist = calculate_total_route_distance(new_route_nodes);\n            orders_swapped_this_iter = true;\n        } else {\n            // --- Route Relocation Operation ---\n            // The relocate_node_and_calculate_delta function now returns both new_route and new_total_dist\n            std::tie(new_route_nodes, new_total_dist) = relocate_node_and_calculate_delta(current_route_nodes, current_total_dist);\n        }\n\n        // --- Acceptance Criteria ---\n        if (new_total_dist < current_total_dist) {\n            current_total_dist = new_total_dist;\n            current_route_nodes = new_route_nodes;\n        } else {\n            double prob_acceptance = std::exp((double)(current_total_dist - new_total_dist) / current_T);\n            if (dist_0_1(rng) < prob_acceptance) {\n                current_total_dist = new_total_dist;\n                current_route_nodes = new_route_nodes;\n            } else {\n                // Reject: if orders were swapped, revert them\n                if (orders_swapped_this_iter) {\n                    // Revert the last swap using the stored indices\n                    int order_in_id = current_selected_order_ids_vec[out_vec_idx]; // This is the new order at the old position\n                    int order_out_id = unselected_order_ids_vec[in_vec_idx];     // This is the old order at the new position in unselected\n\n                    current_selected_order_ids_vec[out_vec_idx] = order_out_id;\n                    unselected_order_ids_vec[in_vec_idx] = order_in_id;\n                    \n                    current_selected_orders_map.erase(order_in_id);\n                    current_selected_orders_map[order_out_id] = all_orders[order_out_id - 1];\n                }\n            }\n        }\n\n        // --- Update Best Solution ---\n        if (current_total_dist < best_total_dist) {\n            best_total_dist = current_total_dist;\n            best_route_nodes = current_route_nodes;\n            best_selected_order_ids = current_selected_order_ids_vec;\n        }\n    }\n\n    // --- Output ---\n    std::cout << NUM_DELIVERIES_QUOTA;\n    for (int id : best_selected_order_ids) {\n        std::cout << \" \" << id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_route_nodes.size() + 2; // +2 for start and end office points\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (const auto& node : best_route_nodes) {\n        std::cout << \" \" << node.coord.x << \" \" << node.coord.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric> // For std::iota (used by DSU internally or for basic DSU setup)\n#include <iomanip> // For std::fixed, std::setprecision, if needed for debugging\n#include <algorithm> // For std::min/max, etc.\n\n// AC Library DSU\n// Make sure to include this in your project or copy it if not using a judge that provides it.\n// Example: if using local library, it might be #include \"atcoder/dsu.hpp\"\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    long long d; // Precomputed rounded Euclidean distance\n};\n\n// Function to calculate rounded Euclidean distance\nlong long calculate_d(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    // dx*dx + dy*dy can be up to 800^2 + 800^2 = 1,280,000. Fits in long long.\n    // sqrt of 1,280,000 is approx 1131.\n    return std::round(std::sqrt(static_cast<double>(dx * dx + dy * dy)));\n}\n\n// Global constants for problem size\nconst int N_NODES = 400;\nconst int M_EDGES = 1995;\n\n// Heuristic parameters for tuning\n// TAU_MIN: Initial strictness for cost ratio l_i / d_i\n// TAU_MAX: Final leniency for cost ratio l_i / d_i when close to connecting all nodes\n// URGENCY_BUFFER: How many \"extra\" remaining edges we can afford to reject before becoming desperate.\n// These values are based on typical performance for similar online MST heuristics.\nconst double TAU_MIN = 1.3;\nconst double TAU_MAX = 2.2;\nconst int URGENCY_BUFFER = 15;\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    // Read vertex coordinates\n    std::vector<Point> vertices(N_NODES);\n    for (int i = 0; i < N_NODES; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    // Read edge endpoints and precompute d_i (rounded Euclidean distance)\n    std::vector<EdgeInfo> edges(M_EDGES);\n    for (int i = 0; i < M_EDGES; ++i) {\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].d = calculate_d(vertices[edges[i].u], vertices[edges[i].v]);\n    }\n\n    // Initialize DSU for N_NODES vertices\n    atcoder::dsu dsu(N_NODES);\n    int edges_taken_count = 0; // Keep track of how many edges we have adopted\n\n    // Process edges one by one\n    for (int i = 0; i < M_EDGES; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        long long d_val = edges[i].d;\n\n        // Read the actual length l_i for the current edge\n        long long l_val;\n        std::cin >> l_val;\n\n        int decision = 0; // Default decision: 0 (reject)\n\n        // Check if u and v are already connected\n        if (!dsu.same(u, v)) {\n            // u and v are in different components, this edge could connect them.\n            \n            // Get current number of connected components\n            int current_components = dsu.groups().size();\n            // Number of additional edges (merges) needed to connect all components\n            // (N_NODES - 1) total edges for MST, (N_NODES - current_components) edges already taken to reduce components.\n            // So, (N_NODES - 1) - (N_NODES - current_components) = current_components - 1 more edges are needed.\n            int needed_to_connect = current_components - 1; \n\n            // Number of candidate edges remaining to be revealed (excluding the current one)\n            int remaining_candidates = M_EDGES - (i + 1);\n\n            // Calculate the cost ratio l_i / d_i.\n            // d_val is guaranteed to be >= 6 based on problem constraints (min distance > 5).\n            double cost_ratio = static_cast<double>(l_val) / d_val;\n\n            // --- Urgency Check ---\n            // If we're running low on candidate edges relative to what's needed,\n            // we must take this edge to ensure connectivity.\n            // URGENCY_BUFFER provides a safety margin; if needed_to_connect is roughly\n            // equal to or greater than remaining_candidates minus the buffer, we become urgent.\n            if (needed_to_connect >= remaining_candidates - URGENCY_BUFFER) {\n                decision = 1; // Adopt this edge to ensure connectivity\n            } else {\n                // --- Adaptive Threshold Check ---\n                // If not urgent, be selective based on the cost ratio and progress.\n                // The threshold for accepting an edge adapts based on how many edges\n                // we've already adopted relative to the total N-1 needed for an MST.\n                double progress_ratio_taken = static_cast<double>(edges_taken_count) / (N_NODES - 1.0);\n                // current_tau interpolates between TAU_MIN (when edges_taken_count is 0)\n                // and TAU_MAX (when edges_taken_count is N_NODES-1).\n                double current_tau = TAU_MIN + (TAU_MAX - TAU_MIN) * progress_ratio_taken;\n\n                if (cost_ratio <= current_tau) {\n                    decision = 1; // Adopt if its cost is within the current acceptable threshold\n                }\n            }\n        }\n\n        // Apply the decision: merge components if adopted\n        if (decision == 1) {\n            dsu.merge(u, v);\n            edges_taken_count++;\n        }\n\n        // Output the decision (0 or 1) and flush stdout\n        std::cout << decision << std::endl;\n    }\n\n    return 0;\n}\n","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <set>\n#include <algorithm>\n#include <tuple> // For std::tie\n#include <map>   // For BFS path reconstruction\n\nusing namespace std;\n\n// Global constants\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: U, D, L, R\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    // Overload operators for use in sets/maps and comparisons\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    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// Game state variables\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type; // Not used for movement prediction in this solution\nvector<Point> human_pos;\n\n// Board state: 0=passable, 1=impassable (wall)\nvector<vector<int>> board(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n\n// Global BFS data structures (re-used each time BFS is called)\nvector<vector<int>> dist_bfs;\nvector<vector<Point>> parent_bfs;\n\n// Function to check if a point is within grid boundaries\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// BFS to find shortest path distance from start to target_dest_for_human.\n// Also stores parent pointers to reconstruct the first step of the path.\n// `start`: The starting point for BFS (human's current position).\n// `target_dest_for_human`: The specific cell the human wants to move to.\n// `current_blocked_this_turn`: Set of cells that will become walls this turn by other humans.\n// `current_moved_to_this_turn_targets`: Set of cells that other humans are planning to move to this turn.\n// `all_human_current_pos`: Current positions of all humans (to avoid pathfinding through other humans' current spots).\n// `self_idx`: Index of the human for whom BFS is being run (to allow passing through its own start cell).\nint bfs(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n        const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    dist_bfs.assign(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    parent_bfs.assign(GRID_SIZE, vector<Point>(GRID_SIZE, {-1, -1}));\n    queue<Point> q;\n\n    q.push(start);\n    dist_bfs[start.r][start.c] = 0;\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        if (curr == target_dest_for_human) {\n            return dist_bfs[curr.r][curr.c]; // Target reached\n        }\n\n        // Explore 4 cardinal neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.r + DR[i];\n            int nc = curr.c + DC[i];\n            Point next = {nr, nc};\n\n            // Basic checks: within bounds, not visited yet\n            if (!is_valid(nr, nc) || dist_bfs[nr][nc] != -1) continue;\n\n            // Check if 'next' cell is impassable due to existing walls or planned blocks\n            if (board[nr][nc] == 1) continue; // Existing permanent wall\n            if (current_blocked_this_turn.count(next)) continue; // Blocked by another human this turn\n\n            // Check if 'next' cell is a target for another human's move this turn\n            if (current_moved_to_this_turn_targets.count(next)) continue;\n            \n            // Check if 'next' cell is currently occupied by another human (who isn't moving out of it)\n            bool is_other_human_current_pos = false;\n            for(int h_idx_other = 0; h_idx_other < M; ++h_idx_other) {\n                if (h_idx_other == self_idx) continue; // Current human can pass through its own start\n                if (all_human_current_pos[h_idx_other] == next) {\n                    is_other_human_current_pos = true;\n                    break;\n                }\n            }\n            if (is_other_human_current_pos) continue; // Impassable if another human is currently there\n\n            // If all checks pass, 'next' is a valid step\n            dist_bfs[nr][nc] = dist_bfs[curr.r][curr.c] + 1;\n            parent_bfs[nr][nc] = curr;\n            q.push(next);\n        }\n    }\n    return -1; // Target not reachable\n}\n\n// Reconstructs the character for the first move from 'start' to 'target_dest_for_human' based on BFS path.\nchar get_move_char(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n                   const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    if (bfs(start, target_dest_for_human, current_blocked_this_turn, current_moved_to_this_turn_targets, all_human_current_pos, self_idx) == -1) {\n        return '.'; // No path found\n    }\n\n    // Path reconstruction: find the first step from 'start' towards 'target_dest_for_human'\n    Point curr = target_dest_for_human;\n    // Walk back from target until we find the child of 'start'\n    while (parent_bfs[curr.r][curr.c] != start) {\n        curr = parent_bfs[curr.r][curr.c];\n        if (curr.r == -1 || curr.c == -1) return '.'; // Safety break for invalid parent\n    }\n\n    // 'curr' is now the first step from 'start'\n    for (int i = 0; i < 4; ++i) {\n        if (start.r + DR[i] == curr.r && start.c + DC[i] == curr.c) {\n            return MOVE_CHARS[i]; // Return corresponding move character\n        }\n    }\n    return '.'; // Should not be reached if BFS found a path\n}\n\n// Structure to represent a rectangle (inclusive coordinates, 0-indexed)\nstruct Rect {\n    int r1, c1, r2, c2;\n    int area() const { \n        if (r1 < 0 || c1 < 0 || r2 >= GRID_SIZE || c2 >= GRID_SIZE || r1 > r2 || c1 > c2) return 0; // Handle invalid rectangles\n        return (r2 - r1 + 1) * (c2 - c1 + 1); \n    }\n    // Check if a point is inside the rectangle\n    bool contains(Point p) const {\n        return p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2;\n    }\n};\n\nRect target_rect = {0, 0, 0, 0}; // The main region humans will try to enclose\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read initial pet information\n    cin >> N;\n    pet_pos.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i];\n        pet_pos[i].r--; // Convert to 0-indexed\n        pet_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // Read initial human information\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].r >> human_pos[i].c;\n        human_pos[i].r--; // Convert to 0-indexed\n        human_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // --- Initialization Phase: Find the best target rectangle ---\n    long long max_heuristic_score = -1; \n    Rect best_initial_rect = {-1, -1, -1, -1}; // Initialize with an invalid rectangle\n\n    // Brute force search for the best pet-free rectangle\n    for (int r1 = 0; r1 < GRID_SIZE; ++r1) {\n        for (int c1 = 0; c1 < GRID_SIZE; ++c1) {\n            for (int r2 = r1; r2 < GRID_SIZE; ++r2) {\n                for (int c2 = c1; c2 < GRID_SIZE; ++c2) {\n                    Rect current_rect = {r1, c1, r2, c2};\n                    bool is_pet_free = true;\n                    // Check if any pet is inside the current rectangle\n                    for (int i = 0; i < N; ++i) {\n                        if (current_rect.contains(pet_pos[i])) {\n                            is_pet_free = false;\n                            break;\n                        }\n                    }\n\n                    if (is_pet_free) {\n                        long long current_area = current_rect.area();\n                        if (current_area == 0) continue; // Skip 0-area rectangles\n                        \n                        long long dist_sum = 0;\n                        // Calculate sum of Manhattan distances from humans to their closest perimeter cell of `current_rect`\n                        vector<Point> perimeter_of_rect_itself;\n                        for (int c = c1; c <= c2; ++c) {\n                            perimeter_of_rect_itself.push_back({r1, c});\n                            if (r1 != r2) perimeter_of_rect_itself.push_back({r2, c});\n                        }\n                        for (int r = r1 + 1; r < r2; ++r) { // Start from r1+1 to avoid double-counting corners with top/bottom rows\n                            perimeter_of_rect_itself.push_back({r, c1});\n                            if (c1 != c2) perimeter_of_rect_itself.push_back({r, c2});\n                        }\n                        \n                        // If perimeter is empty (e.g. invalid rect), assign a high penalty.\n                        // A valid single cell (1x1 rect) has a perimeter of 1 point.\n                        if (!perimeter_of_rect_itself.empty()) {\n                            for (int i = 0; i < M; ++i) {\n                                int min_dist_to_perimeter = 100000; // Initialize with a large value\n                                for (const auto& p_cell : perimeter_of_rect_itself) {\n                                    min_dist_to_perimeter = min(min_dist_to_perimeter, abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c));\n                                }\n                                dist_sum += min_dist_to_perimeter;\n                            }\n                        } else { \n                            dist_sum = 100000 * M; // High penalty for unapproachable/empty perimeter\n                        }\n\n                        // Heuristic score: (Area) - (Weight * Sum_of_Distances)\n                        // A weight of 1 is chosen to balance area against human travel time.\n                        long long current_heuristic_score = current_area - dist_sum * 1; \n\n                        if (current_heuristic_score > max_heuristic_score) {\n                            max_heuristic_score = current_heuristic_score;\n                            best_initial_rect = current_rect;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback: If no pet-free rectangle found or area is too small.\n    if (best_initial_rect.area() == 0 || best_initial_rect.area() < M * 5) { \n        target_rect = {5, 5, 24, 24}; // Default to 20x20 central square (0-indexed)\n    } else {\n        target_rect = best_initial_rect;\n    }\n\n    // Generate the set of actual target wall cells that humans will block\n    // These are cells adjacent to target_rect, but outside target_rect.\n    set<Point> wall_target_cells_set;\n    for (int r_cell = 0; r_cell < GRID_SIZE; ++r_cell) {\n        for (int c_cell = 0; c_cell < GRID_SIZE; ++c_cell) {\n            Point p = {r_cell, c_cell};\n            if (target_rect.contains(p)) continue; // Cannot block inside the target rect\n            bool is_adjacent_to_target_rect_internal = false;\n            for (int d = 0; d < 4; ++d) {\n                Point neighbor = {r_cell + DR[d], c_cell + DC[d]};\n                if (target_rect.contains(neighbor)) {\n                    is_adjacent_to_target_rect_internal = true;\n                    break;\n                }\n            }\n            if (is_adjacent_to_target_rect_internal) {\n                wall_target_cells_set.insert(p);\n            }\n        }\n    }\n    // Convert to vector for easier iteration with indices.\n    vector<Point> target_wall_goals_vector(wall_target_cells_set.begin(), wall_target_cells_set.end());\n    \n    // `human_target_wall_goals[i]` stores the specific wall cell that human 'i' is trying to block.\n    vector<Point> human_target_wall_goals(M, {-1,-1}); \n\n    // --- Main Loop: 300 turns of human actions and pet movements ---\n    for (int turn = 0; turn < MAX_TURNS; ++turn) {\n        // 1. Determine `can_block_grid`: which cells are valid to block this turn.\n        // Initialize to true, then mark invalid ones.\n        vector<vector<bool>> can_block_grid(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n        // Pets make cells unblockable\n        for (int i = 0; i < N; ++i) {\n            Point p = pet_pos[i];\n            // Cell containing pet is unblockable\n            if(is_valid(p.r, p.c)) can_block_grid[p.r][p.c] = false; \n            // Cells adjacent to a pet are unblockable\n            for (int d = 0; d < 4; ++d) { \n                int nr = p.r + DR[d];\n                int nc = p.c + DC[d];\n                if (is_valid(nr, nc)) {\n                    can_block_grid[nr][nc] = false;\n                }\n            }\n        }\n        // Humans make cells unblockable (their own position)\n        for (int i = 0; i < M; ++i) {\n            Point h = human_pos[i];\n            if(is_valid(h.r, h.c)) can_block_grid[h.r][h.c] = false; \n        }\n\n        // 2. Human Action Planning\n        vector<char> actions_output(M, '.'); // Stores the final action character for each human\n        vector<Point> next_human_pos_candidates(M); // Stores each human's position AFTER actions\n        for(int i=0; i<M; ++i) next_human_pos_candidates[i] = human_pos[i]; // Default: stay put\n\n        set<Point> current_blocked_this_turn;       // Cells chosen to be blocked by humans THIS turn\n        set<Point> current_moved_to_this_turn_targets; // Cells chosen to be moved into by humans THIS turn\n\n        // 2.1. Update each human's block goal\n        // Humans greedily pick the closest, unblocked, blockable wall target cell that is not already assigned to another human.\n        for (int i = 0; i < M; ++i) {\n            // Re-assign goal if current goal is completed, invalid, or already blocked\n            if (human_target_wall_goals[i].r == -1 || \n                !is_valid(human_target_wall_goals[i].r, human_target_wall_goals[i].c) ||\n                board[human_target_wall_goals[i].r][human_target_wall_goals[i].c] == 1) { \n                \n                Point best_goal = {-1,-1};\n                int min_dist = 100000;\n\n                // Temporarily track goals assigned to other humans (within this turn's assignment phase)\n                set<Point> temp_assigned_goals;\n                for(int j=0; j<M; ++j) {\n                    if (j != i && human_target_wall_goals[j].r != -1) {\n                        temp_assigned_goals.insert(human_target_wall_goals[j]);\n                    }\n                }\n\n                for (const auto& p_cell : target_wall_goals_vector) { // Iterate over actual wall target cells\n                    // Check if the wall target cell is currently:\n                    //   1. Passable (not already a permanent wall)\n                    //   2. Blockable (no pets nearby, not occupied by human/pet)\n                    //   3. Not already being blocked by another human this turn (from current_blocked_this_turn)\n                    //   4. Not already assigned as a goal to another human (for current goal assignment phase)\n                    if (board[p_cell.r][p_cell.c] == 0 && can_block_grid[p_cell.r][p_cell.c] && \n                        !current_blocked_this_turn.count(p_cell) && !temp_assigned_goals.count(p_cell)) {\n                        \n                        // Distance from human's current position to the cell *they would block*\n                        int dist = abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c); // Manhattan distance\n                        if (dist < min_dist) {\n                            min_dist = dist;\n                            best_goal = p_cell;\n                        }\n                    }\n                }\n                human_target_wall_goals[i] = best_goal; // Assign the new best goal\n            }\n        }\n        \n        // 2.2. Phase 1: Determine BLOCK actions\n        // Humans who are adjacent to their block goal perform the block action.\n        for (int i = 0; i < M; ++i) {\n            if (human_target_wall_goals[i].r != -1) {\n                Point goal_to_block = human_target_wall_goals[i]; // This is the cell to make impassable\n                for (int d = 0; d < 4; ++d) { // Check if human is adjacent to this goal_to_block\n                    if (human_pos[i].r + DR[d] == goal_to_block.r && human_pos[i].c + DC[d] == goal_to_block.c) { \n                        // Human is adjacent to goal_to_block. Can they block it?\n                        if (board[goal_to_block.r][goal_to_block.c] == 0 && can_block_grid[goal_to_block.r][goal_to_block.c] && !current_blocked_this_turn.count(goal_to_block)) {\n                            actions_output[i] = BLOCK_CHARS[d]; // Set block action\n                            current_blocked_this_turn.insert(goal_to_block); // Mark as blocked for this turn\n                            board[goal_to_block.r][goal_to_block.c] = 1; // Temporarily update board for pathfinding in Phase 2\n                            human_target_wall_goals[i] = {-1,-1}; // Goal achieved, reset\n                        }\n                        break; // A human can only perform one action (block or move)\n                    }\n                }\n            }\n        }\n        \n        // 2.3. Phase 2: Determine MOVE actions for humans who did not block.\n        // Use a priority queue to resolve conflicts for moving to the same cell.\n        struct MoveCandidate {\n            int human_idx;\n            Point next_pos; // The cell human will move TO\n            char move_char;\n            int priority; // Higher priority (e.g., closer to goal) is better\n            bool operator<(const MoveCandidate& other) const {\n                return priority < other.priority; // Min-priority queue for default, so this makes it max-priority.\n            }\n        };\n        priority_queue<MoveCandidate> move_queue;\n\n        for (int i = 0; i < M; ++i) {\n            if (actions_output[i] == '.') { // Only if human didn't block in Phase 1\n                Point wall_cell_to_block = human_target_wall_goals[i];\n                if (wall_cell_to_block.r != -1) { // If there's still a wall target to move towards\n                    // Find the best position for the human to *stand* in order to block 'wall_cell_to_block'.\n                    // This means finding a cell adjacent to 'wall_cell_to_block' that is pathable for the human.\n                    Point target_human_stand_pos = {-1,-1};\n                    int min_dist_to_stand_pos = 100000;\n\n                    for(int d=0; d<4; ++d) {\n                        Point candidate_stand_pos = {wall_cell_to_block.r + DR[d], wall_cell_to_block.c + DC[d]};\n                        \n                        // Preliminary checks for a valid 'stand_pos' (more thorough check in BFS)\n                        if (is_valid(candidate_stand_pos.r, candidate_stand_pos.c) &&\n                            board[candidate_stand_pos.r][candidate_stand_pos.c] == 0 && // Not existing wall\n                            !current_blocked_this_turn.count(candidate_stand_pos)) { // Not blocked this turn\n                            \n                            int dist = abs(human_pos[i].r - candidate_stand_pos.r) + abs(human_pos[i].c - candidate_stand_pos.c); // Manhattan distance\n                            if (dist < min_dist_to_stand_pos) {\n                                min_dist_to_stand_pos = dist;\n                                target_human_stand_pos = candidate_stand_pos;\n                            }\n                        }\n                    }\n\n                    if (target_human_stand_pos.r != -1 && target_human_stand_pos != human_pos[i]) { // Found a valid stand position, and it's not current position\n                        // Use BFS to get the first move character towards target_human_stand_pos\n                        char move_c = get_move_char(human_pos[i], target_human_stand_pos, \n                                                    current_blocked_this_turn, current_moved_to_this_turn_targets, \n                                                    human_pos, i); \n                        if (move_c != '.') { // If a path was found\n                            Point first_step = human_pos[i]; // Will be updated\n                            for (int d_idx = 0; d_idx < 4; ++d_idx) {\n                                if (MOVE_CHARS[d_idx] == move_c) {\n                                    first_step = {human_pos[i].r + DR[d_idx], human_pos[i].c + DC[d_idx]};\n                                    break;\n                                }\n                            }\n                            // Priority is based on negative distance to target_human_stand_pos. Smaller distance means higher priority\n                            move_queue.push({i, first_step, move_c, -min_dist_to_stand_pos}); \n                        }\n                    }\n                }\n            }\n        }\n\n        // Process the move_queue to resolve conflicts (multiple humans wanting to move to the same cell)\n        while (!move_queue.empty()) {\n            MoveCandidate mc = move_queue.top();\n            move_queue.pop();\n\n            if (actions_output[mc.human_idx] == '.') { // If human hasn't been assigned an action yet\n                // Check if the target cell for this move is free (not blocked or targeted by another human)\n                if (!current_blocked_this_turn.count(mc.next_pos) && !current_moved_to_this_turn_targets.count(mc.next_pos)) {\n                    actions_output[mc.human_idx] = mc.move_char; // Assign the move action\n                    next_human_pos_candidates[mc.human_idx] = mc.next_pos; // Update planned position\n                    current_moved_to_this_turn_targets.insert(mc.next_pos); // Mark as targeted\n                }\n                // Else: Conflict occurred, the human stays put (action remains '.')\n            }\n        }\n\n        // 3. Output actions for all humans\n        for (int i = 0; i < M; ++i) {\n            cout << actions_output[i];\n        }\n        cout << endl; // Newline after all actions\n        fflush(stdout); // Crucial for interactive problems\n\n        // 4. Update game state (board and human_pos) based on actions\n        for (int i = 0; i < M; ++i) {\n            // If the action was a block, update the board state permanently\n            // Check if it's not a '.' and not one of the move characters ('U', 'D', 'L', 'R')\n            if (actions_output[i] != '.' && string(MOVE_CHARS).find(actions_output[i]) == string::npos) {\n                Point blocked_cell = human_pos[i]; // Default value\n                char block_char = actions_output[i];\n                for(int d=0; d<4; ++d) {\n                    if (BLOCK_CHARS[d] == block_char) {\n                        blocked_cell = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                        break;\n                    }\n                }\n                if (is_valid(blocked_cell.r, blocked_cell.c)) { // Sanity check for blocked_cell\n                    board[blocked_cell.r][blocked_cell.c] = 1; // Mark cell as impassable\n                }\n            }\n            human_pos[i] = next_human_pos_candidates[i]; // Update human positions\n        }\n\n        // 5. Read pet movements and update pet positions\n        string pet_moves_str;\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves_str;\n            if (pet_moves_str == \".\") continue; // Pet did not move\n            \n            for (char move_char : pet_moves_str) {\n                for (int d = 0; d < 4; ++d) {\n                    if (MOVE_CHARS[d] == move_char) {\n                        pet_pos[i].r += DR[d];\n                        pet_pos[i].c += DC[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int H = 20;\nconst int W = 20;\nconst int MAX_PATH_LENGTH = 200;\n\n// Global variables for problem input\nint start_r, start_c, target_r, target_c;\ndouble p_forget_val;\nbool has_wall_right[H][W - 1]; // wall between (r,c) and (r,c+1)\nbool has_wall_down[H - 1][W];  // wall between (r,c) and (r+1,c)\n\n// Directions for movement\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar move_chars[] = {'U', 'D', 'L', 'R'};\n\n// Helper function to calculate next position, staying if wall or boundary\npair<int, int> get_next_pos(int r, int c, char move_char) {\n    int nr = r, nc = c; // Default to staying\n    if (move_char == 'U') {\n        if (r > 0 && !has_wall_down[r - 1][c]) {\n            nr = r - 1;\n        }\n    } else if (move_char == 'D') {\n        if (r < H - 1 && !has_wall_down[r][c]) {\n            nr = r + 1;\n        }\n    } else if (move_char == 'L') {\n        if (c > 0 && !has_wall_right[r][c - 1]) {\n            nc = c - 1;\n        }\n    } else if (move_char == 'R') {\n        if (c < W - 1 && !has_wall_right[r][c]) {\n            nc = c + 1;\n        }\n    }\n    return {nr, nc};\n}\n\n// DP states (declared globally to avoid reallocations and for performance)\nvector<vector<double>> current_dp_state(H, vector<double>(W));\nvector<vector<double>> next_dp_state(H, vector<double>(W));\n\n// Evaluates a given path string\ndouble evaluate(const string& path) {\n    // Reset initial state for a new path evaluation\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_dp_state[i][j] = 0.0;\n        }\n    }\n    current_dp_state[start_r][start_c] = 1.0;\n\n    double total_expected_score = 0.0;\n\n    for (int k = 0; k < path.length(); ++k) {\n        // Clear next_dp_state for this turn's calculations\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                next_dp_state[i][j] = 0.0;\n            }\n        }\n\n        double prob_reach_this_turn = 0.0;\n        char move_char = path[k];\n\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                if (current_dp_state[r][c] == 0.0) continue; // No probability mass\n\n                // Option 1: Forgets char (prob p_forget_val), stays at (r,c)\n                // current_dp_state[r][c] is prob of being at (r,c) AND NOT AT TARGET.\n                // So (r,c) cannot be (target_r, target_c).\n                // Thus, staying at (r,c) does not make him reach the target.\n                next_dp_state[r][c] += current_dp_state[r][c] * p_forget_val;\n\n                // Option 2: Remembers char (prob 1-p_forget_val), moves according to move_char\n                pair<int, int> next_pos = get_next_pos(r, c, move_char);\n                int nr = next_pos.first;\n                int nc = next_pos.second;\n\n                if (nr == target_r && nc == target_c) {\n                    // Reached target at turn k+1\n                    prob_reach_this_turn += current_dp_state[r][c] * (1.0 - p_forget_val);\n                } else {\n                    // Did not reach target\n                    next_dp_state[nr][nc] += current_dp_state[r][c] * (1.0 - p_forget_val);\n                }\n            }\n        }\n\n        total_expected_score += prob_reach_this_turn * (401.0 - (k + 1));\n        current_dp_state.swap(next_dp_state); // Efficiently update current_dp_state\n    }\n    return total_expected_score;\n}\n\n// BFS to find the shortest path\nstring get_bfs_path() {\n    vector<vector<int>> dist(H, vector<int>(W, -1));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> move_to_parent(H, vector<char>(W, ' '));\n    queue<pair<int, int>> q;\n\n    q.push({start_r, start_c});\n    dist[start_r][start_c] = 0;\n\n    // Using std::queue for simplicity, it's efficient enough for 400 cells\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        if (r == target_r && c == target_c) break; // Found target\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            char move_char = move_chars[i];\n\n            // Check boundaries and walls (using consistent logic with get_next_pos)\n            bool can_move = true;\n            if (move_char == 'U') {\n                if (r == 0 || has_wall_down[r - 1][c]) can_move = false;\n            } else if (move_char == 'D') {\n                if (r == H - 1 || has_wall_down[r][c]) can_move = false;\n            } else if (move_char == 'L') {\n                if (c == 0 || has_wall_right[r][c - 1]) can_move = false;\n            } else if (move_char == 'R') {\n                if (c == W - 1 || has_wall_right[r][c]) can_move = false;\n            }\n\n            if (!can_move) continue;\n            \n            // If can_move, the next position is (nr, nc)\n            if (dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                parent[nr][nc] = {r, c};\n                move_to_parent[nr][nc] = move_char;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path_str = \"\";\n    int curr_r = target_r;\n    int curr_c = target_c;\n    \n    // According to problem statement, start and target are guaranteed to be different\n    // and all squares are reachable. So dist[target_r][target_c] should not be -1.\n    while (curr_r != start_r || curr_c != start_c) {\n        path_str += move_to_parent[curr_r][curr_c];\n        pair<int, int> p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read input\n    cin >> start_r >> start_c >> target_r >> target_c >> p_forget_val;\n\n    for (int i = 0; i < H; ++i) {\n        string row_h;\n        cin >> row_h;\n        for (int j = 0; j < W - 1; ++j) {\n            has_wall_right[i][j] = (row_h[j] == '1');\n        }\n    }\n    for (int i = 0; i < H - 1; ++i) {\n        string row_v;\n        cin >> row_v;\n        for (int j = 0; j < W; ++j) {\n            has_wall_down[i][j] = (row_v[j] == '1');\n        }\n    }\n\n    // Timer setup\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0; // Use 1.95 seconds to be safe\n\n    // Initial path (BFS shortest path)\n    string best_path_str = get_bfs_path();\n    double best_score = evaluate(best_path_str);\n    string current_path_str = best_path_str;\n    double current_score = best_score;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    // SA parameters\n    double T_start = 2000.0; // Starting temperature\n    double T_end = 1.0;     // Ending temperature\n\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) break;\n\n        double T = T_start * pow(T_end / T_start, elapsed_ms / TIME_LIMIT_MS);\n        \n        string new_path_str = current_path_str;\n        \n        // Adaptive operation selection probabilities\n        double current_len = current_path_str.length();\n        double insert_prob, delete_prob, change_prob;\n\n        // Tune probabilities based on current path length\n        if (current_len < MAX_PATH_LENGTH * 0.5) { // If path is very short\n            insert_prob = 0.5; delete_prob = 0.1; change_prob = 0.4;\n        } else if (current_len < MAX_PATH_LENGTH * 0.8) { // If path is moderately short\n            insert_prob = 0.4; delete_prob = 0.2; change_prob = 0.4;\n        } else if (current_len > MAX_PATH_LENGTH * 0.95) { // If path is very long\n            insert_prob = 0.05; delete_prob = 0.5; change_prob = 0.45;\n        } else { // Default or moderate length\n            insert_prob = 0.25; delete_prob = 0.25; change_prob = 0.5;\n        }\n        \n        double op_choice_rand = prob_dist(rng);\n\n        // --- Operation 1: Change character ---\n        if (op_choice_rand < change_prob) { \n            if (new_path_str.empty()) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            char original_char = new_path_str[idx];\n            \n            char new_char;\n            do {\n                uniform_int_distribution<int> char_dist(0, 3);\n                new_char = move_chars[char_dist(rng)];\n            } while (new_char == original_char);\n            \n            new_path_str[idx] = new_char;\n        } \n        // --- Operation 2: Insert character ---\n        else if (op_choice_rand < change_prob + insert_prob) {\n            if (new_path_str.length() >= MAX_PATH_LENGTH) continue;\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length()); \n            int idx = idx_dist(rng);\n            uniform_int_distribution<int> char_dist(0, 3);\n            char char_to_insert = move_chars[char_dist(rng)];\n            \n            new_path_str.insert(idx, 1, char_to_insert);\n        } \n        // --- Operation 3: Delete character ---\n        else { \n            if (new_path_str.empty()) continue; // Path cannot be empty\n            if (new_path_str.length() == 1 && (start_r == target_r && start_c == target_c)) continue; // Don't make path empty if start=target\n\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            \n            new_path_str.erase(idx, 1);\n        }\n\n        // Evaluate new path\n        double new_score = evaluate(new_path_str);\n\n        // SA acceptance criterion\n        if (new_score > current_score || prob_dist(rng) < exp((new_score - current_score) / T)) {\n            current_score = new_score;\n            current_path_str = new_path_str;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path_str = current_path_str;\n            }\n        }\n    }\n\n    cout << best_path_str << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple> // For std::tuple\n\n// Define grid dimensions\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0=Left, 1=Up, 2=Right, 3=Down\n// di, dj: changes in row and column for each direction\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// initial_to[tile_type][entry_direction] -> exit_direction\n// Provided by problem statement\nconst int initial_to[8][4] = {\n    {1, 0, -1, -1}, // Type 0: L-U curve (0-1)\n    {-1, 2, 1, -1}, // Type 1: U-R curve (1-2)\n    {-1, -1, 3, 2}, // Type 2: R-D curve (2-3)\n    {3, -1, -1, 0}, // Type 3: D-L curve (3-0)\n    {1, 0, 3, 2},   // Type 4: L-U and R-D (0-1, 2-3)\n    {3, 2, 1, 0},   // Type 5: U-R and D-L (1-2, 3-0)\n    {2, -1, 0, -1}, // Type 6: horizontal straight (0-2)\n    {-1, 3, -1, 1}  // Type 7: vertical straight (1-3)\n};\n\n// Stores the initial tile types read from input\nstd::vector<std::vector<int>> initial_tiles(H, std::vector<int>(W));\n// Stores the current rotation for each tile (0-3)\nstd::vector<std::vector<int>> current_rotations(H, std::vector<int>(W));\n\n// Precompute effective_to table for faster lookup\n// effective_to[initial_tile_type][rotation_count][entry_direction] -> exit_direction\nint effective_to[8][4][4];\n\nvoid precompute_effective_to() {\n    for (int t_initial = 0; t_initial < 8; ++t_initial) {\n        for (int r_rot = 0; r_rot < 4; ++r_rot) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // 1. Convert absolute entry direction to tile's original orientation\n                int d_base = (d_entry - r_rot + 4) % 4;\n                \n                // 2. Find exit direction in tile's original orientation\n                int exit_base = initial_to[t_initial][d_base];\n                \n                // 3. If broken, mark as -1\n                if (exit_base == -1) {\n                    effective_to[t_initial][r_rot][d_entry] = -1;\n                } else {\n                    // 4. Convert exit direction back to absolute orientation\n                    effective_to[t_initial][r_rot][d_entry] = (exit_base + r_rot) % 4;\n                }\n            }\n        }\n    }\n}\n\n// Function to calculate the exit direction for a given tile and entry\ninline int get_exit_dir(int r, int c, int d_entry) {\n    return effective_to[initial_tiles[r][c]][current_rotations[r][c]][d_entry];\n}\n\nstruct VisitedState {\n    int id;  // Unique ID for the current calculate_score() call or active path\n    int len; // Path length when this state was first visited in current active path\n};\n// Use static to initialize once to {0,0} for all entries\nstatic VisitedState visited_tracking[H][W][4];\nstatic int current_search_id = 0; // Incremented for each calculate_score() call\n\nlong long calculate_score() {\n    std::vector<long long> loop_lengths;\n    current_search_id++; // New unique ID for this score calculation\n\n    // `active_path_id` is used to mark nodes *currently in the path exploration*.\n    // `current_search_id` is used to mark nodes that have been *fully processed*\n    // (either part of a completed cycle or a path that dead-ended/merged).\n    int active_path_id = current_search_id + 1;\n\n    for (int r = 0; r < H; ++r) {\n        for (int c = 0; c < W; ++c) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                if (visited_tracking[r][c][d_entry].id == current_search_id ||\n                    visited_tracking[r][c][d_entry].id == active_path_id) {\n                    continue; // Already processed or currently being explored\n                }\n\n                int curr_r = r;\n                int curr_c = c;\n                int curr_d_entry = d_entry;\n                long long path_len = 0;\n                \n                // Store nodes in current path for later global marking\n                std::vector<std::tuple<int, int, int>> nodes_in_current_path_segment;\n\n                while (true) {\n                    // Check if current node is out of bounds\n                    if (curr_r < 0 || curr_r >= H || curr_c < 0 || curr_c >= W) {\n                        break; // Out of bounds\n                    }\n                    \n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == active_path_id) {\n                        // Cycle detected! Current node was visited in this active path.\n                        long long cycle_start_len = visited_tracking[curr_r][curr_c][curr_d_entry].len;\n                        loop_lengths.push_back(path_len - cycle_start_len);\n                        break;\n                    }\n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == current_search_id) {\n                        // Merged into an already processed path/cycle (from an earlier exploration in this `calculate_score` call)\n                        break;\n                    }\n\n                    // Mark current node as 'in active path' and record its length\n                    visited_tracking[curr_r][curr_c][curr_d_entry] = {active_path_id, (int)path_len};\n                    nodes_in_current_path_segment.emplace_back(curr_r, curr_c, curr_d_entry); // Store nodes for later global marking\n\n                    int d_exit = get_exit_dir(curr_r, curr_c, curr_d_entry);\n                    if (d_exit == -1) {\n                        break; // Broken line\n                    }\n\n                    int next_r = curr_r + di[d_exit];\n                    int next_c = curr_c + dj[d_exit];\n                    int next_d_entry = (d_exit + 2) % 4; // Direction into the next tile\n                    path_len++;\n\n                    curr_r = next_r;\n                    curr_c = next_c;\n                    curr_d_entry = next_d_entry;\n                }\n\n                // After path ends (break from loop), mark all nodes visited in `nodes_in_current_path_segment`\n                // as 'processed for current_search_id'. This includes nodes part of detected cycles.\n                for (const auto& node : nodes_in_current_path_segment) {\n                    visited_tracking[std::get<0>(node)][std::get<1>(node)][std::get<2>(node)].id = current_search_id;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) {\n        return 0;\n    }\n\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend()); // Sort descending\n    return loop_lengths[0] * loop_lengths[1];\n}\n\n// Random number generator\nstd::mt19937 mt;\n\nvoid solve() {\n    auto start_time = std::chrono::high_resolution_clock::now();\n\n    // Read initial tile types\n    for (int i = 0; i < H; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < W; ++j) {\n            initial_tiles[i][j] = row_str[j] - '0';\n        }\n    }\n\n    precompute_effective_to();\n\n    // Initialize random number generator\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\n    mt.seed(seed);\n\n    // Initial solution: random rotations\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_rotations[i][j] = mt() % 4;\n        }\n    }\n\n    std::vector<std::vector<int>> best_rotations = current_rotations;\n    long long current_score = calculate_score();\n    long long best_score = current_score;\n\n    // Simulated Annealing parameters\n    // T_START chosen to be large enough given potential max score ~3.24 * 10^6\n    double T_START = 200000.0; \n    double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds out of 2.0s\n    \n    long long iteration_count = 0;\n\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) { \n            break;\n        }\n\n        // Linear cooling schedule\n        double T = T_START * (1.0 - elapsed_ms / TIME_LIMIT_MS);\n        if (T < 0.1) T = 0.1; // Prevent T from becoming zero or negative too early\n\n        // Generate neighbor: pick one random tile and change its rotation\n        int r_idx = mt() % H;\n        int c_idx = mt() % W;\n        int old_rot = current_rotations[r_idx][c_idx];\n        int new_rot = (old_rot + (mt() % 3) + 1) % 4; // Ensures new_rot is different from old_rot\n\n        current_rotations[r_idx][c_idx] = new_rot;\n        long long neighbor_score = calculate_score();\n        \n        long long delta_score = neighbor_score - current_score;\n\n        if (delta_score > 0 || std::uniform_real_distribution<double>(0.0, 1.0)(mt) < std::exp(delta_score / T)) {\n            current_score = neighbor_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations;\n            }\n        } else {\n            // Revert to old rotation\n            current_rotations[r_idx][c_idx] = old_rot;\n        }\n        iteration_count++;\n    }\n\n    // Output best rotations\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++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}\n","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\n// --- Constants and Global Variables ---\nconst long long TIME_LIMIT_MS = 2800; // 2.8 seconds for computation\nconst double T_START = 200.0;        // Initial temperature for Simulated Annealing\nconst double T_END = 0.01;           // Final temperature for Simulated Annealing\n\nint N;               // Board size\nint MAX_S_VALUE;     // Maximum possible S value (N*N - 1)\nlong long MAX_MOVES; // Maximum allowed operations (T = 2 * N^3)\n// W_S will be initialized based on MAX_MOVES for better prioritization\nlong double W_S;     \nlong double W_K = 1.0; // Weight for K (number of operations) in energy function\n\n// Directions for empty square movement\n// 0: U (empty moves up, tile from (er-1, ec) slides D into (er, ec))\n// 1: D (empty moves down, tile from (er+1, ec) slides U into (er, ec))\n// 2: L (empty moves left, tile from (er, ec-1) slides R into (er, ec))\n// 3: R (empty moves right, tile from (er, ec+1) slides L into (er, ec))\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_char[] = {'U', 'D', 'L', 'R'};\nint opposite_dir[] = {1, 0, 3, 2}; // e.g., opposite of U(0) is D(1)\n\n// Global random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- DSU Structure for Score Calculation ---\nstruct DSU {\n    vector<int> parent;\n    vector<int> comp_size;\n    vector<int> num_edges;\n    vector<bool> has_cycle;\n    int num_cells;\n\n    DSU(int n_squared) : num_cells(n_squared) {\n        parent.resize(num_cells);\n        iota(parent.begin(), parent.end(), 0); // Initialize parent[i] = i\n        comp_size.assign(num_cells, 1);        // Each cell starts as a component of size 1\n        num_edges.assign(num_cells, 0);        // Each component starts with 0 edges\n        has_cycle.assign(num_cells, false);    // No cycles initially\n    }\n\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\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            // Union by size/rank: attach smaller tree to larger tree\n            if (comp_size[root_i] < comp_size[root_j])\n                swap(root_i, root_j);\n            parent[root_j] = root_i;\n            comp_size[root_i] += comp_size[root_j];\n            num_edges[root_i] += num_edges[root_j]; // Add edges from merged component\n            num_edges[root_i]++;                     // Add the new edge\n            has_cycle[root_i] = has_cycle[root_i] || has_cycle[root_j]; // Propagate cycle info\n        } else {\n            num_edges[root_i]++;         // Edge added within the same component\n            has_cycle[root_i] = true;    // This implies a cycle\n        }\n    }\n};\n\n// --- BoardState Structure ---\nstruct BoardState {\n    vector<vector<int>> board;\n    int empty_r, empty_c;\n    string moves;\n    int last_move_idx; // Index of the last move (0:U, 1:D, 2:L, 3:R), -1 if no previous move\n\n    BoardState(int n_val) : board(n_val, vector<int>(n_val)), empty_r(-1), empty_c(-1), last_move_idx(-1) {}\n\n    // Calculate the score S for the current board configuration\n    // S is the number of vertices in the largest tree component (connected and acyclic)\n    int calculate_S() const {\n        DSU dsu(N * N);\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // The empty cell is not part of the graph formed by tiles\n                if (r == empty_r && c == empty_c) continue;\n\n                int current_tile = board[r][c];\n                int current_idx = r * N + c;\n\n                // Check downward connection with (r+1, c)\n                if (r + 1 < N) {\n                    // Ensure the neighbor cell (r+1,c) is not the empty square\n                    if (!(r + 1 == empty_r && c == empty_c)) { \n                        int neighbor_tile = board[r+1][c];\n                        int neighbor_idx = (r+1) * N + c;\n                        // An edge exists if (r,c) has a downward line (bit 8) AND (r+1,c) has an upward line (bit 2)\n                        if ((current_tile & 8) && (neighbor_tile & 2)) {\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n                // Check rightward connection with (r, c+1)\n                if (c + 1 < N) {\n                    // Ensure the neighbor cell (r,c+1) is not the empty square\n                    if (!(r == empty_r && c + 1 == empty_c)) {\n                        int neighbor_tile = board[r][c+1];\n                        int neighbor_idx = r * N + (c+1);\n                        // An edge exists if (r,c) has a rightward line (bit 4) AND (r,c+1) has a leftward line (bit 1)\n                        if ((current_tile & 4) && (neighbor_tile & 1)) {\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n            }\n        }\n\n        int max_S = 0;\n        // Iterate through all possible cell indices to find roots.\n        // It's more robust to iterate all cells and then find their roots rather than only roots_to_check\n        // if some cells might not have been visited as part of an edge.\n        // However, for connected component logic, iterating unique roots after processing all edges is standard.\n        // The issue is if a tile is totally isolated, it won't be part of any union,\n        // and its root would be itself.\n        // The original logic `dsu.parent[i] == i` ensures checking all components.\n        for (int i = 0; i < N * N; ++i) {\n            // Skip the empty square when evaluating components.\n            if (i == empty_r * N + empty_c) continue;\n\n            if (dsu.parent[i] == i) { // If 'i' is the root of a component\n                // A component is considered a \"tree\" for scoring if it has no cycles\n                // (and its number of edges is (num_vertices - 1)).\n                // The DSU logic correctly maintains `has_cycle` and `num_edges` such that\n                // if `!dsu.has_cycle[i]`, then `dsu.num_edges[i]` will be `dsu.comp_size[i] - 1`.\n                if (!dsu.has_cycle[i]) {\n                    max_S = max(max_S, dsu.comp_size[i]);\n                }\n            }\n        }\n        return max_S;\n    }\n};\n\n// --- Main Function ---\nint main() {\n    ios_base::sync_with_stdio(false); // Faster I/O\n    cin.tie(NULL);\n\n    cin >> N >> MAX_MOVES;\n\n    MAX_S_VALUE = N * N - 1; // Total number of tiles, excluding the empty one\n    W_S = (long double)MAX_MOVES; // Set W_S to T for strong prioritization of S\n\n    BoardState current_state(N);\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            current_state.board[i][j] = stoi(string(1, row_str[j]), nullptr, 16);\n            if (current_state.board[i][j] == 0) { // Found the empty square\n                current_state.empty_r = i;\n                current_state.empty_c = j;\n            }\n        }\n    }\n\n    // Initialize best state with the initial state\n    BoardState best_state = current_state;\n    int current_S = current_state.calculate_S();\n    int current_K = 0; // Number of operations starts at 0\n\n    int best_S = current_S;\n    int best_K = current_K;\n\n    // Calculate initial energy\n    long double current_energy = (long double)(MAX_S_VALUE - current_S) * W_S + current_K * W_K;\n    long double best_energy = current_energy;\n\n    auto start_time = chrono::steady_clock::now();\n    long long iter_count = 0;\n\n    uniform_real_distribution<long double> dist_prob(0.0, 1.0); // For acceptance probability\n\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() < TIME_LIMIT_MS) {\n        iter_count++;\n\n        // Calculate current temperature based on elapsed time\n        long double progress = (long double)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / TIME_LIMIT_MS;\n        long double temp = T_START * pow(T_END / T_START, progress);\n        \n        // Prevent division by zero or numerical instability if temperature becomes extremely small.\n        // T_END=0.01 already ensures it won't be zero, but this is a safe guard.\n        if (temp < 1e-12) temp = 1e-12; \n\n        // Determine possible moves\n        vector<int> possible_moves_indices;\n        for (int i = 0; i < 4; ++i) { // Iterate through U, D, L, R directions\n            int next_empty_r = current_state.empty_r + dr[i];\n            int next_empty_c = current_state.empty_c + dc[i];\n\n            // Check if move is within board boundaries\n            if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                // If there was a previous move, avoid immediately reversing it\n                if (current_state.last_move_idx == -1 || i != opposite_dir[current_state.last_move_idx]) {\n                    possible_moves_indices.push_back(i);\n                }\n            }\n        }\n        \n        // Fallback: If no non-reverting moves are possible (e.g., in a corner or along an edge,\n        // and only one move leads back to the interior or a different position),\n        // then consider all valid moves, including reversing. This prevents getting stuck.\n        if (possible_moves_indices.empty()) {\n            for (int i = 0; i < 4; ++i) {\n                int next_empty_r = current_state.empty_r + dr[i];\n                int next_empty_c = current_state.empty_c + dc[i];\n                if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                     possible_moves_indices.push_back(i);\n                }\n            }\n            // If still empty, it means no moves are possible, which shouldn't happen for N>=2.\n            // N >= 6 is guaranteed by problem constraints.\n            if (possible_moves_indices.empty()) { \n                 continue;\n            }\n        }\n\n        // Pick a random move from the possible options\n        uniform_int_distribution<int> dist_valid_dir(0, possible_moves_indices.size() - 1);\n        int move_idx = possible_moves_indices[dist_valid_dir(rng)];\n\n        int prev_empty_r = current_state.empty_r;\n        int prev_empty_c = current_state.empty_c;\n        int moved_tile_r = prev_empty_r + dr[move_idx];\n        int moved_tile_c = prev_empty_c + dc[move_idx];\n        \n        // Create the next state by copying the current state and applying the move.\n        // Board size is small enough (10x10 max) that copying is efficient.\n        BoardState next_state = current_state;\n        \n        // Perform the move: tile at (moved_tile_r, moved_tile_c) moves to (prev_empty_r, prev_empty_c)\n        next_state.board[prev_empty_r][prev_empty_c] = next_state.board[moved_tile_r][moved_tile_c];\n        next_state.board[moved_tile_r][moved_tile_c] = 0; // The original spot of the moved tile becomes empty\n        next_state.empty_r = moved_tile_r;\n        next_state.empty_c = moved_tile_c;\n        next_state.moves += dir_char[move_idx]; // Record the move\n        next_state.last_move_idx = move_idx;     // Update last move index\n\n        int next_K = next_state.moves.length();\n        if (next_K > MAX_MOVES) {\n            // If this move exceeds the maximum allowed operations, reject it immediately.\n            // The problem statement clearly says \"If the number of operations exceeds T... it will be judged as WA\".\n            // Therefore, we must ensure our final output adheres to this limit.\n            // Continuing the search with K > MAX_MOVES might lead to a solution within the limit later,\n            // but for safety and simplicity, we currently discard such paths during exploration.\n            continue; \n        }\n\n        // Calculate S and energy for the next state\n        int next_S = next_state.calculate_S();\n        long double next_energy = (long double)(MAX_S_VALUE - next_S) * W_S + next_K * W_K;\n\n        long double delta_E = next_energy - current_energy;\n\n        // Simulated Annealing acceptance criteria\n        if (delta_E < 0 || dist_prob(rng) < exp(-delta_E / temp)) {\n            // Accept the new state\n            current_state = next_state;\n            current_S = next_S;\n            current_K = next_K;\n            current_energy = next_energy;\n            \n            // Update the best solution found so far\n            // Prioritize S first, then K (fewer moves for same S)\n            if (current_S > best_S) {\n                best_S = current_S;\n                best_K = current_K;\n                best_state = current_state;\n                best_energy = current_energy;\n            } else if (current_S == best_S && current_K < best_K) { \n                best_K = current_K;\n                best_state = current_state;\n                best_energy = current_energy;\n            }\n        }\n    }\n\n    // Output debug information to stderr\n    cerr << \"Iterations: \" << iter_count << endl;\n    cerr << \"Best S: \" << best_S << \" / \" << MAX_S_VALUE << endl;\n    cerr << \"Best K: \" << best_K << \" / \" << MAX_MOVES << endl;\n    \n    // Calculate final score for the best found state based on problem formula\n    long long final_score;\n    if (best_S == MAX_S_VALUE) {\n        final_score = round(500000.0 * (2.0 - (long double)best_K / MAX_MOVES));\n    } else {\n        final_score = round(500000.0 * ((long double)best_S / MAX_S_VALUE));\n    }\n    cerr << \"Final Score: \" << final_score << endl;\n\n    // Output the sequence of moves to stdout\n    cout << best_state.moves << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <algorithm>\n#include <unordered_map>\n\n// Using long long for coordinates and intermediate calculations for lines\n// Max value for Ax + By + C is ~2*10^18, fits in long long.\n\nusing namespace std;\n\n// --- Time and Random Number Generator ---\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nuniform_int_distribution<long long> dist_line_coord(-1000000000LL, 1000000000LL); // Line point coordinates\nuniform_int_distribution<int> dist_k_idx(0, 99); // For picking which line to perturb, K is fixed at 100\nuniform_int_distribution<int> dist_coord_choice(0, 3); // For picking px, py, qx, qy to perturb\nuniform_real_distribution<double> dist_01(0.0, 1.0);\n\n// --- Global variables ---\nint N_strawberries;\nint K_max_cuts; \nvector<int> a_attendees(11); // a_d for d=1 to 10. a_attendees[0] unused.\nlong long total_attendees_demand = 0; // Sum of a_d\n\nstruct Strawberry {\n    long long x, y;\n};\nvector<Strawberry> strawberries;\n\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C; // Line equation Ax + By + C = 0\n\n    Line(long long p1x, long long p1y, long long p2x, long long p2y) :\n        px(p1x), py(p1y), qx(p2x), qy(p2y) {\n        // Ensure distinct points; if identical, slightly move one to make it distinct.\n        if (p1x == p2x && p1y == p2y) { \n            p2x++; // Move qx by 1 unit to make it distinct. Within bounds if p2x is not max.\n            if (p2x > 1000000000LL) p2x -= 2; // If max, move other way.\n        }\n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n        \n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        // Normalize such that A is positive, or if A is 0, B is positive.\n        // This ensures a canonical representation for the line.\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n    Line() : px(0), py(0), qx(1), qy(0), A(0), B(-1), C(0) {} // Default horizontal line y=0\n\n    void perturb(double temp_ratio) {\n        long long perturb_magnitude = (long long)(2e8 * temp_ratio) + 1; // Range decreases with temp_ratio (0 to 1)\n        if (perturb_magnitude < 10) perturb_magnitude = 10;\n        \n        long long old_px = px, old_py = py, old_qx = qx, old_qy = qy; // Store all old values for potential revert\n        \n        long long *coord_ptr;\n        switch (dist_coord_choice(rng)) {\n            case 0: coord_ptr = &px; break;\n            case 1: coord_ptr = &py; break;\n            case 2: coord_ptr = &qx; break;\n            default: coord_ptr = &qy; break;\n        }\n        long long new_coord_val = *coord_ptr + uniform_int_distribution<long long>(-perturb_magnitude, perturb_magnitude)(rng);\n        *coord_ptr = max(-1000000000LL, min(1000000000LL, new_coord_val));\n\n        // After perturbing, ensure points are distinct. If not, revert to original.\n        if (px == qx && py == qy) {\n            px = old_px; py = old_py; qx = old_qx; qy = old_qy;\n        }\n        \n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n\n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n};\n\n// Custom hash for vector<char> for unordered_map\nstruct VecCharHash {\n    std::size_t operator()(const std::vector<char>& v) const {\n        std::size_t seed = v.size();\n        for (char i : v) {\n            seed ^= (std::size_t)i + 0x9e3779b9 + (seed << 6) + (seed >> 2);\n        }\n        return seed;\n    }\n};\n\n// State variables for Simulated Annealing\nvector<vector<char>> strawberry_line_sides_current; // strawberry_line_sides_current[j][i] is sign for strawberry j w.r.t line i\nvector<bool> strawberry_is_lost_current; // strawberry_is_lost_current[j] is true if strawberry j is on any line\nunordered_map<vector<char>, int, VecCharHash> piece_strawberry_counts_current; // Counts of strawberries for each unique line side vector\nvector<long long> b_d_current(11, 0); // Current counts of pieces with d strawberries\nlong long current_score = 0;\nvector<Line> current_lines;\n\n\n// Function to calculate score based on a given b_d vector\nlong long calculate_score(const vector<long long>& b_d_vec) {\n    long long actual_distributed = 0;\n    for (int d = 1; d <= 10; ++d) {\n        actual_distributed += min(a_attendees[d], (int)b_d_vec[d]);\n    }\n    // Score formula: round(10^6 * sum(min(a_d,b_d)) / sum(a_d))\n    if (total_attendees_demand == 0) return 0; // Avoid division by zero\n    return round(1e6 * (double)actual_distributed / total_attendees_demand);\n}\n\n// Function to generate a random line (for initial solution or full replacement)\nLine generate_random_line() {\n    long long p1x, p1y, p2x, p2y;\n    do {\n        p1x = dist_line_coord(rng);\n        p1y = dist_line_coord(rng);\n        p2x = dist_line_coord(rng);\n        p2y = dist_line_coord(rng);\n    } while (p1x == p2x && p1y == p2y); // Loop until distinct points are generated\n    return Line(p1x, p1y, p2x, p2y);\n}\n\n\n// Performs a full evaluation of the given set of lines.\n// Populates strawberry_line_sides_current, strawberry_is_lost_current, \n// piece_strawberry_counts_current, b_d_current, and current_score.\nvoid full_evaluate(const vector<Line>& lines) {\n    strawberry_line_sides_current.assign(N_strawberries, vector<char>(K_max_cuts));\n    strawberry_is_lost_current.assign(N_strawberries, false);\n    piece_strawberry_counts_current.clear();\n    fill(b_d_current.begin(), b_d_current.end(), 0);\n\n    for (int j = 0; j < N_strawberries; ++j) {\n        for (int i = 0; i < K_max_cuts; ++i) {\n            long long val = lines[i].A * strawberries[j].x + lines[i].B * strawberries[j].y + lines[i].C;\n            if (val == 0) {\n                strawberry_is_lost_current[j] = true;\n                break; // This strawberry is lost, no need to check other lines\n            }\n            strawberry_line_sides_current[j][i] = (val > 0 ? 1 : -1);\n        }\n        if (!strawberry_is_lost_current[j]) {\n            piece_strawberry_counts_current[strawberry_line_sides_current[j]]++;\n        }\n    }\n\n    for (const auto& pair : piece_strawberry_counts_current) {\n        if (pair.second > 0 && pair.second <= 10) { \n            b_d_current[pair.second]++;\n        }\n    }\n    current_score = calculate_score(b_d_current);\n}\n\nvoid solve() {\n    cin >> N_strawberries >> K_max_cuts;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a_attendees[d];\n        total_attendees_demand += a_attendees[d];\n    }\n    strawberries.resize(N_strawberries);\n    for (int i = 0; i < N_strawberries; ++i) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n\n    // Initial solution: K_max_cuts random lines\n    current_lines.resize(K_max_cuts);\n    for (int i = 0; i < K_max_cuts; ++i) {\n        current_lines[i] = generate_random_line();\n    }\n    \n    // Perform initial full evaluation\n    full_evaluate(current_lines);\n\n    vector<Line> best_lines = current_lines;\n    long long best_score = current_score;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.95; // seconds\n\n    double T_start = 1e7; \n    double T_end = 1e-1;   // Final temperature, low enough to accept only very good changes towards the end\n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double temp_ratio = elapsed_time / TIME_LIMIT; // Goes from 0.0 to 1.0\n        double T = T_start * pow(T_end / T_start, temp_ratio); // Exponential cooling schedule\n\n        // Choose a line to perturb\n        int line_idx_to_perturb = dist_k_idx(rng);\n        Line original_line_at_idx = current_lines[line_idx_to_perturb];\n        Line candidate_line = original_line_at_idx;\n        candidate_line.perturb(1.0 - temp_ratio); // Perturb range decreases as temp_ratio approaches 1.0\n\n        // --- Simulate changes and calculate new_score ---\n        // Temporary state for the candidate solution. These are copies.\n        vector<long long> temp_b_d = b_d_current;\n        unordered_map<vector<char>, int, VecCharHash> temp_piece_strawberry_counts = piece_strawberry_counts_current;\n\n        // Vectors to store changes needed to commit if accepted.\n        // These store the *new* state for 'line_idx_to_perturb' or 'is_lost'.\n        vector<char> next_signs_at_idx(N_strawberries);\n        vector<bool> next_is_lost_status(N_strawberries);\n\n        // Iterate through all strawberries to simulate changes\n        for (int j = 0; j < N_strawberries; ++j) {\n            bool was_lost_j = strawberry_is_lost_current[j];\n            char old_sign_at_idx_j = was_lost_j ? 0 : strawberry_line_sides_current[j][line_idx_to_perturb];\n\n            long long val = candidate_line.A * strawberries[j].x + candidate_line.B * strawberries[j].y + candidate_line.C;\n            char new_sign_at_idx_j = (val == 0) ? 0 : (val > 0 ? 1 : -1);\n\n            // Store proposed new state for this strawberry in temporary commit vectors\n            next_signs_at_idx[j] = new_sign_at_idx_j;\n            next_is_lost_status[j] = (new_sign_at_idx_j == 0);\n\n            // Check if this strawberry's *overall piece status* changes.\n            // Case 1: Was lost, remains lost. No change to any piece count for this strawberry.\n            if (was_lost_j && (new_sign_at_idx_j == 0)) {\n                continue;\n            }\n            // Case 2: Was not lost, remains not lost, and sign for line_idx doesn't change. No change.\n            if (!was_lost_j && !(new_sign_at_idx_j == 0) && (old_sign_at_idx_j == new_sign_at_idx_j)) {\n                continue;\n            }\n            \n            // This strawberry's effective piece status changes, so update temp_b_d and temp_piece_strawberry_counts\n            \n            // If it was in a piece, remove it from old piece (before its modification)\n            if (!was_lost_j) { \n                int old_count = temp_piece_strawberry_counts[strawberry_line_sides_current[j]];\n                if (old_count >= 1 && old_count <= 10) {\n                    temp_b_d[old_count]--;\n                }\n                temp_piece_strawberry_counts[strawberry_line_sides_current[j]]--;\n            }\n\n            // If it now belongs to a piece, add it to the new piece\n            if (!(new_sign_at_idx_j == 0)) { // If it is not lost\n                // Construct the new key by taking the old key and changing sign for line_idx_to_perturb\n                vector<char> new_key_j = strawberry_line_sides_current[j]; \n                new_key_j[line_idx_to_perturb] = new_sign_at_idx_j; \n                \n                temp_piece_strawberry_counts[new_key_j]++;\n                int new_count = temp_piece_strawberry_counts[new_key_j];\n\n                if (new_count >= 1 && new_count <= 10) {\n                    temp_b_d[new_count]++;\n                }\n            }\n        }\n        \n        long long new_score = calculate_score(temp_b_d);\n\n        if (new_score > current_score || dist_01(rng) < exp((double)(new_score - current_score) / T)) {\n            // Accept the change\n            current_lines[line_idx_to_perturb] = candidate_line;\n            b_d_current = temp_b_d;\n            piece_strawberry_counts_current = temp_piece_strawberry_counts;\n            current_score = new_score;\n\n            // Commit changes to strawberry_line_sides_current and strawberry_is_lost_current for all strawberries\n            for (int j = 0; j < N_strawberries; ++j) {\n                strawberry_is_lost_current[j] = next_is_lost_status[j];\n                if (!strawberry_is_lost_current[j]) {\n                    strawberry_line_sides_current[j][line_idx_to_perturb] = next_signs_at_idx[j];\n                }\n            }\n\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_lines = current_lines;\n            }\n        } else {\n            // Reject: no changes to `current_lines`, `b_d_current`, `piece_strawberry_counts_current`.\n            // `strawberry_line_sides_current` and `strawberry_is_lost_current` were not modified globally in the loop,\n            // so no revert needed for them.\n        }\n    }\n\n    // Output best solution found\n    cout << K_max_cuts << endl;\n    for (const auto& line : best_lines) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << endl;\n    }\n}\n\n// Main function to run the solution\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <chrono>\n\n// To manage execution time\nstd::chrono::high_resolution_clock::time_point start_time;\ndouble time_limit_ms = 4900.0; // 4.9 seconds to be safe\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        return !(*this == other);\n    }\n    // For sorting in set/map, etc.\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\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\nstruct RectangleOp {\n    Point p1, p2, p3, p4;\n};\n\nint N_global;\ndouble center_coord;\nstd::vector<std::vector<bool>> has_dot;\n\n// For condition 3: tracking drawn segments\n// horizontal_drawn[y][x]: segment (x,y)-(x+1,y)\nstd::vector<std::vector<bool>> horizontal_drawn;\n// vertical_drawn[x][y]: segment (x,y)-(x,y+1)\nstd::vector<std::vector<bool>> vertical_drawn;\n// diag_up_drawn[x][y]: segment (x,y)-(x+1,y+1) (slope +1)\nstd::vector<std::vector<bool>> diag_up_drawn;\n// diag_down_drawn[x][y]: segment (x,y+1)-(x+1,y) (slope -1)\nstd::vector<std::vector<bool>> diag_down_drawn;\n\n// Weights precomputation\nstd::vector<std::vector<double>> point_weights;\n\n// Precompute weights for all points\nvoid precompute_weights() {\n    point_weights.resize(N_global, std::vector<double>(N_global));\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            point_weights[i][j] = pow(i - center_coord, 2) + pow(j - center_coord, 2) + 1.0;\n        }\n    }\n}\n\ndouble get_weight(Point p) {\n    if (p.x < 0 || p.x >= N_global || p.y < 0 || p.y >= N_global) return -1.0; // Invalid point\n    return point_weights[p.x][p.y];\n}\n\nbool is_in_bounds(Point p) {\n    return p.x >= 0 && p.x < N_global && p.y >= 0 && p.y < N_global;\n}\n\n// Helper to check if a point on perimeter is an allowed dot (one of p2,p3,p4)\nbool is_allowed_dot(Point p, Point p2, Point p3, Point p4) {\n    return p == p2 || p == p3 || p == p4;\n}\n\n// Function to check condition 2 (no other dots on perimeter)\n// Iterates grid points on each segment.\nbool check_perimeter_dots(Point p1, Point p2, Point p3, Point p4) {\n    auto check_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        int steps = std::max(std::abs(dx), std::abs(dy));\n\n        if (steps == 0) return true; // Degenerate segment\n\n        for (int i = 1; i < steps; ++i) { // Exclude endpoints\n            Point p = {start.x + dx * i / steps, start.y + dy * i / steps};\n            if (p.x * steps != start.x * steps + dx * i || p.y * steps != start.y * steps + dy * i) continue; // Only check integer points\n\n            if (has_dot[p.x][p.y] && !is_allowed_dot(p, p2, p3, p4)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    if (!check_segment(p1, p2)) return false;\n    if (!check_segment(p2, p3)) return false;\n    if (!check_segment(p3, p4)) return false;\n    if (!check_segment(p4, p1)) return false;\n    return true;\n}\n\n// Function to check condition 3 (no shared segment with positive length)\nbool check_shared_segments(Point p1, Point p2, Point p3, Point p4) {\n    auto check_and_mark_segment = [&](Point start, Point end, bool dry_run) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                if (vertical_drawn[x][y]) return false;\n                if (!dry_run) vertical_drawn[x][y] = true;\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                if (horizontal_drawn[y][x]) return false;\n                if (!dry_run) horizontal_drawn[y][x] = true;\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                if (diag_up_drawn[min_x + i][min_y + i]) return false;\n                if (!dry_run) diag_up_drawn[min_x + i][min_y + i] = true;\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            int x_inc = (dx > 0) ? 1 : -1;\n            int y_inc = (dy > 0) ? 1 : -1; // dx=-dy means x_inc = -y_inc\n            \n            // Normalize start and end points for consistent indexing.\n            // A segment (x, y+1) -> (x+1, y) is defined by (x,y) for diag_down_drawn\n            // This maps the segment's \"top-left\" corner of its bounding box.\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end); // Ensure start.x <= end.x\n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                // Determine the correct (x,y) for diag_down_drawn[x][y] for (x, y+1)-(x+1, y)\n                // If the segment is (current_start.x, current_start.y) to (current_start.x+1, current_start.y-1)\n                // The index for diag_down_drawn is (current_start.x, current_start.y-1)\n                int current_x = current_start.x + i;\n                int current_y = current_start.y - i -1; // y-coord of lower-left corner\n\n                if (diag_down_drawn[current_x][current_y]) return false;\n                if (!dry_run) diag_down_drawn[current_x][current_y] = true;\n            }\n        }\n        return true;\n    };\n\n    if (!check_and_mark_segment(p1, p2, true)) return false;\n    if (!check_and_mark_segment(p2, p3, true)) return false;\n    if (!check_and_mark_segment(p3, p4, true)) return false;\n    if (!check_and_mark_segment(p4, p1, true)) return false;\n\n    return true; // All checks passed for dry run\n}\n\nvoid mark_segments_drawn(Point p1, Point p2, Point p3, Point p4) {\n    auto mark_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                vertical_drawn[x][y] = true;\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                horizontal_drawn[y][x] = true;\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                diag_up_drawn[min_x + i][min_y + i] = true;\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end);\n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                int current_x = current_start.x + i;\n                int current_y = current_start.y - i -1; // This is the y-coord of the lower left corner (x,y) where the segment is (x,y+1)-(x+1,y)\n                diag_down_drawn[current_x][current_y] = true;\n            }\n        }\n    };\n\n    mark_segment(p1, p2);\n    mark_segment(p2, p3);\n    mark_segment(p3, p4);\n    mark_segment(p4, p1);\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    start_time = std::chrono::high_resolution_clock::now();\n\n    int M;\n    std::cin >> N_global >> M;\n\n    center_coord = (N_global - 1) / 2.0;\n\n    has_dot.resize(N_global, std::vector<bool>(N_global, false));\n    horizontal_drawn.resize(N_global, std::vector<bool>(N_global - 1, false));\n    vertical_drawn.resize(N_global - 1, std::vector<bool>(N_global, false));\n    diag_up_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n    diag_down_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n\n\n    std::vector<Point> current_dots_list;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        std::cin >> x >> y;\n        current_dots_list.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    precompute_weights();\n\n    std::vector<RectangleOp> operations;\n    int loop_count = 0;\n    const int max_loops = 5000; // Cap the total main loop iterations to avoid TLE for extreme cases\n\n    while (loop_count < max_loops) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n\n        double best_P1_weight = -1.0;\n        RectangleOp best_op;\n        bool found_op = false;\n\n        // Iterate over all pairs of existing dots P2 and P4\n        for (int i = 0; i < current_dots_list.size(); ++i) {\n            Point p2 = current_dots_list[i];\n            for (int j = 0; j < current_dots_list.size(); ++j) {\n                if (i == j) continue;\n                Point p4 = current_dots_list[j];\n\n                // --- Try Axis-aligned rectangle ---\n                Point p1_aa = {p2.x, p4.y};\n                Point p3_aa = {p4.x, p2.y};\n\n                if (is_in_bounds(p1_aa) && !has_dot[p1_aa.x][p1_aa.y] &&\n                    is_in_bounds(p3_aa) && has_dot[p3_aa.x][p3_aa.y] &&\n                    p1_aa != p2 && p1_aa != p3_aa && p1_aa != p4) // Ensure non-degenerate rectangle\n                {\n                    if (check_perimeter_dots(p1_aa, p2, p3_aa, p4) &&\n                        check_shared_segments(p1_aa, p2, p3_aa, p4)) {\n                        double current_weight = get_weight(p1_aa);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_aa, p2, p3_aa, p4};\n                            found_op = true;\n                        }\n                    }\n                }\n\n                // --- Try 45-degree inclined rectangle ---\n                // P1.x = (P2.x + P4.x - (P2.y - P4.y)) / 2\n                // P1.y = (P2.y + P4.y + (P2.x - P4.x)) / 2\n                // P3.x = (P2.x + P4.x + (P2.y - P4.y)) / 2\n                // P3.y = (P2.y + P4.y - (P2.x - P4.x)) / 2\n                int sum_x = p2.x + p4.x;\n                int sum_y = p2.y + p4.y;\n                int diff_x = p2.x - p4.x;\n                int diff_y = p2.y - p4.y;\n\n                // Check for integer coordinates after transformation\n                if ((sum_x - diff_y) % 2 == 0 && (sum_y + diff_x) % 2 == 0 &&\n                    (sum_x + diff_y) % 2 == 0 && (sum_y - diff_x) % 2 == 0) {\n                    Point p1_45 = {(sum_x - diff_y) / 2, (sum_y + diff_x) / 2};\n                    Point p3_45 = {(sum_x + diff_y) / 2, (sum_y - diff_x) / 2};\n\n                    if (is_in_bounds(p1_45) && !has_dot[p1_45.x][p1_45.y] &&\n                        is_in_bounds(p3_45) && has_dot[p3_45.x][p3_45.y] &&\n                        p1_45 != p2 && p1_45 != p3_45 && p1_45 != p4) { // non-degenerate\n                        if (check_perimeter_dots(p1_45, p2, p3_45, p4) &&\n                            check_shared_segments(p1_45, p2, p3_45, p4)) {\n                            double current_weight = get_weight(p1_45);\n                            if (current_weight > best_P1_weight) {\n                                best_P1_weight = current_weight;\n                                best_op = {p1_45, p2, p3_45, p4};\n                                found_op = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found_op) {\n            break; // No more valid operations\n        }\n\n        // Perform the best operation\n        operations.push_back(best_op);\n        has_dot[best_op.p1.x][best_op.p1.y] = true;\n        current_dots_list.push_back(best_op.p1); // Add new dot to list for future operations\n        mark_segments_drawn(best_op.p1, best_op.p2, best_op.p3, best_op.p4);\n        loop_count++;\n    }\n\n    std::cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        std::cout << op.p1.x << \" \" << op.p1.y << \" \"\n                  << op.p2.x << \" \" << op.p2.y << \" \"\n                  << op.p3.x << \" \" << op.p3.y << \" \"\n                  << op.p4.x << \" \" << op.p4.y << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc015":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <map>\n#include <cmath>\n#include <queue> // For BFS in component calculation\n\n// Using std namespace for convenience in competitive programming context\nusing namespace std;\n\n// Constants for board size\nconst int N = 10; \n\n// Global board state\nvector<vector<int>> board(N, vector<int>(N, 0)); // 0: empty, 1,2,3: flavors\n\n// Stores the flavors of candies in the order they are received (f_1 to f_100)\nvector<int> flavors_data(100);\n\n// Function to find the (r, c) coordinates of the p-th empty cell\npair<int, int> get_coords_from_p_idx(int p_idx) {\n    int count = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) {\n                count++;\n                if (count == p_idx) {\n                    return {r, c};\n                }\n            }\n        }\n    }\n    return {-1, -1}; // Should not happen in a valid problem scenario\n}\n\n// Function to apply a tilt operation to a given board\nvoid apply_tilt(vector<vector<int>>& current_board, char dir) {\n    if (dir == 'F') { // Forward (up, towards row 0)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = 0; r < N; ++r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = 0; r < N; ++r) {\n                if (r < candies_in_col.size()) {\n                    current_board[r][c] = candies_in_col[r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'B') { // Backward (down, towards row N-1)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = N - 1; r >= 0; --r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = N - 1; r >= 0; --r) {\n                if ((N - 1 - r) < candies_in_col.size()) { // Fill from bottom up\n                    current_board[r][c] = candies_in_col[N - 1 - r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'L') { // Left (towards col 0)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = 0; c < N; ++c) {\n                if (c < candies_in_row.size()) {\n                    current_board[r][c] = candies_in_row[c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'R') { // Right (towards col N-1)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = N - 1; c >= 0; --c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = N - 1; c >= 0; --c) {\n                if ((N - 1 - c) < candies_in_row.size()) { // Fill from right to left\n                    current_board[r][c] = candies_in_row[N - 1 - c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    }\n}\n\n// Helper function to calculate the sum of n_i^2 for a given board state\n// This directly calculates the numerator of the actual scoring function.\nlong long calculate_sum_n_sq(const vector<vector<int>>& current_board) {\n    long long total_n_sq = 0;\n    \n    // For each flavor (1, 2, 3) independently\n    for (int flavor_to_check = 1; flavor_to_check <= 3; ++flavor_to_check) {\n        vector<vector<bool>> visited_for_flavor(N, vector<bool>(N, false));\n        \n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] == flavor_to_check && !visited_for_flavor[r][c]) {\n                    // Start a BFS to find component size for this flavor\n                    int current_component_size = 0;\n                    queue<pair<int, int>> q; \n                    q.push({r, c});\n                    visited_for_flavor[r][c] = true;\n                    \n                    while(!q.empty()){\n                        pair<int, int> curr = q.front();\n                        q.pop();\n                        current_component_size++;\n\n                        int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n                        int dc[] = {0, 0, -1, 1};\n\n                        for (int i = 0; i < 4; ++i) {\n                            int nr = curr.first + dr[i];\n                            int nc = curr.second + dc[i];\n\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                                current_board[nr][nc] == flavor_to_check && !visited_for_flavor[nr][nc]) {\n                                visited_for_flavor[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                    total_n_sq += (long long)current_component_size * current_component_size;\n                }\n            }\n        }\n    }\n    return total_n_sq;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read all candy flavors (f_1 to f_100)\n    // d_counts is no longer used for region assignment but is kept as it might be useful for other heuristics.\n    // For this specific direct sum n_i^2 optimization, it's not strictly necessary.\n    vector<int> d_counts(4, 0); \n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors_data[i];\n        d_counts[flavors_data[i]]++;\n    }\n\n    // Previous region assignment logic removed, as it's no longer used for evaluation.\n    \n    // Main loop: process each candy one by one\n    char directions[] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p_t;\n        cin >> p_t; // Read the index of the empty cell for the current candy\n\n        // Find coordinates for the new candy\n        pair<int, int> new_candy_coords = get_coords_from_p_idx(p_t);\n        int r_new = new_candy_coords.first;\n        int c_new = new_candy_coords.second;\n\n        // Place the new candy on the board\n        board[r_new][c_new] = flavors_data[t];\n\n        long long best_tilt_score_n_sq = -1; // Initialize with a small number, scores are non-negative\n        char best_dir = ' ';\n\n        // Evaluate each of the four possible tilt directions\n        for (char dir : directions) {\n            vector<vector<int>> temp_board = board; // Create a copy of the board for simulation\n            apply_tilt(temp_board, dir); // Simulate the tilt\n\n            // Calculate the score (sum of n_i^2) for the simulated board state\n            long long current_tilt_score_n_sq = calculate_sum_n_sq(temp_board);\n            \n            // Update best direction if current tilt yields a higher score\n            if (current_tilt_score_n_sq > best_tilt_score_n_sq) {\n                best_tilt_score_n_sq = current_tilt_score_n_sq;\n                best_dir = dir;\n            }\n        }\n\n        // Apply the chosen best tilt to the actual board\n        apply_tilt(board, best_dir);\n\n        // Output the chosen direction and flush stdout\n        cout << best_dir << endl;\n    }\n\n    return 0;\n}\n","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <map>\n#include <iomanip>\n#include <cmath> // For std::round, std::abs\n\n// Adjacency matrix representation\nusing AdjMatrix = std::vector<std::vector<bool>>;\n\n// Function to convert adjacency matrix to string representation\nstd::string graph_to_string(const AdjMatrix& adj, int N) {\n    std::string s = \"\";\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Function to convert string representation to adjacency matrix\nAdjMatrix string_to_graph(const std::string& s, int N) {\n    AdjMatrix adj(N, std::vector<bool>(N, false));\n    int k_str = 0; // Index for the string s\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[k_str] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            k_str++;\n        }\n    }\n    return adj;\n}\n\n// Computes WL refinement color histogram (fingerprint) of a graph\nstd::map<int, int> compute_wl_fingerprint(const AdjMatrix& adj, int N, int wl_iters) {\n    std::vector<int> colors(N);\n    // Initial colors based on degrees\n    for (int i = 0; i < N; ++i) {\n        int degree = 0;\n        for (int j = 0; j < N; ++j) {\n            if (adj[i][j]) {\n                degree++;\n            }\n        }\n        colors[i] = degree;\n    }\n\n    // If wl_iters is 0, just return the degree distribution as fingerprint\n    if (wl_iters == 0) {\n        std::map<int, int> histogram;\n        for (int c : colors) {\n            histogram[c]++;\n        }\n        return histogram;\n    }\n\n    // For WL iterations > 0\n    for (int iter = 0; iter < wl_iters; ++iter) {\n        std::map<std::vector<int>, int> color_map; // Maps unique (current_color, sorted_neighbor_colors) to a new integer color\n        int next_color_idx = 0; // Counter for assigning new unique colors for this iteration\n\n        std::vector<int> new_colors(N);\n        for (int i = 0; i < N; ++i) {\n            std::vector<int> neighbor_colors;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    neighbor_colors.push_back(colors[j]);\n                }\n            }\n            std::sort(neighbor_colors.begin(), neighbor_colors.end());\n\n            // Construct key for color_map: current color + sorted list of neighbor colors\n            std::vector<int> current_key = {colors[i]};\n            current_key.insert(current_key.end(), neighbor_colors.begin(), neighbor_colors.end());\n            \n            // Assign a new unique color if this key hasn't been seen before\n            if (color_map.find(current_key) == color_map.end()) {\n                color_map[current_key] = next_color_idx++;\n            }\n            new_colors[i] = color_map[current_key];\n        }\n        colors = new_colors; // Update colors for the next iteration\n    }\n\n    // Compute histogram of final colors\n    std::map<int, int> histogram;\n    for (int c : colors) {\n        histogram[c]++;\n    }\n    return histogram;\n}\n\n// Calculates squared Euclidean distance between two color histograms\ndouble histogram_distance(const std::map<int, int>& h1, const std::map<int, int>& h2) {\n    double dist_sq = 0;\n    \n    // Collect all unique colors present in either histogram\n    std::vector<int> all_colors_keys;\n    for(const auto& pair : h1) all_colors_keys.push_back(pair.first);\n    for(const auto& pair : h2) all_colors_keys.push_back(pair.first);\n    std::sort(all_colors_keys.begin(), all_colors_keys.end());\n    all_colors_keys.erase(std::unique(all_colors_keys.begin(), all_colors_keys.end()), all_colors_keys.end());\n\n    for (int color : all_colors_keys) {\n        int count1 = h1.count(color) ? h1.at(color) : 0;\n        int count2 = h2.count(color) ? h2.at(color) : 0;\n        dist_sq += (double)(count1 - count2) * (count1 - count2);\n    }\n    return dist_sq;\n}\n\n// Global variables for problem parameters and generated graphs\nint M_param;\ndouble EPSILON_param;\nint N_chosen;\nstd::vector<AdjMatrix> G_graphs;\nstd::vector<std::map<int, int>> G_fingerprints; // Precomputed fingerprints for G_graphs\nstd::vector<int> G_edge_counts; // Precomputed edge counts for G_graphs\nint WL_ITERS_chosen; // Number of WL iterations to use\nint E_total_possible; // Total possible edges for N_chosen vertices\n\n// Function to precompute N and all M graphs G_k\nvoid precompute_graphs() {\n    // Determine N based on M and epsilon. Heuristic choice.\n    // Tries to balance the need for more distinct graphs (larger M, epsilon) with score penalty (larger N).\n    // Adjusted heuristic: reduced EPSILON_param multiplier to make N smaller for higher epsilon.\n    N_chosen = std::min(100, std::max(4, (int)(M_param * 0.4 + 20 + EPSILON_param * 30)));\n\n    // Determine WL_ITERS based on epsilon. Heuristic choice.\n    // Fewer iterations for higher epsilon to prevent noise from propagating too much.\n    // wl_iters can be 0, meaning only initial degree distribution is used.\n    WL_ITERS_chosen = std::max(0, 3 - (int)(EPSILON_param * 5)); // Added max(0, ..) to allow 0 iterations\n\n    E_total_possible = N_chosen * (N_chosen - 1) / 2; // Total possible edges\n    \n    G_graphs.resize(M_param);\n    G_fingerprints.resize(M_param);\n    G_edge_counts.resize(M_param);\n\n    // List all possible edges to facilitate random selection\n    std::vector<std::pair<int, int>> all_possible_edges;\n    for (int i = 0; i < N_chosen; ++i) {\n        for (int j = i + 1; j < N_chosen; ++j) {\n            all_possible_edges.push_back({i, j});\n        }\n    }\n\n    for (int k = 0; k < M_param; ++k) {\n        AdjMatrix current_G(N_chosen, std::vector<bool>(N_chosen, false));\n        \n        // Target number of edges for G_k.\n        // Distributed from 0 to E_total across M graphs.\n        int target_edges_count = std::round((double)k / (M_param - 1) * E_total_possible);\n        if (M_param == 1) target_edges_count = 0; // Special case for M=1 to avoid division by zero\n        \n        // Generate edges using a pseudo-random approach.\n        // A fixed seed 'k' ensures G_k is deterministic and distinct for each k.\n        std::mt19937 rng(k); \n        std::vector<std::pair<int, int>> shuffled_edges = all_possible_edges;\n        std::shuffle(shuffled_edges.begin(), shuffled_edges.end(), rng);\n\n        // Add the target number of edges\n        int actual_edges = 0;\n        for (int i = 0; i < target_edges_count; ++i) {\n            auto edge = shuffled_edges[i];\n            current_G[edge.first][edge.second] = true;\n            current_G[edge.second][edge.first] = true;\n            actual_edges++;\n        }\n        G_graphs[k] = current_G;\n        G_edge_counts[k] = actual_edges; // Store precomputed edge count\n        \n        // Precompute fingerprint for efficiency\n        G_fingerprints[k] = compute_wl_fingerprint(current_G, N_chosen, WL_ITERS_chosen);\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read M and epsilon\n    std::cin >> M_param >> EPSILON_param;\n\n    // Perform precomputation (determine N, generate G_k graphs and their fingerprints)\n    precompute_graphs();\n\n    // Output N and the M generated graphs\n    std::cout << N_chosen << std::endl;\n    for (int k = 0; k < M_param; ++k) {\n        std::cout << graph_to_string(G_graphs[k], N_chosen) << std::endl;\n    }\n    std::cout << std::flush; // Crucial for interactive problems\n\n    // Calculate normalization factor for WL distance. Max possible squared difference in a histogram of N vertices.\n    // E.g., one graph has all N vertices of color C1, other graph has all N vertices of color C2.\n    // dist = (N-0)^2 + (0-N)^2 = 2N^2. So 2N^2 is a good normalization factor.\n    double wl_norm_factor = 2.0 * N_chosen * N_chosen;\n    if (N_chosen <= 1) wl_norm_factor = 1.0; // Avoid division by zero, N_chosen >= 4 so this is mostly defensive.\n\n    // Calculate weight alpha for combining distances.\n    // Alpha scales from 0 (pure WL) to 1 (pure edge count diff) as epsilon goes from 0 to 0.4.\n    double alpha_weight = EPSILON_param / 0.4;\n    if (EPSILON_param < 0.001) alpha_weight = 0.0; // Effectively 0 for very small epsilon\n    if (EPSILON_param > 0.399) alpha_weight = 1.0; // Effectively 1 for very large epsilon\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str; // Read the received graph H_k\n        \n        // Compute fingerprint for H_k\n        AdjMatrix H_adj = string_to_graph(H_str, N_chosen);\n        std::map<int, int> H_fingerprint = compute_wl_fingerprint(H_adj, N_chosen, WL_ITERS_chosen);\n        \n        // Count edges in H_k\n        int H_edge_count = 0;\n        for (char c : H_str) {\n            if (c == '1') {\n                H_edge_count++;\n            }\n        }\n\n        double min_total_dist = -1.0;\n        int best_t = -1;\n\n        // Compare H_k's fingerprint and edge count with all precomputed G_t\n        for (int t = 0; t < M_param; ++t) {\n            // WL distance\n            double wl_dist = histogram_distance(H_fingerprint, G_fingerprints[t]);\n            double normalized_wl_dist = wl_dist / wl_norm_factor;\n\n            // Edge count difference distance\n            double edge_diff = std::abs((double)H_edge_count - G_edge_counts[t]);\n            double normalized_edge_diff = edge_diff / (double)E_total_possible;\n            if (E_total_possible == 0) normalized_edge_diff = 0.0; // Should not happen with N>=4\n\n            // Combined distance\n            double current_total_dist = (1.0 - alpha_weight) * normalized_wl_dist + alpha_weight * normalized_edge_diff;\n            \n            if (best_t == -1 || current_total_dist < min_total_dist) {\n                min_total_dist = current_total_dist;\n                best_t = t;\n            }\n        }\n        std::cout << best_t << std::endl; // Output the prediction\n        std::cout << std::flush; // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <limits>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <map>\n#include <iomanip> // For setprecision\n#include <random>\n\nusing namespace std;\n\n// Using long long for distances to avoid overflow for sums\nconst long long INF = numeric_limits<long long>::max() / 2; // A sufficiently large value that avoids overflow when added to\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Node {\n    long long dist;\n    int u;\n    bool operator>(const Node& other) const {\n        return dist > other.dist;\n    }\n};\n\nstruct EdgeInfo {\n    int u, v, w, id;\n    long double val; // combined importance score: extra_dist * edge_betweenness\n};\n\nvector<vector<pair<int, int>>> adj; // adj[u] = list of {v, edge_id}\nvector<Edge> edges_data;\nint N_global, M_global, D_global, K_global;\n\n// Dijkstra's algorithm to find shortest paths from a source s\n// Optionally excludes a specific edge for extra_dist calculation\n// Returns a vector of distances from s to all other vertices.\nvector<long long> dijkstra(int s, const vector<vector<pair<int, int>>>& current_adj, int excluded_edge_id = -1) {\n    vector<long long> dist(N_global, INF);\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n    dist[s] = 0;\n    pq.push({0, s});\n\n    while (!pq.empty()) {\n        long long d = pq.top().dist;\n        int u = pq.top().u;\n        pq.pop();\n\n        if (d > dist[u]) continue; // Already found a shorter path\n\n        for (auto& edge_pair : current_adj[u]) {\n            int v = edge_pair.first;\n            int edge_id = edge_pair.second;\n\n            if (edge_id == excluded_edge_id) continue;\n\n            long long weight = edges_data[edge_id].w;\n            if (dist[u] != INF && dist[u] + weight < dist[v]) { // dist[u] != INF check to prevent overflow\n                dist[v] = dist[u] + weight;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Brandes' algorithm for Edge Betweenness Centrality\n// Returns a vector where element i is the betweenness centrality of edge_data[i]\nvector<long double> calculate_edge_betweenness() {\n    vector<long double> edge_betweenness(M_global, 0.0);\n\n    for (int s = 0; s < N_global; ++s) {\n        vector<long long> dist(N_global, INF);\n        vector<long long> num_shortest_paths(N_global, 0); // Count of shortest paths from s to v\n        vector<vector<int>> predecessors(N_global); // For each v, a list of vertices u that precede v on shortest paths from s\n        vector<int> stack; // To process vertices in decreasing order of distance\n\n        priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n        dist[s] = 0;\n        num_shortest_paths[s] = 1;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            long long d = pq.top().dist;\n            int u = pq.top().u;\n            pq.pop();\n\n            if (d > dist[u]) continue; \n            \n            stack.push_back(u); // Add to stack for processing in reverse order of distance\n\n            for (auto& edge_pair : adj[u]) {\n                int v = edge_pair.first;\n                int edge_id = edge_pair.second;\n                long long weight = edges_data[edge_id].w;\n\n                if (dist[u] != INF) { // Only consider paths from reachable u\n                    if (dist[u] + weight < dist[v]) {\n                        dist[v] = dist[u] + weight;\n                        num_shortest_paths[v] = num_shortest_paths[u];\n                        predecessors[v].clear();\n                        predecessors[v].push_back(u);\n                        pq.push({dist[v], v});\n                    } else if (dist[u] + weight == dist[v]) {\n                        num_shortest_paths[v] += num_shortest_paths[u];\n                        predecessors[v].push_back(u);\n                    }\n                }\n            }\n        }\n\n        vector<long double> delta(N_global, 0.0); // Dependency of s on v\n        while (!stack.empty()) {\n            int v = stack.back();\n            stack.pop_back();\n\n            for (int u_pred : predecessors[v]) {\n                // Fraction of shortest paths from s to v that pass through u_pred\n                // num_shortest_paths[v] must be > 0 here, because v is reachable from s\n                long double path_fraction = (long double)num_shortest_paths[u_pred] / num_shortest_paths[v];\n                long double contribution = path_fraction * (1.0 + delta[v]);\n                \n                // Find edge_id for (u_pred, v)\n                int found_edge_id = -1;\n                for(const auto& edge_pair : adj[u_pred]) {\n                    if (edge_pair.first == v) {\n                        found_edge_id = edge_pair.second;\n                        break; \n                    }\n                }\n                \n                if (found_edge_id != -1) { // Should always be found for edges on shortest paths\n                    edge_betweenness[found_edge_id] += contribution;\n                }\n                delta[u_pred] += contribution;\n            }\n        }\n    }\n    return edge_betweenness;\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    cin >> N_global >> M_global >> D_global >> K_global;\n\n    adj.resize(N_global);\n    edges_data.resize(M_global);\n\n    for (int i = 0; i < M_global; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v; // 0-indexed\n        edges_data[i] = {u, v, w, i};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i}); // Add edge for both directions\n    }\n\n    // Skip coordinates input as they are not used in this solution\n    for (int i = 0; i < N_global; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge betweenness centrality for each edge\n    vector<long double> edge_betweenness = calculate_edge_betweenness();\n\n    // 2. Precompute extra_dist for each edge (d'(u,v) - w when edge (u,v) is removed)\n    vector<long long> extra_dist(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        int u = edges_data[i].u;\n        int v = edges_data[i].v;\n        int w = edges_data[i].w;\n        vector<long long> dist_from_u_without_edge = dijkstra(u, adj, i);\n        // If u and v become disconnected, consider the path effectively infinite (10^9 from problem)\n        // Ensure extra_dist is non-negative\n        extra_dist[i] = (dist_from_u_without_edge[v] == INF) ? (1000000000LL - w) : (dist_from_u_without_edge[v] - w);\n        if (extra_dist[i] < 0) extra_dist[i] = 0; \n    }\n    \n    // 3. Combine scores: val[e_idx] = extra_dist[e_idx] * edge_betweenness[e_idx]\n    vector<EdgeInfo> edge_infos(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        edge_infos[i] = {edges_data[i].u, edges_data[i].v, edges_data[i].w, i, (long double)extra_dist[i] * edge_betweenness[i]};\n    }\n    \n    // 4. Initial assignment (r[M]): Sort edges by combined importance (val) and assign round-robin\n    sort(edge_infos.begin(), edge_infos.end(), [](const EdgeInfo& a, const EdgeInfo& b) {\n        return a.val > b.val;\n    });\n\n    vector<int> r(M_global); // repair day for each edge (1-indexed)\n    vector<int> day_load(D_global + 1, 0); // Number of edges assigned to each day\n    vector<long double> current_sum_val(D_global + 1, 0.0); // Sum of val for edges assigned to each day\n\n    for (int i = 0; i < M_global; ++i) {\n        int edge_id = edge_infos[i].id;\n        int day = (i % D_global) + 1; // Round-robin assignment based on sorted importance\n        r[edge_id] = day;\n        day_load[day]++;\n        current_sum_val[day] += edge_infos[i].val;\n    }\n    \n    // Calculate initial estimated frustration score (sum of average vals per day)\n    long double current_total_approx_score = 0.0;\n    for (int k = 1; k <= D_global; ++k) {\n        if (day_load[k] > 0) {\n            current_total_approx_score += current_sum_val[k] / day_load[k];\n        }\n    }\n\n    vector<int> best_r = r;\n    long double best_total_approx_score = current_total_approx_score;\n\n    // Simulated Annealing parameters\n    double time_limit_sec = 5.9; // Allocate 5.9 seconds for SA\n    long double T_start = 1e12; // Starting temperature\n    long double T_end = 1e-4;   // Ending temperature\n    \n    // Random number generation setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_edge(0, M_global - 1);\n    uniform_int_distribution<int> dist_day(1, D_global);\n    uniform_real_distribution<long double> dist_01(0.0, 1.0);\n\n    // SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time_sec = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time_sec > time_limit_sec) {\n            break;\n        }\n\n        // Linear cooling schedule\n        long double current_T = T_start * (1.0 - elapsed_time_sec / time_limit_sec);\n        if (current_T < T_end) current_T = T_end;\n\n        int edge_idx = dist_edge(rng); // Randomly pick an edge to move\n        int day_from = r[edge_idx];\n        int day_to = dist_day(rng); // Randomly pick a target day\n\n        // Check feasibility and efficiency constraints\n        if (day_from == day_to || day_load[day_to] >= K_global) {\n            continue; // Cannot move to same day or to an already full day\n        }\n\n        long double val_e = edge_infos[edge_idx].val; // Importance value of the edge being moved\n\n        // Calculate old average frustration for affected days\n        long double old_f_from = current_sum_val[day_from] / day_load[day_from];\n        long double old_f_to = (day_load[day_to] > 0) ? (current_sum_val[day_to] / day_load[day_to]) : 0.0; // If day_to is empty, old frustration is 0\n\n        // Calculate new average frustration if move is accepted\n        long double new_f_from = (day_load[day_from] > 1) ? ((current_sum_val[day_from] - val_e) / (day_load[day_from] - 1.0)) : 0.0; // If day_from becomes empty, new frustration is 0\n        long double new_f_to = (current_sum_val[day_to] + val_e) / (day_load[day_to] + 1.0);\n        \n        long double delta_score = (new_f_from - old_f_from) + (new_f_to - old_f_to);\n\n        // Acceptance criteria for Simulated Annealing\n        if (delta_score < 0 || dist_01(rng) < exp(-delta_score / current_T)) {\n            // Accept the move\n            r[edge_idx] = day_to;\n            day_load[day_from]--;\n            day_load[day_to]++;\n            current_sum_val[day_from] -= val_e;\n            current_sum_val[day_to] += val_e;\n            current_total_approx_score += delta_score;\n\n            // Update best solution found so far\n            if (current_total_approx_score < best_total_approx_score) {\n                best_total_approx_score = current_total_approx_score;\n                best_r = r;\n            }\n        }\n    }\n\n    // Output the best assignment found\n    for (int i = 0; i < M_global; ++i) {\n        cout << best_r[i] << (i == M_global - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}\n","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <queue>\n#include <chrono>\n\nusing namespace std;\n\n// Global D for convenience\nint D;\n\n// Struct for 3D point\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& 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 Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\n// Represents a polycube shape as a vector of relative points\nusing Shape = vector<Point>;\n\n// Function to apply a rotation to a point relative to its origin (0,0,0)\nPoint rotate_point(const Point& p, int rot_idx) {\n    // This defines the 24 unique rotations\n    // The specific order is somewhat arbitrary but covers all possibilities.\n    // Each case maps (x,y,z) to a permutation of (+/-x, +/-y, +/-z)\n    switch (rot_idx) {\n        case 0: return {p.x, p.y, p.z}; // +X+Y+Z\n        case 1: return {p.x, p.z, -p.y}; // +X+Z-Y\n        case 2: return {p.x, -p.y, -p.z}; // +X-Y-Z\n        case 3: return {p.x, -p.z, p.y}; // +X-Z+Y\n        \n        case 4: return {-p.x, -p.y, p.z}; // -X-Y+Z\n        case 5: return {-p.x, -p.z, -p.y}; // -X-Z-Y\n        case 6: return {-p.x, p.y, -p.z}; // -X+Y-Z\n        case 7: return {-p.x, p.z, p.y}; // -X+Z+Y\n\n        case 8: return {p.y, p.x, -p.z}; // +Y+X-Z\n        case 9: return {p.y, p.z, p.x}; // +Y+Z+X\n        case 10: return {p.y, -p.x, p.z}; // +Y-X+Z\n        case 11: return {p.y, -p.z, -p.x}; // +Y-Z-X\n\n        case 12: return {-p.y, p.x, p.z}; // -Y+X+Z\n        case 13: return {-p.y, p.z, -p.x}; // -Y+Z-X\n        case 14: return {-p.y, -p.x, -p.z}; // -Y-X-Z\n        case 15: return {-p.y, -p.z, p.x}; // -Y-Z+X\n        \n        case 16: return {p.z, p.x, p.y}; // +Z+X+Y\n        case 17: return {p.z, p.y, -p.x}; // +Z+Y-X\n        case 18: return {p.z, -p.x, -p.y}; // +Z-X-Y\n        case 19: return {p.z, -p.y, p.x}; // +Z-Y+X\n        \n        case 20: return {-p.z, p.x, p.y}; // -Z+X+Y\n        case 21: return {-p.z, p.y, -p.x}; // -Z+Y-X\n        case 22: return {-p.z, -p.x, -p.y}; // -Z-X-Y\n        case 23: return {-p.z, -p.y, p.x}; // -Z-Y+X\n    }\n    return p; // Should not be reached\n}\n\n// Function to canonicalize a shape (vector of relative points)\nShape get_canonical_form(const Shape& shape) {\n    if (shape.empty()) return {};\n\n    Shape canonical_shape = shape;\n    // Initial sort to have a baseline for comparison\n    sort(canonical_shape.begin(), canonical_shape.end());\n\n    for (int rot_idx = 0; rot_idx < 24; ++rot_idx) {\n        Shape rotated_shape_temp;\n        for (const auto& p : shape) {\n            rotated_shape_temp.push_back(rotate_point(p, rot_idx));\n        }\n\n        // Translate to (0,0,0) origin\n        int min_x = D, min_y = D, min_z = D;\n        for (const auto& p : rotated_shape_temp) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated_shape_temp) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n\n        sort(rotated_shape_temp.begin(), rotated_shape_temp.end());\n        if (rotated_shape_temp < canonical_shape) {\n            canonical_shape = rotated_shape_temp;\n        }\n    }\n    return canonical_shape;\n}\n\n// Data structures for block management\nmap<Shape, int> canonical_shape_to_assigned_id;\nvector<Shape> block_definitions; // Stores the actual canonical shape for each ID (1-indexed)\nvector<int> block_volumes;       // Stores volume for each ID\nvector<bool> block_used_in_1;    // True if block ID is used in obj 1\nvector<bool> block_used_in_2;    // True if block ID is used in obj 2\nint current_b_id = 1;            // Next available block ID. Block IDs are 1-indexed.\n\n// Gets a block ID for a given shape, assigning a new one if not seen\n// The shape_points_relative must be relative to its own minimal bounding box corner (0,0,0)\nint get_or_assign_block_id(const Shape& shape_points_relative, int volume) {\n    Shape canonical_shape = get_canonical_form(shape_points_relative);\n    if (canonical_shape_to_assigned_id.count(canonical_shape)) {\n        return canonical_shape_to_assigned_id[canonical_shape];\n    } else {\n        int new_id = current_b_id++;\n        canonical_shape_to_assigned_id[canonical_shape] = new_id;\n        block_definitions.push_back(canonical_shape); // Store canonical form\n        block_volumes.push_back(volume);\n        block_used_in_1.push_back(false); // Initialize usage flags\n        block_used_in_2.push_back(false);\n        return new_id;\n    }\n}\n\n// BFS to find a connected component and return its absolute points.\n// Also modifies `grid_to_search` by setting visited cells to 0.\n// Returns a pair: {vector of absolute points, relative shape}\npair<vector<Point>, Shape> find_and_extract_component(vector<vector<vector<int>>>& grid_to_search, int start_x, int start_y, int start_z) {\n    vector<Point> absolute_points;\n    Shape relative_shape;\n\n    if (start_x < 0 || start_x >= D || start_y < 0 || start_y >= D || start_z < 0 || start_z >= D || grid_to_search[start_x][start_y][start_z] == 0) {\n        return {absolute_points, relative_shape};\n    }\n\n    queue<Point> q;\n    q.push({start_x, start_y, start_z});\n    grid_to_search[start_x][start_y][start_z] = 0; // Mark as visited and remove from current grid\n    absolute_points.push_back({start_x, start_y, start_z});\n\n    int dx[] = {0, 0, 0, 0, 1, -1};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {1, -1, 0, 0, 0, 0};\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            int nz = curr.z + dz[i];\n\n            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D && grid_to_search[nx][ny][nz] == 1) {\n                grid_to_search[nx][ny][nz] = 0; // Mark as visited\n                q.push({nx, ny, nz});\n                absolute_points.push_back({nx, ny, nz});\n            }\n        }\n    }\n    \n    // Translate the component points to be relative to their bounding box min corner\n    if (absolute_points.empty()) return {absolute_points, relative_shape};\n\n    int min_x = D, min_y = D, min_z = D;\n    for (const auto& p : absolute_points) {\n        min_x = min(min_x, p.x);\n        min_y = min(min_y, p.y);\n        min_z = min(min_z, p.z);\n    }\n    \n    for (const auto& p : absolute_points) {\n        relative_shape.push_back({p.x - min_x, p.y - min_y, p.z - min_z});\n    }\n    sort(relative_shape.begin(), relative_shape.end());\n    \n    return {absolute_points, relative_shape};\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D;\n\n    vector<string> f1_str(D), r1_str(D), f2_str(D), r2_str(D);\n    for (int i = 0; i < D; ++i) cin >> f1_str[i];\n    for (int i = 0; i < D; ++i) cin >> r1_str[i];\n    for (int i = 0; i < D; ++i) cin >> f2_str[i];\n    for (int i = 0; i < D; ++i) cin >> r2_str[i];\n\n    // U_i_grid[x][y][z] == 1 if (x,y,z) can be occupied based on silhouettes\n    vector<vector<vector<int>>> U1_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U2_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U_intersect_grid_mutable(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                bool in_u1 = (f1_str[z][x] == '1' && r1_str[z][y] == '1');\n                bool in_u2 = (f2_str[z][x] == '1' && r2_str[z][y] == '1');\n                \n                if (in_u1) U1_grid_mutable[x][y][z] = 1;\n                if (in_u2) U2_grid_mutable[x][y][z] = 1;\n                if (in_u1 && in_u2) U_intersect_grid_mutable[x][y][z] = 1;\n            }\n        }\n    }\n\n    vector<vector<vector<int>>> b1_final(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_final(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Create dummy entries for 0-indexed vectors, as block IDs are 1-indexed\n    block_definitions.push_back({}); // Placeholder for block ID 0\n    block_volumes.push_back(0);\n    block_used_in_1.push_back(false);\n    block_used_in_2.push_back(false);\n\n    // 1. Fill shared space (U_intersect_grid_mutable) with large components\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U_intersect_grid_mutable[x][y][z] == 1) { // If cell is available and not yet processed\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U_intersect_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n\n                    if (!absolute_points.empty()) { // Should always be true if grid_to_search[x][y][z] was 1\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_1[block_id] = true; \n                        block_used_in_2[block_id] = true;\n                        \n                        for (const auto& p_abs : absolute_points) {\n                            b1_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                            b2_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                            // Also mark in U1_grid_mutable and U2_grid_mutable as used, so they aren't re-processed\n                            U1_grid_mutable[p_abs.x][p_abs.y][p_abs.z] = 0;\n                            U2_grid_mutable[p_abs.x][p_abs.y][p_abs.z] = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // 2. Fill remaining U1_grid_mutable (object 1 specific blocks)\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U1_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U1_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_1[block_id] = true;\n\n                        for (const auto& p_abs : absolute_points) {\n                            b1_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Fill remaining U2_grid_mutable (object 2 specific blocks)\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U2_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U2_grid_mutable, x, y, z);\n                    vector<Point>& absolute_points = component_data.first;\n                    Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int block_id = get_or_assign_block_id(relative_shape, absolute_points.size());\n                        block_used_in_2[block_id] = true;\n\n                        for (const auto& p_abs : absolute_points) {\n                            b2_final[p_abs.x][p_abs.y][p_abs.z] = block_id;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    // The current `current_b_id - 1` is the total number of unique block shapes.\n    // Each of these blocks is guaranteed to be used in at least one object due to the placement logic.\n    cout << current_b_id - 1 << endl;\n\n    // Output b1\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b1_final[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    // Output b2\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b2_final[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\nconst long long INF_LL = 4e18; // Sufficiently large infinity for long long\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\nstruct Edge {\n    int id; // original edge index (0 to M-1)\n    int u, v;\n    long long w;\n};\n\nstruct EdgeInfo { // For adjacency list\n    int to_node;\n    long long weight;\n    int original_edge_idx;\n};\n\n// For Dijkstra\nstruct State {\n    long long cost;\n    int u;\n\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\nint N, M, K;\nvector<Point> nodes;\nvector<Edge> edges_data;\nvector<Point> residents;\nvector<vector<EdgeInfo>> adj; // adjacency list for graph\n\n// Precomputed distances\nvector<vector<long long>> dist_res_node_sq; // dist_res_node_sq[k][i] = squared Euclidean distance from resident k to node i\nvector<long long> dist_from_1; // Shortest path cost from node 1 to node i\nvector<int> parent_on_spt_node; // parent_on_spt_node[i] = parent node in SPT from node 1\nvector<int> parent_on_spt_edge_idx; // parent_on_spt_edge_idx[i] = original edge index of (parent[i], i)\n\n// Global random generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to calculate squared Euclidean distance\nlong long distSq(Point p1, 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\n// Calculate rounded Euclidean distance\nint round_dist_val(long long dist_sq) {\n    return static_cast<int>(round(sqrt((long double)dist_sq))); // Cast to long double for sqrt for precision\n}\n\n// Dijkstra from node 1\nvoid run_dijkstra() {\n    dist_from_1.assign(N + 1, INF_LL);\n    parent_on_spt_node.assign(N + 1, -1);\n    parent_on_spt_edge_idx.assign(N + 1, -1);\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist_from_1[1] = 0;\n    pq.push({0, 1});\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        long long d = current.cost;\n        int u = current.u;\n\n        if (d > dist_from_1[u]) continue;\n\n        for (auto& edge_info : adj[u]) {\n            int v = edge_info.to_node;\n            long long weight = edge_info.weight;\n            int edge_idx = edge_info.original_edge_idx;\n\n            if (dist_from_1[u] + weight < dist_from_1[v]) {\n                dist_from_1[v] = dist_from_1[u] + weight;\n                parent_on_spt_node[v] = u;\n                parent_on_spt_edge_idx[v] = edge_idx;\n                pq.push({dist_from_1[v], v});\n            }\n        }\n    }\n}\n\n// Recalculates edge cost for a given set of active stations\nlong long calculate_edge_cost_from_active_stations(const set<int>& active_stations, vector<int>& B_output_temp) {\n    set<int> edges_on_idx_set;\n    long long current_edge_cost = 0;\n\n    for (int u : active_stations) {\n        if (dist_from_1[u] == INF_LL) { \n            return INF_LL; // Should not happen if `active_stations` are already filtered or cost is set to INF_LL\n        }\n        if (u == 1) continue; \n        \n        int curr = u;\n        while (curr != 1 && parent_on_spt_node[curr] != -1) {\n            int edge_idx = parent_on_spt_edge_idx[curr];\n            if (edges_on_idx_set.find(edge_idx) == edges_on_idx_set.end()) {\n                edges_on_idx_set.insert(edge_idx);\n                current_edge_cost += edges_data[edge_idx].w;\n            }\n            curr = parent_on_spt_node[curr];\n        }\n    }\n    \n    // Populate B_output_temp\n    B_output_temp.assign(M, 0);\n    for (int j = 0; j < M; ++j) {\n        if (edges_on_idx_set.count(j)) {\n            B_output_temp[j] = 1;\n        }\n    }\n\n    return current_edge_cost;\n}\n\n\nvoid solve() {\n    // Precomputation (read input, run Dijkstra, calculate resident-node distances)\n    nodes.resize(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        cin >> nodes[i].x >> nodes[i].y;\n        nodes[i].id = i;\n    }\n\n    adj.resize(N + 1);\n    edges_data.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges_data[j].u >> edges_data[j].v >> edges_data[j].w;\n        edges_data[j].id = j;\n        adj[edges_data[j].u].push_back({edges_data[j].v, edges_data[j].w, j});\n        adj[edges_data[j].v].push_back({edges_data[j].u, edges_data[j].w, j});\n    }\n\n    residents.resize(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n\n    run_dijkstra();\n\n    dist_res_node_sq.resize(K, vector<long long>(N + 1));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            dist_res_node_sq[k][i] = distSq(residents[k], nodes[i]);\n        }\n    }\n    \n    // Initial solution (Greedy approach)\n    vector<int> P_current(N + 1, 0);\n    \n    // For each resident, assign it to its closest reachable station (within 5000 radius).\n    // Then combine P values for stations.\n    for (int k = 0; k < K; ++k) {\n        int best_station_for_k = -1;\n        long long min_dist_sq_for_k = (long long)5001 * 5001; // Max guaranteed distance is 5000\n        for (int i = 1; i <= N; ++i) {\n            if (dist_from_1[i] == INF_LL) continue; // Station must be reachable from 1\n            if (dist_res_node_sq[k][i] <= (long long)5000 * 5000) {\n                if (dist_res_node_sq[k][i] < min_dist_sq_for_k) {\n                    min_dist_sq_for_k = dist_res_node_sq[k][i];\n                    best_station_for_k = i;\n                }\n            }\n        }\n        if (best_station_for_k != -1) {\n            P_current[best_station_for_k] = max(P_current[best_station_for_k], round_dist_val(min_dist_sq_for_k));\n        } else {\n             // This indicates a problem as per problem statement guarantee. Should not happen.\n        }\n    }\n    // Cap all P values at 5000\n    for(int i=1; i<=N; ++i) {\n        P_current[i] = min(P_current[i], 5000);\n    }\n    \n    vector<int> B_best(M);\n    long long best_S = INF_LL;\n    vector<int> P_best = P_current;\n\n    // State variables for SA (to allow incremental updates)\n    long long current_P_cost_SA = 0;\n    set<int> active_stations_SA;\n    vector<int> num_covering_stations_for_resident(K, 0);\n    int num_residents_fully_covered = 0;\n\n    // Initialize SA state variables from P_current\n    for (int i = 1; i <= N; ++i) {\n        if (P_current[i] > 0 && dist_from_1[i] == INF_LL) { // If an initially active station is unreachable\n            current_P_cost_SA = INF_LL; // Mark initial state as invalid\n            break;\n        }\n        current_P_cost_SA += (long long)P_current[i] * P_current[i];\n        if (P_current[i] > 0) {\n            active_stations_SA.insert(i);\n        }\n    }\n    if (current_P_cost_SA != INF_LL) { // If initial P cost is valid (all active stations reachable)\n        for (int k = 0; k < K; ++k) {\n            for (int i = 1; i <= N; ++i) {\n                if (P_current[i] > 0) {\n                    if (dist_res_node_sq[k][i] <= (long long)P_current[i] * P_current[i]) {\n                        num_covering_stations_for_resident[k]++;\n                    }\n                }\n            }\n            if (num_covering_stations_for_resident[k] > 0) {\n                num_residents_fully_covered++;\n            }\n        }\n    }\n    \n    long long current_edge_cost_SA = 0;\n    if (current_P_cost_SA != INF_LL && num_residents_fully_covered == K) {\n        vector<int> temp_B(M); // Placeholder for calculate_edge_cost_from_active_stations\n        current_edge_cost_SA = calculate_edge_cost_from_active_stations(active_stations_SA, temp_B);\n        best_S = current_P_cost_SA + current_edge_cost_SA;\n        P_best = P_current;\n    }\n\n\n    // Simulated Annealing\n    chrono::high_resolution_clock::time_point start_time = chrono::high_resolution_clock::now();\n    long double current_temp;\n    if (best_S == INF_LL) { \n        current_temp = 1e9; \n    } else {\n        current_temp = (long double)best_S / 100.0; // Dynamic initial temperature\n    }\n    long double end_temp = 1.0;\n    long double time_limit = 1.95; // seconds\n    \n    // Parameters for SA moves\n    const int P_ADJUST_RANGE = 500; \n    \n    long long iter_count = 0;\n    while (true) {\n        chrono::high_resolution_clock::time_point current_time = chrono::high_resolution_clock::now();\n        long double elapsed_time = chrono::duration_cast<chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        if (elapsed_time > time_limit) {\n            break;\n        }\n        \n        current_temp = end_temp + (current_temp - end_temp) * (1.0 - elapsed_time / time_limit);\n        \n        vector<int> P_next = P_current; // P_next is a copy for perturbation\n        long long next_P_cost = current_P_cost_SA;\n        set<int> next_active_stations = active_stations_SA;\n        vector<int> next_num_covering_stations = num_covering_stations_for_resident;\n        int next_num_residents_fully_covered = num_residents_fully_covered;\n\n        int target_node = rng() % N + 1;\n        int old_P_val = P_current[target_node]; // Use P_current for old P value\n\n        if (dist_from_1[target_node] == INF_LL) { // Don't bother with unreachable nodes\n            continue;\n        }\n\n        int move_type = rng() % 100;\n\n        if (move_type < 60) { // Type 0: Adjust P_i for a random station i (60% chance)\n            int rand_delta = (rng() % (2 * P_ADJUST_RANGE + 1)) - P_ADJUST_RANGE;\n            int new_P_val = old_P_val + rand_delta;\n            new_P_val = max(0, min(5000, new_P_val));\n            P_next[target_node] = new_P_val;\n\n            // Update incremental costs\n            next_P_cost -= (long long)old_P_val * old_P_val;\n            next_P_cost += (long long)new_P_val * new_P_val;\n\n            if (old_P_val == 0 && new_P_val > 0) { // Station became active\n                next_active_stations.insert(target_node);\n            } else if (old_P_val > 0 && new_P_val == 0) { // Station became inactive\n                next_active_stations.erase(target_node);\n            }\n\n            // Update coverage counts incrementally for O(K) complexity\n            for (int k = 0; k < K; ++k) {\n                bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                if (old_covered_by_target && !new_covered_by_target) {\n                    next_num_covering_stations[k]--;\n                    if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                } else if (!old_covered_by_target && new_covered_by_target) {\n                    next_num_covering_stations[k]++;\n                    if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                }\n            }\n\n        } else { // Type 1: Try to turn off a station and re-assign coverage (40% chance)\n            \n            // If target_node is currently OFF, try turning it ON (random P)\n            if (old_P_val == 0) { \n                int new_P_val = rng() % 5001; // Random P between 0 and 5000\n                P_next[target_node] = new_P_val;\n\n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_P_cost += (long long)new_P_val * new_P_val;\n\n                if (new_P_val > 0) {\n                    next_active_stations.insert(target_node);\n                }\n\n                // Update coverage counts incrementally\n                for (int k = 0; k < K; ++k) {\n                    bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                    bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                    if (old_covered_by_target && !new_covered_by_target) {\n                        next_num_covering_stations[k]--;\n                        if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                    } else if (!old_covered_by_target && new_covered_by_target) {\n                        next_num_covering_stations[k]++;\n                        if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                    }\n                }\n\n            } else { // If target_node is currently ON, try turning it OFF and re-assign\n                // Temporarily remove target_node's coverage from next_num_covering_stations\n                // This makes it easy to find truly uncovered residents for re-assignment\n                for(int k=0; k<K; ++k){\n                    if(dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val){\n                        next_num_covering_stations[k]--;\n                        if(next_num_covering_stations[k] == 0){\n                            next_num_residents_fully_covered--;\n                        }\n                    }\n                }\n\n                P_next[target_node] = 0; \n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_active_stations.erase(target_node);\n\n                // For each resident that became uncovered, find the best station to cover it\n                for(int k=0; k<K; ++k){\n                    if(next_num_covering_stations[k] == 0){ // This resident is now uncovered\n                        int best_alt_station = -1;\n                        long long min_dist_sq = INF_LL; \n                        for(int i=1; i<=N; ++i){ \n                            if(dist_from_1[i] == INF_LL) continue; // Only consider reachable stations\n                            if(dist_res_node_sq[k][i] < min_dist_sq){\n                                min_dist_sq = dist_res_node_sq[k][i];\n                                best_alt_station = i;\n                            }\n                        }\n                        if(best_alt_station != -1){\n                            int old_alt_P = P_next[best_alt_station]; // Use P_next (which might already be updated)\n                            long long required_P_sq = min_dist_sq;\n                            int required_P = round_dist_val(required_P_sq);\n                            int new_alt_P = max(old_alt_P, min(5000, required_P));\n                            \n                            // Apply change to P_next and update costs incrementally\n                            P_next[best_alt_station] = new_alt_P;\n                            next_P_cost -= (long long)old_alt_P * old_alt_P;\n                            next_P_cost += (long long)new_alt_P * new_alt_P;\n                            if (old_alt_P == 0 && new_alt_P > 0) {\n                                next_active_stations.insert(best_alt_station);\n                            }\n                            // Update coverage for this resident 'k' by best_alt_station\n                            // (Only for k, not all residents affected by best_alt_station's P change)\n                            if (dist_res_node_sq[k][best_alt_station] <= (long long)new_alt_P * new_alt_P) {\n                                next_num_covering_stations[k]++;\n                                if(next_num_covering_stations[k] == 1) { // It just became covered again\n                                    next_num_residents_fully_covered++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        long long S_current_val = current_P_cost_SA + current_edge_cost_SA;\n        long long S_next = INF_LL;\n\n        if (next_num_residents_fully_covered == K) {\n            vector<int> B_temp(M);\n            long long next_edge_cost = calculate_edge_cost_from_active_stations(next_active_stations, B_temp);\n            S_next = next_P_cost + next_edge_cost;\n        }\n\n        if (S_next < best_S) {\n            P_current = P_next;\n            current_P_cost_SA = next_P_cost;\n            active_stations_SA = next_active_stations;\n            num_covering_stations_for_resident = next_num_covering_stations;\n            num_residents_fully_covered = next_num_residents_fully_covered;\n            current_edge_cost_SA = S_next - current_P_cost_SA; // derive edge cost from S_next and P_cost\n            best_S = S_next;\n            P_best = P_next;\n        } else if (S_next != INF_LL) {\n            long double prob = exp((S_current_val - S_next) / current_temp);\n            if (uniform_real_distribution<long double>(0.0, 1.0)(rng) < prob) {\n                P_current = P_next;\n                current_P_cost_SA = next_P_cost;\n                active_stations_SA = next_active_stations;\n                num_covering_stations_for_resident = next_num_covering_stations;\n                num_residents_fully_covered = next_num_residents_fully_covered;\n                current_edge_cost_SA = S_next - current_P_cost_SA;\n            }\n        }\n        \n        iter_count++;\n    }\n\n    // Final calculation for output\n    vector<int> B_final(M);\n    calculate_edge_cost_from_active_stations(active_stations_SA, B_final); \n\n    // Output\n    for (int i = 1; i <= N; ++i) {\n        cout << P_best[i] << (i == N ? \"\" : \" \");\n    }\n    cout << endl;\n    for (int j = 0; j < M; ++j) {\n        cout << B_final[j] << (j == M - 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 >> K;\n    solve();\n\n    return 0;\n}\n","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <tuple>   // For std::tuple\n\n// N is fixed to 30 for all inputs.\n// The problem defines N as the number of tiers.\n// Tiers are 0-indexed from 0 to N-1.\n// Ball coordinates are (x,y) where 0 <= x <= N-1 and 0 <= y <= x.\nconst int N = 30;\n\n// Global data structures for the pyramid state and operations.\n// The pyramid itself, storing the ball numbers.\nstd::vector<std::vector<int>> pyramid(N);\n\n// To quickly find the coordinates of a ball given its number.\n// `current_pos_of_value[ball_number]` stores `{x, y}`.\nstd::vector<std::pair<int, int>> current_pos_of_value(N * (N + 1) / 2);\n\n// Stores the sequence of swap operations.\n// Each operation is a tuple `{x1, y1, x2, y2}`.\nstd::vector<std::tuple<int, int, int, int>> operations;\n\n/**\n * @brief Performs a swap between two balls at given coordinates and records the operation.\n *\n * This function updates the `pyramid` and `current_pos_of_value` data structures\n * to reflect the swap, and adds the operation to the `operations` list.\n * The coordinates (r1, c1) and (r2, c2) must refer to adjacent balls.\n *\n * @param r1 Row coordinate of the first ball.\n * @param c1 Column coordinate of the first ball.\n * @param r2 Row coordinate of the second ball.\n * @param c2 Column coordinate of the second ball.\n */\nvoid perform_swap(int r1, int c1, int r2, int c2) {\n    int val1 = pyramid[r1][c1];\n    int val2 = pyramid[r2][c2];\n\n    // Swap values in the pyramid grid\n    pyramid[r1][c1] = val2;\n    pyramid[r2][c2] = val1;\n\n    // Update the mapping from value to its current position\n    current_pos_of_value[val1] = {r2, c2};\n    current_pos_of_value[val2] = {r1, c1};\n\n    // Record the swap operation\n    operations.emplace_back(r1, c1, r2, c2);\n}\n\n/**\n * @brief Sifts down an element at (r, c) to satisfy the min-pyramid property.\n *\n * This function repeatedly compares the ball at (r, c) with its two children\n * ((r+1, c) and (r+1, c+1)). If the parent ball is larger than either child,\n * it swaps the parent with the smallest child. This process continues until\n * the parent ball is smaller than or equal to both its children, or it reaches\n * the bottom tier.\n * This is an iterative implementation of the sift-down (or heapify-down) process.\n *\n * @param r Row coordinate of the ball to sift down.\n * @param c Column coordinate of the ball to sift down.\n */\nvoid sift_down(int r, int c) {\n    while (true) {\n        int parent_val = pyramid[r][c];\n        int min_val = parent_val; // Initialize min_val with parent's value\n        int target_r = r;         // Initialize target_r and target_c to parent's position\n        int target_c = c;\n\n        // Check left child: (r+1, c)\n        // Ensure that (r,c) is not in the last tier (N-1)\n        if (r + 1 < N) {\n            int child1_val = pyramid[r+1][c];\n            if (child1_val < min_val) {\n                min_val = child1_val;\n                target_r = r + 1;\n                target_c = c;\n            }\n        }\n\n        // Check right child: (r+1, c+1)\n        // Ensure (r,c) is not in the last tier AND (r+1, c+1) is a valid coordinate.\n        // For a tier x, valid column indices are from 0 to x.\n        // So for tier r+1, column c+1 must satisfy c+1 <= r+1.\n        if (r + 1 < N && c + 1 <= r + 1) {\n            int child2_val = pyramid[r+1][c+1];\n            // Crucially, compare against `min_val` (which might be child1_val already),\n            // not directly `parent_val`, to find the smallest among parent and both children.\n            if (child2_val < min_val) {\n                min_val = child2_val;\n                target_r = r + 1;\n                target_c = c + 1;\n            }\n        }\n\n        // If no child was smaller than the parent (or if it's a leaf node),\n        // the element is in its correct position relative to its children.\n        if (target_r == r && target_c == c) {\n            break; // Sifting process complete for this element\n        } else {\n            // Swap the current ball with the smallest child\n            perform_swap(r, c, target_r, target_c);\n\n            // Continue sifting down from the new position of the swapped element\n            r = target_r;\n            c = target_c;\n        }\n    }\n}\n\n\nint main() {\n    // Optimize C++ standard streams for competitive programming.\n    // This unties cin from cout and disables synchronization with C stdio,\n    // speeding up input/output operations.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read the initial state of the pyramid from standard input.\n    // Each row 'i' has 'i+1' balls.\n    for (int i = 0; i < N; ++i) {\n        pyramid[i].resize(i + 1); // Allocate space for balls in tier 'i'\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> pyramid[i][j];\n            // Store the initial position of each ball number.\n            current_pos_of_value[pyramid[i][j]] = {i, j};\n        }\n    }\n\n    // Apply the bottom-up heapify algorithm to satisfy the min-pyramid property.\n    // We iterate from the second-to-last tier (N-2) up to the top tier (0).\n    // For each ball in these tiers, we call sift_down to ensure it's smaller\n    // than its children. Since we process tiers bottom-up, when we sift down\n    // an element, its children's sub-pyramids are already correctly heapified.\n    for (int r = N - 2; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            sift_down(r, c);\n        }\n    }\n\n    // Output the total number of operations performed.\n    std::cout << operations.size() << std::endl;\n    // Output each swap operation in the specified format.\n    for (const auto& op : operations) {\n        std::cout << std::get<0>(op) << \" \"\n                  << std::get<1>(op) << \" \"\n                  << std::get<2>(op) << \" \"\n                  << std::get<3>(op) << std::endl;\n    }\n\n    return 0;\n}\n","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::abs\n\n// Global constants\nconst int D = 9;\nconst int DR[] = {-1, 1, 0, 0}; // delta row for neighbors (up, down, left, right)\nconst int DC[] = {0, 0, -1, 1}; // delta col for neighbors\n\n// Grid cell states\nconst int EMPTY = -1;\nconst int OBSTACLE = -2;\nconst int ENTRANCE_CELL = -3; // Renamed to avoid conflict with function entrance_r/c\nconst int UNVISITED = -1; // For BFS distance arrays\n\n// Global variables for the warehouse state\nint grid[D][D]; // Stores container ID (0 to M-1), or EMPTY/OBSTACLE/ENTRANCE_CELL\nbool is_obstacle[D][D];\nint static_dist[D][D]; // BFS distance from entrance on an empty grid\nstd::vector<std::pair<int, int>> static_ranked_squares; // Sorted by static_dist\nstd::map<std::pair<int, int>, int> square_to_static_rank; // Maps (r,c) to its rank in static_ranked_squares\n\nstd::pair<int, int> container_pos[D * D]; // Maps container ID to its (r,c) location\nint M; // Total number of containers\n\n// Coordinates of the entrance\nint entrance_r, entrance_c;\n\n// BFS utility function\n// Returns a vector of reachable empty squares (for placement phase)\n// Also populates reachable_container_ids_ptr if provided (for transport-out phase)\nstd::vector<std::pair<int, int>> bfs_reachable_info(\n    int (&current_grid)[D][D],\n    int (&current_dist)[D][D], // Output: distances from entrance\n    const bool* extracted_containers_mask_ptr, // Pointer to mask for extracted containers (nullptr for placement)\n    std::set<int>* reachable_container_ids_ptr // Output: reachable container IDs (nullptr for placement)\n) {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            current_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    current_dist[entrance_r][entrance_c] = 0;\n\n    std::vector<std::pair<int, int>> reachable_empty_squares_candidates;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue; // Out of bounds\n            if (is_obstacle[nr][nc]) continue; // Obstacle\n\n            if (current_dist[nr][nc] == UNVISITED) { // Not visited yet\n                if (current_grid[nr][nc] == EMPTY) {\n                    current_dist[nr][nc] = current_dist[r][c] + 1;\n                    q.push({nr, nc});\n                    reachable_empty_squares_candidates.push_back({nr, nc});\n                } else if (current_grid[nr][nc] == ENTRANCE_CELL) { \n                    // Entrance is traversable and starting point, already visited at dist 0.\n                    // No need to push again or add to reachable_empty_squares_candidates.\n                } else if (current_grid[nr][nc] >= 0) { // Contains a container\n                    int container_id = current_grid[nr][nc];\n                    if (extracted_containers_mask_ptr && extracted_containers_mask_ptr[container_id]) { \n                        // Container already extracted, treat as empty and traversable\n                        current_dist[nr][nc] = current_dist[r][c] + 1;\n                        q.push({nr, nc});\n                        reachable_empty_squares_candidates.push_back({nr, nc}); // Add as an available \"empty\" path square\n                    } else { \n                        // Container still present, cannot traverse, but is reachable for extraction\n                        if (reachable_container_ids_ptr) {\n                            reachable_container_ids_ptr->insert(container_id);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return reachable_empty_squares_candidates;\n}\n\n// Precomputes static distances from the entrance on an empty grid\nvoid precompute_static_distances() {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            static_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    static_dist[entrance_r][entrance_c] = 0;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (is_obstacle[nr][nc]) continue;\n\n            if (static_dist[nr][nc] == UNVISITED) {\n                static_dist[nr][nc] = static_dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Collect all valid container squares and sort them by static distance\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (!is_obstacle[i][j] && (i != entrance_r || j != entrance_c)) {\n                static_ranked_squares.push_back({i, j});\n            }\n        }\n    }\n\n    // Sort by static_dist, then row, then column for consistent ranking\n    std::sort(static_ranked_squares.begin(), static_ranked_squares.end(), [](const auto& a, const auto& b) {\n        if (static_dist[a.first][a.second] != static_dist[b.first][b.second]) {\n            return static_dist[a.first][a.second] < static_dist[b.first][b.second];\n        }\n        if (a.first != b.first) {\n            return a.first < b.first;\n        }\n        return a.second < b.second;\n    });\n\n    for (int i = 0; i < static_ranked_squares.size(); ++i) {\n        square_to_static_rank[static_ranked_squares[i]] = i;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_obstacles;\n    std::cin >> D >> N_obstacles; // D is fixed at 9, but read for generality\n\n    entrance_r = 0;\n    entrance_c = (D - 1) / 2;\n\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            grid[i][j] = EMPTY;\n            is_obstacle[i][j] = false;\n        }\n    }\n    grid[entrance_r][entrance_c] = ENTRANCE_CELL;\n\n    for (int k = 0; k < N_obstacles; ++k) {\n        int r_obs, c_obs;\n        std::cin >> r_obs >> c_obs;\n        is_obstacle[r_obs][c_obs] = true;\n        grid[r_obs][c_obs] = OBSTACLE;\n    }\n\n    M = D * D - 1 - N_obstacles; // Total number of containers\n\n    precompute_static_distances();\n\n    // Placement Phase\n    int current_dist[D][D]; // Temporary array for BFS distances in current state\n    bool dummy_extracted_mask[D*D] = {false}; // Placeholder, not used in placement phase BFS\n\n    for (int d = 0; d < M; ++d) {\n        int t_d; // Container ID\n        std::cin >> t_d;\n\n        std::vector<std::pair<int, int>> reachable_empty_squares =\n            bfs_reachable_info(grid, current_dist, dummy_extracted_mask, nullptr); // Nullptr for transport-out specific parameters\n\n        int best_score_diff = M + 1; // Max possible diff is M-1, so M+1 is a safe initial high value\n        std::pair<int, int> best_pos = {-1, -1};\n\n        for (const auto& p : reachable_empty_squares) {\n            int r = p.first;\n            int c = p.second;\n            int static_rank = square_to_static_rank[p];\n            int score_diff = std::abs(t_d - static_rank);\n\n            if (score_diff < best_score_diff) {\n                best_score_diff = score_diff;\n                best_pos = p;\n            } else if (score_diff == best_score_diff) {\n                // Tie-breaking rules for placement:\n                // 1. Prefer smaller current_dist (currently closer to entrance)\n                if (current_dist[r][c] < current_dist[best_pos.first][best_pos.second]) {\n                    best_pos = p;\n                }\n                // 2. If current_dist is also tied, prefer smaller static_dist (inherently closer)\n                else if (current_dist[r][c] == current_dist[best_pos.first][best_pos.second]) {\n                    if (static_dist[r][c] < static_dist[best_pos.first][best_pos.second]) {\n                        best_pos = p;\n                    }\n                    // 3. If static_dist is also tied, prefer smaller row, then smaller column (lexicographical)\n                    else if (static_dist[r][c] == static_dist[best_pos.first][best_pos.second]) {\n                        if (r < best_pos.first) {\n                            best_pos = p;\n                        } else if (r == best_pos.first) {\n                            if (c < best_pos.second) {\n                                best_pos = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        grid[best_pos.first][best_pos.second] = t_d;\n        container_pos[t_d] = best_pos;\n\n        std::cout << best_pos.first << \" \" << best_pos.second << std::endl;\n    }\n\n    // Transport-Out Phase\n    std::vector<int> b_sequence(M);\n    bool extracted_containers_mask[D*D]; // Tracks which containers have been extracted\n    for(int i = 0; i < D*D; ++i) extracted_containers_mask[i] = false;\n\n    for (int k = 0; k < M; ++k) {\n        std::set<int> reachable_containers;\n        // BFS to find all reachable containers given current grid state and extracted_containers_mask\n        bfs_reachable_info(grid, current_dist, extracted_containers_mask, &reachable_containers);\n\n        int min_reachable_id = -1;\n        if (!reachable_containers.empty()) {\n            min_reachable_id = *reachable_containers.begin(); // std::set keeps elements sorted, so begin() is the smallest\n        } else {\n            // This case should ideally not be reached if the problem guarantees connectivity\n            // and we always place containers in reachable spots.\n            // As a fallback, this would mean searching for the smallest unextracted ID,\n            // but this indicates a problem with logic or problem constraints.\n            // For now, assume a container is always reachable.\n            for (int id = 0; id < M; ++id) {\n                if (!extracted_containers_mask[id]) {\n                    min_reachable_id = id;\n                    break;\n                }\n            }\n        }\n\n        b_sequence[k] = min_reachable_id;\n        extracted_containers_mask[min_reachable_id] = true; // Mark container as extracted\n    }\n\n    for (int k = 0; k < M; ++k) {\n        std::pair<int, int> pos = container_pos[b_sequence[k]];\n        std::cout << pos.first << \" \" << pos.second << std::endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>   // For tracking affected pairs in adjacency check\n#include <tuple> // For std::tie\n\nusing namespace std;\n\n// Fixed grid size and number of wards\nconst int N = 50;\nconst int M = 100;\n\n// Original map from input\nint c[N][N];\n// Created map (modified during SA)\nint d[N][N];\n\n// Required adjacencies: adj_req[u][v] is true if u and v must be adjacent\nbool adj_req[M + 1][M + 1];\n\n// Current adjacencies in 'd' map: adj_count[u][v] stores number of edges between color u and color v\nint adj_count[M + 1][M + 1];\n\n// Number of cells for each color in 'd' map\nint num_cells[M + 1];\n\n// Stores coordinates of cells for each color\nvector<pair<int, int>> ward_cells[M + 1];\n// Stores the index of a cell (r,c) within ward_cells[d[r][c]].\n// This allows O(1) removal from ward_cells by swapping with the last element.\nint cell_idx_in_ward_cells[N][N];\n\n// Directions for neighbors (up, down, left, right)\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\n\n// Check if coordinates (r, c_val) are within the grid bounds\ninline bool is_valid_coord(int r, int c_val) {\n    return r >= 0 && r < N && c_val >= 0 && c_val < N;\n}\n\n// Check if a color 'k' is connected in the 'd' map.\n// If (excluded_r, excluded_c) is specified, that cell is temporarily ignored for connectivity.\nbool check_color_connectivity(int k, int excluded_r = -1, int excluded_c = -1) {\n    int current_num_k_cells = num_cells[k];\n    if (excluded_r != -1 && d[excluded_r][excluded_c] == k) {\n        current_num_k_cells--; // If the excluded cell has color k, reduce the count\n    }\n\n    if (current_num_k_cells == 0) return true; // Empty ward is trivially connected\n\n    // Find a starting point for BFS for color k\n    int start_r = -1, start_c = -1;\n    // Iterate through ward_cells to find a valid starting point that is not the excluded cell\n    for (auto p : ward_cells[k]) {\n        if (p.first == excluded_r && p.second == excluded_c) continue;\n        start_r = p.first;\n        start_c = p.second;\n        break;\n    }\n\n    if (start_r == -1) { // No cells of color k left after exclusion, but current_num_k_cells > 0. This shouldn't happen if num_cells is accurate.\n        return current_num_k_cells == 0;\n    }\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_count = 0;\n\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    reachable_count++;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == k && !visited[nr][nc]) {\n                if (nr == excluded_r && nc == excluded_c) continue; // Skip the excluded cell\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_count++;\n            }\n        }\n    }\n    return reachable_count == current_num_k_cells;\n}\n\n// Check if color 0 is connected (to the outside) in the 'd' map\nbool check_zero_connectivity() {\n    int current_zero_count = num_cells[0];\n    if (current_zero_count == 0) return true; // No 0s, trivially connected\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_zeros = 0;\n\n    // Add all boundary cells that are color 0 to the queue\n    for (int r = 0; r < N; ++r) {\n        if (d[r][0] == 0 && !visited[r][0]) {\n            q.push({r, 0});\n            visited[r][0] = true;\n            reachable_zeros++;\n        }\n        if (d[r][N - 1] == 0 && !visited[r][N - 1]) {\n            q.push({r, N - 1});\n            visited[r][N - 1] = true;\n            reachable_zeros++;\n        }\n    }\n    for (int c_val = 1; c_val < N - 1; ++c_val) { // Avoid double counting corners\n        if (d[0][c_val] == 0 && !visited[0][c_val]) {\n            q.push({0, c_val});\n            visited[0][c_val] = true;\n            reachable_zeros++;\n        }\n        if (d[N - 1][c_val] == 0 && !visited[N - 1][c_val]) {\n            q.push({N - 1, c_val});\n            visited[N - 1][c_val] = true;\n            reachable_zeros++;\n        }\n    }\n\n    // If no boundary '0' cells, but there are other '0' cells, they are disconnected.\n    if (current_zero_count > 0 && reachable_zeros == 0) return false;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == 0 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_zeros++;\n            }\n        }\n    }\n    return reachable_zeros == current_zero_count;\n}\n\nvoid solve() {\n    // Read input\n    int n_val, m_val;\n    cin >> n_val >> m_val; // N, M are fixed, but read them\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> c[i][j];\n        }\n    }\n\n    // Initialize d with c, and calculate initial state metrics\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            d[i][j] = c[i][j];\n            num_cells[d[i][j]]++;\n            // Add to ward_cells and record its index for O(1) removal later\n            cell_idx_in_ward_cells[i][j] = ward_cells[d[i][j]].size();\n            ward_cells[d[i][j]].push_back({i, j});\n        }\n    }\n\n    // Precompute required adjacencies (adj_req) from original map 'c'\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = c[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_req[curr_color][0] = adj_req[0][curr_color] = true;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = c[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_req[curr_color][neighbor_color] = adj_req[neighbor_color][curr_color] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initialize current adjacencies (adj_count) from 'd' (which is initially 'c')\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = d[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_count[min(curr_color, 0)][max(curr_color, 0)]++;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = d[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_count[min(curr_color, neighbor_color)][max(curr_color, neighbor_color)]++;\n                    }\n                }\n            }\n        }\n    }\n\n    // Each edge between two non-zero colors (u,v) where u,v > 0 is counted twice.\n    // So, divide by 2 for pairs (u,v) where u,v > 0.\n    // Pairs involving 0 (boundary adjacencies) are only counted once (when processing the non-zero cell).\n    // So for u=0 or v=0, we should not divide.\n    for (int u = 1; u <= M; ++u) { // Iterate only non-zero colors for u\n        for (int v = u; v <= M; ++v) { // Iterate only non-zero colors for v, ensuring u <= v\n            adj_count[u][v] /= 2;\n        }\n    }\n\n    // Store best map and score. Score is number of non-zero cells (maximize this).\n    vector<vector<int>> best_d(N, vector<int>(N));\n    int current_score = N * N - num_cells[0];\n    int best_score = current_score;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            best_d[i][j] = d[i][j];\n        }\n    }\n\n    // --- Simulated Annealing parameters ---\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95; // seconds (slightly less than 2s to allow for output)\n    double T_start = 2000.0;        // Initial temperature\n    double T_end = 1.0;             // Final temperature\n    long long iter_count = 0;       // Iteration counter\n\n    // Distributions for random selection\n    uniform_int_distribution<int> dist_rc(0, N - 1); // For random row/col\n    uniform_int_distribution<int> dist_color_m(1, M); // For random ward color (1 to M)\n    uniform_real_distribution<double> dist_real(0.0, 1.0); // For acceptance probability\n\n    // Main SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int r = dist_rc(rng);       // Random row\n        int c_val = dist_rc(rng);   // Random column\n        int old_color = d[r][c_val]; // Current color of the cell\n        int new_color;              // Proposed new color\n\n        // Strategy to pick new_color:\n        // Prioritize reducing 0s, then explore other moves\n        if (old_color == 0) {\n            // Try to fill this 0 cell with a neighboring ward's color\n            vector<int> non_zero_neighbors;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] != 0) {\n                    non_zero_neighbors.push_back(d[nr][nc]);\n                }\n            }\n\n            if (!non_zero_neighbors.empty()) {\n                // Pick a random non-zero neighbor's color\n                uniform_int_distribution<int> dist_neighbor_idx(0, non_zero_neighbors.size() - 1);\n                new_color = non_zero_neighbors[dist_neighbor_idx(rng)];\n            } else {\n                // If no non-zero neighbors, pick a random ward color (less effective, might create isolated components)\n                new_color = dist_color_m(rng);\n            }\n        } else { // Current cell is a ward color (1 to M)\n            // Option 1: Change to 0 (might fix forbidden adjacencies, but increases 0s)\n            // Option 2: Change to another non-zero color (assimilation/swap with neighbor)\n            if (dist_real(rng) < 0.5) { // 50% chance to try changing to 0\n                new_color = 0;\n            } else { // 50% chance to try changing to a neighbor's color\n                vector<int> neighbor_colors;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc)) {\n                        neighbor_colors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!neighbor_colors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, neighbor_colors.size() - 1);\n                    new_color = neighbor_colors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); // Random if no neighbors, fallback\n                }\n            }\n        }\n\n        if (new_color == old_color) continue; // No effective change, skip\n\n        // --- Prepare for tentative move and checks ---\n        // Store original state to revert if move is invalid/rejected\n        int original_d_rc_val = d[r][c_val];\n\n        vector<tuple<int, int, int>> temp_adj_count_deltas; // {u, v, delta}\n        set<pair<int, int>> affected_adj_pairs; // Track unique (u,v) pairs affected\n\n        // Update adj_count based on (r,c_val) -> (new_color)\n        // This is done before changing d[r][c_val] to correctly reflect adjacencies with neighbors.\n        // Neighbors of (r,c_val) are still in their original colors.\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c_val + DC[i];\n            if (is_valid_coord(nr, nc)) {\n                int neighbor_color = d[nr][nc]; // Neighbor's current color\n\n                // Remove old_color's adjacency with neighbor_color\n                if (old_color != neighbor_color) {\n                    int u = min(old_color, neighbor_color);\n                    int v = max(old_color, neighbor_color);\n                    adj_count[u][v]--;\n                    temp_adj_count_deltas.emplace_back(u, v, 1); // For reverting: add 1\n                    affected_adj_pairs.insert({u, v});\n                }\n                // Add new_color's adjacency with neighbor_color\n                if (new_color != neighbor_color) {\n                    int u = min(new_color, neighbor_color);\n                    int v = max(new_color, neighbor_color);\n                    adj_count[u][v]++;\n                    temp_adj_count_deltas.emplace_back(u, v, -1); // For reverting: subtract 1\n                    affected_adj_pairs.insert({u, v});\n                }\n            }\n        }\n        // Handle boundary adjacencies with color 0\n        if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n            if (old_color != 0) {\n                int u = min(old_color, 0);\n                int v = max(old_color, 0);\n                adj_count[u][v]--;\n                temp_adj_count_deltas.emplace_back(u, v, 1);\n                affected_adj_pairs.insert({u, v});\n            }\n            if (new_color != 0) {\n                int u = min(new_color, 0);\n                int v = max(new_color, 0);\n                adj_count[u][v]++;\n                temp_adj_count_deltas.emplace_back(u, v, -1);\n                affected_adj_pairs.insert({u, v});\n            }\n        }\n\n        // Tentatively apply d[r][c_val] = new_color;\n        d[r][c_val] = new_color;\n\n        // --- Perform validity checks ---\n        bool move_is_valid = true;\n\n        // 1. Local Adjacency Check: No required adjacencies broken, no forbidden ones created\n        for (auto p : affected_adj_pairs) {\n            int u = p.first;\n            int v = p.second;\n            bool current_adj_exists = (adj_count[u][v] > 0);\n            if (current_adj_exists != adj_req[u][v]) {\n                move_is_valid = false;\n                break;\n            }\n        }\n        if (!move_is_valid) {\n            // Revert d[r][c_val] and adj_count immediately\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue; // Skip to next iteration\n        }\n\n        // 2. Connectivity check for old_color (if it's not 0 and shrinking)\n        // A move can cause an old_color to split only if num_cells[old_color] > 1.\n        // If it becomes 0 after this change (num_cells[old_color] == 1 initially), it's trivially connected.\n        // The adjacency check ensures that if the only cell of old_color is removed, its required adjacencies\n        // are not broken.\n        if (old_color != 0 && num_cells[old_color] > 1) {\n            // Heuristic: If (r,c_val) had 0 or 1 neighbor of old_color, connectivity is likely fine.\n            // Only perform BFS if (r,c_val) was connected to multiple old_color cells\n            int old_color_neighbors_count = 0;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == old_color) {\n                    old_color_neighbors_count++;\n                }\n            }\n            // If it had multiple connections, removal might split the component\n            if (old_color_neighbors_count >= 2) {\n                if (!check_color_connectivity(old_color, r, c_val)) {\n                    move_is_valid = false;\n                }\n            }\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 3. Connectivity check for new_color (if it's not 0 and expanding/connecting)\n        // If num_cells[new_color] was 0, and now it becomes 1 (i.e. this is the first cell), it's connected.\n        // If num_cells[new_color] > 0, the new cell must connect to existing new_color cells.\n        if (new_color != 0) {\n            if (num_cells[new_color] > 0) { // new_color already exists, so (r,c_val) must connect to it\n                bool connected_to_new_color_region = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc) && d[nr][nc] == new_color) {\n                        connected_to_new_color_region = true;\n                        break;\n                    }\n                }\n                if (!connected_to_new_color_region) {\n                    // If no new_color neighbors, it forms an isolated component, which is invalid\n                    move_is_valid = false;\n                }\n            }\n            // If num_cells[new_color] was 0 (now becomes 1), it is trivially connected. No need to check.\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 4. Connectivity check for color 0 (expensive but crucial)\n        if (!check_zero_connectivity()) {\n            move_is_valid = false;\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // --- Move is valid, now decide on acceptance ---\n        // Update num_cells first\n        num_cells[old_color]--;\n        num_cells[new_color]++;\n\n        int new_score = N * N - num_cells[0]; // Score is number of non-zero cells\n\n        // Simulated Annealing acceptance logic\n        if (new_score > current_score || dist_real(rng) < exp((new_score - current_score) / T)) {\n            // Accept the move: update ward_cells permanently (O(1) with indexed swap)\n            // Remove (r,c_val) from old_color's ward_cells\n            int old_idx = cell_idx_in_ward_cells[r][c_val];\n            pair<int, int> last_cell_of_old_color = ward_cells[old_color].back();\n            ward_cells[old_color][old_idx] = last_cell_of_old_color;\n            cell_idx_in_ward_cells[last_cell_of_old_color.first][last_cell_of_old_color.second] = old_idx;\n            ward_cells[old_color].pop_back();\n\n            // Add (r,c_val) to new_color's ward_cells\n            cell_idx_in_ward_cells[r][c_val] = ward_cells[new_color].size();\n            ward_cells[new_color].push_back({r, c_val});\n\n            current_score = new_score;\n\n            if (new_score > best_score) {\n                best_score = new_score;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        best_d[i][j] = d[i][j];\n                    }\n                }\n            }\n        } else {\n            // Reject the move: revert changes to d, adj_count, num_cells\n            num_cells[old_color]++;\n            num_cells[new_color]--;\n            d[r][c_val] = original_d_rc_val; // Revert d[r][c_val]\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n        }\n    } // End of SA loop\n\n    // Output the best map found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_d[i][j] << (j == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n#include <map>\n\n// DSU structure\nstruct DSU {\n    std::vector<int> parent;\n    std::vector<int> sz; // Stores size of component for root\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    // Returns true if i and j were in different sets and are now united.\n    // comp_estimated_weight must be provided to update the new root's estimated weight.\n    bool unite(int i, int j, std::vector<double>& comp_estimated_weight) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            // Union by size\n            if (sz[root_i] < sz[root_j]) std::swap(root_i, root_j);\n            \n            // Weighted average for the new component's estimated weight\n            double new_weight = (comp_estimated_weight[root_i] * sz[root_i] + comp_estimated_weight[root_j] * sz[root_j]) / (sz[root_i] + sz[root_j]);\n\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            comp_estimated_weight[root_i] = new_weight;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global random number generator\nstd::mt19937 mt;\n\n// Function to perform a query\nstd::string query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int item_idx : L) {\n        std::cout << \" \" << item_idx;\n    }\n    for (int item_idx : R) {\n        std::cout << \" \" << item_idx;\n    }\n    std::cout << std::endl; // Flush output\n    \n    std::string result;\n    std::cin >> result;\n    return result;\n}\n\n// Function to calculate variance for the partitioning\ndouble calculate_variance(int D, const std::vector<double>& group_sums) {\n    if (D == 0) return 0.0;\n    double sum_t = 0.0;\n    for (double t : group_sums) {\n        sum_t += t;\n    }\n    double mean_t = sum_t / D;\n    double variance = 0.0;\n    for (double t : group_sums) {\n        variance += (t - mean_t) * (t - mean_t);\n    }\n    return variance / D;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Use current time as seed for random number generator\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N, D, Q;\n    std::cin >> N >> D >> Q;\n\n    DSU dsu(N);\n    std::vector<double> comp_estimated_weight(N);\n    for (int i = 0; i < N; ++i) {\n        comp_estimated_weight[i] = 1.0; // Initial estimated weight for each component root\n    }\n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.9; // seconds\n\n    // Query parameters\n    const double initial_learning_rate = 0.05;\n    const double final_learning_rate = 0.001;\n    const int max_group_query_size = 5;\n\n    for (int q_idx = 0; q_idx < Q; ++q_idx) {\n        double current_learning_rate = initial_learning_rate - (initial_learning_rate - final_learning_rate) * q_idx / Q;\n\n        std::vector<int> active_roots;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.parent[i] == i) { // Check if 'i' is a root\n                active_roots.push_back(i);\n            }\n        }\n\n        std::vector<int> L_items, R_items;\n        int root_L_comp = -1, root_R_comp = -1; // Roots of components chosen for L and R\n\n        if (active_roots.size() < 2) { \n            // All items in one component, or only one item left. \n            // If N is sufficiently large (>= 2), we can still pick two distinct items.\n            int item1 = mt() % N;\n            int item2 = mt() % N;\n            while (item1 == item2) {\n                item2 = mt() % N;\n            }\n            L_items.push_back(item1);\n            R_items.push_back(item2);\n            root_L_comp = dsu.find(item1);\n            root_R_comp = dsu.find(item2);\n        } else {\n            // Pick two distinct random roots\n            std::shuffle(active_roots.begin(), active_roots.end(), mt);\n            root_L_comp = active_roots[0];\n            root_R_comp = active_roots[1];\n\n            // Get items belonging to these components\n            std::vector<int> items_in_root1_comp;\n            std::vector<int> items_in_root2_comp;\n            for (int i = 0; i < N; ++i) {\n                if (dsu.find(i) == root_L_comp) items_in_root1_comp.push_back(i);\n                if (dsu.find(i) == root_R_comp) items_in_root2_comp.push_back(i);\n            }\n            \n            // Randomly select L_size and R_size\n            int L_size = 1 + mt() % max_group_query_size;\n            int R_size = 1 + mt() % max_group_query_size;\n\n            L_size = std::min((int)items_in_root1_comp.size(), L_size);\n            R_size = std::min((int)items_in_root2_comp.size(), R_size);\n\n            // Ensure L_size and R_size are at least 1, unless component is empty (should not happen for active roots)\n            if (L_size == 0 && !items_in_root1_comp.empty()) L_size = 1;\n            if (R_size == 0 && !items_in_root2_comp.empty()) R_size = 1;\n\n            std::shuffle(items_in_root1_comp.begin(), items_in_root1_comp.end(), mt);\n            std::shuffle(items_in_root2_comp.begin(), items_in_root2_comp.end(), mt);\n\n            for (int k = 0; k < L_size; ++k) L_items.push_back(items_in_root1_comp[k]);\n            for (int k = 0; k < R_size; ++k) R_items.push_back(items_in_root2_comp[k]);\n        }\n        \n        // Safety check, although should be covered by logic above\n        if (L_items.empty() || R_items.empty()) {\n            if (N > 1) { // If N is large enough for two distinct items\n                 L_items.clear(); R_items.clear();\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else { // N=1, cannot make a query, but N >= 30, so this won't happen.\n                continue; // Skip query.\n            }\n        }\n\n        std::string result = query(L_items, R_items);\n\n        // Calculate current estimated sums based on component representatives\n        double sum_L_est = 0.0;\n        for (int item_idx : L_items) sum_L_est += comp_estimated_weight[dsu.find(item_idx)];\n        double sum_R_est = 0.0;\n        for (int item_idx : R_items) sum_R_est += comp_estimated_weight[dsu.find(item_idx)];\n\n        if (result == \"=\") {\n            // For 1-1 comparison of different components: merge\n            if (L_items.size() == 1 && R_items.size() == 1 && root_L_comp != root_R_comp) {\n                dsu.unite(L_items[0], R_items[0], comp_estimated_weight);\n            } else if (root_L_comp != root_R_comp) { // Group equality for different components\n                // Adjust component weights to make their estimated sums equal\n                // New weight for root_L_comp s.t. current_sum_L becomes (current_sum_L + current_sum_R)/2\n                double target_sum = (sum_L_est + sum_R_est) / 2.0;\n                if (sum_L_est > 1e-9) comp_estimated_weight[root_L_comp] *= (target_sum / sum_L_est);\n                if (sum_R_est > 1e-9) comp_estimated_weight[root_R_comp] *= (target_sum / sum_R_est);\n            }\n            // If roots are the same, equality doesn't give new relative information between them.\n        } else { // Inequality: L is lighter (<) or heavier (>) than R\n            if (result == \"<\") { // Actual L < Actual R\n                // Our estimates should decrease L's component weight, increase R's\n                comp_estimated_weight[root_L_comp] *= (1.0 - current_learning_rate);\n                comp_estimated_weight[root_R_comp] *= (1.0 + current_learning_rate);\n            } else { // Actual L > Actual R (result == \">\")\n                // Our estimates should increase L's component weight, decrease R's\n                comp_estimated_weight[root_L_comp] *= (1.0 + current_learning_rate);\n                comp_estimated_weight[root_R_comp] *= (1.0 - current_learning_rate);\n            }\n        }\n\n        // Ensure weights are positive. Minimum weight is 1 as per problem constraints on w_i.\n        comp_estimated_weight[root_L_comp] = std::max(1.0, comp_estimated_weight[root_L_comp]);\n        comp_estimated_weight[root_R_comp] = std::max(1.0, comp_estimated_weight[root_R_comp]);\n    }\n\n    // Phase 2: Partitioning using Simulated Annealing\n    std::vector<double> final_weights(N);\n    for (int i = 0; i < N; ++i) {\n        final_weights[i] = comp_estimated_weight[dsu.find(i)];\n    }\n\n    std::vector<int> item_to_group(N);\n    std::vector<int> item_indices(N);\n    std::iota(item_indices.begin(), item_indices.end(), 0);\n\n    // Initial greedy assignment: sort items by estimated weight descending\n    std::sort(item_indices.begin(), item_indices.end(), [&](int a, int b) {\n        return final_weights[a] > final_weights[b];\n    });\n\n    std::vector<double> group_sums(D, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int item_idx = item_indices[i];\n        int min_group = 0;\n        for (int d = 1; d < D; ++d) {\n            if (group_sums[d] < group_sums[min_group]) {\n                min_group = d;\n            }\n        }\n        item_to_group[item_idx] = min_group;\n        group_sums[min_group] += final_weights[item_idx];\n    }\n\n    // Simulated Annealing parameters\n    double T_start = 1000.0; // Starting temperature\n    double T_end = 1.0;      // Ending temperature (small but not zero)\n\n    auto current_time = std::chrono::high_resolution_clock::now();\n    double elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n\n    long long iter_count = 0;\n    while (elapsed_time < TIME_LIMIT) {\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * std::pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int item_to_move_idx = mt() % N;\n        int current_group = item_to_group[item_to_move_idx];\n        int new_group = mt() % D;\n        \n        if (new_group == current_group) {\n            // No actual move, just update time and continue\n            current_time = std::chrono::high_resolution_clock::now();\n            elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n            continue; \n        }\n\n        // Calculate potential new variance without actually changing state yet\n        std::vector<double> next_group_sums = group_sums;\n        next_group_sums[current_group] -= final_weights[item_to_move_idx];\n        next_group_sums[new_group] += final_weights[item_to_move_idx];\n        \n        double next_variance = calculate_variance(D, next_group_sums);\n        double current_variance = calculate_variance(D, group_sums); // Re-calculate to ensure it's up to date with any previous changes\n\n        if (next_variance < current_variance) {\n            // Always accept better solution\n            current_variance = next_variance;\n            group_sums = next_group_sums;\n            item_to_group[item_to_move_idx] = new_group;\n        } else {\n            // Accept worse solution with probability\n            double prob = std::exp((current_variance - next_variance) / T);\n            if (std::uniform_real_distribution<double>(0.0, 1.0)(mt) < prob) {\n                current_variance = next_variance;\n                group_sums = next_group_sums;\n                item_to_group[item_to_move_idx] = new_group;\n            }\n        }\n        \n        current_time = std::chrono::high_resolution_clock::now();\n        elapsed_time = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        std::cout << item_to_group[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <algorithm> // For std::max or other utilities if needed\n\n// Fixed constants for N and M as per problem statement\nconst int N_BOXES = 200;\nconst int M_STACKS = 10;\n\n// Structure to hold the state of a box\nstruct BoxInfo {\n    int stack_idx;  // 0-indexed stack number (0 to M_STACKS-1)\n    int height_idx; // 0-indexed height from bottom (0 to stack.size()-1)\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n_input, m_input; // Read N and M, though they are fixed\n    std::cin >> n_input >> m_input;\n\n    // stacks[i] is a deque representing stack i, from bottom to top\n    std::vector<std::deque<int>> stacks(M_STACKS);\n    // box_location[v] stores BoxInfo for box v (1-indexed box_id)\n    std::vector<BoxInfo> box_location(N_BOXES + 1);\n\n    // Initialize stacks and box_location from input\n    for (int i = 0; i < M_STACKS; ++i) {\n        for (int j = 0; j < N_BOXES / M_STACKS; ++j) {\n            int box_id;\n            std::cin >> box_id;\n            stacks[i].push_back(box_id);\n            box_location[box_id] = {i, j};\n        }\n    }\n\n    std::vector<std::pair<int, int>> operations;\n    // long long total_energy_expended = 0; // For debugging/local testing, not required for output\n\n    // Iterate for each box from 1 to N_BOXES in ascending order\n    for (int v = 1; v <= N_BOXES; ++v) {\n        int current_stack_idx = box_location[v].stack_idx;\n        int current_height_idx = box_location[v].height_idx;\n\n        // If box v is already carried out, skip (e.g., if problem logic was different, or error)\n        // With current strict 1..N order, this check mainly guards against logical errors.\n        if (current_stack_idx == -1) {\n            continue;\n        }\n\n        // Check if box v is at the top of its stack\n        if (current_height_idx == stacks[current_stack_idx].size() - 1) {\n            // Box v is at the top, can be carried out\n            operations.push_back({v, 0}); // Operation 2: (v, 0)\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n        } else {\n            // Box v is not at the top, need to move boxes above it\n\n            // Identify the bottom-most box of the block to be moved\n            int block_bottom_box_id = stacks[current_stack_idx][current_height_idx + 1];\n            // Calculate number of boxes to move (k in problem statement)\n            int num_boxes_to_move = stacks[current_stack_idx].size() - (current_height_idx + 1);\n            // total_energy_expended += (long long)num_boxes_to_move + 1; // Add cost (k+1)\n\n            // Choose destination stack for Operation 1\n            int dest_stack_idx = -1;\n            int max_top_box_val = -1; // For heuristic: pick stack with highest top box value\n\n            // Strategy 1: Prioritize empty stacks\n            for (int d = 0; d < M_STACKS; ++d) {\n                if (d == current_stack_idx) continue; // Cannot move to the same stack\n                if (stacks[d].empty()) {\n                    dest_stack_idx = d;\n                    break; // Found an empty stack, use it\n                }\n            }\n\n            // Strategy 2: If no empty stack, choose stack with the highest value at its top\n            if (dest_stack_idx == -1) {\n                for (int d = 0; d < M_STACKS; ++d) {\n                    if (d == current_stack_idx) continue;\n                    // At this point, stacks[d] is guaranteed not empty\n                    if (stacks[d].back() > max_top_box_val) {\n                        max_top_box_val = stacks[d].back();\n                        dest_stack_idx = d;\n                    }\n                }\n            }\n\n            // Perform Operation 1: move block_bottom_box_id and boxes above it to dest_stack_idx\n            // Output stack_idx as 1-indexed, so dest_stack_idx + 1\n            operations.push_back({block_bottom_box_id, dest_stack_idx + 1});\n\n            // Temporarily store boxes that will be moved\n            std::vector<int> boxes_to_move;\n            for (size_t i = current_height_idx + 1; i < stacks[current_stack_idx].size(); ++i) {\n                boxes_to_move.push_back(stacks[current_stack_idx][i]);\n            }\n            \n            // Resize the original stack to remove the moved boxes\n            stacks[current_stack_idx].resize(current_height_idx + 1);\n\n            // Add the moved boxes to the destination stack and update their locations\n            for (int box_id : boxes_to_move) {\n                box_location[box_id] = {dest_stack_idx, (int)stacks[dest_stack_idx].size()};\n                stacks[dest_stack_idx].push_back(box_id);\n            }\n            \n            // After moving, box v is now at the top of its original stack.\n            // Update v's height_idx to reflect its new top position\n            box_location[v].height_idx = stacks[current_stack_idx].size() - 1;\n\n            // Perform Operation 2: carry out box v\n            operations.push_back({v, 0});\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n        }\n    }\n\n    // Output the sequence of operations\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip> // For setprecision\n#include <functional> // For std::function\n\nusing namespace std;\n\nint N;\nvector<string> H_walls; // h[i][j] wall between (i,j) and (i+1,j)\nvector<string> V_walls; // v[i][j] wall between (i,j) and (i,j+1)\nvector<vector<int>> D_values; // d[i][j] dirt susceptibility\n\n// Directions: D, R, U, L\nint DR[] = {1, 0, -1, 0};\nint DC[] = {0, 1, 0, -1};\nchar DIR_CHARS[] = {'D', 'R', 'U', 'L'};\nchar REV_DIR_CHARS[] = {'U', 'L', 'D', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Get next position after moving in a given direction\nPos get_next_pos(Pos current, int dir_idx) {\n    return {current.r + DR[dir_idx], current.c + DC[dir_idx]};\n}\n\n// Check if move is valid (within bounds and no wall)\nbool is_valid_move(Pos current, int dir_idx) {\n    int nr = current.r + DR[dir_idx];\n    int nc = current.c + DC[dir_idx];\n\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n        return false; // Out of bounds\n    }\n\n    // Check for walls\n    if (dir_idx == 0) { // Down: from (r,c) to (r+1,c)\n        return H_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 1) { // Right: from (r,c) to (r,c+1)\n        return V_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 2) { // Up: from (r,c) to (r-1,c)\n        // Wall between (r-1,c) and (r,c) is H_walls[r-1][c]\n        return H_walls[nr][nc] == '0'; \n    } else if (dir_idx == 3) { // Left: from (r,c) to (r,c-1)\n        // Wall between (r,c-1) and (r,c) is V_walls[r][c-1]\n        return V_walls[nr][nc] == '0';\n    }\n    return false; // Should not happen\n}\n\n// Calculate exact score based on path_moves and visits\ndouble calculate_exact_score(int L, const vector<vector<int>>& visits_data, const vector<vector<int>>& d_values) {\n    double total_S_sum_terms = 0.0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int sq_idx = i * N + j;\n            const auto& cell_visits = visits_data[sq_idx];\n\n            if (cell_visits.empty()) {\n                // This means an illegal path (square not visited)\n                return 1e18; // Very high penalty\n            }\n\n            double sum_term_for_cell = 0.0;\n            int N_ij = cell_visits.size();\n\n            for (int k = 0; k < N_ij - 1; ++k) {\n                long long T = cell_visits[k+1] - cell_visits[k];\n                sum_term_for_cell += (double)T * (T - 1) / 2.0;\n            }\n            // For the last interval that wraps around\n            long long T_last = L - cell_visits[N_ij-1] + cell_visits[0];\n            sum_term_for_cell += (double)T_last * (T_last - 1) / 2.0;\n\n            total_S_sum_terms += d_values[i][j] * sum_term_for_cell;\n        }\n    }\n    return total_S_sum_terms / L;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    H_walls.resize(N - 1);\n    V_walls.resize(N);\n    D_values.resize(N, vector<int>(N));\n\n    for (int i = 0; i < N - 1; ++i) cin >> H_walls[i];\n    for (int i = 0; i < N; ++i) cin >> V_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D_values[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    string current_path_moves_str;\n    \n    // Initial DFS path generation\n    vector<bool> dfs_visited_cells(N * N, false);\n    \n    // Lambda function for DFS path building\n    function<void(Pos)> build_dfs_path = \n        [&](Pos current) {\n        int current_idx = current.r * N + current.c;\n        dfs_visited_cells[current_idx] = true;\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            int next_idx = next.r * N + next.c;\n\n            if (next.r < 0 || next.r >= N || next.c < 0 || next.c >= N) continue; // Out of bounds check\n            if (!is_valid_move(current, dir_idx)) continue; // Wall check\n            if (dfs_visited_cells[next_idx]) continue; // Already visited\n\n            current_path_moves_str += DIR_CHARS[dir_idx];\n            build_dfs_path(next);\n            current_path_moves_str += REV_DIR_CHARS[dir_idx];\n        }\n    };\n    \n    build_dfs_path({0,0});\n    string initial_dfs_path_moves = current_path_moves_str; // Store initial path as a fallback\n    int current_L = current_path_moves_str.length();\n\n    // Build visits list from the initial DFS path\n    vector<vector<int>> current_visits(N * N);\n    Pos temp_pos = {0,0};\n    for (int t = 0; t < current_L; ++t) {\n        char move_char = current_path_moves_str[t];\n        int dir_idx = -1;\n        for(int i=0; i<4; ++i) if(DIR_CHARS[i] == move_char) dir_idx = i;\n        temp_pos = get_next_pos(temp_pos, dir_idx);\n        current_visits[temp_pos.r * N + temp_pos.c].push_back(t + 1); // t+1 because 1-indexed time\n    }\n\n    double current_score = calculate_exact_score(current_L, current_visits, D_values);\n    double best_score = current_score;\n    string best_path_moves = current_path_moves_str; // Initialize best path\n\n    // Set up random number generators for Simulated Annealing\n    mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double T_start = 1000.0; // Initial temperature (can be related to max D_value)\n    double T_end = 0.1;     // Final temperature, tuned lower\n    long long max_iterations_for_temp = 1000000; // Reference for cooling schedule progression, tuned higher\n\n    int iter_count = 0;\n    // Iterate for a maximum of 1.95 seconds (leaving some margin for output/cleanup)\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1950) {\n        iter_count++;\n        // Linear cooling schedule\n        double T = T_start + (T_end - T_start) * ((double)iter_count / max_iterations_for_temp);\n        if (T < T_end) T = T_end; // Ensure temp doesn't drop below T_end\n\n        // Try adding a 2-move loop from (0,0) to an adjacent cell and back\n        Pos zero_zero_pos = {0,0};\n        \n        int dir_idx = rng() % 4; // Random direction for neighbor of (0,0)\n        Pos next_loop_pos = get_next_pos(zero_zero_pos, dir_idx);\n        \n        // Check if the loop is valid (within bounds, no walls for both moves)\n        if (next_loop_pos.r < 0 || next_loop_pos.r >= N || next_loop_pos.c < 0 || next_loop_pos.c >= N) continue;\n        if (!is_valid_move(zero_zero_pos, dir_idx)) continue;\n        int rev_dir_idx = (dir_idx + 2) % 4; // Direction to move back to (0,0)\n        if (!is_valid_move(next_loop_pos, rev_dir_idx)) continue;\n\n        string added_moves = string(1, DIR_CHARS[dir_idx]) + string(1, REV_DIR_CHARS[rev_dir_idx]);\n        string temp_path_moves = current_path_moves_str + added_moves;\n        int temp_L = current_L + 2;\n        \n        if (temp_L > 100000) continue; // Path length limit\n\n        vector<vector<int>> temp_visits = current_visits; // Create a copy of current visits data\n        \n        // Add new visit times for the two cells involved in the loop\n        // The first new visit is for `next_loop_pos` at `current_L + 1`\n        // The second new visit is for `zero_zero_pos` at `current_L + 2`\n        int next_loop_idx = next_loop_pos.r * N + next_loop_pos.c;\n        int zero_zero_idx = zero_zero_pos.r * N + zero_zero_pos.c;\n\n        // Use lower_bound and insert to maintain sorted order efficiently (O(k) where k is vector size)\n        auto it_next = lower_bound(temp_visits[next_loop_idx].begin(), temp_visits[next_loop_idx].end(), current_L + 1);\n        temp_visits[next_loop_idx].insert(it_next, current_L + 1);\n\n        auto it_zero = lower_bound(temp_visits[zero_zero_idx].begin(), temp_visits[zero_zero_idx].end(), current_L + 2);\n        temp_visits[zero_zero_idx].insert(it_zero, current_L + 2);\n        \n        double temp_score = calculate_exact_score(temp_L, temp_visits, D_values);\n        \n        double delta_score = temp_score - current_score;\n\n        if (delta_score < 0 || (T > 0 && dist_real(rng) < exp(-delta_score / T))) {\n            current_path_moves_str = temp_path_moves;\n            current_L = temp_L;\n            current_visits = temp_visits;\n            current_score = temp_score;\n\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_path_moves = current_path_moves_str;\n            }\n        }\n    }\n\n    // Final check for the best_path_moves: ensure it truly ends at (0,0)\n    Pos final_pos_check = {0,0};\n    for (char move_char : best_path_moves) {\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        final_pos_check = get_next_pos(final_pos_check, dir_idx);\n    }\n\n    if (!(final_pos_check == Pos{0,0})) {\n        // Fallback to the initial DFS path if the best_path_moves somehow became invalid.\n        // This is a safety measure to avoid WA on \"does not return to (0,0)\".\n        // It indicates a very subtle bug in the SA path update logic that wasn't identified.\n        // Outputting initial_dfs_path_moves guarantees valid path.\n        cerr << \"WARNING: best_path_moves does not end at (0,0). Falling back to initial DFS path.\" << endl;\n        cout << initial_dfs_path_moves << endl;\n    } else {\n        cout << best_path_moves << endl;\n    }\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm>\n#include <tuple> // For std::tuple comparison\n#include <cmath> // For std::abs\n\n// Aho-Corasick Node definition\nstruct ACNode {\n    std::array<int, 26> go; // Transition links for characters 'A'-'Z'\n    int fail; // Failure link\n    std::vector<int> pattern_indices; // Indices of patterns ending at this node (or via failure links)\n    int depth; // Length of string represented by this node\n\n    ACNode() : fail(0), depth(0) {\n        go.fill(0); // Initialize all transitions to 0 (root node)\n    }\n};\n\nstd::vector<ACNode> ac_trie; // The Aho-Corasick automaton trie\nstd::vector<bool> global_found_tks; // Tracks which of the M patterns have been found\nint M_val; // Stores the total number of patterns (M)\n\n// Builds the Aho-Corasick automaton from the given patterns\nvoid build_ac(const std::vector<std::string>& patterns) {\n    ac_trie.clear();\n    ac_trie.emplace_back(); // Root node (node 0)\n    M_val = patterns.size();\n    global_found_tks.assign(M_val, false); // Initialize all patterns as not found\n\n    // 1. Build Trie structure: Insert all patterns into the trie\n    for (int p_idx = 0; p_idx < M_val; ++p_idx) {\n        int curr = 0; // Start from the root\n        for (char ch : patterns[p_idx]) {\n            int c_idx = ch - 'A';\n            if (ac_trie[curr].go[c_idx] == 0) { // If transition doesn't exist, create a new node\n                ac_trie[curr].go[c_idx] = ac_trie.size(); // Assign new node ID\n                ac_trie.emplace_back(); // Add new node to the trie\n                ac_trie.back().depth = ac_trie[curr].depth + 1; // Set its depth\n            }\n            curr = ac_trie[curr].go[c_idx]; // Move to the next node\n        }\n        ac_trie[curr].pattern_indices.push_back(p_idx); // Mark this node as an end point for pattern p_idx\n    }\n\n    // 2. Build Failure Links and propagate output patterns using BFS\n    std::queue<int> q;\n    // For all direct children of the root, their failure link points to the root (0)\n    for (int i = 0; i < 26; ++i) {\n        if (ac_trie[0].go[i] != 0) {\n            ac_trie[ac_trie[0].go[i]].fail = 0; // Set fail link\n            q.push(ac_trie[0].go[i]); // Add to BFS queue\n        }\n    }\n\n    while (!q.empty()) {\n        int u = q.front(); // Current node\n        q.pop();\n\n        // Propagate pattern_indices from the failure link:\n        // Any patterns found via `u`'s failure link are also considered found when at `u`\n        int f = ac_trie[u].fail;\n        for (int p_idx : ac_trie[f].pattern_indices) {\n            ac_trie[u].pattern_indices.push_back(p_idx);\n        }\n        // Note: For distinct patterns, `pattern_indices` won't usually have duplicates this way.\n        // If necessary, `std::sort` and `std::unique` could be used here for robustness.\n\n        // For each character in the alphabet\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            if (ac_trie[u].go[c_idx] != 0) { // If a direct child `v` exists for char `c_idx`\n                int v = ac_trie[u].go[c_idx];\n                // The fail link of `v` is found by following `u`'s fail link, then trying to match `c_idx`\n                ac_trie[v].fail = ac_trie[ac_trie[u].fail].go[c_idx];\n                q.push(v); // Add `v` to the BFS queue\n            } else { // If no direct child `v` for char `c_idx`, create a \"shortcut\"\n                // This makes `go[c_idx]` from `u` behave as if it's `go[c_idx]` from `u`'s failure link\n                ac_trie[u].go[c_idx] = ac_trie[ac_trie[u].fail].go[c_idx];\n            }\n        }\n    }\n}\n\n// Get the next state in the Aho-Corasick automaton.\n// This function relies on the precomputed 'go' links which already include fail link shortcuts.\nint get_next_ac_state(int current_node, char ch) {\n    int c_idx = ch - 'A';\n    return ac_trie[current_node].go[c_idx];\n}\n\n// Checks for newly found patterns at the given node and updates the global_found_tks array.\nvoid check_and_update_patterns(int node_id) {\n    for (int p_idx : ac_trie[node_id].pattern_indices) {\n        if (!global_found_tks[p_idx]) { // If this pattern hasn't been marked as found yet\n            global_found_tks[p_idx] = true; // Mark it as found\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_grid, M_patterns;\n    std::cin >> N_grid >> M_patterns;\n\n    int s_i, s_j; // Initial finger position\n    std::cin >> s_i >> s_j;\n\n    std::vector<std::string> A_grid(N_grid);\n    // Precompute coordinates for each character on the grid for efficient lookup\n    std::vector<std::vector<std::pair<int, int>>> char_to_coords(26);\n    for (int i = 0; i < N_grid; ++i) {\n        std::cin >> A_grid[i];\n        for (int j = 0; j < N_grid; ++j) {\n            char_to_coords[A_grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    std::vector<std::string> t_patterns(M_patterns);\n    for (int k = 0; k < M_patterns; ++k) {\n        std::cin >> t_patterns[k];\n    }\n\n    build_ac(t_patterns); // Build the Aho-Corasick automaton\n\n    std::pair<int, int> current_pos = {s_i, s_j}; // Current finger position\n    int current_ac_node = 0; // Current state in the Aho-Corasick automaton (starts at root)\n    std::vector<std::pair<int, int>> operations; // List to store the sequence of operations\n\n    // Check if any patterns are found by the empty string (root node).\n    // This is typically not the case for non-empty patterns but ensures correctness for any edge cases.\n    check_and_update_patterns(0);\n\n    // Main greedy loop: continue until all patterns are found or the operation limit is reached\n    while (true) {\n        int found_count = 0;\n        for(bool b : global_found_tks) {\n            if (b) found_count++;\n        }\n\n        if (found_count == M_patterns) {\n            break; // All patterns found, goal achieved\n        }\n        if (operations.size() >= 5000) {\n            break; // Operation limit reached, cannot perform more actions\n        }\n\n        int best_nr = -1, best_nc = -1; // Coordinates for the best next move\n        char best_char_to_append = ' '; // Character for the best next move\n        \n        // Metric for choosing the best next operation:\n        // Using a tuple for lexicographical comparison:\n        // 1. Maximize newly found patterns (`temp_new_tks_count`).\n        // 2. Minimize typing cost (`-current_move_cost` because tuple comparison is maximizing).\n        // 3. Maximize Aho-Corasick node depth (`ac_trie[next_node].depth`).\n        std::tuple<int, int, int> best_metric = {-1, 1, -1}; // Initialize with values any valid choice will beat\n\n        // Iterate through all possible next characters and their positions on the keyboard\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            char c = 'A' + c_idx;\n            for (auto [nr, nc] : char_to_coords[c_idx]) { // Iterate through all physical locations of character 'c'\n                int current_move_cost = std::abs(nr - current_pos.first) + std::abs(nc - current_pos.second) + 1;\n                int next_node = get_next_ac_state(current_ac_node, c); // Get the AC state after appending 'c'\n\n                // Temporarily count how many *new* patterns would be found by this specific choice\n                int temp_new_tks_count = 0;\n                for (int p_idx : ac_trie[next_node].pattern_indices) {\n                    if (!global_found_tks[p_idx]) { // If this pattern hasn't been found yet\n                        temp_new_tks_count++;\n                    }\n                }\n                \n                std::tuple<int, int, int> current_metric = {temp_new_tks_count, -current_move_cost, ac_trie[next_node].depth};\n\n                if (current_metric > best_metric) { // Compare using tuple's lexicographical order\n                    best_metric = current_metric;\n                    best_nr = nr;\n                    best_nc = nc;\n                    best_char_to_append = c;\n                }\n            }\n        }\n\n        // If no valid character choice was found, it implies that no move improves the score\n        // (which usually means all patterns are found, or we've hit a state where no further progress is possible\n        // under the greedy heuristic). This should ideally not happen if M_patterns are not all found and ops < 5000.\n        if (best_nr == -1) {\n            break; \n        }\n\n        // Perform the chosen best operation\n        operations.push_back({best_nr, best_nc});\n        current_pos = {best_nr, best_nc}; // Update finger position\n        current_ac_node = get_next_ac_state(current_ac_node, best_char_to_append); // Update AC state\n        check_and_update_patterns(current_ac_node); // Update the global set of found patterns\n    }\n\n    // Output the sequence of operations as required by the problem statement\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc030":"","ahc031":"long long calculate_delta_cost(int d, const Rect& old_r, const Rect& new_r, int k_id,\n                                 const bool H_prev_day[W+1][W], const bool V_prev_day[W][W+1],\n                                 GridManager& gm, long long current_total_cost) {\n    // 1. Calculate delta area cost:\n    long long delta_area_cost = 0;\n    // Remove old_r's contribution\n    if (old_r.area() < a_global[d][k_id]) delta_area_cost -= 100LL * (a_global[d][k_id] - old_r.area());\n    // Add new_r's contribution\n    if (new_r.area() < a_global[d][k_id]) delta_area_cost += 100LL * (a_global[d][k_id] - new_r.area());\n\n    // 2. Calculate delta partition cost:\n    long long delta_partition_cost = 0;\n    \n    // Temporarily revert the placed_rects entry for k_id to old_r\n    // (since gm.place(new_r, k_id) was already called for validation)\n    // We need the state *before* gm.place(new_r, k_id) to figure out diffs.\n    // The safest way is to manage `H_curr` and `V_curr` arrays incrementally.\n    \n    // Instead of directly calculating delta, calculate new total cost based on `gm.placed_rects`\n    // (which now includes new_r) and then subtract `current_total_cost`.\n    // This implies `calculate_day_cost` is called directly, but its performance needs to be improved\n    // beyond `O(W^2)`.\n\n    // Optimized `calculate_day_cost` for incremental SA updates:\n    // Store `H_current_sum` and `V_current_sum` (total active partitions)\n    // When `is_occupied[r][c]` changes, it affects 4 segments.\n    // For each affected segment `s = (i,j)-(i',j')`:\n    //  `old_H_curr_s = is_segment_a_border_before_change(s)`\n    //  `new_H_curr_s = is_segment_a_border_after_change(s)`\n    //  If `(old_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    //  If `(new_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    // This is the $O(Area)$ bottleneck.\n    // To implement `is_segment_a_border`, you need `is_occupied` state.\n\n    // A simpler way:\n    // Copy `is_occupied` state to a temporary `is_occupied_temp`\n    // Then `gm.remove(k_id, from_is_occupied_temp)`\n    // Compute `old_local_partition_status` using `is_occupied_temp` within `old_r`'s perimeter + 1 cell buffer.\n    // `gm.place(new_r, to_is_occupied_temp)`\n    // Compute `new_local_partition_status` using `is_occupied_temp` within `new_r`'s perimeter + 1 cell buffer.\n    // Then calculate the `delta_partition_cost` within these local affected regions.\n\n    // For simplicity of implementation (and hoping that AvgArea is small enough on average)\n    // just call the full `calculate_day_cost` after updating `gm.placed_rects`.\n    // With `SA_ITERATIONS` around 1000 per day, total $5 \\times 10^7$ iterations for `calculate_day_cost`.\n    // AvgArea $20000 \\approx 0.02 W^2$.\n    // If average $W^2$ operations is $2 \\times 10^4$, then $5 \\times 10^7 \\times 2 \\times 10^4 = 10^{12}$. Still too much.\n    // This is why `calculate_day_cost` *must* be O(Perimeter) in SA.\n    \n    // Let's go with the O(Perimeter) approach for SA iterations.\n    // Need to precompute `H_curr` and `V_curr` from `is_occupied` once per day.\n    // Then when a rectangle `R_k` changes, we update only the segments around its perimeter.\n    // This implies `H_curr_global[W+1][W]` and `V_curr_global[W][W+1]` must be updated incrementally.\n    \n    // `current_H_states[W+1][W]` and `current_V_states[W][W+1]` (booleans)\n    // `current_H_count`, `current_V_count` (total partition lengths)\n    // On a move:\n    //  `old_r_perimeter_segs = get_perimeter_segments(old_r)`\n    //  `new_r_perimeter_segs = get_perimeter_segments(new_r)`\n    //  For `s` in `old_r_perimeter_segs` and `new_r_perimeter_segs` (union):\n    //    `was_border = is_segment_a_border(s, is_occupied_before_change)`\n    //    `is_border = is_segment_a_border(s, is_occupied_after_change)`\n    //    If `was_border != is_border`:\n    //      if `was_border != global_H_prev[s]`: `delta_cost--`\n    //      if `is_border != global_H_prev[s]`: `delta_cost++`\n    // This `is_segment_a_border` checks `is_occupied` for neighbors of `s`, which means `O(1)` per segment.\n    // Total `O(Perimeter)` for partition cost delta. Area update is $O(Area)$.\n    // So the move is $O(Area + Perimeter)$, which becomes $O(Area)$ in worst case.\n    // Let's assume avg Area is small enough on average for $N=50$ given $W=1000$.\n    // If $W^2/N = 20000$, $Area \\sim 20000$. This is the largest factor.\n    // $50 \\times 1000 \\times 20000 = 10^9$. Maybe SA_ITERATIONS must be smaller, say 1000.\n    // $50 \\times 1000 \\times 20000 = 10^9$. This would be close to 1 second.\n    // $SA\\_ITERATIONS=1000$ per day. Total $50000$ iterations.\n    // Each is $O(Area)$, `20000`. So $50000 \\times 20000 = 10^9$. This will be slow for 3s.\n    // The input generation suggests `a_d,k` sum is around $W^2-E$. Smallest $E$ is $W^2 \\times 0.0025 = 2500$.\n    // So average desired area is typically $W^2/N \\approx 20000$.\n    // Maybe `Area` updates are sparse?\n}\n\nFinal decision: I will implement `calculate_day_cost` with `O(W^2)` per call, and reduce `SA_ITERATIONS` to a very small number (e.g., 50 per day). This makes total operations $D \\times SA\\_ITERATIONS \\times W^2 = 50 \\times 50 \\times 10^6 = 2.5 \\times 10^9$. This might barely pass, or be too slow. A hybrid: `O(Area)` based delta computation during SA, and full `O(W^2)` only once at the end of each day for `global_H_prev` update.\n","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric> // Potentially for std::accumulate, though not strictly used with the new scoring approach\n#include <algorithm> // For std::sort, std::min\n#include <limits>    // For std::numeric_limits\n#include <chrono>    // For high_resolution_clock and duration\n#include <random>    // For mt19937, uniform_int_distribution\n\n// Define MOD constant\nconst int MOD = 998244353;\n\n// Structure to store an performed operation\nstruct Operation {\n    int m, p, q;\n};\n\n// Helper struct to store an option with its gain\nstruct Option {\n    long long gain;\n    int m, p, q;\n\n    // For sorting: higher gain comes first\n    bool operator<(const Option& other) const {\n        return gain > other.gain; // Sort in descending order of gain\n    }\n};\n\n// Function to calculate the total score for a given board state\n// This is used for initial score and comparing final scores of different runs.\nlong long calculate_board_score(const std::vector<std::vector<int>>& board, int N) {\n    long long total_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            total_score += board[i][j];\n        }\n    }\n    return total_score;\n}\n\n\nint main() {\n    // Optimize C++ standard streams for faster input/output.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N, M, K;\n    std::cin >> N >> M >> K;\n\n    // Read initial board values.\n    std::vector<std::vector<int>> initial_board(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_board[i][j]; // a_i,j are guaranteed to be < MOD\n        }\n    }\n\n    // Read all stamp configurations `s_m,i,j`.\n    std::vector<std::vector<std::vector<int>>> s(M, std::vector<std::vector<int>>(3, std::vector<int>(3)));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> s[m][i][j]; // s_m,i,j are guaranteed to be < MOD\n            }\n        }\n    }\n\n    // Initialize random number generator using current time for varied seeds across runs.\n    std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Best overall score found and the sequence of operations that produced it.\n    long long max_overall_score = calculate_board_score(initial_board, N);\n    std::vector<Operation> best_overall_operations;\n\n    // Set a time limit for the iterative process (e.g., 1.95 seconds out of 2.0s total).\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 1.95; // Tunable parameter for time allocation\n\n    // Loop for multiple attempts (Iterated Randomly Perturbed Greedy).\n    // The loop continues as long as there is time remaining.\n    while (true) {\n        auto current_chrono_time = std::chrono::high_resolution_clock::now();\n        double elapsed_seconds = std::chrono::duration<double>(current_chrono_time - start_time).count();\n        if (elapsed_seconds >= TIME_LIMIT_SECONDS) {\n            break; // Stop if time limit is reached.\n        }\n\n        // Start a new greedy run with a fresh copy of the initial board.\n        std::vector<std::vector<int>> current_board = initial_board;\n        std::vector<Operation> current_operations;\n        long long current_run_score = calculate_board_score(current_board, N);\n\n        // Perform up to K operations for this specific run.\n        for (int k_idx = 0; k_idx < K; ++k_idx) {\n            std::vector<Option> possible_options; // List to store all potential operations and their gains.\n\n            // Evaluate all M * (N-2)^2 possible operations.\n            for (int m_idx = 0; m_idx < M; ++m_idx) {\n                for (int p_idx = 0; p_idx <= N - 3; ++p_idx) {\n                    for (int q_idx = 0; q_idx <= N - 3; ++q_idx) {\n                        long long current_gain = 0; // Accumulated gain for the current stamp application.\n\n                        // Calculate the score change if this stamp is applied.\n                        for (int i_s = 0; i_s < 3; ++i_s) {\n                            for (int j_s = 0; j_s < 3; ++j_s) {\n                                int r = p_idx + i_s; // Row on the board\n                                int c = q_idx + j_s; // Column on the board\n\n                                int old_val_mod = current_board[r][c];\n                                // Calculate new value modulo MOD. Use long long for addition to prevent overflow.\n                                int new_val_mod = (int)(((long long)old_val_mod + s[m_idx][i_s][j_s]) % MOD);\n                                \n                                current_gain += (new_val_mod - old_val_mod);\n                            }\n                        }\n                        \n                        // Only consider operations that provide a strict positive gain.\n                        if (current_gain > 0) {\n                             possible_options.push_back({current_gain, m_idx, p_idx, q_idx});\n                        }\n                    }\n                }\n            }\n            \n            // If no operation can increase the score, this run stops early.\n            if (possible_options.empty()) {\n                break;\n            }\n\n            // Sort options by gain in descending order.\n            std::sort(possible_options.begin(), possible_options.end());\n\n            // Define how many top options to consider for random selection.\n            // Using a constant like 10, 15, or 20 is often a good heuristic for N=9, M=20, K=81.\n            // This allows some exploration beyond the absolute best, but still prioritizes good options.\n            const int TOP_X = 15; // Tunable parameter\n            int actual_top_x_count = std::min((int)possible_options.size(), TOP_X);\n\n            // Randomly pick one operation from the top `actual_top_x_count` options.\n            // This distribution is safe even if actual_top_x_count is 1.\n            std::uniform_int_distribution<int> dist(0, actual_top_x_count - 1);\n            int chosen_idx = dist(rng);\n            Option chosen_option = possible_options[chosen_idx];\n\n            // Apply the chosen operation to update the board state for this run.\n            for (int i_s = 0; i_s < 3; ++i_s) {\n                for (int j_s = 0; j_s < 3; ++j_s) {\n                    int r = chosen_option.p + i_s;\n                    int c = chosen_option.q + j_s;\n                    current_board[r][c] = (int)(((long long)current_board[r][c] + s[chosen_option.m][i_s][j_s]) % MOD);\n                }\n            }\n            // Update the score for the current run incrementally.\n            current_run_score += chosen_option.gain;\n            // Record the operation performed.\n            current_operations.push_back({chosen_option.m, chosen_option.p, chosen_option.q});\n        } // End of k_idx loop for one greedy run\n\n        // After completing one full greedy run (or breaking early), check if it's the best so far.\n        if (current_run_score > max_overall_score) {\n            max_overall_score = current_run_score;\n            best_overall_operations = current_operations;\n        }\n    } // End of time-limited loop for multiple runs\n\n    // Output the number of operations in the best sequence found.\n    std::cout << best_overall_operations.size() << std::endl;\n    // Output each operation's details (stamp index, top-left row, top-left column).\n    for (const auto& op : best_overall_operations) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n\n    return 0;\n}\n","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <algorithm>\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 { // For map keys\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint DR[] = {-1, 1, 0, 0}; // U, D, L, R\nint DC[] = {0, 0, -1, 1};\n\n// Correct way to get char from dr,dc\nchar get_dir_char(int dr, int dc) {\n    if (dr == -1 && dc == 0) return 'U';\n    if (dr == 1 && dc == 0) return 'D';\n    if (dr == 0 && dc == -1) return 'L';\n    if (dr == 0 && dc == 1) return 'R';\n    return '.'; // Should not happen for a valid move\n}\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int holding_container_id; // -1 if not holding\n    bool is_large;\n    bool is_bombed;\n};\n\nstruct State {\n    vector<vector<int>> board; // container ID, -1 if empty\n    vector<Crane> cranes;\n    vector<int> incoming_idx; // next container index for each receiving gate (row)\n    vector<int> next_dispatch_val; // next container ID expected at each dispatch gate (row)\n    vector<vector<int>> A; // initial incoming container sequence\n    map<int, Pos> container_locations; // Map container_id to its (r,c) position or {-1,-1} if in crane's hand or not on board\n};\n\n// BFS to find the next step (dr, dc) and path cost\n// Returns {dr, dc} for the next step. {0,0} if no path or already at target.\n// path_cost_out will be set to the cost of the path, or -1 if no path.\nPos get_next_step(const State& current_state, int crane_id, Pos start_pos, Pos target_pos,\n                  bool is_holding_container, bool is_large_crane,\n                  const vector<Pos>& other_crane_current_pos_snapshot, // Snapshot of all crane positions before planning\n                  const vector<Pos>& other_crane_target_next_pos_planned, // Planned next positions for higher priority cranes (j < crane_id)\n                  int& path_cost_out) {\n\n    if (start_pos == target_pos) {\n        path_cost_out = 0;\n        return {0,0};\n    }\n\n    queue<pair<Pos, vector<Pos>>> q; // Pos, path_to_Pos\n    map<Pos, int> dist; // Using map for visited/distance because Pos is not easily hashable for unordered_map\n\n    vector<Pos> initial_path;\n    initial_path.push_back(start_pos);\n\n    q.push({start_pos, initial_path});\n    dist[start_pos] = 0;\n\n    Pos next_step_dir = {0,0};\n    path_cost_out = -1; // Default to no path found\n\n    while (!q.empty()) {\n        Pos u = q.front().first;\n        vector<Pos> path = q.front().second;\n        int d = dist[u];\n        q.pop();\n\n        if (u == target_pos) {\n            // Path found. The first step is path[1] - path[0]\n            path_cost_out = d;\n            if (path.size() > 1) { // If path length > 0, there is a next step\n                next_step_dir = {path[1].r - start_pos.r, path[1].c - start_pos.c};\n            }\n            return next_step_dir;\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos v = {u.r + DR[i], u.c + DC[i]};\n\n            if (v.r < 0 || v.r >= N || v.c < 0 || v.c >= N) continue; // Out of bounds\n\n            // Check for container on destination square (for small cranes holding cargo)\n            if (!is_large_crane && is_holding_container && current_state.board[v.r][v.c] != -1) {\n                continue; // Small crane carrying a container cannot move into occupied square\n            }\n\n            bool collision = false;\n            for (int j = 0; j < N; ++j) {\n                if (j == crane_id || current_state.cranes[j].is_bombed) continue; // Skip self or bombed cranes\n\n                Pos other_curr_j = other_crane_current_pos_snapshot[j]; // The actual current position of crane j\n                Pos other_next_j_planned = other_crane_target_next_pos_planned[j]; // The *planned* next position of crane j (if j < crane_id)\n\n                if (j < crane_id) { // Higher priority crane, its next position is already planned\n                    if (v == other_next_j_planned) { // Check if target cell v is taken by a higher priority crane's planned move\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == other_next_j_planned) { // Check for swap collision with higher priority crane\n                        collision = true; break;\n                    }\n                } else { // Lower priority crane, it hasn't planned its move yet, so use its current position\n                    if (v == other_curr_j) { // Check if target cell v is currently occupied by a lower priority crane\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == current_state.cranes[j].pos) { // Check for swap collision with lower priority crane\n                        collision = true; break;\n                    }\n                }\n            }\n            if (collision) continue;\n\n            // Check if already visited or found a shorter path\n            if (dist.find(v) == dist.end() || dist[v] > d + 1) {\n                dist[v] = d + 1;\n                vector<Pos> new_path = path;\n                new_path.push_back(v);\n                q.push({v, new_path});\n            }\n        }\n    }\n    return {0,0}; // No path found, return (0,0) direction\n}\n\n\nvoid solve() {\n    State current_state;\n    current_state.board.assign(N, vector<int>(N, -1));\n    current_state.A.assign(N, vector<int>(N));\n    current_state.incoming_idx.assign(N, 0);\n    current_state.next_dispatch_val.assign(N, 0);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> current_state.A[i][j];\n        }\n    }\n\n    current_state.cranes.resize(N);\n    for (int i = 0; i < N; ++i) {\n        current_state.cranes[i].id = i;\n        current_state.cranes[i].pos = {i, 0};\n        current_state.cranes[i].holding_container_id = -1;\n        current_state.cranes[i].is_large = (i == 0);\n        current_state.cranes[i].is_bombed = false;\n        current_state.container_locations[-1] = {-1,-1}; // Dummy entry\n    }\n\n    int turns = 0;\n    int dispatched_count = 0;\n\n    vector<string> all_crane_actions(N, \"\");\n\n    while (dispatched_count < N*N && turns < MAX_TURNS) {\n        turns++;\n        \n        // 0. Store current crane positions for BFS collision detection\n        vector<Pos> other_crane_current_pos_snapshot(N);\n        for(int i=0; i<N; ++i) other_crane_current_pos_snapshot[i] = current_state.cranes[i].pos;\n\n        // 1. Incoming containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.incoming_idx[i] < N) {\n                bool gate_has_container = (current_state.board[i][0] != -1);\n                bool gate_has_crane = false;\n                for(int k=0; k<N; ++k) {\n                    if (!current_state.cranes[k].is_bombed && current_state.cranes[k].pos.r == i && current_state.cranes[k].pos.c == 0) {\n                        gate_has_crane = true;\n                        break;\n                    }\n                }\n                if (!gate_has_container && !gate_has_crane) {\n                    int container_id = current_state.A[i][current_state.incoming_idx[i]];\n                    current_state.board[i][0] = container_id;\n                    current_state.container_locations[container_id] = {i,0};\n                    current_state.incoming_idx[i]++;\n                }\n            }\n        }\n\n        // 2. Crane actions planning\n        vector<char> current_turn_actions_char(N, '.');\n        vector<Pos> target_next_crane_pos_planned(N); // For prioritized collision detection, stores planned next pos for cranes j < k\n        vector<int> target_next_crane_holding_planned(N); // For P/Q updates\n\n        // Initialize planned positions and holding status to current state\n        for (int k = 0; k < N; ++k) {\n            target_next_crane_pos_planned[k] = current_state.cranes[k].pos;\n            target_next_crane_holding_planned[k] = current_state.cranes[k].holding_container_id;\n        }\n\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) {\n                current_turn_actions_char[k] = '.';\n                continue;\n            }\n\n            Pos crane_curr_pos = current_state.cranes[k].pos;\n            int holding_id = current_state.cranes[k].holding_container_id;\n\n            // Priority 1: Deliver if holding the correct container at the dispatch gate\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                if (is_next_dispatch && crane_curr_pos.r == target_row && crane_curr_pos.c == N - 1) {\n                    current_turn_actions_char[k] = 'Q';\n                    target_next_crane_holding_planned[k] = -1; // Released\n                    // Container will be removed from board in step 3\n                    continue;\n                }\n            }\n\n            // If holding a container, move it towards its destination\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                Pos actual_target_dest = {target_row, (is_next_dispatch ? N - 1 : N - 2)};\n                \n                // Small crane handling for cross-row moves with cargo (drop at N/2 column)\n                if (!current_state.cranes[k].is_large && crane_curr_pos.r != target_row) {\n                    Pos release_mid_pos = {crane_curr_pos.r, N/2};\n                    if (crane_curr_pos == release_mid_pos) {\n                        current_turn_actions_char[k] = 'Q';\n                        target_next_crane_holding_planned[k] = -1; // Released\n                        current_state.container_locations[holding_id] = release_mid_pos; // Mark container's new location\n                    } else {\n                        // Move towards release_mid_pos\n                        int cost;\n                        Pos dir = get_next_step(current_state, k, crane_curr_pos, release_mid_pos, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                        if (cost != -1) {\n                            current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                            target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                        } else {\n                            current_turn_actions_char[k] = '.';\n                        }\n                    }\n                } else { // Large crane, or small crane already in correct row, or small crane not needing cross-row (i.e. only moving along row)\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, actual_target_dest, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n                continue; // Crane has a container, its action is determined\n            }\n\n            // If not holding a container, find a task\n            int best_cost = MAX_TURNS + 1; // High value\n            Pos best_pick_pos = {-1,-1};\n            int best_item_id = -1;\n            Pos best_release_pos = {-1,-1};\n            \n            // Helper for pathfinding cost\n            auto calculate_cost = [&](Pos target_for_pickup) {\n                int cost;\n                get_next_step(current_state, k, crane_curr_pos, target_for_pickup, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                return cost;\n            };\n            \n            // Check if a container is already targeted by a higher-priority crane or held\n            auto is_container_busy = [&](int container_id) {\n                if (container_id == -1) return true;\n                for (int j = 0; j < N; ++j) {\n                    if (current_state.cranes[j].id != k && current_state.cranes[j].holding_container_id == container_id) return true;\n                }\n                return false;\n            };\n\n            // Task search priorities (high to low):\n\n            // Option 1: Pick up 'next_dispatch_val'\n            for (int i = 0; i < N; ++i) {\n                int C = current_state.next_dispatch_val[i];\n                if (current_state.container_locations.count(C) && current_state.container_locations[C].r != -1) { // Container exists on board\n                    Pos c_pos = current_state.container_locations[C];\n                    if (is_container_busy(C)) continue;\n                    \n                    // Small crane can only pick up if container is in its row or large crane.\n                    if (!current_state.cranes[k].is_large && c_pos.r != k) continue;\n\n                    int cost = calculate_cost(c_pos);\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = c_pos;\n                        best_item_id = C;\n                        best_release_pos = {i, N-1}; // Ultimate destination\n                    }\n                }\n            }\n            \n            // Option 2: Clear receiving gate (row i, col 0)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.incoming_idx[i] < N && current_state.board[i][0] != -1) {\n                    int C = current_state.board[i][0];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,0});\n                    if (cost != -1 && cost < best_cost) { \n                        best_cost = cost;\n                        best_pick_pos = {i,0};\n                        best_item_id = C;\n                        // Determine temp release pos based on container's target row\n                        if (C/N == i) best_release_pos = {i,1}; // Stay in row, move right one cell\n                        else best_release_pos = {i, N/2}; // Move to middle column, large crane will pick up (handled by option 5 for large crane)\n                    }\n                }\n            }\n\n            // Option 3: Clear dispatch gate (row i, col N-1)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != current_state.next_dispatch_val[i]) {\n                    int C = current_state.board[i][N-1];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,N-1});\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = {i,N-1};\n                        best_item_id = C;\n                        // Determine temp release pos based on container's target row\n                        if (C/N == i) best_release_pos = {i,N-2}; // Stay in row, move left one cell\n                        else best_release_pos = {i, N/2}; // Move to middle column, large crane will pick up\n                    }\n                }\n            }\n            \n            // Option 4: Move container to its staging area (row, N-2) if in correct row but too far left\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N-2; ++c) { // Check cells to the left of N-2\n                    int C = current_state.board[r][c];\n                    if (C != -1 && C/N == r && C != current_state.next_dispatch_val[r]) {\n                        if (is_container_busy(C)) continue;\n\n                        // Small crane can only pick up if container is in its row\n                        if (!current_state.cranes[k].is_large && r != k) continue;\n\n                        int cost = calculate_cost({r,c});\n                        if (cost != -1 && cost < best_cost) {\n                            best_cost = cost;\n                            best_pick_pos = {r,c};\n                            best_item_id = C;\n                            best_release_pos = {r,N-2}; // Staging area for its own row\n                        }\n                    }\n                }\n            }\n\n            // Option 5: Move container to its row's middle column (C/N, N/2) - for cross-row moves (Large crane only).\n            if (current_state.cranes[k].is_large) { // Only large crane handles cross-row pickups\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        int C = current_state.board[r][c];\n                        if (C != -1 && C/N != r) { // Container in wrong row\n                            if (is_container_busy(C)) continue;\n                            int cost = calculate_cost({r,c});\n                            if (cost != -1 && cost < best_cost) {\n                                best_cost = cost;\n                                best_pick_pos = {r,c};\n                                best_item_id = C;\n                                best_release_pos = {C/N,N/2}; // Release in its target row's middle column\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Execute the chosen task\n            if (best_cost != MAX_TURNS + 1) { // A task was found\n                if (crane_curr_pos == best_pick_pos) {\n                    current_turn_actions_char[k] = 'P';\n                    target_next_crane_holding_planned[k] = best_item_id;\n                    current_state.container_locations[best_item_id] = {-1,-1}; // In crane's hand (not on board)\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, best_pick_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.'; // Should ideally not happen if best_cost was valid\n                    }\n                }\n            } else { // No urgent task, move to a parking spot\n                Pos parking_pos = current_state.cranes[k].is_large ? Pos{0, N/2} : Pos{k, 1}; // Large crane at center-top, small cranes at their row's column 1\n                if (crane_curr_pos == parking_pos) {\n                    current_turn_actions_char[k] = '.';\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, parking_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n            }\n        }\n\n        // Apply all planned actions\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) continue;\n\n            char action = current_turn_actions_char[k];\n            all_crane_actions[k] += action;\n\n            if (action == 'P') {\n                int container_id = current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c];\n                current_state.cranes[k].holding_container_id = container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = -1;\n            } else if (action == 'Q') {\n                int container_id = current_state.cranes[k].holding_container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = container_id;\n                current_state.cranes[k].holding_container_id = -1;\n                current_state.container_locations[container_id] = current_state.cranes[k].pos; // Container back on board\n            } else if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n                current_state.cranes[k].pos = target_next_crane_pos_planned[k];\n            }\n        }\n        \n        // 3. Dispatch containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] == current_state.next_dispatch_val[i]) {\n                int dispatched_id = current_state.board[i][N-1];\n                current_state.board[i][N-1] = -1;\n                current_state.container_locations.erase(dispatched_id); // Container removed from the game\n                current_state.next_dispatch_val[i]++;\n                dispatched_count++;\n            }\n        }\n    }\n\n    // Output results\n    for (int i = 0; i < N; ++i) {\n        cout << all_crane_actions[i] << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n\n// N is fixed at 20 for this problem\nconst int N = 20;\n\n// Global variables to store the current state\nint H[N][N]; // Current heights of the grid cells\nint current_r = 0; // Current row of the dump truck\nint current_c = 0; // Current column of the dump truck\nlong long truck_load = 0; // Current amount of soil loaded on the truck\nstd::vector<std::string> ops; // Stores the sequence of operations\n\n// Calculates Manhattan distance between two cells\nlong long manhattan_dist(int r1, int c1, int r2, int c2) {\n    return std::abs(r1 - r2) + std::abs(c1 - c2);\n}\n\n// Moves the truck to the target coordinates and records the movement operations\nvoid move_truck_to(int target_r, int target_c) {\n    while (current_r < target_r) {\n        ops.push_back(\"D\");\n        current_r++;\n    }\n    while (current_r > target_r) {\n        ops.push_back(\"U\");\n        current_r--;\n    }\n    while (current_c < target_c) {\n        ops.push_back(\"R\");\n        current_c++;\n    }\n    while (current_c > target_c) {\n        ops.push_back(\"L\");\n        current_c--;\n    }\n}\n\n// Structure to hold cell coordinates and a calculated distance, used for sorting candidates\nstruct CandidateCell {\n    int r, c;\n    long long dist;\n\n    bool operator<(const CandidateCell& other) const {\n        return dist < other.dist;\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int dummy_N; // Read N, but it's fixed at 20\n    std::cin >> dummy_N;\n\n    long long total_initial_positive_soil = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> H[i][j];\n            if (H[i][j] > 0) {\n                total_initial_positive_soil += H[i][j];\n            }\n        }\n    }\n\n    long long soil_moved_to_level_sinks = 0; // Tracks the total soil moved to fulfill negative heights\n    const int K_CANDIDATES = 10; // Number of closest sources/sinks to consider for efficiency\n\n    // Timer for execution time limit\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds to be safe (total limit is 2.0 sec)\n\n    // Main loop: continues until all soil is leveled or operation/time limits are reached\n    while (soil_moved_to_level_sinks < total_initial_positive_soil) {\n        if (ops.size() >= 99000) { // Max 100000 turns, stop early to avoid exceeding\n            break;\n        }\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) {\n            break;\n        }\n\n        std::vector<CandidateCell> all_sources; // List of all cells with H > 0\n        std::vector<CandidateCell> all_sinks;   // List of all cells with H < 0\n\n        // Populate sources and sinks lists\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (H[i][j] > 0) {\n                    // For sources, calculate distance from current truck position\n                    all_sources.push_back({i, j, manhattan_dist(current_r, current_c, i, j)});\n                } else if (H[i][j] < 0) {\n                    // For sinks, distance will be calculated later from a potential source\n                    all_sinks.push_back({i, j, 0}); \n                }\n            }\n        }\n\n        // If no sources or sinks remain, the leveling is complete (or stuck)\n        if (all_sources.empty() || all_sinks.empty()) {\n            break;\n        }\n\n        // Sort sources by their distance from the current truck position\n        std::sort(all_sources.begin(), all_sources.end());\n\n        long long min_cost = -1; // Stores the minimum cost found for a transfer\n        int best_sr = -1, best_sc = -1, best_dr = -1, best_dc = -1; // Coordinates of the best source/sink\n        long long best_D = 0; // Amount of soil for the best transfer\n\n        // Iterate through a limited number of closest source candidates\n        int num_source_candidates = std::min((int)all_sources.size(), K_CANDIDATES);\n        for (int i = 0; i < num_source_candidates; ++i) {\n            int sr = all_sources[i].r;\n            int sc = all_sources[i].c;\n\n            // Create a temporary list of sinks, calculating their distance from the current source candidate\n            std::vector<CandidateCell> current_sink_candidates;\n            for (const auto& sink : all_sinks) {\n                current_sink_candidates.push_back({sink.r, sink.c, manhattan_dist(sr, sc, sink.r, sink.c)});\n            }\n            // Sort these sinks by their distance from the current source candidate\n            std::sort(current_sink_candidates.begin(), current_sink_candidates.end());\n\n            // Iterate through a limited number of closest sink candidates for this source\n            int num_sink_candidates = std::min((int)current_sink_candidates.size(), K_CANDIDATES);\n            for (int j = 0; j < num_sink_candidates; ++j) {\n                int dr = current_sink_candidates[j].r;\n                int dc = current_sink_candidates[j].c;\n\n                // Calculate the amount of soil to transfer: min of available at source and needed at sink\n                long long D = std::min((long long)H[sr][sc], -(long long)H[dr][dc]);\n                if (D <= 0) continue; // No actual transfer possible\n\n                // Calculate the total cost for this specific (source, sink, amount) transfer\n                long long cost_to_source = manhattan_dist(current_r, current_c, sr, sc) * 100LL;\n                long long cost_source_to_sink = manhattan_dist(sr, sc, dr, dc) * (100LL + D);\n                long long current_total_cost = cost_to_source + cost_source_to_sink + 2LL * D;\n\n                // Update if this transfer is cheaper than previously found ones\n                if (min_cost == -1 || current_total_cost < min_cost) {\n                    min_cost = current_total_cost;\n                    best_sr = sr; best_sc = sc;\n                    best_dr = dr; best_dc = dc;\n                    best_D = D;\n                }\n            }\n        }\n\n        // If no valid transfer was found in this iteration (min_cost still -1), break the loop\n        if (min_cost == -1) {\n            break;\n        }\n\n        // Execute the operations for the chosen best transfer\n        \n        // 1. Move truck to the best source\n        move_truck_to(best_sr, best_sc);\n        \n        // 2. Load soil\n        ops.push_back(\"+\" + std::to_string(best_D));\n        truck_load += best_D;\n        H[best_sr][best_sc] -= best_D; // Update source cell's height\n        \n        // 3. Move truck to the best sink\n        move_truck_to(best_dr, best_dc);\n        \n        // 4. Unload soil\n        ops.push_back(\"-\" + std::to_string(best_D));\n        truck_load -= best_D;\n        H[best_dr][best_dc] += best_D; // Update sink cell's height\n        soil_moved_to_level_sinks += best_D; // Increment total soil leveled\n    }\n\n    // Output all recorded operations\n    for (const std::string& op : ops) {\n        std::cout << op << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <cmath>   // For std::exp\n\n// --- Global variables for N, M, T and X_seeds ---\nint N_global, M_global, T_global;\nstd::vector<std::vector<int>> X_seeds_global; // Current seeds available for planting\nstd::vector<int> initial_X_max_global;       // Max value for each criterion from initial seeds\n\n// --- RNG ---\n// Use std::mt19937_64 for potentially better randomness and larger range.\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper function to calculate potential for a pair ---\n// Returns the sum of max values for each criterion between two seeds.\n// seed_idx1 and seed_idx2 are indices into X_seeds_global.\nlong long calculate_pair_potential(int seed_idx1, int seed_idx2) {\n    long long potential = 0;\n    for (int l = 0; l < M_global; ++l) {\n        potential += std::max(X_seeds_global[seed_idx1][l], X_seeds_global[seed_idx2][l]);\n    }\n    return potential;\n}\n\n// --- Helper function to get adjacent coordinates ---\n// Returns a vector of {row, col} pairs for direct neighbors of (r, c).\nstd::vector<std::pair<int, int>> get_adjacent_coords(int r, int c) {\n    std::vector<std::pair<int, int>> adj;\n    int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n    int dc[] = {0, 0, -1, 1};\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_global && nc >= 0 && nc < N_global) {\n            adj.push_back({nr, nc});\n        }\n    }\n    return adj;\n}\n\n// --- Function to calculate total score for a grid configuration ---\n// Sum of potential values for all adjacent pairs in the grid.\nlong long calculate_grid_score(const std::vector<std::vector<int>>& A) {\n    long long total_score = 0;\n    // Horizontal adjacencies\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global - 1; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i][j+1]);\n        }\n    }\n    // Vertical adjacencies\n    for (int i = 0; i < N_global - 1; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i+1][j]);\n        }\n    }\n    return total_score;\n}\n\nvoid solve() {\n    std::cin >> N_global >> M_global >> T_global;\n\n    int seed_count = 2 * N_global * (N_global - 1);\n    X_seeds_global.resize(seed_count, std::vector<int>(M_global));\n    initial_X_max_global.resize(M_global, 0);\n\n    // Read initial seeds and compute initial_X_max_global\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M_global; ++j) {\n            std::cin >> X_seeds_global[i][j];\n            initial_X_max_global[j] = std::max(initial_X_max_global[j], X_seeds_global[i][j]);\n        }\n    }\n\n    // Main simulation loop for T turns\n    for (int turn = 0; turn < T_global; ++turn) {\n        // 1. Select seeds for planting:\n        // Calculate a combined score for all current seeds and pick the top N*N.\n        // The combined score considers V_k + a bonus for carrying initial global max traits.\n        std::vector<std::pair<long long, int>> seed_scores(seed_count); // {combined_score, seed_idx}\n        for (int i = 0; i < seed_count; ++i) {\n            long long current_Vk = 0;\n            int trait_count = 0;\n            for (int l = 0; l < M_global; ++l) {\n                current_Vk += X_seeds_global[i][l];\n                if (X_seeds_global[i][l] == initial_X_max_global[l]) {\n                    trait_count++;\n                }\n            }\n            // Tuning parameter alpha: 100LL. If a seed has an X_l equal to global max,\n            // it's considered as valuable as 100 points in its sum. Max X_l is 100.\n            // This prioritizes seeds carrying traits that are globally optimal.\n            long long combined_score = current_Vk + 100LL * trait_count; \n            seed_scores[i] = {combined_score, i};\n        }\n        std::sort(seed_scores.rbegin(), seed_scores.rend()); // Sort descending by combined_score\n\n        std::vector<int> selected_seeds_indices(N_global * N_global);\n        for (int i = 0; i < N_global * N_global; ++i) {\n            selected_seeds_indices[i] = seed_scores[i].second;\n        }\n\n        // 2. Determine placement using Simulated Annealing\n        std::vector<std::vector<int>> current_A(N_global, std::vector<int>(N_global));\n        \n        // Initial placement for SA: random permutation of selected seeds\n        std::shuffle(selected_seeds_indices.begin(), selected_seeds_indices.end(), rng);\n        int k_idx = 0;\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                current_A[i][j] = selected_seeds_indices[k_idx++];\n            }\n        }\n\n        long long current_score = calculate_grid_score(current_A);\n        std::vector<std::vector<int>> best_A = current_A;\n        long long best_score = current_score;\n\n        // SA parameters (tuned for AHC035 constraints)\n        double start_temp = 20000.0; \n        double end_temp = 100.0;    \n        long long max_iterations = 250000; // Total iterations if no time limit hit (safety)\n        \n        // Time budget for SA loop (e.g., 180ms per turn to stay within 2s total)\n        auto start_time = std::chrono::high_resolution_clock::now();\n        std::chrono::milliseconds time_budget(180); \n\n        std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        std::uniform_int_distribution<int> dist_rc(0, N_global - 1); // For random row/col\n\n        for (long long iter = 0; iter < max_iterations; ++iter) {\n            // Check time budget\n            auto current_time = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time) > time_budget) {\n                break; \n            }\n\n            // Calculate current temperature with exponential decay\n            double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / max_iterations);\n\n            // Pick two random distinct cells to swap\n            int r1 = dist_rc(rng);\n            int c1 = dist_rc(rng);\n            int r2 = dist_rc(rng);\n            int c2 = dist_rc(rng);\n            while (r1 == r2 && c1 == c2) { // Ensure distinct cells\n                r2 = dist_rc(rng);\n                c2 = dist_rc(rng);\n            }\n\n            int seed1_idx = current_A[r1][c1]; // Original seed at (r1,c1)\n            int seed2_idx = current_A[r2][c2]; // Original seed at (r2,c2)\n\n            // Calculate change in score (delta_score) efficiently\n            long long old_adj_contrib = 0;\n            std::vector<std::pair<int, int>> neighbors_r1c1 = get_adjacent_coords(r1, c1);\n            std::vector<std::pair<int, int>> neighbors_r2c2 = get_adjacent_coords(r2, c2);\n\n            for (auto p : neighbors_r1c1) {\n                // If the other swapped cell is a neighbor, exclude it.\n                // The direct edge contribution (P(seed1, seed2)) is part of `current_score`\n                // and does not change when the seeds are swapped.\n                if (!(p.first == r2 && p.second == c2)) { \n                    old_adj_contrib += calculate_pair_potential(seed1_idx, current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    old_adj_contrib += calculate_pair_potential(seed2_idx, current_A[p.first][p.second]);\n                }\n            }\n\n            // Temporarily perform the swap\n            current_A[r1][c1] = seed2_idx;\n            current_A[r2][c2] = seed1_idx;\n\n            long long new_adj_contrib = 0;\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r1][c1], current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r2][c2], current_A[p.first][p.second]);\n                }\n            }\n            \n            long long delta_score = new_adj_contrib - old_adj_contrib;\n            long long new_score = current_score + delta_score;\n\n            // Metropolis criterion for acceptance\n            if (new_score > current_score || dist_prob(rng) < std::exp(static_cast<double>(new_score - current_score) / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_A = current_A;\n                }\n            } else {\n                // Revert the swap if not accepted\n                current_A[r1][c1] = seed1_idx;\n                current_A[r2][c2] = seed2_idx;\n            }\n        }\n        \n        // Output the best placement found for this turn\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                std::cout << best_A[i][j];\n                if (j < N_global - 1) {\n                    std::cout << \" \";\n                } else {\n                    std::cout << std::endl;\n                }\n            }\n        }\n        std::cout.flush(); // Flush output to interactive judge\n\n        // 3. Read the new seeds for the next turn\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M_global; ++j) {\n                std::cin >> X_seeds_global[i][j];\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    solve();\n    \n    return 0;\n}\n","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for grid and problem parameters\nint N, M, V_MAX;\n\n// Current state of takoyaki (sources and targets)\nset<pair<int, int>> current_s_takoyaki; // Takoyaki that need to be picked up\nset<pair<int, int>> current_t_empty;    // Target squares that need takoyaki\n\n// Robotic arm state\nstruct Vec2 {\n    int x, y; // x for row, y for col\n    Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }\n    Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }\n    long long dist_sq(const Vec2& other) const { return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y); }\n};\n\nVec2 root_pos;\nvector<Vec2> rel_vecs; // relative position of vertex u to its parent p_u\nvector<int> orient_idx; // 0:right, 1:down, 2:left, 3:up (problem's definition)\n\n// For positions calculation\nvector<Vec2> abs_pos;\nvector<bool> is_fingertip;\nvector<int> parent_map; // parent_map[u] gives parent of u\nvector<int> L_map; // L_map[u] gives length of (parent[u], u)\n\nvector<bool> fingertip_holding; // Whether each fingertip is holding a takoyaki\n\n// PROBLEM_REL_DX, PROBLEM_REL_DY for cardinal directions (0:R, 1:D, 2:L, 3:U)\n// These define the (row_diff, col_diff) for a segment pointing in that direction.\n// R: (0,1)\n// D: (1,0)\n// L: (0,-1)\n// U: (-1,0)\nconst int PROBLEM_REL_DX[] = {0, 1, 0, -1}; \nconst int PROBLEM_REL_DY[] = {1, 0, -1, 0};\n\n// Rotate a vector (dr, dc) 90 degrees clockwise (dr -> dc, dc -> -dr)\n// Example from problem: (0,L) -> (L,0)\nVec2 rotate_cw_problem(const Vec2& v) { return {v.y, -v.x}; }\n// Rotate a vector (dr, dc) 90 degrees counter-clockwise (dr -> -dc, dc -> dr)\n// Example: (0,L) -> (-L,0)\nVec2 rotate_ccw_problem(const Vec2& v) { return {-v.y, v.x}; }\n\n// Update absolute positions of all vertices\nvoid update_abs_pos() {\n    abs_pos[0] = root_pos;\n    for (size_t i = 1; i < abs_pos.size(); ++i) {\n        abs_pos[i] = abs_pos[parent_map[i]] + rel_vecs[i];\n    }\n}\n\n// Calculate centroid of a set of points\nVec2 calculate_centroid(const set<pair<int, int>>& points) {\n    if (points.empty()) {\n        return {-1, -1}; // Invalid centroid\n    }\n    long long sum_x = 0, sum_y = 0;\n    for (const auto& p : points) {\n        sum_x += p.first;\n        sum_y += p.second;\n    }\n    return {(int)round((double)sum_x / points.size()), (int)round((double)sum_y / points.size())};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> V_MAX;\n\n    set<pair<int, int>> initial_sources_raw; // To store original sources\n    set<pair<int, int>> target_goals_raw; // To store original targets\n\n    // Read initial takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                initial_sources_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Read target takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                target_goals_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Initialize current_s_takoyaki and current_t_empty by removing already satisfied takoyaki\n    current_s_takoyaki = initial_sources_raw;\n    current_t_empty = target_goals_raw;\n\n    for (auto it = current_t_empty.begin(); it != current_t_empty.end(); ) {\n        if (current_s_takoyaki.count(*it)) {\n            current_s_takoyaki.erase(*it);\n            it = current_t_empty.erase(it);\n        } else {\n            ++it;\n        }\n    }\n\n    // Design the robotic arm (V' = V_MAX, star graph, all edges length 1)\n    int V_prime = V_MAX; // Number of vertices in the arm\n    cout << V_prime << endl;\n\n    parent_map.resize(V_prime);\n    L_map.resize(V_prime);\n    is_fingertip.resize(V_prime, false);\n    \n    // Root is 0. Children 1 to V_prime-1 are fingertips.\n    for (int u = 1; u < V_prime; ++u) {\n        // Parent of u is 0, length 1\n        cout << 0 << \" \" << 1 << endl;\n        parent_map[u] = 0;\n        L_map[u] = 1; // All fingertips are length 1 away from root\n        is_fingertip[u] = true;\n    }\n\n    // Initial root position (center of the grid)\n    root_pos = {N / 2, N / 2};\n    cout << root_pos.x << \" \" << root_pos.y << endl;\n\n    // Initialize arm state\n    abs_pos.resize(V_prime);\n    rel_vecs.resize(V_prime);\n    orient_idx.resize(V_prime, 0); // All edges initially point right (direction 0)\n\n    for (int u = 1; u < V_prime; ++u) {\n        rel_vecs[u] = {L_map[u] * PROBLEM_REL_DX[0], L_map[u] * PROBLEM_REL_DY[0]}; // (L,0) for parent-child edge\n    }\n\n    fingertip_holding.resize(V_prime, false); // No fingertip holds takoyaki initially\n\n    // Operation loop\n    for (int turn = 0; turn < 100000; ++turn) {\n        if (current_t_empty.empty()) {\n            break; // All takoyaki delivered\n        }\n\n        // 1. Calculate absolute positions based on current root_pos and relative vectors\n        update_abs_pos();\n\n        // 2. Determine root movement\n        string command_root_move = \".\";\n        Vec2 target_centroid = {-1, -1};\n\n        int holding_count = 0;\n        for(int i=0; i<V_prime; ++i) if(is_fingertip[i] && fingertip_holding[i]) holding_count++;\n\n        if (holding_count > 0) { // If holding takoyaki, prioritize moving to target empty spots\n            target_centroid = calculate_centroid(current_t_empty);\n        } else { // If no takoyaki held, prioritize moving to source takoyaki\n            target_centroid = calculate_centroid(current_s_takoyaki);\n        }\n        \n        // If no target or source left, break or idle\n        if (target_centroid.x == -1) { \n            break; \n        }\n\n        int next_rx = root_pos.x;\n        int next_ry = root_pos.y;\n\n        int dx_diff = target_centroid.x - root_pos.x;\n        int dy_diff = target_centroid.y - root_pos.y;\n\n        // Prioritize moving along the larger difference axis\n        if (abs(dx_diff) >= abs(dy_diff)) {\n            if (dx_diff > 0) { // Move Down (increase row index)\n                if (root_pos.x + 1 < N) {\n                    next_rx = root_pos.x + 1;\n                    command_root_move = \"D\";\n                }\n            } else if (dx_diff < 0) { // Move Up (decrease row index)\n                if (root_pos.x - 1 >= 0) {\n                    next_rx = root_pos.x - 1;\n                    command_root_move = \"U\";\n                }\n            }\n        } \n        \n        // If no movement determined yet, or movement on X axis was impossible, try the Y axis\n        if (command_root_move == \".\" || (abs(dx_diff) < abs(dy_diff) && abs(dy_diff) > 0)) { // Only try if Y diff is larger or X move was skipped\n            if (dy_diff > 0) { // Move Right (increase col index)\n                if (root_pos.y + 1 < N) {\n                    next_ry = root_pos.y + 1;\n                    command_root_move = \"R\";\n                }\n            } else if (dy_diff < 0) { // Move Left (decrease col index)\n                if (root_pos.y - 1 >= 0) {\n                    next_ry = root_pos.y - 1;\n                    command_root_move = \"L\";\n                }\n            }\n        }\n\n        // Apply root movement\n        root_pos.x = next_rx;\n        root_pos.y = next_ry;\n        \n        // Update positions after root move (needed for rotation logic)\n        update_abs_pos();\n\n        // 3. Determine rotations\n        string command_rotations_str(V_prime - 1, '.'); // For non-root vertices (1 to V_prime-1)\n        vector<int> desired_orient_idx(V_prime, -1); // -1 means no specific rotation desired for this turn\n\n        // Prioritize placing takoyaki\n        // Try to assign holding fingertips to target squares\n        for (int d = 0; d < 4; ++d) { // For each cardinal direction (0:R, 1:D, 2:L, 3:U)\n            // Target cell one unit away from root in direction d\n            Vec2 target_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (target_cell.x >= 0 && target_cell.x < N && target_cell.y >= 0 && target_cell.y < N &&\n                current_t_empty.count({target_cell.x, target_cell.y})) {\n                \n                // Find a holding fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n\n        // Then assign empty fingertips to source squares\n        for (int d = 0; d < 4; ++d) {\n            // Source cell one unit away from root in direction d\n            Vec2 source_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (source_cell.x >= 0 && source_cell.x < N && source_cell.y >= 0 && source_cell.y < N &&\n                current_s_takoyaki.count({source_cell.x, source_cell.y})) {\n                \n                // Find an empty fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && !fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n        \n        // Apply rotations based on desired_orient_idx\n        for (int u = 1; u < V_prime; ++u) { // Only non-root vertices can rotate (fingertips in this design)\n            if (desired_orient_idx[u] != -1) {\n                int current_d = orient_idx[u];\n                int target_d = desired_orient_idx[u];\n\n                if (current_d == target_d) {\n                    command_rotations_str[u - 1] = '.'; // No rotation needed\n                } else {\n                    // Calculate shortest rotation path (1 step CW vs 1 step CCW)\n                    int cw_diff = (target_d - current_d + 4) % 4;\n                    int ccw_diff = (current_d - target_d + 4) % 4;\n\n                    if (cw_diff == 1) { // 90 deg CW\n                        command_rotations_str[u - 1] = 'R';\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else if (ccw_diff == 1) { // 90 deg CCW\n                        command_rotations_str[u - 1] = 'L';\n                        orient_idx[u] = (orient_idx[u] + 3) % 4;\n                        rel_vecs[u] = rotate_ccw_problem(rel_vecs[u]);\n                    } else if (cw_diff == 2) { // 180 deg, takes 2 turns. Pick one direction (CW).\n                        command_rotations_str[u - 1] = 'R'; \n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else { // Should not happen for 0-3 directions, but for safety\n                         command_rotations_str[u - 1] = '.';\n                    }\n                }\n            } else {\n                command_rotations_str[u - 1] = '.'; // No specific target, no rotation\n            }\n        }\n        \n        // Update positions after rotations\n        update_abs_pos();\n\n        // 4. Determine grab/release actions\n        // String to store P/'.' for each vertex 0 to V_prime-1.\n        // command_P_actions_part[i] will store the action for vertex i.\n        string command_P_actions_part(V_prime, '.'); \n        \n        // Process fingertips in order of ID (1 to V_prime-1) as problem states vertex order.\n        // Vertex 0 (root) is not a fingertip, so command_P_actions_part[0] remains '.'\n        for (int u = 1; u < V_prime; ++u) { \n            Vec2 current_tip_pos = abs_pos[u];\n\n            // Check if fingertip is within grid boundaries\n            if (current_tip_pos.x < 0 || current_tip_pos.x >= N || current_tip_pos.y < 0 || current_tip_pos.y >= N) {\n                continue; // Fingertip outside grid, cannot act\n            }\n\n            if (fingertip_holding[u]) { // If currently holding a takoyaki\n                if (current_t_empty.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Place takoyaki on target square\n                    command_P_actions_part[u] = 'P'; // Action for vertex 'u' is stored at index 'u'\n                    current_t_empty.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = false;\n                }\n            } else { // If not holding a takoyaki\n                if (current_s_takoyaki.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Pick up takoyaki from source square\n                    command_P_actions_part[u] = 'P';\n                    current_s_takoyaki.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = true;\n                }\n            }\n        }\n        \n        // Output combined command string\n        // Format: [root_move_char][V_prime-1 rotation_chars][V_prime P_chars]\n        cout << command_root_move << command_rotations_str << command_P_actions_part << endl;\n    }\n\n    return 0;\n}\n","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <set>\n// #include <optional> // optional is no longer strictly needed for 'hole' but can be kept if desired\n\nusing namespace std;\n\n// Timer utility\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    double time_limit_ms;\n\n    Timer(double limit_ms) : time_limit_ms(limit_ms) {\n        start_time = chrono::high_resolution_clock::now();\n    }\n\n    bool is_time_up() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() >= time_limit_ms;\n    }\n\n    double get_elapsed_time_ms() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n    }\n};\n\n// Point structure\nstruct Point {\n    int x, y;\n};\n\n// Rectangle structure\nstruct Rect {\n    int x_min, y_min, x_max, y_max;\n    long long length() const {\n        // Degenerate rectangle (width or height is 0 or negative) has 0 length\n        if (x_min >= x_max || y_min >= y_max) return 0; \n        return 2LL * (x_max - x_min) + 2LL * (y_max - y_min);\n    }\n};\n\n// Fenwick Tree (BIT) for 2D range sum queries\ntemplate <typename T>\nstruct FenwickTree2D {\n    int max_x_idx, max_y_idx;\n    vector<vector<T>> bit;\n\n    FenwickTree2D(int mx_idx, int my_idx) : max_x_idx(mx_idx), max_y_idx(my_idx) {\n        // Fenwick tree indices are 1-based, so size mx_idx+1, my_idx+1\n        bit.assign(max_x_idx + 1, vector<T>(max_y_idx + 1, 0));\n    }\n\n    void update(int x, int y, T delta) { // x, y are 0-based compressed indices\n        for (int i = x + 1; i <= max_x_idx; i += i & -i) {\n            for (int j = y + 1; j <= max_y_idx; j += j & -j) {\n                bit[i][j] += delta;\n            }\n        }\n    }\n\n    T query(int x, int y) { // query sum from (0,0) to (x,y) inclusive (0-based compressed indices)\n        T sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i) {\n            for (int j = y + 1; j > 0; j -= j & -j) {\n                sum += bit[i][j];\n            }\n        }\n        return sum;\n    }\n\n    // query sum for rectangle [x1, x2] x [y1, y2] (0-based compressed indices)\n    T query_rect_sum(int x1, int y1, int x2, int y2) { \n        // If the rectangle is inverted or empty in terms of compressed indices, it contains no points\n        if (x1 > x2 || y1 > y2) return 0;\n\n        T sum = query(x2, y2);\n        if (x1 > 0) sum -= query(x1 - 1, y2);\n        if (y1 > 0) sum -= query(x2, y1 - 1);\n        if (x1 > 0 && y1 > 0) sum += query(x1 - 1, y1 - 1);\n        return sum;\n    }\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nvector<int> unique_xs, unique_ys;\nmap<int, int> x_to_idx, y_to_idx;\nFenwickTree2D<int>* ft_ptr = nullptr; // Pointer to FenwickTree2D\n\n// Score calculation wrapper for real coordinates using compressed FT\nlong long calculate_rect_score(const Rect& rect) {\n    // If the rectangle is degenerate (width or height is 0 or negative), it cannot contain any points.\n    if (rect.x_min >= rect.x_max || rect.y_min >= rect.y_max) return 0; \n\n    // Find compressed indices for the given real coordinate rectangle\n    auto it_x1 = lower_bound(unique_xs.begin(), unique_xs.end(), rect.x_min);\n    if (it_x1 == unique_xs.end()) return 0; // rect.x_min is beyond all unique x-coordinates\n    int x1_idx = distance(unique_xs.begin(), it_x1);\n\n    auto it_x2 = upper_bound(unique_xs.begin(), unique_xs.end(), rect.x_max);\n    if (it_x2 == unique_xs.begin()) return 0; // rect.x_max is smaller than all unique x-coordinates\n    int x2_idx = distance(unique_xs.begin(), it_x2) - 1; // Largest unique_x_coord <= rect.x_max\n\n    auto it_y1 = lower_bound(unique_ys.begin(), unique_ys.end(), rect.y_min);\n    if (it_y1 == unique_ys.end()) return 0; \n    int y1_idx = distance(unique_ys.begin(), it_y1);\n\n    auto it_y2 = upper_bound(unique_ys.begin(), unique_ys.end(), rect.y_max);\n    if (it_y2 == unique_ys.begin()) return 0; \n    int y2_idx = distance(unique_ys.begin(), it_y2) - 1;\n\n    // Check if the compressed index range itself is valid (x1_idx <= x2_idx and y1_idx <= y2_idx)\n    // This handles cases where rect.x_min > rect.x_max (after compression logic)\n    if (x1_idx > x2_idx || y1_idx > y2_idx) return 0; \n\n    return ft_ptr->query_rect_sum(x1_idx, y1_idx, x2_idx, y2_idx);\n}\n\n// Polygon state for SA: now only a single rectangle\nstruct PolygonState {\n    Rect outer;\n    long long value; // Score (mackerels - sardines)\n    long long total_len; // Total length of edges\n    vector<Point> vertices; // Actual vertices for output\n\n    PolygonState() : value(0), total_len(0), outer({0,0,0,0}) {} // Default empty state\n\n    void calculate_polygon_data() {\n        // Outer rect must be valid (x_min < x_max and y_min < y_max)\n        if (outer.x_min >= outer.x_max || outer.y_min >= outer.y_max) { \n            value = -1; // Indicate invalid state (negative value for invalid)\n            total_len = 0;\n            vertices.clear();\n            return;\n        }\n        \n        value = calculate_rect_score(outer);\n        total_len = outer.length();\n\n        vertices.clear();\n        // Generate vertices for output if score is non-negative\n        // For a valid, non-degenerate rectangle, these 4 points are always distinct.\n        // The output polygon will be a simple rectangle with 4 vertices.\n        vertices.push_back({outer.x_min, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_max});\n        vertices.push_back({outer.x_min, outer.y_max});\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer(1900); // 1.9 seconds time limit for main SA loop\n\n    cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    set<int> x_coords_set, y_coords_set;\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        x_coords_set.insert(mackerels[i].x);\n        y_coords_set.insert(mackerels[i].y);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        x_coords_set.insert(sardines[i].x);\n        y_coords_set.insert(sardines[i].y);\n    }\n\n    // Coordinate compression\n    unique_xs.assign(x_coords_set.begin(), x_coords_set.end());\n    unique_ys.assign(y_coords_set.begin(), y_coords_set.end());\n\n    // Ensure 0 and 100000 are in unique_xs/ys as potential boundaries for rectangles.\n    // This is important because a rectangle might span these boundaries even if no points are exactly on them.\n    if (unique_xs.empty() || unique_xs.front() != 0) { unique_xs.insert(unique_xs.begin(), 0); }\n    if (unique_xs.back() != 100000) { unique_xs.push_back(100000); }\n    if (unique_ys.empty() || unique_ys.front() != 0) { unique_ys.insert(unique_ys.begin(), 0); }\n    if (unique_ys.back() != 100000) { unique_ys.push_back(100000); }\n    \n    // Re-sort if necessary (std::set keeps elements sorted, so unique_xs.assign copies them in order. \n    // Manual insert at begin/end might break this if elements are not at the extrema, but 0 and 100000 are extrema.)\n    // However, it's safer to ensure they are sorted if inserts were made. std::set properties ensure this is usually fine.\n    // With `insert` and `push_back` as written for 0 and 100000, `unique_xs` and `unique_ys` remain sorted.\n\n    // Populate maps for fast lookup from real coordinate to compressed index\n    for (int i = 0; i < unique_xs.size(); ++i) x_to_idx[unique_xs[i]] = i;\n    for (int i = 0; i < unique_ys.size(); ++i) y_to_idx[unique_ys[i]] = i;\n\n    // Initialize 2D Fenwick Tree using compressed indices\n    FenwickTree2D<int> ft(unique_xs.size(), unique_ys.size());\n    ft_ptr = &ft;\n\n    for (int i = 0; i < N; ++i) { // Mackerels contribute +1\n        ft.update(x_to_idx[mackerels[i].x], y_to_idx[mackerels[i].y], 1);\n    }\n    for (int i = 0; i < N; ++i) { // Sardines contribute -1\n        ft.update(x_to_idx[sardines[i].x], y_to_idx[sardines[i].y], -1);\n    }\n\n    // Initialize random number generator\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_idx_x(0, unique_xs.size() - 1);\n    uniform_int_distribution<int> rand_idx_y(0, unique_ys.size() - 1);\n    uniform_real_distribution<double> rand_prob(0.0, 1.0);\n    \n    // Initial solution: a large rectangle covering the entire possible area\n    PolygonState best_polygon;\n    best_polygon.outer = {0, 0, 100000, 100000};\n    best_polygon.calculate_polygon_data(); // Calculate score and vertices for initial state\n    \n    // If the initial full map rectangle is degenerate, invalid, or yields a negative score\n    // (meaning a score of 1 in the contest, effectively), initialize with a minimal valid rectangle.\n    // The current calculate_polygon_data sets value=-1 for invalid, and total_len=0.\n    // So, if best_polygon.value is -1, it implies an invalid rectangle, or actual score < 0.\n    if (best_polygon.value < 0 || best_polygon.total_len > 400000) {\n        best_polygon.outer = {0,0,1,1}; // A minimal 1x1 rectangle at origin. Valid, length 4, 4 vertices.\n        best_polygon.calculate_polygon_data();\n    }\n\n    PolygonState current_polygon = best_polygon; // Start SA from this point\n\n    double T_start = 2000.0; // Initial temperature: A heuristic, roughly the maximum possible (mackerel - sardine) difference\n    double T_end = 1.0;      // Final temperature: Low enough to favor improvements but still allow small worsening moves\n    long long iter_count = 0;\n    long long max_iterations = 500000; // Increase iterations as calculations are faster now\n\n    while (!timer.is_time_up() && iter_count < max_iterations) {\n        iter_count++;\n        PolygonState next_polygon = current_polygon;\n\n        // Only modify the outer rectangle's boundaries\n        int dim_to_change = uniform_int_distribution<int>(0, 3)(rng); // 0:x_min, 1:y_min, 2:x_max, 3:y_max\n        int new_val_idx;\n        \n        if (dim_to_change == 0) { // Modify x_min\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max); // Ensure x_min <= x_max\n        } else if (dim_to_change == 1) { // Modify y_min\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max); // Ensure y_min <= y_max\n        } else if (dim_to_change == 2) { // Modify x_max\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min); // Ensure x_max >= x_min\n        } else { // Modify y_max\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min); // Ensure y_max >= y_min\n        }\n        \n        next_polygon.calculate_polygon_data(); // Recalculate score and other data for the new state\n        \n        // Validity check: Must result in a valid polygon (value >= 0, length within limits)\n        if (next_polygon.value < 0 || next_polygon.total_len > 400000) {\n            continue; // This move is invalid, discard and try again\n        }\n\n        // Simulated Annealing acceptance criteria\n        double current_temp = T_start * pow(T_end / T_start, timer.get_elapsed_time_ms() / timer.time_limit_ms);\n        double acceptance_prob = 1.0;\n        if (next_polygon.value < current_polygon.value) {\n            // If the new solution is worse, accept it with a probability that decreases with temperature\n            acceptance_prob = exp((double)(next_polygon.value - current_polygon.value) / current_temp);\n        }\n\n        if (rand_prob(rng) < acceptance_prob) {\n            current_polygon = next_polygon; // Accept the new solution\n            if (current_polygon.value > best_polygon.value) {\n                best_polygon = current_polygon; // Update overall best solution found\n            }\n        }\n    }\n\n    // Output the best polygon found\n    // If best_polygon.value is negative (which shouldn't happen with the fallback {0,0,1,1} initialization, \n    // but as a safeguard), output the minimal 1x1 polygon for a score of 1.\n    if (best_polygon.value < 0) {\n        cout << 4 << endl;\n        cout << \"0 0\" << endl;\n        cout << \"1 0\" << endl;\n        cout << \"1 1\" << endl;\n        cout << \"0 1\" << endl;\n    } else {\n        cout << best_polygon.vertices.size() << endl;\n        for (const auto& v : best_polygon.vertices) {\n            cout << v.x << \" \" << v.y << endl;\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <map>\n#include <iomanip> // For std::fixed, std::setprecision\n#include <chrono> // For timing\n#include <cmath> // For std::exp, std::pow, std::sqrt\n\n// Random number generator\nstd::mt19937 rng;\n\n// Global parameters from input\nint N_GLOBAL;\nint T_TOTAL_GLOBAL;\nlong long SIGMA_GLOBAL;\nstd::vector<long long> W_PRIME_GLOBAL, H_PRIME_GLOBAL; // Initial observed dimensions\n\n// Current estimates for true widths and heights, using double for precision\nstd::vector<double> current_estimated_w, current_estimated_h;\n\n// Struct to represent a single placement operation\nstruct Operation {\n    int p;     // Rectangle index (0 to N-1)\n    int r;     // Rotation (0: no, 1: 90-deg)\n    char d;    // Direction ('U' or 'L')\n    int b;     // Reference rectangle index (-1 for origin or 0 to p-1)\n};\n\n// Struct to store details of a rectangle after it's been placed\nstruct PlacedRectInfo {\n    long long x, y, w, h; // Coordinates and dimensions\n    int p_idx;             // Original index of the rectangle\n    bool rotated;          // True if rotated\n};\n\n// Helper function for random integer generation\nint random_int(int min, int max) {\n    std::uniform_int_distribution<int> dist(min, max);\n    return dist(rng);\n}\n\n// Helper function for random char selection\nchar random_char(char c1, char c2) {\n    return (random_int(0, 1) == 0) ? c1 : c2;\n}\n\n// Helper for random double in range [0, 1)\ndouble random_double_01() {\n    std::uniform_real_distribution<double> dist(0.0, 1.0);\n    return dist(rng);\n}\n\n// Simulates the placement of rectangles given a set of operations and current dimension estimates.\n// Returns the predicted bounding box (W, H) and the detailed info of placed rectangles.\nstd::pair<std::pair<long long, long long>, std::vector<PlacedRectInfo>>\nsimulate_placement(const std::vector<Operation>& ops,\n                   const std::vector<double>& est_w,\n                   const std::vector<double>& est_h) {\n    \n    std::vector<PlacedRectInfo> placed_rect_infos;\n    std::map<int, PlacedRectInfo> p_idx_to_info; // Map from original rectangle index to its PlacedRectInfo\n\n    long long max_X = 0;\n    long long max_Y = 0;\n\n    for (const auto& op : ops) {\n        // Get estimated dimensions and apply rotation\n        long long current_w = static_cast<long long>(est_w[op.p]);\n        long long current_h = static_cast<long long>(est_h[op.p]);\n        \n        if (op.r == 1) { // Rotate 90 degrees\n            std::swap(current_w, current_h);\n        }\n\n        // Clamp dimensions to problem constraints [1, 10^9]\n        current_w = std::max(1LL, std::min(1000000000LL, current_w));\n        current_h = std::max(1LL, std::min(1000000000LL, current_h));\n\n        long long new_x = 0;\n        long long new_y = 0;\n\n        if (op.d == 'U') {\n            // Determine the x-coordinate of the left edge\n            long long target_x_left = 0;\n            if (op.b != -1) {\n                // Ensure op.b is a valid index and present in p_idx_to_info\n                // op.b ranges from -1 to p-1, so if op.b >= 0, it must be in p_idx_to_info\n                if (p_idx_to_info.count(op.b)) { \n                    target_x_left = p_idx_to_info[op.b].x + p_idx_to_info[op.b].w;\n                }\n            }\n            new_x = target_x_left;\n\n            // Find the highest point (max y + h) that the new rectangle would sit on\n            long long y_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for horizontal overlap with placed_r\n                if (placed_r.x < new_x + current_w && placed_r.x + placed_r.w > new_x) {\n                    y_stop_level = std::max(y_stop_level, placed_r.y + placed_r.h);\n                }\n            }\n            new_y = y_stop_level;\n\n        } else { // op.d == 'L'\n            // Determine the y-coordinate of the top edge\n            long long target_y_top = 0;\n            if (op.b != -1) {\n                // Ensure op.b is a valid index and present in p_idx_to_info\n                if (p_idx_to_info.count(op.b)) {\n                    target_y_top = p_idx_to_info[op.b].y + p_idx_to_info[op.b].h;\n                }\n            }\n            new_y = target_y_top;\n\n            // Find the rightmost point (max x + w) that the new rectangle would push against\n            long long x_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for vertical overlap with placed_r\n                if (placed_r.y < new_y + current_h && placed_r.y + placed_r.h > new_y) {\n                    x_stop_level = std::max(x_stop_level, placed_r.x + placed_r.w);\n                }\n            }\n            new_x = x_stop_level;\n        }\n\n        // Store info for the newly placed rectangle\n        PlacedRectInfo info = {new_x, new_y, current_w, current_h, op.p, (op.r == 1)};\n        placed_rect_infos.push_back(info); // For tracking order of placement\n        p_idx_to_info[op.p] = info;      // For quick lookup by original index\n\n        // Update overall bounding box dimensions\n        max_X = std::max(max_X, new_x + current_w);\n        max_Y = std::max(max_Y, new_y + current_h);\n    }\n\n    return {{max_X, max_Y}, placed_rect_infos};\n}\n\n// Generates an initial random placement strategy\nstd::vector<Operation> generate_random_strategy(int N) {\n    std::vector<Operation> ops(N);\n    for (int i = 0; i < N; ++i) {\n        ops[i].p = i; // Always place rectangles in ascending order of their original indices\n        ops[i].r = random_int(0, 1);\n        ops[i].d = random_char('U', 'L');\n        ops[i].b = random_int(-1, i - 1); // Reference rectangle must be -1 or a previously placed index\n    }\n    return ops;\n}\n\n// Main solution function\nvoid solve() {\n    // Read initial N, T, sigma and rectangle measurements\n    std::cin >> N_GLOBAL >> T_TOTAL_GLOBAL >> SIGMA_GLOBAL;\n\n    W_PRIME_GLOBAL.resize(N_GLOBAL);\n    H_PRIME_GLOBAL.resize(N_GLOBAL);\n    current_estimated_w.resize(N_GLOBAL);\n    current_estimated_h.resize(N_GLOBAL);\n\n    for (int i = 0; i < N_GLOBAL; ++i) {\n        std::cin >> W_PRIME_GLOBAL[i] >> H_PRIME_GLOBAL[i];\n        current_estimated_w[i] = static_cast<double>(W_PRIME_GLOBAL[i]);\n        current_estimated_h[i] = static_cast<double>(H_PRIME_GLOBAL[i]);\n    }\n\n    // Initialize the best strategy found so far across all turns\n    std::vector<Operation> overall_best_ops = generate_random_strategy(N_GLOBAL);\n    auto initial_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n    long long overall_best_score_predicted = initial_sim_result.first.first + initial_sim_result.first.second;\n\n    // Time management for local search\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 2.9; // Allow some buffer for I/O and final calculations\n\n    // Simulated Annealing temperature parameters\n    // T_GLOBAL_START determines the initial temperature for SA in the first turn.\n    // Adjusted based on average estimated rectangle side lengths to be more robust.\n    double T_GLOBAL_START = 0;\n    for(int i=0; i<N_GLOBAL; ++i) T_GLOBAL_START += (current_estimated_w[i] + current_estimated_h[i]);\n    T_GLOBAL_START /= N_GLOBAL; // Average side length sum per rectangle\n    T_GLOBAL_START *= 10.0;     // Scale up for initial temperature, arbitrary tuning.\n    T_GLOBAL_START = std::max(T_GLOBAL_START, 100000.0); // Minimum temp to ensure it's not too small.\n\n    const double T_GLOBAL_END_RATIO = 0.01; // Global temp decays to T_GLOBAL_START * T_GLOBAL_END_RATIO over all turns.\n    const double T_INNER_END_RATIO = 0.001; // Inner temp decays to T_TURN_START * T_INNER_END_RATIO over local search iterations.\n    const int NUM_LOCAL_SEARCH_ATTEMPTS = 50; \n    \n    for (int turn = 0; turn < T_TOTAL_GLOBAL; ++turn) {\n        // Calculate the current global temperature for this turn.\n        double turn_progress = (double)turn / T_TOTAL_GLOBAL;\n        double T_turn_start = T_GLOBAL_START * std::pow(T_GLOBAL_END_RATIO, turn_progress);\n\n        // Keep track of the best solution found during this SA run for this turn\n        std::vector<Operation> current_ops_SA = overall_best_ops; // Start SA from the current overall best\n        long long current_score_SA = overall_best_score_predicted;\n        \n        std::vector<Operation> best_ops_in_SA = overall_best_ops;\n        long long best_score_in_SA = overall_best_score_predicted;\n\n        for (int iter = 0; iter < NUM_LOCAL_SEARCH_ATTEMPTS; ++iter) {\n            std::vector<Operation> candidate_ops = current_ops_SA; // Start from current SA state\n            int p_idx_to_change = random_int(0, N_GLOBAL - 1); // Pick a random rectangle to perturb\n\n            // Randomly choose one parameter to mutate\n            int mutate_type = random_int(0, 2); // 0: r (rotation), 1: d (direction), 2: b (reference)\n\n            if (mutate_type == 0) { // Mutate rotation\n                candidate_ops[p_idx_to_change].r = 1 - candidate_ops[p_idx_to_change].r;\n            } else if (mutate_type == 1) { // Mutate direction\n                candidate_ops[p_idx_to_change].d = (candidate_ops[p_idx_to_change].d == 'U' ? 'L' : 'U');\n            } else { // Mutate reference rectangle (b_i)\n                candidate_ops[p_idx_to_change].b = random_int(-1, p_idx_to_change - 1);\n            }\n\n            // Simulate the candidate strategy and evaluate its score\n            auto sim_result = simulate_placement(candidate_ops, current_estimated_w, current_estimated_h);\n            long long candidate_score = sim_result.first.first + sim_result.first.second;\n\n            // Simulated Annealing acceptance condition\n            double inner_iter_progress = (double)iter / NUM_LOCAL_SEARCH_ATTEMPTS;\n            double temp_for_this_iter = T_turn_start * std::pow(T_INNER_END_RATIO, inner_iter_progress);\n            \n            // Prevent division by zero if temp becomes extremely small, or other numerical issues\n            if (temp_for_this_iter < 1.0) temp_for_this_iter = 1.0; \n\n            if (candidate_score < current_score_SA) {\n                current_ops_SA = candidate_ops;\n                current_score_SA = candidate_score;\n                // If this is better than the overall best found in this SA run, update it\n                if (current_score_SA < best_score_in_SA) {\n                    best_ops_in_SA = current_ops_SA;\n                    best_score_in_SA = current_score_SA;\n                }\n            } else {\n                // Accept worse solutions with a probability\n                double acceptance_prob = std::exp(-(double)(candidate_score - current_score_SA) / temp_for_this_iter);\n                if (random_double_01() < acceptance_prob) {\n                    current_ops_SA = candidate_ops;\n                    current_score_SA = candidate_score;\n                }\n            }\n        } // End of NUM_LOCAL_SEARCH_ATTEMPTS loop (inner SA)\n\n        // After SA, update overall_best_ops if a better solution was found\n        // `best_score_in_SA` is used as `current_score_SA` might be a worse accepted state.\n        if (best_score_in_SA < overall_best_score_predicted) {\n            overall_best_ops = best_ops_in_SA;\n            overall_best_score_predicted = best_score_in_SA;\n        }\n\n        // Output the chosen (overall best) strategy for this turn\n        std::cout << N_GLOBAL << std::endl;\n        for (const auto& op : overall_best_ops) {\n            std::cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << std::endl;\n        }\n        std::cout << std::flush; // Crucial for interactive problems\n\n        // Read observed W' and H' from the judge\n        long long W_observed, H_observed;\n        std::cin >> W_observed >> H_observed;\n\n        // --- Update dimension estimates based on feedback ---\n        // Simulate overall_best_ops with current_estimated_w/h to get W_predicted, H_predicted\n        auto sim_result_for_update = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        long long W_predicted = sim_result_for_update.first.first;\n        long long H_predicted = sim_result_for_update.first.second;\n\n        // Calculate scaling ratios. Predicted W/H should not be zero since min_w/h is 1.\n        double W_ratio = static_cast<double>(W_observed) / W_predicted;\n        double H_ratio = static_cast<double>(H_observed) / H_predicted;\n\n        // Learning rate decreases over turns to stabilize estimates\n        double learn_rate = 0.05 / std::sqrt(turn + 1.0); \n        // Regularization rate to pull estimates back towards initial observations\n        double initial_reversion_rate = 0.01 / std::sqrt(turn + 1.0); \n\n        for (int i = 0; i < N_GLOBAL; ++i) {\n            // Adjust estimates based on observed vs. predicted global dimensions\n            current_estimated_w[i] = current_estimated_w[i] * (1.0 + learn_rate * (W_ratio - 1.0));\n            current_estimated_h[i] = current_estimated_h[i] * (1.0 + learn_rate * (H_ratio - 1.0));\n\n            // Regularize towards the initial noisy measurements w'_i, h'_i\n            current_estimated_w[i] = (1.0 - initial_reversion_rate) * current_estimated_w[i] + initial_reversion_rate * W_PRIME_GLOBAL[i];\n            current_estimated_h[i] = (1.0 - initial_reversion_rate) * current_estimated_h[i] + initial_reversion_rate * H_PRIME_GLOBAL[i];\n\n            // Clamp estimates within reasonable bounds (problem implies these max values)\n            current_estimated_w[i] = std::max(1.0, std::min(1000000000.0, current_estimated_w[i]));\n            current_estimated_h[i] = std::max(1.0, std::min(1000000000.0, current_estimated_h[i]));\n        }\n\n        // Re-calculate the overall best predicted score with the new estimates\n        // This is important because the estimation of dimensions has changed.\n        // It ensures `overall_best_score_predicted` is always based on current estimates\n        // and is ready for the next turn's SA.\n        overall_best_score_predicted = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.first + \n                                       simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.second;\n\n        // Check if remaining time is too low to continue effectively\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT_SECONDS) {\n            // std::cerr << \"# Time out at turn \" << turn << std::endl; // Comment for visualizer\n            break; \n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for speed\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Seed the random number generator\n    rng.seed(std::chrono::system_clock::now().time_since_epoch().count());\n\n    // Call the solver function\n    solve();\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <queue>\n#include <chrono>\n#include <random>\n// #include <map> // Not strictly needed, but included in thinking process\n\n// Global random number generator\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Structure to hold graph and problem data\nstruct ProblemData {\n    int N, M, H_limit;\n    std::vector<int> A;\n    std::vector<std::vector<int>> adj; // Adjacency list for the original graph\n    // Edges and coords are not used by the SA algorithm, but kept for completeness\n    std::vector<std::pair<int, int>> edges;\n    std::vector<std::pair<int, int>> coords;\n};\n\n// Structure to hold a solution candidate (parent array, score, heights)\nstruct Solution {\n    std::vector<int> parent;\n    long long score;\n    std::vector<int> heights; // Heights for current parent configuration\n\n    Solution(int N_val) : parent(N_val, -1), score(0), heights(N_val, -1) {}\n};\n\n// Function to evaluate a given parent array and compute heights\n// Returns score, and populates heights_out. Returns -1 for invalid states.\n// Invalid states include cycles or height constraint violations.\nlong long eval_score(const ProblemData& pd, const std::vector<int>& p, std::vector<int>& heights_out) {\n    int N = pd.N;\n    int H_limit = pd.H_limit;\n    const std::vector<int>& A = pd.A;\n\n    std::vector<std::vector<int>> children_lists(N);\n    std::vector<bool> is_root(N, true);\n    for (int v = 0; v < N; ++v) {\n        if (p[v] != -1) {\n            // Basic parent validity check (within bounds, not self)\n            // This is a safety check; forms_cycle and problem constraints should handle most of this.\n            if (p[v] < 0 || p[v] >= N || p[v] == v) { \n                return -1; // Invalid parent reference\n            }\n            children_lists[p[v]].push_back(v);\n            is_root[v] = false;\n        }\n    }\n\n    std::fill(heights_out.begin(), heights_out.end(), -1);\n    long long current_total_score = 0;\n    \n    // Use a queue for BFS\n    std::queue<int> q;\n\n    for (int r = 0; r < N; ++r) {\n        // If 'r' is a root and has not been processed yet (i.e., not part of another tree)\n        if (is_root[r] && heights_out[r] == -1) { \n            q.push(r);\n            heights_out[r] = 0;\n            current_total_score += (1LL * (heights_out[r] + 1) * A[r]);\n\n            while (!q.empty()) {\n                int u = q.front();\n                q.pop();\n\n                if (heights_out[u] > H_limit) { // Height constraint violation for this tree\n                    return -1;\n                }\n\n                for (int v_child : children_lists[u]) {\n                    if (heights_out[v_child] == -1) { // If not yet visited in this tree\n                        heights_out[v_child] = heights_out[u] + 1;\n                        if (heights_out[v_child] > H_limit) { // Height constraint violation\n                            return -1;\n                        }\n                        current_total_score += (1LL * (heights_out[v_child] + 1) * A[v_child]);\n                        q.push(v_child);\n                    } else {\n                        // This case implies a cycle or a structural inconsistency in the parent array.\n                        // The forms_cycle check should catch most ancestor-descendant cycles.\n                        // Any remaining detected cycle would make this an invalid forest.\n                        return -1; \n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure all nodes have been assigned a height (i.e., are part of some tree).\n    // If any node remains with heights_out[v] == -1, it means the parent array 'p'\n    // does not form a spanning forest. This shouldn't happen for a valid set of parents.\n    for(int v = 0; v < N; ++v){\n        if(heights_out[v] == -1){\n            return -1; // Indicates a disjoint node/subgraph not correctly rooted or parented\n        }\n    }\n\n    return current_total_score;\n}\n\n// Function to check for cycles efficiently during a proposed parent change\n// Returns true if new_p is an ancestor of v (which means setting parent[v] = new_p forms a cycle)\nbool forms_cycle(int v, int new_p, const std::vector<int>& current_p, const ProblemData& pd) {\n    if (new_p == -1) return false;\n\n    // Traverse up from new_p using current parent pointers\n    int curr = new_p;\n    for(int i = 0; i <= pd.H_limit + 1 && curr != -1; ++i) { \n        if (curr == v) {\n            return true; // Found v, so v is an ancestor of new_p, forms a cycle\n        }\n        curr = current_p[curr];\n    }\n    return false; // No cycle detected within the typical height limit\n}\n\nvoid solve() {\n    ProblemData pd;\n    std::cin >> pd.N >> pd.M >> pd.H_limit;\n    pd.A.resize(pd.N);\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.A[i];\n    pd.adj.resize(pd.N);\n    pd.edges.resize(pd.M); // Not strictly used by this SA approach, but might be useful for other heuristics\n    for (int i = 0; i < pd.M; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        pd.adj[u].push_back(v);\n        pd.adj[v].push_back(u);\n        pd.edges[i] = {u, v}; \n    }\n    pd.coords.resize(pd.N); // Not used by this SA approach\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.coords[i].first >> pd.coords[i].second;\n\n    // Initial solution: all nodes are roots\n    Solution current_sol(pd.N);\n    current_sol.score = eval_score(pd, current_sol.parent, current_sol.heights);\n    if (current_sol.score == -1) { // This should ideally not happen for the initial \"all roots\" state if N > 0\n                                   // But if N=0 or other weird inputs, better handle it.\n                                   // For N > 0, an initial state of all roots is always valid.\n        current_sol.score = std::accumulate(pd.A.begin(), pd.A.end(), 0LL); // Min score (all roots, h=0)\n        std::fill(current_sol.heights.begin(), current_sol.heights.end(), 0);\n    }\n\n    Solution best_sol = current_sol;\n\n    // Simulated Annealing parameters\n    // Using time-based annealing\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Slightly less than 2 seconds to be safe\n    double start_temp = 500.0;           // Initial temperature (adjust based on problem scale)\n    double end_temp = 1.0;               // Final temperature\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n\n    // Main Simulated Annealing loop\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration<double, std::milli>(current_time - start_time).count();\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            break;\n        }\n\n        double progress = elapsed_ms / TIME_LIMIT_MS;\n        double temp = start_temp * (1.0 - progress) + end_temp * progress; // Linear cooling\n\n        // Choose a random vertex to modify\n        int v = rng() % pd.N;\n\n        // Store original parent of v, so we can revert if the move is rejected\n        int original_p_v = current_sol.parent[v];\n        \n        // Generate candidate parents: -1 (make root) and all neighbors of v\n        std::vector<int> candidate_parents;\n        candidate_parents.push_back(-1); // Option to make v a root\n        for (int neighbor : pd.adj[v]) {\n            // Ensure neighbor is not v itself (shouldn't happen for simple graphs, but safe check)\n            if (neighbor != v) { \n                candidate_parents.push_back(neighbor);\n            }\n        }\n\n        // Pick a random candidate parent\n        int new_p = candidate_parents[rng() % candidate_parents.size()];\n        \n        // Temporarily apply the move\n        current_sol.parent[v] = new_p;\n\n        // Check for cycles *before* full evaluation to save time\n        if (forms_cycle(v, new_p, current_sol.parent, pd)) {\n             current_sol.parent[v] = original_p_v; // Revert\n             continue; // Invalid move due to cycle, try next iteration\n        }\n        \n        // Evaluate the new state\n        std::vector<int> new_heights(pd.N);\n        long long new_score = eval_score(pd, current_sol.parent, new_heights);\n\n        if (new_score != -1) { // Valid move (no height limit violation or structural error)\n            if (new_score > best_sol.score) {\n                best_sol.score = new_score;\n                best_sol.parent = current_sol.parent;\n                best_sol.heights = new_heights; // Store heights (optional, for analysis)\n            }\n\n            // Simulated Annealing acceptance condition\n            if (new_score > current_sol.score || \n                dist_0_1(rng) < std::exp((double)(new_score - current_sol.score) / temp)) {\n                \n                current_sol.score = new_score;\n                current_sol.heights = new_heights;\n            } else {\n                // Revert the change (move rejected)\n                current_sol.parent[v] = original_p_v;\n            }\n        } else {\n            // Revert the change (invalid move due to height limit or structural error)\n            current_sol.parent[v] = original_p_v;\n        }\n    }\n\n    // Output the best solution found\n    for (int i = 0; i < pd.N; ++i) {\n        std::cout << best_sol.parent[i] << (i == pd.N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <limits>  // For std::numeric_limits\n\n// Structure to store an operation\nstruct Operation {\n    char direction;\n    int index;\n\n    Operation(char d, int i) : direction(d), index(i) {}\n};\n\n// Structure to encapsulate the best choice found in an iteration\nstruct BestChoice {\n    double cost_per_oni; // Primary metric: moves / num_oni_removed (minimize)\n    int num_oni_removed; // Secondary metric: maximize\n    int moves_count;     // Tertiary metric: minimize\n    std::pair<int, int> target_oni_pos; // The specific Oni this action was calculated for\n    char direction;\n    int index;\n\n    // Default constructor for initialization to \"worst possible\" values\n    BestChoice() : cost_per_oni(std::numeric_limits<double>::max()),\n                   num_oni_removed(0), // Maximize this, so start low\n                   moves_count(std::numeric_limits<int>::max()),\n                   target_oni_pos({-1, -1}), direction(' '), index(-1) {}\n\n    // Method to check if 'this' choice is strictly better than 'other'\n    bool is_strictly_better_than(const BestChoice& other) const {\n        // 1. Compare cost_per_oni (less is better)\n        if (cost_per_oni < other.cost_per_oni) return true;\n        if (cost_per_oni > other.cost_per_oni) return false;\n\n        // 2. cost_per_oni is equal, compare num_oni_removed (more is better)\n        if (num_oni_removed > other.num_oni_removed) return true;\n        if (num_oni_removed < other.num_oni_removed) return false;\n\n        // 3. num_oni_removed is equal, compare moves_count (less is better)\n        if (moves_count < other.moves_count) return true;\n\n        return false; // Not strictly better\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N;\n    std::cin >> N;\n\n    // Store initial Fukunokami positions for constant lookup, as they never move\n    std::set<std::pair<int, int>> fuku_positions_set;\n    // Store current Oni positions. This set will be modified as Oni are removed.\n    std::set<std::pair<int, int>> current_oni_positions_set;\n\n    for (int i = 0; i < N; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                current_oni_positions_set.insert({i, j});\n            } else if (row_str[j] == 'o') {\n                fuku_positions_set.insert({i, j});\n            }\n        }\n    }\n\n    std::vector<Operation> operations;\n\n    // Continue as long as there are Oni on the board\n    while (!current_oni_positions_set.empty()) {\n        BestChoice best_overall_choice;\n\n        // Iterate through all currently present Oni to find the best action.\n        // The iteration order of std::set provides a stable tie-breaking for target_oni_pos\n        for (const auto& oni_pos : current_oni_positions_set) {\n            int r = oni_pos.first;\n            int c = oni_pos.second;\n\n            // --- Check Upward path ---\n            bool up_clear = true;\n            int oni_in_up_path_count = 0;\n            // Iterate from row 0 up to and including 'r' in column 'c'\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    up_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_up_path_count++;\n                }\n            }\n\n            if (up_clear) {\n                int moves = 2 * (r + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_up_path_count;\n                // 'num_oni_removed' is guaranteed to be at least 1 (the target Oni itself)\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_up_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'U';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Downward path ---\n            bool down_clear = true;\n            int oni_in_down_path_count = 0;\n            // Iterate from row 'r' down to and including 'N-1' in column 'c'\n            for (int k_row = r; k_row < N; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    down_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_down_path_count++;\n                }\n            }\n\n            if (down_clear) {\n                int moves = 2 * (N - r);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_down_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_down_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'D';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Leftward path ---\n            bool left_clear = true;\n            int oni_in_left_path_count = 0;\n            // Iterate from column 0 up to and including 'c' in row 'r'\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    left_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_left_path_count++;\n                }\n            }\n\n            if (left_clear) {\n                int moves = 2 * (c + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_left_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_left_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'L';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Rightward path ---\n            bool right_clear = true;\n            int oni_in_right_path_count = 0;\n            // Iterate from column 'c' down to and including 'N-1' in row 'r'\n            for (int k_col = c; k_col < N; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    right_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_right_path_count++;\n                }\n            }\n\n            if (right_clear) {\n                int moves = 2 * (N - c);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_right_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_right_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'R';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n        } // End loop over current_oni_positions_set\n\n        // Apply the best found operations and update the set of Oni\n        int r = best_overall_choice.target_oni_pos.first;\n        int c = best_overall_choice.target_oni_pos.second;\n        char chosen_direction = best_overall_choice.direction;\n        int chosen_index = best_overall_choice.index;\n\n        // The problem guarantee ensures that a valid choice is always found.\n        // If it weren't, chosen_index would be -1, indicating an error or no more Oni.\n        // For robustness, could add: if (chosen_index == -1) break;\n\n        if (chosen_direction == 'U') {\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('U', chosen_index);\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('D', chosen_index);\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'D') {\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('D', chosen_index);\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('U', chosen_index);\n            for (int k_row = r; k_row < N; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'L') {\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('L', chosen_index);\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('R', chosen_index);\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        } else if (chosen_direction == 'R') {\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('R', chosen_index);\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('L', chosen_index);\n            for (int k_col = c; k_col < N; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        }\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        std::cout << op.direction << \" \" << op.index << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric> // For std::accumulate\n#include <cmath>   // For std::abs, std::pow, std::exp\n#include <random>  // For std::mt19937, std::uniform_int_distribution, std::uniform_real_distribution\n#include <chrono>  // For high_resolution_clock\n#include <map>     // For cycle detection\n#include <algorithm> // For std::min (though not strictly used, good practice)\n\n// Use a global random number generator for convenience and efficiency\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Function to calculate the error for a given assignment\n// N: Number of employees\n// L: Total number of weeks\n// T: Target cleaning counts for each employee\n// assignments: Vector of pairs (a_i, b_i) for each employee i\nlong long calculate_error(\n    int N, int L, \n    const std::vector<int>& T, \n    const std::vector<std::pair<int, int>>& assignments\n) {\n    std::vector<long long> actual_final_counts(N, 0); // Stores the final cleaning counts for each employee\n\n    int current_cleaner = 0; // The employee who cleans in the current week (starts with employee 0)\n    // counts_in_sim tracks cleaning counts *during this specific simulation run* for cycle detection\n    std::vector<int> counts_in_sim(N, 0); \n    \n    // For cycle detection:\n    // path_cleaners stores the sequence of employees who cleaned, week by week (0-indexed)\n    std::vector<int> path_cleaners; \n    // visited_states_map maps (cleaner_id, count_parity) -> week_idx (the first week_idx this state was observed)\n    std::map<std::pair<int, int>, int> visited_states_map; \n\n    for (int week_idx = 0; week_idx < L; ++week_idx) {\n        int cleaner_for_this_week = current_cleaner;\n        counts_in_sim[cleaner_for_this_week]++; // Increment count for the current cleaner\n        path_cleaners.push_back(cleaner_for_this_week); // Record this week's cleaner\n\n        // A state is defined by (employee who just finished cleaning, their total cleaning count parity)\n        std::pair<int, int> state_after_cleaning = {cleaner_for_this_week, counts_in_sim[cleaner_for_this_week] % 2};\n\n        // Check if this state has been visited before, indicating a cycle\n        if (visited_states_map.count(state_after_cleaning)) {\n            int cycle_start_idx = visited_states_map[state_after_cleaning]; // Index where the cycle began\n            int cycle_length = week_idx - cycle_start_idx + 1;             // Length of the detected cycle\n\n            // Step 1: Accumulate counts for the pre-cycle part (weeks 0 to cycle_start_idx-1)\n            for (int i = 0; i < cycle_start_idx; ++i) {\n                actual_final_counts[path_cleaners[i]]++;\n            }\n\n            // Step 2: Calculate cleaning counts within one full cycle period\n            std::vector<long long> cycle_counts_one_period(N, 0);\n            for (int i = cycle_start_idx; i <= week_idx; ++i) {\n                cycle_counts_one_period[path_cleaners[i]]++;\n            }\n\n            // Step 3: Distribute remaining weeks using the cycle counts\n            // Total weeks that need to be covered by the cycle from cycle_start_idx until L\n            long long remaining_weeks_to_fill_from_cycle_start = L - cycle_start_idx;\n            \n            if (cycle_length > 0) { // Safety check to prevent division by zero, though cycle_length should always be > 0\n                // Add full cycles\n                long long num_full_cycles = remaining_weeks_to_fill_from_cycle_start / cycle_length;\n                for (int i = 0; i < N; ++i) {\n                    actual_final_counts[i] += num_full_cycles * cycle_counts_one_period[i];\n                }\n                // Add remaining part of a partial cycle at the very end\n                long long remaining_in_partial_cycle = remaining_weeks_to_fill_from_cycle_start % cycle_length;\n                for (int i = 0; i < remaining_in_partial_cycle; ++i) {\n                    actual_final_counts[path_cleaners[cycle_start_idx + i]]++;\n                }\n            }\n            \n            // All L weeks have been accounted for, so we can exit the simulation\n            goto end_simulation; \n        }\n        \n        // If no cycle detected yet, record the current state and its week index\n        visited_states_map[state_after_cleaning] = week_idx;\n\n        // Determine the next cleaner based on current cleaner's count parity and assignments\n        if (counts_in_sim[cleaner_for_this_week] % 2 != 0) { // If total count is odd\n            current_cleaner = assignments[cleaner_for_this_week].first;\n        } else { // If total count is even\n            current_cleaner = assignments[cleaner_for_this_week].second;\n        }\n    }\n\n    // This block is reached if the loop completes without finding a cycle.\n    // This happens if L is small enough that no state repeats, or if L happens to be exactly the pre-cycle length.\n    // In this case, 'path_cleaners' contains the cleaners for all L weeks, and their counts\n    // haven't been added to 'actual_final_counts' yet.\n    for (int i = 0; i < L; ++i) {\n        actual_final_counts[path_cleaners[i]]++;\n    }\n\nend_simulation:; // Label for goto\n\n    // Calculate the total absolute error\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += std::abs(actual_final_counts[i] - T[i]);\n    }\n    return error;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_val, L_val; // Use different variable names to avoid potential shadowing\n    std::cin >> N_val >> L_val;\n\n    std::vector<int> T(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        std::cin >> T[i];\n    }\n\n    std::vector<std::pair<int, int>> best_assignments(N_val);\n    std::vector<std::pair<int, int>> current_assignments(N_val);\n\n    // Initial random assignments for a_i and b_i\n    std::uniform_int_distribution<int> dist_N(0, N_val - 1); // For picking employee IDs [0, N-1]\n    for (int i = 0; i < N_val; ++i) {\n        current_assignments[i] = {dist_N(rng), dist_N(rng)};\n    }\n\n    // Calculate initial state error\n    long long current_error = calculate_error(N_val, L_val, T, current_assignments);\n    long long best_error = current_error;\n    best_assignments = current_assignments; // Deep copy the initial best state\n\n    // Simulated Annealing parameters\n    double start_temp = 2000.0; // Initial temperature (can be tuned)\n    double end_temp = 0.01;     // Final temperature (can be tuned)\n    int iteration_limit = 1000000; // Maximum number of SA iterations (will be capped by time)\n    \n    auto start_time = std::chrono::high_resolution_clock::now();\n    long long time_limit_ms = 1900; // Allot 1.9 seconds for computation, leave 0.1s buffer\n\n    for (int iter = 0; iter < iteration_limit; ++iter) {\n        // Check elapsed time to ensure compliance with the time limit\n        auto current_time = std::chrono::high_resolution_clock::now();\n        long long elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break; // Exit SA loop if time limit approached\n        }\n\n        // Geometric cooling schedule for temperature\n        double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / iteration_limit);\n        \n        // Generate a neighbor state by modifying one a_i or b_i\n        int employee_to_change = dist_N(rng); // Randomly pick an employee\n        bool change_first_val = (rng() % 2 == 0); // Randomly decide to change a_i (true) or b_i (false)\n        \n        // Store the original value to allow reverting if the move is not accepted\n        int original_val_to_revert;\n        if (change_first_val) {\n            original_val_to_revert = current_assignments[employee_to_change].first;\n            current_assignments[employee_to_change].first = dist_N(rng); // Propose a new random value\n        } else {\n            original_val_to_revert = current_assignments[employee_to_change].second;\n            current_assignments[employee_to_change].second = dist_N(rng); // Propose a new random value\n        }\n\n        // Calculate the error for the new (modified) assignments\n        long long next_error = calculate_error(N_val, L_val, T, current_assignments);\n\n        if (next_error < current_error) {\n            // If the new solution is better, always accept it\n            current_error = next_error;\n            if (next_error < best_error) {\n                // If it's the best solution found so far, update best_assignments\n                best_error = next_error;\n                best_assignments = current_assignments; // Deep copy\n            }\n        } else {\n            // If the new solution is worse, accept it with a certain probability\n            double probability = std::exp(-(static_cast<double>(next_error - current_error)) / temp);\n            std::uniform_real_distribution<double> dist_real(0.0, 1.0); // For generating a random probability\n            if (dist_real(rng) < probability) {\n                current_error = next_error; // Accept the worse solution\n            } else {\n                // If the worse solution is not accepted, revert the change\n                if (change_first_val) {\n                    current_assignments[employee_to_change].first = original_val_to_revert;\n                } else {\n                    current_assignments[employee_to_change].second = original_val_to_revert;\n                }\n            }\n        }\n    }\n\n    // Output the best assignments found after the SA process\n    for (int i = 0; i < N_val; ++i) {\n        std::cout << best_assignments[i].first << \" \" << best_assignments[i].second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::sqrt, std::floor, std::ceil, std::max\n\n// Structure to hold city bounding box\nstruct Rect {\n    int lx, rx, ly, ry;\n};\n\n// Structure to hold city data\nstruct City {\n    int id;\n    int cx, cy; // Center coordinates, using integer division for consistency with sample\n    unsigned int z_order_val; // Z-order curve value for sorting\n    Rect bounds;\n};\n\n// Disjoint Set Union structure for Kruskal's algorithm\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) return i;\n        return parent[i] = find(parent[i]);\n    }\n    bool 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            return true;\n        }\n        return false;\n    }\n};\n\n// Edge structure for Kruskal's\nstruct Edge {\n    int u, v;\n    std::pair<int, long long> weight; // rank (0=queried, 1=estimated), estimated_dist_sq\n};\n\n// Helper for Z-order curve: bit interleaving (Morton code)\n// Optimized for 16-bit inputs (max value 65535) resulting in 32-bit output.\n// Coordinates up to 10000 fit into 14 bits.\n// For example, an input of 10000 will have its 14 bits interleaved into a 32-bit output.\nunsigned int morton_encode(unsigned int x, unsigned int y) {\n    x = (x | (x << 8)) & 0x00FF00FF;\n    x = (x | (x << 4)) & 0x0F0F0F0F;\n    x = (x | (x << 2)) & 0x33333333;\n    x = (x | (x << 1)) & 0x55555555;\n    y = (y | (y << 8)) & 0x00FF00FF;\n    y = (y | (y << 4)) & 0x0F0F0F0F;\n    y = (y | (y << 2)) & 0x33333333;\n    y = (y | (y << 1)) & 0x55555555;\n    return x | (y << 1);\n}\n\n// Functions to calculate min/max squared distance components along one axis\nlong long calc_min_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff;\n    if (r1_max < r2_min) { // Rect 1 is entirely before Rect 2 on this axis\n        diff = r2_min - r1_max;\n    } else if (r2_max < r1_min) { // Rect 2 is entirely before Rect 1 on this axis\n        diff = r1_min - r2_max;\n    } else { // Rectangles overlap on this axis\n        diff = 0;\n    }\n    return diff * diff;\n}\n\nlong long calc_max_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff1 = (long long)r1_max - r2_min;\n    long long diff2 = (long long)r2_max - r1_min;\n    return std::max(diff1 * diff1, diff2 * diff2);\n}\n\n// Function to calculate estimated squared distance using min/max bounds range midpoint\nlong long estimated_dist_mid_range_sq(int u_id, int v_id, const std::vector<City>& cities_data) {\n    const Rect& r_u = cities_data[u_id].bounds;\n    const Rect& r_v = cities_data[v_id].bounds;\n\n    long long min_dx_sq = calc_min_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long min_dy_sq = calc_min_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_min_sq = min_dx_sq + min_dy_sq;\n\n    long long max_dx_sq = calc_max_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long max_dy_sq = calc_max_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_max_sq = max_dx_sq + max_dy_sq;\n\n    // Use the midpoint of the possible squared distance range\n    return (d_min_sq + d_max_sq) / 2;\n}\n\n\n// Function to make a query to the judge\nstd::vector<std::pair<int, int>> make_query(const std::vector<int>& c_subset) {\n    std::cout << \"? \" << c_subset.size();\n    for (int city_id : c_subset) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl; // Flush!\n\n    std::vector<std::pair<int, int>> result;\n    result.reserve(c_subset.size() - 1);\n    for (size_t i = 0; i < c_subset.size() - 1; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        if (u > v) std::swap(u, v); // Ensure canonical form (u < v)\n        result.push_back({u, v});\n    }\n    return result;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL); // Untie cin and cout for faster I/O, though flushing is still needed for queries\n\n    int N, M, Q, L_actual, W;\n    std::cin >> N >> M >> Q >> L_actual >> 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_data(N);\n    for (int i = 0; i < N; ++i) {\n        cities_data[i].id = i;\n        std::cin >> cities_data[i].bounds.lx >> cities_data[i].bounds.rx >> cities_data[i].bounds.ly >> cities_data[i].bounds.ry;\n        \n        // Use center for Z-order calculation as well\n        cities_data[i].cx = (cities_data[i].bounds.lx + cities_data[i].bounds.rx) / 2;\n        cities_data[i].cy = (cities_data[i].bounds.ly + cities_data[i].bounds.ry) / 2;\n        cities_data[i].z_order_val = morton_encode(cities_data[i].cx, cities_data[i].cy);\n    }\n\n    // 1. Initial Grouping: Sort by Z-order curve value\n    std::vector<int> p(N); // p stores sorted city IDs\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return cities_data[i].z_order_val < cities_data[j].z_order_val;\n    });\n\n    std::vector<std::vector<int>> tentative_groups(M);\n    int current_city_idx_p = 0;\n    for (int k = 0; k < M; ++k) {\n        tentative_groups[k].reserve(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            tentative_groups[k].push_back(p[current_city_idx_p++]);\n        }\n    }\n\n    // 2. Query Phase\n    std::set<std::pair<int, int>> queried_edges;\n    int Q_rem = Q;\n\n    // Phase 1: Query small groups entirely\n    for (int k = 0; k < M; ++k) {\n        if (G[k] >= 2 && G[k] <= L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k]; // Use const ref\n            std::vector<std::pair<int, int>> res_edges = make_query(current_group);\n            for (auto edge : res_edges) {\n                queried_edges.insert(edge);\n            }\n            Q_rem--;\n        }\n    }\n\n    // Phase 2: Query large groups with adaptive step_size\n    long long num_chunks_to_query_if_step1 = 0; // Total count of (G_k - L_actual + 1) for large groups\n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual) { // This condition ensures G[k] >= L_actual + 1, so G[k] - L_actual >= 1\n            num_chunks_to_query_if_step1 += (G[k] - L_actual + 1);\n        }\n    }\n\n    int step_size = 1;\n    if (Q_rem > 0 && num_chunks_to_query_if_step1 > 0) {\n        // Calculate step_size to distribute Q_rem queries among the total chunks\n        step_size = static_cast<int>(std::ceil(static_cast<double>(num_chunks_to_query_if_step1) / Q_rem));\n        step_size = std::max(1, step_size); // Ensure step_size is at least 1\n    } else {\n        step_size = N + 1; // Effectively skip this phase if no queries left or no large groups to query\n    }\n    \n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k];\n            int last_queried_start = -1; // To track the starting index of the last query made\n            \n            for (int i = 0; i <= (int)current_group.size() - L_actual; i += step_size) {\n                if (Q_rem <= 0) break;\n                \n                std::vector<int> c_subset;\n                c_subset.reserve(L_actual);\n                for (int j = 0; j < L_actual; ++j) {\n                    c_subset.push_back(current_group[i+j]);\n                }\n                \n                std::vector<std::pair<int, int>> res_edges = make_query(c_subset);\n                for (auto edge : res_edges) {\n                    queried_edges.insert(edge);\n                }\n                Q_rem--;\n                last_queried_start = i;\n            }\n\n            // Handle cities at the end of the group that might not have been fully covered\n            // Query the last L_actual cities if the last possible window was not queried\n            // and we still have queries left.\n            if (Q_rem > 0) { // Check Q_rem again\n                int ideal_last_start_idx = (int)current_group.size() - L_actual;\n                if (ideal_last_start_idx >= 0 && last_queried_start != ideal_last_start_idx) { // Ensure ideal_last_start_idx is valid\n                    std::vector<int> c_subset_end;\n                    c_subset_end.reserve(L_actual);\n                    for(int j = ideal_last_start_idx; j < current_group.size(); ++j) {\n                        c_subset_end.push_back(current_group[j]);\n                    }\n                    if (c_subset_end.size() >= 2) { // Ensure minimum size for query\n                        std::vector<std::pair<int, int>> res_edges = make_query(c_subset_end);\n                        for (auto edge : res_edges) {\n                            queried_edges.insert(edge);\n                        }\n                        Q_rem--;\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Output Phase\n    std::cout << \"!\" << std::endl;\n\n    for (int k = 0; k < M; ++k) {\n        // Output cities in group k\n        for (int i = 0; i < G[k]; ++i) {\n            std::cout << tentative_groups[k][i] << (i == G[k] - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] == 1) { // A single city group needs no roads\n            continue;\n        }\n\n        // Prepare edges for MST\n        std::vector<Edge> edges_for_mst;\n        const std::vector<int>& current_group = tentative_groups[k];\n        \n        // Create all possible edges within the group\n        for (size_t i = 0; i < current_group.size(); ++i) {\n            for (size_t j = i + 1; j < current_group.size(); ++j) {\n                int u = current_group[i];\n                int v = current_group[j];\n                \n                // Ensure u < v for canonical form (matches queried_edges)\n                if (u > v) std::swap(u, v); \n                \n                int rank = 1; // 1 for estimated, 0 for queried\n                if (queried_edges.count({u, v})) {\n                    rank = 0;\n                }\n                \n                long long dist_sq = estimated_dist_mid_range_sq(u, v, cities_data); // Use new estimation\n                edges_for_mst.push_back({u, v, {rank, dist_sq}});\n            }\n        }\n\n        // Sort edges\n        std::sort(edges_for_mst.begin(), edges_for_mst.end(), [](const Edge& a, const Edge& b) {\n            if (a.weight.first != b.weight.first) {\n                return a.weight.first < b.weight.first;\n            }\n            // Tie-break with estimated squared distance\n            if (a.weight.second != b.weight.second) {\n                return a.weight.second < b.weight.second;\n            }\n            // Final tie-break with lexicographical order of cities\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Run Kruskal's\n        DSU dsu(N); // Initialize DSU for all N cities for simplicity\n        std::vector<std::pair<int, int>> mst_output_edges;\n        int edges_count = 0;\n        for (const auto& edge : edges_for_mst) {\n            if (edges_count == G[k] - 1) break; // Found enough edges\n            \n            if (dsu.unite(edge.u, edge.v)) {\n                mst_output_edges.push_back({edge.u, edge.v});\n                edges_count++;\n            }\n        }\n\n        // Output MST edges (lexicographically within group, as required by problem)\n        std::sort(mst_output_edges.begin(), mst_output_edges.end());\n        for (const auto& edge : mst_output_edges) {\n            std::cout << edge.first << \" \" << edge.second << std::endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int N_SIZE = 20;\n\n// Directions for movement and alter actions\n// Corresponding to U, D, L, R\nint DR[] = {-1, 1, 0, 0}; \nint DC[] = {0, 0, -1, 1}; \nchar DIR_CHARS[] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int r, c;\n    int cost;\n\n    // Custom comparator for priority queue (min-heap)\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Enum to categorize the type of action that led to a state\nenum ActionType {\n    MOVE,\n    MOVE_REMOVE_BLOCK,    // Move into a square that was blocked, removing the block first\n    SLIDE_WALL,           // Slide, stopping because of an N x N boundary wall\n    SLIDE_EXISTING_BLOCK  // Slide, stopping because of an existing block\n};\n\n// Information to reconstruct the path\nstruct ParentInfo {\n    int pr, pc; // previous row, previous column\n    ActionType type;\n    char dir_char; // direction character for the action (U, D, L, R)\n    int br, bc;   // block row, block column (relevant for SLIDE_EXISTING_BLOCK or MOVE_REMOVE_BLOCK)\n                  // For SLIDE_WALL, it's (-1,-1).\n};\n\n// Global board state, tracks currently existing blocks\nset<pair<int, int>> current_blocks;\n\n// Helper function to check if coordinates are within grid bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_SIZE && c >= 0 && c < N_SIZE;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M; // N will be 20, M will be 40 as per problem statement\n    cin >> N >> M;\n\n    vector<pair<int, int>> targets(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> targets[k].first >> targets[k].second;\n    }\n\n    vector<pair<char, char>> all_actions; // Stores the final sequence of actions to output\n\n    int current_r = targets[0].first;\n    int current_c = targets[0].second;\n\n    // Iterate through each target segment (from current_pos to next target)\n    for (int k = 0; k < M - 1; ++k) {\n        int start_r = current_r;\n        int start_c = current_c;\n        int target_r = targets[k+1].first;\n        int target_c = targets[k+1].second;\n\n        // Dijkstra's algorithm for shortest path in terms of turns\n        vector<vector<int>> dist(N, vector<int>(N, INF));\n        vector<vector<ParentInfo>> parent(N, vector<ParentInfo>(N)); \n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[start_r][start_c] = 0;\n        pq.push({start_r, start_c, 0});\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n            int d = current.cost;\n\n            // If we found a shorter path previously, skip this one\n            if (d > dist[r][c]) {\n                continue;\n            }\n            // If we reached the target, we found the shortest path for this segment\n            if (r == target_r && c == target_c) {\n                break; \n            }\n\n            // --- Explore possible Move actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                if (!is_valid(nr, nc)) continue; // Check bounds\n\n                int cost = 0;\n                ActionType type;\n                if (current_blocks.count({nr, nc})) {\n                    // Moving onto a square that currently has a block.\n                    // This costs 1 for Alter (to remove the block) + 1 for Move. Total 2 turns.\n                    cost = 2;\n                    type = MOVE_REMOVE_BLOCK;\n                } else {\n                    // Moving onto an empty square. Costs 1 for Move.\n                    cost = 1;\n                    type = MOVE;\n                }\n\n                if (d + cost < dist[nr][nc]) {\n                    dist[nr][nc] = d + cost;\n                    parent[nr][nc] = {r, c, type, dir_char, nr, nc}; // br, bc store coord of block removed for MOVE_REMOVE_BLOCK\n                    pq.push({nr, nc, d + cost});\n                }\n            }\n\n            // --- Explore possible Slide actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int dr = DR[i];\n                int dc = DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                int current_slide_r = r;\n                int current_slide_c = c;\n                \n                // This loop finds all possible valid stopping points for a slide in a given direction.\n                while (true) {\n                    // Tentatively advance one step to find the next square the slide *could* reach.\n                    int next_r = current_slide_r + dr;\n                    int next_c = current_slide_c + dc;\n\n                    // If the next square is out of bounds or blocked by an existing block,\n                    // we cannot slide *into* it. Thus, current_slide_r,c is a potential stopping point.\n                    if (!is_valid(next_r, next_c) || current_blocks.count({next_r, next_c})) {\n                        // We can only stop at current_slide_r,c if we've actually moved.\n                        // If current_slide_r,c is still (r,c), it means we can't even slide one square.\n                        if (current_slide_r == r && current_slide_c == c) {\n                             break; // Cannot slide even one square, no valid stops in this direction.\n                        }\n\n                        // current_slide_r,c is a valid stopping square.\n                        int stop_r = current_slide_r;\n                        int stop_c = current_slide_c;\n                        \n                        // The \"stopper\" is either the boundary or the existing block at (next_r, next_c)\n                        int stopper_block_r = next_r;\n                        int stopper_block_c = next_c;\n\n                        int slide_cost = 1; // All valid slides cost 1 turn\n                        ActionType type;\n\n                        if (!is_valid(stopper_block_r, stopper_block_c)) {\n                            type = SLIDE_WALL;\n                            stopper_block_r = -1; stopper_block_c = -1; // Sentinel\n                        } else { // It must be an existing block at (stopper_block_r, stopper_block_c)\n                            type = SLIDE_EXISTING_BLOCK;\n                        }\n\n                        if (d + slide_cost < dist[stop_r][stop_c]) {\n                            dist[stop_r][stop_c] = d + slide_cost;\n                            parent[stop_r][stop_c] = {r, c, type, dir_char, stopper_block_r, stopper_block_c};\n                            pq.push({stop_r, stop_c, d + slide_cost});\n                        }\n                        break; // This slide path ends here, either at boundary or existing block\n                    }\n\n                    // If next_r,c is valid and not blocked, we slide past current_slide_r,c.\n                    // So, current_slide_r,c itself cannot be a stopping point (because nothing stops us there).\n                    // Update current_slide_r,c to next_r,c and continue to find further stops.\n                    current_slide_r = next_r;\n                    current_slide_c = next_c;\n                }\n            }\n        }\n\n        // --- Path reconstruction and action recording ---\n        vector<tuple<int,int,ActionType,char,int,int>> path_segments_info;\n        int curr_r = target_r;\n        int curr_c = target_c;\n\n        // Traverse parent pointers backwards from target to start, storing segment info.\n        // This gives actions in reverse order of execution.\n        while (curr_r != start_r || curr_c != start_c) {\n            ParentInfo p = parent[curr_r][curr_c];\n            path_segments_info.emplace_back(p.pr, p.pc, p.type, p.dir_char, p.br, p.bc);\n            curr_r = p.pr;\n            curr_c = p.pc;\n        }\n        // Reverse to get actions in the correct execution order.\n        reverse(path_segments_info.begin(), path_segments_info.end()); \n\n        // Process each action segment in forward order and update global blocks and the action list\n        for (const auto& info : path_segments_info) {\n            int pr, pc, br, bc;\n            ActionType type;\n            char dir_char;\n            tie(pr, pc, type, dir_char, br, bc) = info;\n\n            if (type == MOVE) {\n                all_actions.emplace_back('M', dir_char);\n            } else if (type == MOVE_REMOVE_BLOCK) {\n                all_actions.emplace_back('A', dir_char); // First Alter to remove block at (br,bc)\n                current_blocks.erase({br, bc});           // Update global block state (remove it)\n                all_actions.emplace_back('M', dir_char); // Then Move\n            } else if (type == SLIDE_WALL || type == SLIDE_EXISTING_BLOCK) {\n                // No Alter action needed for these slide types, just the Slide itself.\n                // The block for SLIDE_EXISTING_BLOCK is already there and isn't toggled by us.\n                all_actions.emplace_back('S', dir_char);\n            }\n        }\n\n        // Update current player position for the next segment\n        current_r = target_r;\n        current_c = target_c;\n    }\n    \n    // Output all recorded actions\n    for (const auto& action : all_actions) {\n        cout << action.first << \" \" << action.second << endl;\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // for std::iota\n\n// Use a custom random number generator for better control and performance\nstd::mt19937_64 mt_rand(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Company data structure\nstruct Company {\n    int id;\n    int x, y, r; // desired location (cell x,y) and desired area\n};\n\n// Rectangle structure\nstruct Rect {\n    int x1, y1, x2, y2; // [x1, x2) x [y1, y2)\n    long long area() const {\n        return (long long)(x2 - x1) * (y2 - y1);\n    }\n    // Check if point (px, py) is contained (for 0.5 offset points, this means cell (px, py) is contained)\n    bool contains(int px, int py) const {\n        return x1 <= px && px < x2 && y1 <= py && py < y2;\n    }\n};\n\n// Node in the D&C tree\nstruct Node {\n    Rect rect; // The bounding box for this node\n    bool is_leaf;\n    int company_id; // Valid if is_leaf is true, stores original company index\n    bool is_vertical_cut; // True for vertical, false for horizontal\n    int cut_coord; // The coordinate of the cut\n    std::vector<int> company_indices; // Indices of companies that fall into this node's rectangle\n    int parent_idx; // Index to parent node\n    int left_child_idx; // Index to left/bottom child\n    int right_child_idx; // Index to right/top child\n\n    // Added fields for SA optimization: min/max coordinates of companies in children subtrees\n    // Initialized to values outside 0-9999 range to correctly find min/max\n    int left_comp_min_x, left_comp_max_x;\n    int left_comp_min_y, left_comp_max_y;\n    int right_comp_min_x, right_comp_max_x;\n    int right_comp_min_y, right_comp_max_y;\n\n    Node(Rect r, bool leaf, int id, const std::vector<int>& indices)\n        : rect(r), is_leaf(leaf), company_id(id), is_vertical_cut(false), cut_coord(-1),\n          company_indices(indices), parent_idx(-1), left_child_idx(-1), right_child_idx(-1),\n          left_comp_min_x(10001), left_comp_max_x(-1), left_comp_min_y(10001), left_comp_max_y(-1),\n          right_comp_min_x(10001), right_comp_max_x(-1), right_comp_min_y(10001), right_comp_max_y(-1) {}\n};\n\nstd::vector<Company> companies_data;\nstd::vector<Rect> final_ad_rects;\nstd::vector<Node> tree_nodes;\nint N_global;\nstd::vector<int> internal_node_indices; // To store indices of internal nodes for SA\n\n// Calculate satisfaction for a single company\ndouble calculate_satisfaction(const Company& company, const Rect& ad_rect) {\n    if (!ad_rect.contains(company.x, company.y)) {\n        return 0.0;\n    }\n    long long s_i = ad_rect.area();\n    long long r_i = company.r;\n    if (s_i == 0) return 0.0; // Area must be positive as per problem statement\n    double ratio = (double)std::min(r_i, s_i) / std::max(r_i, s_i);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Helper function to collect company IDs in a subtree\nvoid get_companies_in_subtree(int node_idx, std::vector<int>& company_ids_in_subtree) {\n    const Node& node = tree_nodes[node_idx];\n    if (node.is_leaf) {\n        if (node.company_id != -1) {\n            company_ids_in_subtree.push_back(node.company_id);\n        }\n        return;\n    }\n    get_companies_in_subtree(node.left_child_idx, company_ids_in_subtree);\n    get_companies_in_subtree(node.right_child_idx, company_ids_in_subtree);\n}\n\n// Recursive function to build the D&C tree and determine initial rectangle placements\nvoid build_tree_and_solve(int node_idx, int x1, int y1, int x2, int y2, std::vector<int>&& indices) {\n    tree_nodes[node_idx].rect = {x1, y1, x2, y2};\n    tree_nodes[node_idx].company_indices = indices; // Store indices for SA bounds calculation later\n\n    if (indices.empty()) {\n        tree_nodes[node_idx].is_leaf = true; // Mark as leaf, no company\n        return;\n    }\n    if (indices.size() == 1) {\n        tree_nodes[node_idx].is_leaf = true;\n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n    \n    // This is an internal node\n    internal_node_indices.push_back(node_idx);\n\n    int best_v_cut_coord = -1;\n    long long min_v_area_diff = -1;\n    int best_v_split_point_idx = -1;\n\n    int best_h_cut_coord = -1;\n    long long min_h_area_diff = -1;\n    int best_h_split_point_idx = -1;\n\n    long long total_r_sum = 0;\n    for (int idx : indices) total_r_sum += companies_data[idx].r;\n\n    // Try Vertical Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].x < companies_data[j].x;\n    });\n    long long current_left_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_left_r_sum += companies_data[indices[k]].r;\n        int max_x_left_group = companies_data[indices[k]].x;\n        int min_x_right_group = companies_data[indices[k+1]].x;\n        \n        // The cut coordinate `C` must satisfy: max_x_left_group < C <= min_x_right_group\n        // And also `x1 < C < x2`\n        int candidate_cut_coord = max_x_left_group + 1;\n        \n        if (candidate_cut_coord > min_x_right_group || candidate_cut_coord < x1 + 1 || candidate_cut_coord > x2 - 1) {\n             continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_left_r_sum - (total_r_sum - current_left_r_sum));\n        if (best_v_cut_coord == -1 || diff < min_v_area_diff) {\n            min_v_area_diff = diff;\n            best_v_cut_coord = candidate_cut_coord;\n            best_v_split_point_idx = k + 1;\n        }\n    }\n\n    // Try Horizontal Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data[i].y < companies_data[j].y;\n    });\n    long long current_bottom_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_bottom_r_sum += companies_data[indices[k]].r;\n        int max_y_bottom_group = companies_data[indices[k]].y;\n        int min_y_top_group = companies_data[indices[k+1]].y;\n        \n        int candidate_cut_coord = max_y_bottom_group + 1;\n\n        if (candidate_cut_coord > min_y_top_group || candidate_cut_coord < y1 + 1 || candidate_cut_coord > y2 - 1) {\n            continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_bottom_r_sum - (total_r_sum - current_bottom_r_sum));\n        if (best_h_cut_coord == -1 || diff < min_h_area_diff) {\n            min_h_area_diff = diff;\n            best_h_cut_coord = candidate_cut_coord;\n            best_h_split_point_idx = k + 1;\n        }\n    }\n    \n    // Choose the best cut among vertical and horizontal\n    int final_cut_coord = -1;\n    int final_split_point_idx = -1;\n    bool is_vertical_cut_chosen = false;\n\n    // Random choice if area differences are equal for v/h cuts\n    std::uniform_int_distribution<int> dist_01_int(0, 1);\n\n    if (best_v_cut_coord != -1 && best_h_cut_coord != -1) {\n        if (min_v_area_diff < min_h_area_diff) {\n            final_cut_coord = best_v_cut_coord;\n            final_split_point_idx = best_v_split_point_idx;\n            is_vertical_cut_chosen = true;\n        } else if (min_h_area_diff < min_v_area_diff) {\n            final_cut_coord = best_h_cut_coord;\n            final_split_point_idx = best_h_split_point_idx;\n            is_vertical_cut_chosen = false;\n        } else { // min_v_area_diff == min_h_area_diff: random choice\n            if (dist_01_int(mt_rand) == 0) { // 50/50 chance\n                final_cut_coord = best_v_cut_coord;\n                final_split_point_idx = best_v_split_point_idx;\n                is_vertical_cut_chosen = true;\n            } else {\n                final_cut_coord = best_h_cut_coord;\n                final_split_point_idx = best_h_split_point_idx;\n                is_vertical_cut_chosen = false;\n            }\n        }\n    } else if (best_v_cut_coord != -1) {\n        final_cut_coord = best_v_cut_coord;\n        final_split_point_idx = best_v_split_point_idx;\n        is_vertical_cut_chosen = true;\n    } else if (best_h_cut_coord != -1) {\n        final_cut_coord = best_h_cut_coord;\n        final_split_point_idx = best_h_split_point_idx;\n        is_vertical_cut_chosen = false;\n    } else {\n        // Fallback: If no valid cut is found, assign the entire region to the first company.\n        // This should only happen for very small regions or degenerate point distributions\n        // where it's impossible to make a valid cut for multiple companies.\n        tree_nodes[node_idx].is_leaf = true; \n        tree_nodes[node_idx].company_id = indices[0];\n        final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    tree_nodes[node_idx].cut_coord = final_cut_coord;\n    tree_nodes[node_idx].is_vertical_cut = is_vertical_cut_chosen;\n\n    // Re-sort indices based on the chosen cut dimension for partitioning\n    if (is_vertical_cut_chosen) {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].x < companies_data[j].x;\n        });\n    } else {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data[i].y < companies_data[j].y;\n        });\n    }\n\n    std::vector<int> left_indices(indices.begin(), indices.begin() + final_split_point_idx);\n    std::vector<int> right_indices(indices.begin() + final_split_point_idx, indices.end());\n\n    tree_nodes[node_idx].left_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    tree_nodes[node_idx].right_child_idx = tree_nodes.size();\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    tree_nodes.back().parent_idx = node_idx;\n\n    if (is_vertical_cut_chosen) {\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, final_cut_coord, y2, std::move(left_indices));\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, final_cut_coord, y1, x2, y2, std::move(right_indices));\n    } else { // Horizontal cut\n        build_tree_and_solve(tree_nodes[node_idx].left_child_idx, x1, y1, x2, final_cut_coord, std::move(left_indices)); // 'left' means bottom here\n        build_tree_and_solve(tree_nodes[node_idx].right_child_idx, x1, final_cut_coord, x2, y2, std::move(right_indices)); // 'right' means top here\n    }\n}\n\n// Function to calculate and store min/max company coordinates for children\nvoid calculate_child_company_bounds_recursive(int node_idx) {\n    Node& node = tree_nodes[node_idx];\n\n    if (node.is_leaf) {\n        return;\n    }\n\n    // Recursively call for children first (post-order traversal)\n    calculate_child_company_bounds_recursive(node.left_child_idx);\n    calculate_child_company_bounds_recursive(node.right_child_idx);\n\n    // Calculate bounds for left child's companies\n    int current_min_x_left = 10001, current_max_x_left = -1;\n    int current_min_y_left = 10001, current_max_y_left = -1;\n    for (int company_idx : tree_nodes[node.left_child_idx].company_indices) {\n        current_min_x_left = std::min(current_min_x_left, companies_data[company_idx].x);\n        current_max_x_left = std::max(current_max_x_left, companies_data[company_idx].x);\n        current_min_y_left = std::min(current_min_y_left, companies_data[company_idx].y);\n        current_max_y_left = std::max(current_max_y_left, companies_data[company_idx].y);\n    }\n    node.left_comp_min_x = current_min_x_left;\n    node.left_comp_max_x = current_max_x_left;\n    node.left_comp_min_y = current_min_y_left;\n    node.left_comp_max_y = current_max_y_left;\n\n    // Calculate bounds for right child's companies\n    int current_min_x_right = 10001, current_max_x_right = -1;\n    int current_min_y_right = 10001, current_max_y_right = -1;\n    for (int company_idx : tree_nodes[node.right_child_idx].company_indices) {\n        current_min_x_right = std::min(current_min_x_right, companies_data[company_idx].x);\n        current_max_x_right = std::max(current_max_x_right, companies_data[company_idx].x);\n        current_min_y_right = std::min(current_min_y_right, companies_data[company_idx].y);\n        current_max_y_right = std::max(current_max_y_right, companies_data[company_idx].y);\n    }\n    node.right_comp_min_x = current_min_x_right;\n    node.right_comp_max_x = current_max_x_right;\n    node.right_comp_min_y = current_min_y_right;\n    node.right_comp_max_y = current_max_y_right;\n}\n\n// Function to update rectangles in a subtree after a cut coordinate changes\nvoid update_subtree_rects(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = tree_nodes[node_idx];\n    node.rect = {x1, y1, x2, y2};\n\n    if (node.is_leaf) {\n        if (node.company_id != -1) { \n            final_ad_rects[node.company_id] = {x1, y1, x2, y2};\n        }\n        return;\n    }\n\n    if (node.is_vertical_cut) {\n        update_subtree_rects(node.left_child_idx, x1, y1, node.cut_coord, y2);\n        update_subtree_rects(node.right_child_idx, node.cut_coord, y1, x2, y2);\n    } else { // Horizontal cut\n        update_subtree_rects(node.left_child_idx, x1, y1, x2, node.cut_coord);\n        update_subtree_rects(node.right_child_idx, x1, node.cut_coord, x2, y2);\n    }\n}\n\nvoid simulated_annealing(double time_limit_ms) {\n    auto start_time = std::chrono::steady_clock::now();\n    \n    // Calculate initial score once here\n    double current_score = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        current_score += calculate_satisfaction(companies_data[i], final_ad_rects[i]);\n    }\n\n    double best_score = current_score;\n    std::vector<Rect> best_ad_rects = final_ad_rects;\n\n    // SA parameters (tuned values)\n    double T_start = 0.2; // Adjusted based on typical score delta\n    double T_end = 1e-9;\n    \n    std::uniform_real_distribution<double> dist_01(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_internal_node_idx(0, internal_node_indices.size() - 1);\n\n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms >= time_limit_ms) {\n            break;\n        }\n\n        // Cooling schedule (exponential)\n        double T = T_start * std::pow(T_end / T_start, elapsed_ms / time_limit_ms);\n\n        // Pick a random internal node to modify its cut\n        int node_idx_to_modify = internal_node_indices[dist_internal_node_idx(mt_rand)];\n        Node& node_to_modify = tree_nodes[node_idx_to_modify];\n        \n        // Parent's rect boundaries are stored in node_to_modify.rect\n        int parent_x1 = node_to_modify.rect.x1;\n        int parent_y1 = node_to_modify.rect.y1;\n        int parent_x2 = node_to_modify.rect.x2;\n        int parent_y2 = node_to_modify.rect.y2;\n        \n        int min_cut_coord_bound, max_cut_coord_bound;\n\n        if (node_to_modify.is_vertical_cut) {\n            // Use precomputed bounds\n            // If left_comp_max_x is -1, means no companies in left child, so it doesn't constrain\n            int max_x_in_left_subtree = node_to_modify.left_comp_max_x;\n            // If right_comp_min_x is 10001, means no companies in right child, so it doesn't constrain\n            int min_x_in_right_subtree = node_to_modify.right_comp_min_x;\n            \n            min_cut_coord_bound = std::max(parent_x1 + 1, max_x_in_left_subtree + 1);\n            max_cut_coord_bound = std::min(parent_x2 - 1, min_x_in_right_subtree);\n\n        } else { // Horizontal cut\n            // Use precomputed bounds\n            int max_y_in_bottom_subtree = node_to_modify.left_comp_max_y; // Left child refers to bottom here\n            int min_y_in_top_subtree = node_to_modify.right_comp_min_y;   // Right child refers to top here\n            \n            min_cut_coord_bound = std::max(parent_y1 + 1, max_y_in_bottom_subtree + 1);\n            max_cut_coord_bound = std::min(parent_y2 - 1, min_y_in_top_subtree);\n        }\n\n        if (min_cut_coord_bound > max_cut_coord_bound) {\n            continue; // Cannot move this cut, its position is fixed by point constraints\n        }\n\n        // Store old cut_coord for backtracking\n        int original_cut_coord = node_to_modify.cut_coord;\n        \n        // Generate new cut_coord randomly within valid range\n        std::uniform_int_distribution<int> dist_cut(min_cut_coord_bound, max_cut_coord_bound);\n        node_to_modify.cut_coord = dist_cut(mt_rand);\n        \n        if (original_cut_coord == node_to_modify.cut_coord) { // If random pick same as old, no change\n            continue;\n        }\n\n        // --- Incremental Score Update ---\n        std::vector<int> affected_company_ids;\n        get_companies_in_subtree(node_idx_to_modify, affected_company_ids);\n        \n        double old_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            old_affected_score_sum += calculate_satisfaction(companies_data[comp_id], final_ad_rects[comp_id]);\n        }\n        \n        // Update rectangles for the subtree\n        update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        \n        double new_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            new_affected_score_sum += calculate_satisfaction(companies_data[comp_id], final_ad_rects[comp_id]);\n        }\n\n        double new_total_score = current_score - old_affected_score_sum + new_affected_score_sum;\n\n        if (new_total_score > current_score || dist_01(mt_rand) < std::exp((new_total_score - current_score) / T)) {\n            // Accept new state\n            current_score = new_total_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ad_rects = final_ad_rects;\n            }\n        } else {\n            // Revert to old state\n            node_to_modify.cut_coord = original_cut_coord;\n            // Revert the rectangles in the subtree to their previous state\n            update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n            // current_score remains unchanged\n        }\n    }\n    \n    final_ad_rects = best_ad_rects;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N_global;\n\n    companies_data.resize(N_global);\n    final_ad_rects.resize(N_global);\n    std::vector<int> initial_company_indices(N_global);\n\n    for (int i = 0; i < N_global; ++i) {\n        companies_data[i].id = i;\n        std::cin >> companies_data[i].x >> companies_data[i].y >> companies_data[i].r;\n        initial_company_indices[i] = i;\n    }\n\n    // Build the initial D&C tree\n    tree_nodes.reserve(2 * N_global); // Max nodes in binary tree is 2N-1\n    tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{}); // Root node\n    \n    build_tree_and_solve(0, 0, 0, 10000, 10000, std::move(initial_company_indices));\n    \n    // Precompute min/max company coordinates for children of each internal node\n    // Only if the root is not a leaf (i.e., N_global > 1)\n    if (!tree_nodes[0].is_leaf) { \n        calculate_child_company_bounds_recursive(0);\n    }\n    \n    // Simulated Annealing\n    // Using 4.9 seconds out of 5.0s total time limit.\n    // Ensure internal_node_indices is not empty before starting SA\n    if (!internal_node_indices.empty()) {\n        simulated_annealing(4900.0); \n    }\n    \n    // Output the results\n    for (int i = 0; i < N_global; ++i) {\n        std::cout << final_ad_rects[i].x1 << \" \" << final_ad_rects[i].y1 << \" \"\n                  << final_ad_rects[i].x2 << \" \" << final_ad_rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <bitset>\n#include <random>\n#include <numeric> // For iota\n#include <tuple>   // For std::tuple\n\n// Using standard namespace for convenience in competitive programming\nusing namespace std;\n\n// Constants\nconst int GRID_SIZE = 50;\nconst int MAX_TILES = GRID_SIZE * GRID_SIZE; // Max possible number of tiles (all 1x1)\n\n// Global variables to store input data\nint si, sj; // Start row, start column\nint tile_id_grid[GRID_SIZE][GRID_SIZE]; // tile_id_grid[i][j] stores the tile ID for square (i,j)\nint p_grid[GRID_SIZE][GRID_SIZE];       // p_grid[i][j] stores the score value for square (i,j)\n\n// Global variables for best path found so far\nlong long max_score_global = 0;\nstring best_path_string_global = \"\";\n\n// Random number generator. Using std::mt19937 for better randomness than rand().\nmt19937 rng;\n\n// Structure to represent a potential move\nstruct Move {\n    int r, c;           // Next square's row and column\n    char move_char;     // Character representing the move ('U', 'D', 'L', 'R')\n    int score_value;    // Score obtained by moving to (r, c)\n    int tile_id;        // Tile ID of the next square\n};\n\n// Function to get all valid next moves from the current position (r, c)\n// A move is valid if it stays within grid boundaries and leads to an unvisited tile.\nvector<Move> get_valid_moves(int r, int c, const bitset<MAX_TILES>& visited_tiles) {\n    vector<Move> valid_moves;\n    // Possible movements: Up, Down, Left, Right\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1}; \n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n\n        // Check if the next position is within grid boundaries\n        if (nr >= 0 && nr < GRID_SIZE && nc >= 0 && nc < GRID_SIZE) {\n            int next_tile_id = tile_id_grid[nr][nc];\n            // Check if the tile has not been visited yet\n            if (!visited_tiles[next_tile_id]) {\n                valid_moves.push_back({nr, nc, move_chars[k], p_grid[nr][nc], next_tile_id});\n            }\n        }\n    }\n    return valid_moves;\n}\n\n// Function to generate a single path using a randomized greedy approach.\n// It stops when no more valid moves are available or the time limit for this path generation is near.\npair<long long, string> generate_path(chrono::high_resolution_clock::time_point global_start_time, chrono::milliseconds total_time_limit) {\n    long long current_score = p_grid[si][sj]; // Start with score of initial square\n    string current_path_str = \"\";\n    bitset<MAX_TILES> visited_tiles; // Keep track of visited tiles\n    visited_tiles[tile_id_grid[si][sj]] = true; // Mark initial tile as visited\n    int curr_r = si;\n    int curr_c = sj;\n\n    // Use a local random number generator for path generation, seeded by the global one.\n    // This ensures different paths are generated across calls to generate_path.\n    mt19937 local_rng(rng()); \n\n    // Continue extending the path until no more moves or global time limit is approached\n    while (true) {\n        // Periodically check remaining time to avoid exceeding total_time_limit\n        // Stop if less than 10ms remaining to finish current path and update best.\n        // This small buffer helps ensure the program terminates gracefully within the limit.\n        if (chrono::high_resolution_clock::now() - global_start_time >= total_time_limit - chrono::milliseconds(10)) {\n            break; \n        }\n\n        vector<Move> moves = get_valid_moves(curr_r, curr_c, visited_tiles);\n        if (moves.empty()) {\n            break; // No more valid moves from current position\n        }\n\n        // Sort valid moves by their score value in descending order.\n        // This prioritizes moves that give higher immediate scores.\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.score_value > b.score_value;\n        });\n\n        // Heuristic: consider a \"beam\" of top N moves, and pick one randomly.\n        // This balances greedy exploitation (higher scores) with exploration (trying other options).\n        // `effective_beam_width` is set to 5, meaning we consider the top 5 highest-scoring moves.\n        int effective_beam_width = min((int)moves.size(), 5); \n        \n        // Randomly pick an index within the `effective_beam_width`.\n        // This introduces randomness while still preferring high-scoring moves.\n        uniform_int_distribution<int> dist(0, effective_beam_width - 1);\n        int choice_idx = dist(local_rng);\n        \n        const Move& chosen_move = moves[choice_idx];\n\n        // Update current state based on the chosen move\n        curr_r = chosen_move.r;\n        curr_c = chosen_move.c;\n        current_score += chosen_move.score_value;\n        current_path_str += chosen_move.move_char;\n        visited_tiles[chosen_move.tile_id] = true;\n    }\n    return {current_score, current_path_str};\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed the random number generator using the current time.\n    // This provides a different sequence of random numbers for each execution,\n    // which is crucial for iterated randomized algorithms.\n    rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Read input: starting position (si, sj)\n    cin >> si >> sj;\n\n    // Read tile IDs for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> tile_id_grid[i][j];\n        }\n    }\n\n    // Read score values for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> p_grid[i][j];\n        }\n    }\n\n    // Initialize global best score with the score of the starting square.\n    // The path string is initially empty as no moves have been made yet (start square is implicitly visited).\n    max_score_global = p_grid[si][sj];\n    best_path_string_global = \"\"; \n\n    // Record the start time of the entire program execution\n    auto global_start_time = chrono::high_resolution_clock::now();\n    // Set a total time limit slightly less than 2 seconds (e.g., 1950 ms) to ensure output completes.\n    const auto TOTAL_TIME_LIMIT = chrono::milliseconds(1950); \n\n    // Iteratively generate paths and keep the best one found within the time limit.\n    while (chrono::high_resolution_clock::now() - global_start_time < TOTAL_TIME_LIMIT) {\n        // Call generate_path with the global start time and total time limit.\n        // The path generation function itself will manage its internal time checking.\n        pair<long long, string> result = generate_path(global_start_time, TOTAL_TIME_LIMIT);\n        \n        // If the newly generated path has a higher score, update the global best.\n        if (result.first > max_score_global) {\n            max_score_global = result.first;\n            best_path_string_global = result.second;\n        }\n    }\n\n    // Output the sequence of moves for the highest scoring path found.\n    cout << best_path_string_global << endl;\n\n    return 0;\n}\n","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <algorithm> // For std::reverse\n\n// Constants\nconst int GRID_SIZE = 30;\nconst int NUM_VERTICES = GRID_SIZE * GRID_SIZE;\n\n// Parameters for learning and exploration\nconst double INITIAL_EDGE_ESTIMATE = 5000.0; // Average of possible edge lengths\nconst double C_ALPHA = 20.0;                 // Constant for alpha in learning rate: alpha = 1.0 / (usage_count + C_ALPHA)\nconst double EXPLORATION_BONUS = 200.0;      // Bonus for less-used edges in Dijkstra's to encourage exploration\n                                             // Smaller usage_count -> larger bonus -> shorter effective_weight (as it's subtracted)\n\n// Clamping ranges for estimated edge lengths and effective weights\nconst double MIN_CLAMP_ESTIMATE = 900.0;   // Based on problem constraints (min 1000)\nconst double MAX_CLAMP_ESTIMATE = 9100.0;  // Based on problem constraints (max 9000)\nconst double MIN_CLAMP_EFFECTIVE_WEIGHT = 1.0; // To prevent negative effective edge weights in Dijkstra\n\n// Edge structures\n// h_len[i][j] is edge between (i,j) and (i,j+1)\n// v_len[i][j] is edge between (i,j) and (i+1,j)\n// These arrays store estimated lengths and usage counts for each individual edge.\ndouble estimated_h_len[GRID_SIZE][GRID_SIZE - 1];\ndouble estimated_v_len[GRID_SIZE - 1][GRID_SIZE];\n\nlong long usage_h_count[GRID_SIZE][GRID_SIZE - 1];\nlong long usage_v_count[GRID_SIZE - 1][GRID_SIZE];\n\n// Node to index mapping for Dijkstra's\nint node_to_idx(int r, int c) {\n    return r * GRID_SIZE + c;\n}\n\n// Index to node mapping\nstd::pair<int, int> idx_to_node(int idx) {\n    return {idx / GRID_SIZE, idx % GRID_SIZE};\n}\n\n// Function to clamp a double value within a specified range\ndouble clamp(double val, double min_val, double max_val) {\n    if (val < min_val) return min_val;\n    if (val > max_val) return max_val;\n    return val;\n}\n\n// Dijkstra's algorithm to find the shortest path based on current estimates\nstd::string find_path(int start_r, int start_c, int end_r, int end_c, double& path_estimated_len) {\n    int start_idx = node_to_idx(start_r, start_c);\n    int end_idx = node_to_idx(end_r, end_c);\n\n    std::vector<double> dist(NUM_VERTICES, 1e18); // Stores cumulative effective weights\n    std::vector<int> prev_node(NUM_VERTICES, -1);\n    std::vector<char> prev_dir(NUM_VERTICES, ' ');\n\n    std::priority_queue<std::pair<double, int>, std::vector<std::pair<double, int>>, std::greater<std::pair<double, int>>> pq;\n\n    dist[start_idx] = 0;\n    pq.push({0, start_idx});\n\n    while (!pq.empty()) {\n        double d = pq.top().first;\n        int u_idx = pq.top().second;\n        pq.pop();\n\n        if (d > dist[u_idx]) continue;\n        if (u_idx == end_idx) break;\n\n        int ur = idx_to_node(u_idx).first;\n        int uc = idx_to_node(u_idx).second;\n\n        // Explore neighbors (Up, Down, Left, Right)\n        // U: (ur-1, uc) from (ur, uc)\n        if (ur > 0) {\n            int v_idx = node_to_idx(ur - 1, uc);\n            // Edge is v_len[ur-1][uc]\n            double current_estimate = estimated_v_len[ur - 1][uc];\n            long long current_usage = usage_v_count[ur - 1][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE); // Clamp effective weight\n            \n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'U';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // D: (ur+1, uc) from (ur, uc)\n        if (ur < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur + 1, uc);\n            // Edge is v_len[ur][uc]\n            double current_estimate = estimated_v_len[ur][uc];\n            long long current_usage = usage_v_count[ur][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'D';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // L: (ur, uc-1) from (ur, uc)\n        if (uc > 0) {\n            int v_idx = node_to_idx(ur, uc - 1);\n            // Edge is h_len[ur][uc-1]\n            double current_estimate = estimated_h_len[ur][uc - 1];\n            long long current_usage = usage_h_count[ur][uc - 1];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'L';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // R: (ur, uc+1) from (ur, uc)\n        if (uc < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur, uc + 1);\n            // Edge is h_len[ur][uc]\n            double current_estimate = estimated_h_len[ur][uc];\n            long long current_usage = usage_h_count[ur][uc];\n            double effective_weight = current_estimate - EXPLORATION_BONUS / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'R';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    int curr_idx = end_idx;\n    double actual_path_len_sum = 0.0; // Sum of actual estimated edge lengths (without exploration bonus)\n\n    // Reconstruct path and calculate sum of actual estimated edge lengths\n    while (curr_idx != start_idx && curr_idx != -1) {\n        if (prev_node[curr_idx] == -1) {\n             path_estimated_len = 1e18; \n             return \"\"; // Path not found or error\n        }\n        path_str += prev_dir[curr_idx];\n        \n        int prev_idx = prev_node[curr_idx];\n        int pr = idx_to_node(prev_idx).first;\n        int pc = idx_to_node(prev_idx).second;\n        // int cr = idx_to_node(curr_idx).first; // curr_r, curr_c are from node_to_idx(curr_idx)\n        // int cc = idx_to_node(curr_idx).second;\n\n        // Add the *actual estimated length* of the edge\n        if (prev_dir[curr_idx] == 'U') { // Means we moved from (pr,pc) to (pr-1,pc), so edge is v_len[pr-1][pc]\n            actual_path_len_sum += estimated_v_len[pr-1][pc];\n        } else if (prev_dir[curr_idx] == 'D') { // Means we moved from (pr,pc) to (pr+1,pc), so edge is v_len[pr][pc]\n            actual_path_len_sum += estimated_v_len[pr][pc];\n        } else if (prev_dir[curr_idx] == 'L') { // Means we moved from (pr,pc) to (pr,pc-1), so edge is h_len[pr][pc-1]\n            actual_path_len_sum += estimated_h_len[pr][pc-1];\n        } else { // prev_dir[curr_idx] == 'R' // Means we moved from (pr,pc) to (pr,pc+1), so edge is h_len[pr][pc]\n            actual_path_len_sum += estimated_h_len[pr][pc];\n        }\n        curr_idx = prev_node[curr_idx];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    \n    path_estimated_len = actual_path_len_sum; // This is the total estimated length of the path without exploration bonus\n    return path_str;\n}\n\nvoid solve() {\n    // Initialize estimated edge lengths and usage counts\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            estimated_h_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_h_count[i][j] = 1; \n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            estimated_v_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_v_count[i][j] = 1; \n        }\n    }\n\n    // Main query loop\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        std::cin >> si >> sj >> ti >> tj;\n\n        double current_path_estimated_len; \n        std::string path = find_path(si, sj, ti, tj, current_path_estimated_len);\n        \n        std::cout << path << std::endl;\n        std::cout.flush();\n\n        int observed_path_len_int;\n        std::cin >> observed_path_len_int;\n        double observed_path_len = static_cast<double>(observed_path_len_int);\n\n        // Update edge length estimates\n        // Ensure current_path_estimated_len is not too small to avoid division by zero or extreme scaling.\n        if (current_path_estimated_len < 1.0) current_path_estimated_len = 1.0; \n        double scaling_factor = observed_path_len / current_path_estimated_len;\n        \n        int curr_r = si;\n        int curr_c = sj;\n\n        for (char dir : path) {\n            double* edge_len_ptr;\n            long long* usage_count_ptr;\n            int r_idx, c_idx; // Indices for the specific edge in the respective array\n\n            // Determine which edge was used and its current stats using pre-move coordinates\n            if (dir == 'U') {\n                r_idx = curr_r - 1; // Edge (curr_r-1, curr_c) to (curr_r, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r--; // Move to the new node\n            } else if (dir == 'D') {\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r+1, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r++; // Move to the new node\n            } else if (dir == 'L') {\n                r_idx = curr_r; // Edge (curr_r, curr_c-1) to (curr_r, curr_c)\n                c_idx = curr_c - 1;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c--; // Move to the new node\n            } else { // dir == 'R'\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r, curr_c+1)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c++; // Move to the new node\n            }\n\n            // Apply weighted average update\n            double alpha = 1.0 / (static_cast<double>(*usage_count_ptr) + C_ALPHA);\n            double new_estimate_value = (*edge_len_ptr) * scaling_factor;\n            *edge_len_ptr = clamp((1.0 - alpha) * (*edge_len_ptr) + alpha * new_estimate_value, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            \n            // Increment usage count for the updated edge\n            (*usage_count_ptr)++;\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}\n","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <tuple> \n\n// Global constants\nconst int N_MATRIX = 20; // N is fixed to 20\nint M;\nstd::vector<std::string> S; // Input strings\n\n// Character to integer mapping for internal use (A=0, ..., H=7, .=8)\nstd::map<char, int> char_to_int_map;\nstd::vector<char> int_to_char_map;\n\n// Simulated Annealing parameters\nlong long MAX_ITERATIONS = 100000000; // Large number, actual iterations depend on TIME_LIMIT\ndouble START_TEMP = 2.0;\ndouble END_TEMP = 1e-9;\n\n// Random number generator\nstd::mt19937 mt;\n\n// Time measurement\nstd::chrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 2.9; // seconds\n\n// --- State Variables for SA ---\nstd::vector<std::string> current_grid;\nint num_dots; // number of '.' in current_grid\nint num_matched_strings; // current 'c' value (number of unique strings found at least once)\n\n// For each string s_idx, how many distinct (start_r, start_c, dir) locations does it currently match?\nstd::vector<int> num_actual_matches_for_string; // size M\n\n// Dynamic list of string indices that are currently unmatched\nstd::vector<int> unmatched_string_indices;\n// Maps s_idx to its position in unmatched_string_indices (-1 if matched)\nstd::vector<int> s_idx_to_unmatched_list_pos; // size M\n\n// --- Precomputed data structures for efficient updates ---\n// Each struct represents a unique \"match window\" (a string starting at a specific cell in a specific direction)\nstruct PotentialMatchInfoBase {\n    int s_idx;\n    int sr, sc; // start row, start col\n    int dir;    // 0 for horizontal, 1 for vertical\n};\n\n// Vector storing all unique PotentialMatchInfoBase instances\nstd::vector<PotentialMatchInfoBase> all_potential_match_info_bases; \n\n// For each grid cell (r_covered, c_covered), this list stores pairs of:\n// <index to all_potential_match_info_bases, p_in_s>\n// `p_in_s` is the position of (r_covered, c_covered) within the string S[s_idx]\nstd::vector<std::pair<int, int>> cell_covers[N_MATRIX][N_MATRIX];\n\n// For each potential match (identified by its index `pm_idx`), the number of mismatches (chars don't match or are '.')\nstd::vector<int> num_mismatches_for_potential_match; \n// For each potential match (identified by `pm_idx`), true if it currently matches the grid perfectly\nstd::vector<bool> is_potential_match_active; \n\n// For each s_idx, a list of pm_idx that correspond to it.\nstd::vector<std::vector<int>> potential_matches_for_string;\n\n// Helper for modulo arithmetic (for negative numbers)\nint mod(int i, int n) {\n    return (i % n + n) % n;\n}\n\nvoid init_char_maps() {\n    char_to_int_map['A'] = 0; char_to_int_map['B'] = 1; char_to_int_map['C'] = 2; char_to_int_map['D'] = 3;\n    char_to_int_map['E'] = 4; char_to_int_map['F'] = 5; char_to_int_map['G'] = 6; char_to_int_map['H'] = 7;\n    char_to_int_map['.'] = 8;\n\n    int_to_char_map.resize(9);\n    int_to_char_map[0] = 'A'; int_to_char_map[1] = 'B'; int_to_char_map[2] = 'C'; int_to_char_map[3] = 'D';\n    int_to_char_map[4] = 'E'; int_to_char_map[5] = 'F'; int_to_char_map[6] = 'G'; int_to_char_map[7] = 'H';\n    int_to_char_map[8] = '.';\n}\n\n// Score calculation: objective function for SA\n// Range for c < M: [0, 1)\n// Range for c = M: [1.0 + 2.0*N*N / (2.0*N*N), 1.0 + 2.0*N*N / (2.0*N*N - (N*N-1))] approx [2.0, 2.995]\ndouble calculate_objective(int c, int d) {\n    if (c < M) {\n        return (double)c / M;\n    } else {\n        return 1.0 + (double)(2.0 * N_MATRIX * N_MATRIX) / (2.0 * N_MATRIX * N_MATRIX - d);\n    }\n}\n\nvoid precompute_potential_matches() {\n    potential_matches_for_string.resize(M);\n    std::map<std::tuple<int, int, int, int>, int> potential_match_key_to_idx; \n    int pm_counter = 0; // Counts unique potential match windows\n\n    for (int s_idx = 0; s_idx < M; ++s_idx) {\n        // For each start position (sr, sc) and direction (0=horiz, 1=vert)\n        for (int sr = 0; sr < N_MATRIX; ++sr) {\n            for (int sc = 0; sc < N_MATRIX; ++sc) {\n                // Horizontal match\n                std::tuple<int, int, int, int> pm_key_h = {s_idx, sr, sc, 0}; \n                if (potential_match_key_to_idx.find(pm_key_h) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_h] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 0});\n                }\n                int pm_idx_h = potential_match_key_to_idx[pm_key_h];\n                potential_matches_for_string[s_idx].push_back(pm_idx_h); \n\n                // Vertical match\n                std::tuple<int, int, int, int> pm_key_v = {s_idx, sr, sc, 1}; \n                if (potential_match_key_to_idx.find(pm_key_v) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_v] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 1});\n                }\n                int pm_idx_v = potential_match_key_to_idx[pm_key_v];\n                potential_matches_for_string[s_idx].push_back(pm_idx_v); \n            }\n        }\n    }\n\n    // Now populate cell_covers using all_potential_match_info_bases\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        int k = S[pm_info_base.s_idx].length();\n        for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n            cell_covers[r][c].push_back({pm_idx, p_in_s});\n        }\n    }\n\n    num_mismatches_for_potential_match.resize(pm_counter);\n    is_potential_match_active.resize(pm_counter, false);\n}\n\nvoid initialize_state() {\n    current_grid.assign(N_MATRIX, std::string(N_MATRIX, '.')); \n    \n    // Initialize with random 'A'-'H' characters (mimics input generation)\n    std::uniform_int_distribution<int> dist_char_AH(0, 7); // A-H only\n    for (int r = 0; r < N_MATRIX; ++r) {\n        for (int c = 0; c < N_MATRIX; ++c) {\n            current_grid[r][c] = int_to_char_map[dist_char_AH(mt)];\n        }\n    }\n    num_dots = 0; // No dots initially\n\n    num_matched_strings = 0;\n    num_actual_matches_for_string.assign(M, 0);\n\n    // Initialize unmatched_string_indices and s_idx_to_unmatched_list_pos\n    unmatched_string_indices.reserve(M); // Pre-allocate memory\n    s_idx_to_unmatched_list_pos.assign(M, -1); // -1 means not in list (i.e., matched)\n    for (int i = 0; i < M; ++i) {\n        unmatched_string_indices.push_back(i);\n        s_idx_to_unmatched_list_pos[i] = i;\n    }\n\n    // Calculate initial mismatch counts for all potential match windows\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        const std::string& s = S[pm_info_base.s_idx];\n        int k = s.length();\n        int mismatches = 0;\n\n        for (int p = 0; p < k; ++p) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n            \n            // A mismatch occurs if the grid character doesn't match the string character OR if it's '.'\n            // With A-H initialization, only the first condition applies initially.\n            if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                mismatches++;\n            }\n        }\n        num_mismatches_for_potential_match[pm_idx] = mismatches;\n\n        if (mismatches == 0) { // This potential match is currently active\n            is_potential_match_active[pm_idx] = true;\n            if (num_actual_matches_for_string[pm_info_base.s_idx] == 0) { // First match for this string\n                num_matched_strings++;\n                // Remove this s_idx from unmatched_string_indices\n                int s_idx = pm_info_base.s_idx;\n                int pos = s_idx_to_unmatched_list_pos[s_idx];\n                if (pos != -1) { // It should be in the list\n                    int last_s_idx_in_list = unmatched_string_indices.back();\n                    unmatched_string_indices[pos] = last_s_idx_in_list;\n                    s_idx_to_unmatched_list_pos[last_s_idx_in_list] = pos;\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[s_idx] = -1;\n                }\n            }\n            num_actual_matches_for_string[pm_info_base.s_idx]++;\n        }\n    }\n}\n\n// Stores info about changes to unmatched_string_indices for revert\nstruct UnmatchedListChange {\n    int s_idx;       // The string index that was added/removed\n    int old_pos;     // Its position before change (-1 if not in list)\n    int moved_s_idx; // If a swap occurred, the s_idx that moved to `old_pos`\n};\n\nvoid solve() {\n    start_time = std::chrono::high_resolution_clock::now();\n    \n    init_char_maps();\n    precompute_potential_matches();\n    initialize_state();\n\n    std::uniform_int_distribution<int> dist_rc(0, N_MATRIX - 1);\n    std::uniform_int_distribution<int> dist_char_all(0, int_to_char_map.size() - 1); // 9 options: A-H, .\n    std::uniform_int_distribution<int> dist_char_AH(0, 7); // A-H only\n    std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    double best_score = calculate_objective(num_matched_strings, num_dots);\n    std::vector<std::string> best_grid = current_grid;\n\n    double p_targeted_fix_attempt = 0.8; // Increased probability for targeted fix\n\n    for (long long iter = 0; iter < MAX_ITERATIONS; ++iter) {\n        double current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            std::chrono::high_resolution_clock::now() - start_time).count() / 1e9;\n        if (current_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = START_TEMP * std::pow(END_TEMP / START_TEMP, (double)iter / MAX_ITERATIONS);\n\n        int r_changed_candidate = -1, c_changed_candidate = -1; // The cell to perturb\n        char old_char_candidate = '.', new_char_candidate = '.'; // The proposed change\n\n        bool is_perturbation_generated = false;\n\n        // Strategy 1: Attempt to fix a mismatch for an currently unmatched string\n        if (num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_targeted_fix_attempt) {\n            int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            // Find a potential match window for this string that is currently mismatched\n            std::vector<int> candidates_pm_idx_for_s;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match[pm_idx] > 0) {\n                    candidates_pm_idx_for_s.push_back(pm_idx);\n                }\n            }\n\n            if (!candidates_pm_idx_for_s.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                // Find a cell within this window that is currently mismatched\n                std::vector<std::pair<int, int>> mismatched_cells_in_window; // {r, c, p_in_s}\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    if (current_grid[r_p][c_p] != s_to_fix[p_in_s] || current_grid[r_p][c_p] == '.') {\n                        mismatched_cells_in_window.push_back({r_p, c_p});\n                    }\n                }\n\n                if (!mismatched_cells_in_window.empty()) {\n                    auto target_cell = mismatched_cells_in_window[std::uniform_int_distribution<int>(0, mismatched_cells_in_window.size() - 1)(mt)];\n                    r_changed_candidate = target_cell.first;\n                    c_changed_candidate = target_cell.second;\n                    old_char_candidate = current_grid[r_changed_candidate][c_changed_candidate];\n                    \n                    int p_in_s_for_target = (pm_info_base.dir == 0) ? \n                                             mod(c_changed_candidate - pm_info_base.sc, N_MATRIX) : \n                                             mod(r_changed_candidate - pm_info_base.sr, N_MATRIX);\n\n                    new_char_candidate = s_to_fix[p_in_s_for_target];\n                    if (new_char_candidate != old_char_candidate) { // Only proceed if there's an actual change\n                        is_perturbation_generated = true;\n                    }\n                }\n            }\n        }\n\n        // Strategy 2: General random perturbation (fallback or if selected probabilistically)\n        if (!is_perturbation_generated) {\n            r_changed_candidate = dist_rc(mt);\n            c_changed_candidate = dist_rc(mt);\n            old_char_candidate = current_grid[r_changed_candidate][c_changed_candidate];\n            \n            if (num_matched_strings == M) {\n                // If all strings are matched, try to introduce '.' to reduce d\n                if (dist_prob(mt) < 0.8) { // E.g., 80% chance to propose '.'\n                    new_char_candidate = '.';\n                } else {\n                    new_char_candidate = int_to_char_map[dist_char_all(mt)]; // Random A-H, or .\n                }\n            } else {\n                // If not all strings are matched, prefer filling with A-H (less '.'s)\n                new_char_candidate = int_to_char_map[dist_char_AH(mt)]; // A-H only\n            }\n            if (new_char_candidate == old_char_candidate) continue; // Skip if no effective change\n            is_perturbation_generated = true;\n        }\n\n        if (!is_perturbation_generated) continue; // Should not happen if logic is sound, but defensive.\n\n        // --- Store current state for potential revert ---\n        int prev_num_dots = num_dots;\n        int prev_num_matched_strings_overall = num_matched_strings;\n        \n        // Map to store original match counts for affected strings\n        std::map<int, int> s_idx_to_old_actual_match_count_snapshot; \n        \n        // Record changes to unmatched_string_indices and s_idx_to_unmatched_list_pos for fast revert\n        std::vector<UnmatchedListChange> unmatched_list_changes_for_revert;\n\n        // Temporarily store original mismatch counts and active status for affected potential matches for quick revert\n        std::vector<int> original_mismatches_for_affected_pm;\n        std::vector<bool> original_active_status_for_affected_pm;\n        std::vector<int> affected_pm_indices;\n\n        // --- Apply change and calculate deltas ---\n        // Update num_dots\n        if (old_char_candidate == '.' && new_char_candidate != '.') { num_dots--; }\n        else if (old_char_candidate != '.' && new_char_candidate == '.') { num_dots++; }\n        \n        // Iterate through all potential match windows affected by this cell change\n        for (auto const& p : cell_covers[r_changed_candidate][c_changed_candidate]) {\n            int pm_idx = p.first;\n            int p_in_s = p.second; // Position of (r_changed_candidate, c_changed_candidate) within S[s_idx]\n\n            affected_pm_indices.push_back(pm_idx);\n            original_mismatches_for_affected_pm.push_back(num_mismatches_for_potential_match[pm_idx]);\n            original_active_status_for_affected_pm.push_back(is_potential_match_active[pm_idx]);\n\n            const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n            int s_idx = pm_info_base.s_idx;\n            char required_char = S[s_idx][p_in_s];\n\n            // Store original match count for this string if not already done in the snapshot\n            if (s_idx_to_old_actual_match_count_snapshot.find(s_idx) == s_idx_to_old_actual_match_count_snapshot.end()) {\n                s_idx_to_old_actual_match_count_snapshot[s_idx] = num_actual_matches_for_string[s_idx];\n            }\n\n            // Determine if old/new chars are a mismatch\n            bool old_char_was_bad = (old_char_candidate != required_char || old_char_candidate == '.');\n            bool new_char_is_bad = (new_char_candidate != required_char || new_char_candidate == '.');\n\n            // Update mismatch count for this potential match window\n            if (old_char_was_bad && !new_char_is_bad) { // Cell character changed from bad to good for this match\n                num_mismatches_for_potential_match[pm_idx]--;\n            } else if (!old_char_was_bad && new_char_is_bad) { // Cell character changed from good to bad for this match\n                num_mismatches_for_potential_match[pm_idx]++;\n            }\n\n            // Update active status for this potential match window and string's actual match count\n            bool was_match_active = original_active_status_for_affected_pm.back(); \n            bool is_match_active = (num_mismatches_for_potential_match[pm_idx] == 0);\n\n            if (!was_match_active && is_match_active) {\n                is_potential_match_active[pm_idx] = true;\n                num_actual_matches_for_string[s_idx]++;\n            } else if (was_match_active && !is_match_active) {\n                is_potential_match_active[pm_idx] = false;\n                num_actual_matches_for_string[s_idx]--;\n            }\n        }\n\n        // Calculate actual change in num_matched_strings (c) for the proposed state\n        int proposed_num_matched_strings_overall = prev_num_matched_strings_overall;\n        for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n            if (old_count == 0 && num_actual_matches_for_string[s_idx] > 0) {\n                proposed_num_matched_strings_overall++;\n                // Record for fast revert: string s_idx was removed from unmatched_string_indices\n                int old_pos = s_idx_to_unmatched_list_pos[s_idx];\n                int moved_s_idx = unmatched_string_indices.back();\n                unmatched_list_changes_for_revert.push_back({s_idx, old_pos, moved_s_idx});\n\n                // Apply change: remove s_idx from unmatched_string_indices\n                unmatched_string_indices[old_pos] = moved_s_idx;\n                s_idx_to_unmatched_list_pos[moved_s_idx] = old_pos;\n                unmatched_string_indices.pop_back();\n                s_idx_to_unmatched_list_pos[s_idx] = -1;\n            } else if (old_count > 0 && num_actual_matches_for_string[s_idx] == 0) {\n                proposed_num_matched_strings_overall--;\n                // Record for fast revert: string s_idx was added to unmatched_string_indices\n                unmatched_list_changes_for_revert.push_back({s_idx, -1, -1}); // -1 means no swap occurred\n\n                // Apply change: add s_idx to unmatched_string_indices\n                s_idx_to_unmatched_list_pos[s_idx] = unmatched_string_indices.size();\n                unmatched_string_indices.push_back(s_idx);\n            }\n        }\n\n        // --- Decision (Accept/Revert) ---\n        double current_obj_val = calculate_objective(prev_num_matched_strings_overall, prev_num_dots);\n        double proposed_obj_val = calculate_objective(proposed_num_matched_strings_overall, num_dots);\n\n        if (proposed_obj_val >= current_obj_val || dist_prob(mt) < std::exp((proposed_obj_val - current_obj_val) / T)) {\n            // Accept the change:\n            current_grid[r_changed_candidate][c_changed_candidate] = new_char_candidate;\n            num_matched_strings = proposed_num_matched_strings_overall; \n            // All other variables are already updated for the proposed state\n        } else {\n            // Revert the change:\n            num_dots = prev_num_dots; \n\n            // Revert mismatch counts and active status for affected potential matches\n            for (size_t i = 0; i < affected_pm_indices.size(); ++i) {\n                int pm_idx = affected_pm_indices[i];\n                num_mismatches_for_potential_match[pm_idx] = original_mismatches_for_affected_pm[i];\n                is_potential_match_active[pm_idx] = original_active_status_for_affected_pm[i];\n            }\n\n            // Revert num_actual_matches_for_string for affected strings\n            for (auto const& [s_idx, old_count] : s_idx_to_old_actual_match_count_snapshot) {\n                num_actual_matches_for_string[s_idx] = old_count;\n            }\n\n            // Revert unmatched_string_indices and s_idx_to_unmatched_list_pos\n            for (auto it = unmatched_list_changes_for_revert.rbegin(); it != unmatched_list_changes_for_revert.rend(); ++it) {\n                const auto& change = *it;\n                if (change.old_pos != -1) { // String was removed (became matched)\n                    // Re-add s_idx to its old_pos, moving back the `moved_s_idx`\n                    unmatched_string_indices.push_back(unmatched_string_indices[change.old_pos]); // Put `moved_s_idx` back at end\n                    s_idx_to_unmatched_list_pos[unmatched_string_indices[change.old_pos]] = unmatched_string_indices.size() - 1;\n\n                    unmatched_string_indices[change.old_pos] = change.s_idx;\n                    s_idx_to_unmatched_list_pos[change.s_idx] = change.old_pos;\n                } else { // String was added (became unmatched)\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[change.s_idx] = -1;\n                }\n            }\n            // num_matched_strings remains prev_num_matched_strings_overall\n        }\n        \n        // Update best score and grid AFTER all state variables are consistent (either accepted or reverted)\n        double current_final_obj_val = calculate_objective(num_matched_strings, num_dots);\n        if (current_final_obj_val > best_score) {\n            best_score = current_final_obj_val;\n            best_grid = current_grid;\n        }\n    }\n\n    current_grid = best_grid; // Output the best grid found\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N_input; \n    std::cin >> N_input >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> S[i];\n    }\n\n    solve();\n\n    for (int i = 0; i < N_MATRIX; ++i) {\n        std::cout << current_grid[i] << std::endl;\n    }\n\n    return 0;\n}\n","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm> // For std::reverse\n\n// No external libraries other than standard C++ ones are strictly necessary.\n\nusing namespace std;\n\n// Global variables to store map data and current state for convenience\nint N_global;\nint SI_global, SJ_global;\nvector<string> grid_global;\nvector<vector<int>> costs_global; // Stores char '5'-'9' as int\nvector<vector<bool>> is_road_global; // True if square is a road, false if obstacle\n// visible_left/right/up/down store the inclusive boundaries of the visible segment\n// For example, visible_left_global[r][c] is the minimum column index k such that (r,k) is road and on the path to (r,c)\nvector<vector<int>> visible_left_global, visible_right_global, visible_up_global, visible_down_global; \nint total_road_squares_global = 0; // Total count of road squares\nvector<vector<bool>> covered_status_global; // True if the square has been made visible\nint current_covered_count_global = 0; // Count of currently visible road squares\n\n// Structure for Dijkstra's priority queue state\nstruct State {\n    int r, c;\n    long long cost;\n    // For priority queue: min-heap based on cost\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Precompute visible ranges for each road square (O(N^3))\n// This populates visible_left/right/up/down_global arrays.\nvoid precompute_visibility() {\n    visible_left_global.assign(N_global, vector<int>(N_global));\n    visible_right_global.assign(N_global, vector<int>(N_global));\n    visible_up_global.assign(N_global, vector<int>(N_global));\n    visible_down_global.assign(N_global, vector<int>(N_global));\n\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            if (!is_road_global[i][j]) continue; // Only process road squares\n\n            // Horizontal visibility (left)\n            int left_bound = j;\n            while (left_bound > 0 && is_road_global[i][left_bound - 1]) {\n                left_bound--;\n            }\n            visible_left_global[i][j] = left_bound;\n\n            // Horizontal visibility (right)\n            int right_bound = j;\n            while (right_bound < N_global - 1 && is_road_global[i][right_bound + 1]) {\n                right_bound++;\n            }\n            visible_right_global[i][j] = right_bound;\n\n            // Vertical visibility (up)\n            int up_bound = i;\n            while (up_bound > 0 && is_road_global[up_bound - 1][j]) {\n                up_bound--;\n            }\n            visible_up_global[i][j] = up_bound;\n\n            // Vertical visibility (down)\n            int down_bound = i;\n            while (down_bound < N_global - 1 && is_road_global[down_bound + 1][j]) {\n                down_bound++;\n            }\n            visible_down_global[i][j] = down_bound;\n        }\n    }\n}\n\n// Update the global coverage status based on visiting (r, c) (O(N))\n// Returns the number of newly covered squares.\nint update_coverage_and_count_new(int r, int c) {\n    int newly_covered_count = 0;\n    // Horizontal line of sight\n    for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n        if (is_road_global[r][k] && !covered_status_global[r][k]) {\n            covered_status_global[r][k] = true;\n            newly_covered_count++;\n        }\n    }\n    // Vertical line of sight\n    for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n        if (is_road_global[k][c] && !covered_status_global[k][c]) {\n            covered_status_global[k][c] = true;\n            newly_covered_count++;\n        }\n    }\n    return newly_covered_count;\n}\n\n// Dijkstra from start_r, start_c to find the next best node to visit\n// The \"best\" node maximizes (new coverage gained) / (cost to reach it).\n// Returns {best_r, best_c} and updates path_cost_found with the cost to reach it.\npair<int, int> find_best_next_node(int start_r, int start_c, long long& path_cost_found) {\n    // dist[r][c] stores the minimum cost to reach (r,c) from (start_r, start_c)\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1)); \n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int best_r = -1, best_c = -1;\n    double max_score = -1.0; // Initialize with a very low score\n    long long min_cost_to_best_target = -1; // Stores cost of best found target\n    int max_coverage_gain_best = -1; // Stores coverage gain of best found target (for tie-breaking)\n\n    // Directions for moving (Up, Down, Left, Right)\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        // If a shorter path to (r,c) has already been found and processed, skip\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        // Calculate coverage gain for current (r,c)\n        int coverage_gain_current_node = 0;\n        // Count newly visible squares horizontally\n        for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n            if (is_road_global[r][k] && !covered_status_global[r][k]) coverage_gain_current_node++;\n        }\n        // Count newly visible squares vertically\n        for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n            if (is_road_global[k][c] && !covered_status_global[k][c]) coverage_gain_current_node++;\n        }\n        \n        // We only consider moves that yield new coverage AND require movement (cost > 0).\n        if (coverage_gain_current_node > 0 && cost > 0) { \n            double score = (double)coverage_gain_current_node / cost;\n\n            // Tie-breaking:\n            // 1. Higher score (coverage_gain / cost)\n            // 2. If scores are equal, prefer higher coverage_gain (more squares covered)\n            // 3. If scores and coverage_gain are both equal, prefer lower cost (shorter path)\n            if (score > max_score || \n                (score == max_score && coverage_gain_current_node > max_coverage_gain_best) ||\n                (score == max_score && coverage_gain_current_node == max_coverage_gain_best && cost < min_cost_to_best_target)) \n            {\n                max_score = score;\n                best_r = r;\n                best_c = c;\n                min_cost_to_best_target = cost;\n                max_coverage_gain_best = coverage_gain_current_node;\n            }\n        }\n\n        // Explore neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            // Check if neighbor is within bounds and is a road square\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc]; // Cost to move to (nr,nc)\n                // If a shorter path to (nr,nc) is found\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // If no suitable target was found (best_r remains -1), it means all reachable squares \n    // from start_r, start_c are already covered, or no path with coverage_gain > 0 and cost > 0 exists.\n    if (best_r == -1) { \n        path_cost_found = 0;\n        return {start_r, start_c}; // Return current position\n    }\n\n    path_cost_found = min_cost_to_best_target;\n    return {best_r, best_c};\n}\n\n// Reconstruct path segment using Dijkstra's prev array (O(N^2))\n// This function computes the shortest path between start and end and returns it as a string of moves.\nstring reconstruct_path_segment(int start_r, int start_c, int end_r, int end_c) {\n    if (start_r == end_r && start_c == end_c) return \"\"; // No movement needed\n\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1));\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1})); // To reconstruct path\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int dr[] = {-1, 1, 0, 0}; // Relative moves for U, D, L, R\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (r == end_r && c == end_c) break; // Reached the end node, path found\n\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c}; // Store previous node for path reconstruction\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // Reconstruct path string by backtracking from end_r, end_c to start_r, start_c\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    \n    // If no path was found (end_r, end_c is unreachable)\n    if (dist[end_r][end_c] == -1) {\n        return \"\"; \n    }\n\n    while (curr_r != start_r || curr_c != start_c) {\n        int pr = prev[curr_r][curr_c].first;\n        int pc = prev[curr_r][curr_c].second;\n        \n        // This check guards against errors where prev pointers might be invalid\n        if (pr == -1 || pc == -1) { \n            // Should not happen if a path was found (dist[end_r][end_c] != -1)\n            // and start_r, start_c is the true origin.\n            return \"\"; \n        }\n\n        // Determine the move character based on (pr,pc) to (curr_r,curr_c)\n        if (pr == curr_r - 1 && pc == curr_c) path_segment += 'D'; // Previous was up, current is down (move D)\n        else if (pr == curr_r + 1 && pc == curr_c) path_segment += 'U'; // Previous was down, current is up (move U)\n        else if (pr == curr_r && pc == curr_c - 1) path_segment += 'R'; // Previous was left, current is right (move R)\n        else if (pr == curr_r && pc == curr_c + 1) path_segment += 'L'; // Previous was right, current is left (move L)\n        curr_r = pr;\n        curr_c = pc;\n    }\n    reverse(path_segment.begin(), path_segment.end()); // Path was built backwards, reverse to get correct order\n    return path_segment;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); // Optimize C++ standard streams for faster I/O\n    cin.tie(NULL);\n\n    cin >> N_global >> SI_global >> SJ_global;\n\n    grid_global.resize(N_global);\n    costs_global.assign(N_global, vector<int>(N_global));\n    is_road_global.assign(N_global, vector<bool>(N_global, false));\n    covered_status_global.assign(N_global, vector<bool>(N_global, false));\n\n    for (int i = 0; i < N_global; ++i) {\n        cin >> grid_global[i];\n        for (int j = 0; j < N_global; ++j) {\n            if (grid_global[i][j] == '#') {\n                is_road_global[i][j] = false;\n            } else {\n                is_road_global[i][j] = true;\n                costs_global[i][j] = grid_global[i][j] - '0'; // Convert char digit to int\n                total_road_squares_global++; // Count total road squares\n            }\n        }\n    }\n\n    // Precompute visibility for all road squares\n    precompute_visibility();\n\n    // Initial coverage from the starting point (si,sj)\n    current_covered_count_global += update_coverage_and_count_new(SI_global, SJ_global);\n\n    // Handle the special case where all squares are covered from the starting point\n    // This avoids generating an empty path (t=0), which would result in WA.\n    if (current_covered_count_global == total_road_squares_global) {\n        string initial_move_path = \"\";\n        // Try to move Right-Left\n        if (SJ_global + 1 < N_global && is_road_global[SI_global][SJ_global + 1]) {\n            initial_move_path += 'R';\n            initial_move_path += 'L';\n        } \n        // If R-L isn't possible, try Down-Up\n        else if (SI_global + 1 < N_global && is_road_global[SI_global + 1][SJ_global]) {\n            initial_move_path += 'D';\n            initial_move_path += 'U';\n        } \n        cout << initial_move_path << endl;\n        return 0; // Exit\n    }\n\n    int current_r = SI_global;\n    int current_c = SJ_global;\n    string full_path = \"\";\n\n    // Main loop: find next best node until all squares are covered\n    while (current_covered_count_global < total_road_squares_global) {\n        long long path_cost_to_next_node = 0;\n        pair<int, int> next_target = find_best_next_node(current_r, current_c, path_cost_to_next_node);\n\n        if (next_target.first == current_r && next_target.second == current_c) {\n            // No new valid target with coverage gain and positive cost was found\n            // This suggests all remaining uncovered squares are unreachable, or bug in heuristic.\n            // In a connected graph, all must be reachable. If there are remaining, it's a heuristic issue.\n            break; \n        }\n\n        string segment_str = reconstruct_path_segment(current_r, current_c, next_target.first, next_target.second);\n        \n        int temp_r = current_r;\n        int temp_c = current_c;\n        string current_segment_moves = \"\";\n\n        // Iterate through each move in the segment to next_target\n        // Update coverage and check if all cells are covered along the way\n        for (char move_char : segment_str) {\n            current_segment_moves += move_char;\n            \n            // Determine new (temp_r, temp_c)\n            if (move_char == 'U') temp_r--;\n            else if (move_char == 'D') temp_r++;\n            else if (move_char == 'L') temp_c--;\n            else if (move_char == 'R') temp_c++;\n            \n            // Apply coverage and count newly covered squares\n            current_covered_count_global += update_coverage_and_count_new(temp_r, temp_c);\n\n            // If all squares are now covered, we can stop and return to SI,SJ\n            if (current_covered_count_global == total_road_squares_global) {\n                full_path += current_segment_moves; // Add the path segment taken so far\n                string final_return_segment = reconstruct_path_segment(temp_r, temp_c, SI_global, SJ_global);\n                full_path += final_return_segment;\n                cout << full_path << endl;\n                return 0; // Exit successfully\n            }\n        }\n        \n        // If the entire segment was traversed and still not 100% covered, append it and continue\n        full_path += segment_str; // Append the full segment\n        current_r = next_target.first; // Update current position to the end of the segment\n        current_c = next_target.second;\n    }\n\n    // This part is reached if the loop broke early (e.g., heuristic got stuck)\n    // or if the loop completed by covering all squares but the 100% check inside the loop\n    // didn't trigger an early exit (i.e., the last segment completed at exactly next_target).\n    // In any case, make sure to return to SI,SJ\n    string return_segment = reconstruct_path_segment(current_r, current_c, SI_global, SJ_global);\n    full_path += return_segment;\n\n    cout << full_path << endl; // Output the final path string\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <iomanip>\n#include <map>\n#include <cmath> // For std::round, std::clamp\n\n// Global constants and variables\nconst int MAX_SKILL_VAL = 100; // Upper bound for skills, based on problem generation info\nconst double INITIAL_S_GUESS = 20.0; // Initial guess for skill levels (from s_i,j generation range [20,60])\nconst double LEARNING_RATE_DENOM = 2.0; // Denominator for learning rate. Smaller value means faster learning.\n\nint N, M, K, R;\nstd::vector<std::vector<int>> D; // Task difficulties D[N][K]\nstd::vector<std::vector<int>> adj; // Adjacency list for dependencies: adj[u] lists tasks v that depend on u\nstd::vector<int> in_degree; // Number of prerequisites not yet completed for each task\n\nenum TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint total_tasks_completed = 0;\n\nstruct AssignedTask {\n    int task_id;\n    int start_day;\n};\n\nstd::vector<bool> member_is_free;\nstd::vector<AssignedTask> assigned_task_info; // assigned_task_info[member_idx]\nstd::vector<double> S_sum_D_task_difficulty; // Sum of D values for a task\n\n// Skill estimation\nstd::vector<std::vector<double>> S; // Estimated skill levels S[M][K]\nstd::vector<std::vector<double>> S_lower_bound; // Conservative lower bounds for skills\n\nint current_day = 0;\n\n// Set of ready tasks (in_degree is 0 and NOT_STARTED)\nstd::set<int> ready_tasks_set; // Stores task_id\n\n// Helper functions\ndouble calculate_w_internal(int member_idx, int task_idx) {\n    double w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += std::max(0.0, (double)D[task_idx][k] - S[member_idx][k]);\n    }\n    return w;\n}\n\nint calculate_t_estimated(int member_idx, int task_idx) {\n    double w = calculate_w_internal(member_idx, task_idx);\n    return std::max(1, (int)std::round(w)); // Round to nearest int, minimum 1\n}\n\n// Function to flush standard output\nvoid flush_stdout() {\n    std::cout << std::flush;\n}\n\n// Struct for candidate assignments to sort them\nstruct AssignmentCandidate {\n    int estimated_time;\n    int member_id;\n    int task_id;\n    // For tie-breaking\n    int out_degree; // Number of tasks unlocked by this task\n    double total_task_difficulty; // Sum of D values for the task\n\n    bool operator<(const AssignmentCandidate& other) const {\n        if (estimated_time != other.estimated_time) {\n            return estimated_time < other.estimated_time; // Prioritize shortest estimated time\n        }\n        // Tie-breaking for estimated_time\n        if (out_degree != other.out_degree) {\n            return out_degree > other.out_degree; // Prioritize tasks that unlock more tasks\n        }\n        if (total_task_difficulty != other.total_task_difficulty) {\n            return total_task_difficulty > other.total_task_difficulty; // Prioritize harder tasks\n        }\n        return task_id < other.task_id; // Stable sort by task_id\n    }\n};\n\nint main() {\n    // Faster I/O\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> K >> R;\n\n    D.resize(N, std::vector<int>(K));\n    S_sum_D_task_difficulty.resize(N);\n    for (int i = 0; i < N; ++i) {\n        double current_sum_D = 0;\n        for (int k = 0; k < K; ++k) {\n            std::cin >> D[i][k];\n            current_sum_D += D[i][k];\n        }\n        S_sum_D_task_difficulty[i] = current_sum_D;\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    task_status.resize(N, NOT_STARTED);\n    member_is_free.resize(M, true);\n    assigned_task_info.resize(M);\n\n    S.resize(M, std::vector<double>(K, INITIAL_S_GUESS));\n    S_lower_bound.resize(M, std::vector<double>(K, 0.0));\n\n    // Initialize ready_tasks_set: tasks with no dependencies or all dependencies met\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            ready_tasks_set.insert(i);\n        }\n    }\n\n    while (true) {\n        current_day++;\n\n        // Process daily input (completed tasks)\n        int n_completed;\n        std::cin >> n_completed;\n\n        if (n_completed == -1) {\n            break; // All tasks completed or max days reached, exit program\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_idx;\n            std::cin >> member_idx;\n            --member_idx; // 0-indexed\n\n            int completed_task_id = assigned_task_info[member_idx].task_id;\n            int start_day = assigned_task_info[member_idx].start_day;\n            int actual_t_ij = current_day - start_day + 1; // Actual days taken\n\n            // Update task status\n            task_status[completed_task_id] = COMPLETED;\n            total_tasks_completed++;\n\n            // Skill Estimation Update for member_idx\n            // Infer w_ij from actual_t_ij. If actual_t_ij == 1, assume w_ij=0 (most optimistic).\n            // Otherwise, assume w_ij = actual_t_ij, ignoring small random noise.\n            double observed_w = (actual_t_ij == 1) ? 0.0 : (double)actual_t_ij;\n            double current_predicted_w = calculate_w_internal(member_idx, completed_task_id);\n\n            // Strong evidence for S_lower_bound if task completed in 1 day\n            if (actual_t_ij == 1) { \n                for (int k = 0; k < K; ++k) {\n                    S_lower_bound[member_idx][k] = std::max(S_lower_bound[member_idx][k], (double)D[completed_task_id][k]);\n                }\n            } else { // actual_t_ij > 1, adjust S based on difference between predicted and observed w\n                double error = current_predicted_w - observed_w; // Positive if predicted was too high, negative if too low\n                int active_skills_count = 0; // Count skills where d_ik > S_jk currently\n                for (int k = 0; k < K; ++k) {\n                    if (D[completed_task_id][k] > S[member_idx][k]) {\n                        active_skills_count++;\n                    }\n                }\n\n                if (active_skills_count > 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (D[completed_task_id][k] > S[member_idx][k]) {\n                            // Adjust S[member_idx][k] to reduce the error.\n                            // If error > 0 (predicted w was too high), S[member_idx][k] needs to increase\n                            // If error < 0 (predicted w was too low), S[member_idx][k] needs to decrease\n                            S[member_idx][k] -= error / (active_skills_count * LEARNING_RATE_DENOM);\n                            S[member_idx][k] = std::clamp(S[member_idx][k], 0.0, (double)MAX_SKILL_VAL);\n                        }\n                    }\n                }\n            }\n\n            // Always apply lower bounds after any other adjustments to maintain consistency\n            for (int k = 0; k < K; ++k) {\n                S[member_idx][k] = std::max(S[member_idx][k], S_lower_bound[member_idx][k]);\n            }\n            \n            // Output skill predictions for visualization (round to nearest integer for output)\n            std::cout << \"#s \" << member_idx + 1;\n            for (int k = 0; k < K; ++k) {\n                std::cout << \" \" << static_cast<int>(std::round(S[member_idx][k]));\n            }\n            std::cout << std::endl;\n\n            // Free the member\n            member_is_free[member_idx] = true;\n\n            // Update in_degree for tasks dependent on the completed task\n            for (int dependent_task_id : adj[completed_task_id]) {\n                in_degree[dependent_task_id]--;\n                if (in_degree[dependent_task_id] == 0 && task_status[dependent_task_id] == NOT_STARTED) {\n                    ready_tasks_set.insert(dependent_task_id);\n                }\n            }\n        }\n\n        // Task Assignment Phase\n        std::vector<std::pair<int, int>> assignments_today;\n        std::vector<int> current_free_members;\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            if (member_is_free[m_idx]) {\n                current_free_members.push_back(m_idx);\n            }\n        }\n\n        // Prioritize a subset of ready tasks to consider for efficiency\n        std::vector<int> tasks_to_consider;\n        if (!ready_tasks_set.empty()) {\n            // Priority for selecting tasks to consider:\n            // High out_degree (unlocks more tasks), high average skill difficulty, then lower task_id\n            std::vector<std::pair<int, int>> sorted_ready_tasks; // (priority_score, task_id)\n            for(int tid : ready_tasks_set) {\n                // Heuristic score: combine out_degree (weighted) and average task difficulty\n                // Multiplying by 100 ensures out_degree has significant impact\n                int score = adj[tid].size() * 100 + static_cast<int>(S_sum_D_task_difficulty[tid] / K); \n                sorted_ready_tasks.push_back({score, tid});\n            }\n            std::sort(sorted_ready_tasks.rbegin(), sorted_ready_tasks.rend()); // Sort descending by score\n\n            // Limit the number of tasks considered to avoid O(M * N_ready * K) complexity\n            // Choose M * (some factor) or a fixed max (e.g., 200)\n            int num_to_consider = std::min((int)sorted_ready_tasks.size(), M * 15); \n            for (int i = 0; i < num_to_consider; ++i) {\n                tasks_to_consider.push_back(sorted_ready_tasks[i].second);\n            }\n        }\n\n        std::vector<AssignmentCandidate> candidates;\n        for (int m_idx : current_free_members) {\n            for (int t_idx : tasks_to_consider) {\n                if (task_status[t_idx] == NOT_STARTED) { // Double check task isn't assigned concurrently\n                    candidates.push_back({\n                        calculate_t_estimated(m_idx, t_idx),\n                        m_idx,\n                        t_idx,\n                        (int)adj[t_idx].size(),\n                        S_sum_D_task_difficulty[t_idx]\n                    });\n                }\n            }\n        }\n        std::sort(candidates.begin(), candidates.end());\n\n        // Greedily assign tasks based on sorted candidates\n        for (const auto& candidate : candidates) {\n            int m_idx = candidate.member_id;\n            int t_idx = candidate.task_id;\n\n            if (member_is_free[m_idx] && task_status[t_idx] == NOT_STARTED) {\n                assignments_today.push_back({m_idx + 1, t_idx + 1});\n                member_is_free[m_idx] = false;\n                task_status[t_idx] = IN_PROGRESS;\n                assigned_task_info[m_idx] = {t_idx, current_day}; // Store start day and task ID\n                ready_tasks_set.erase(t_idx); // Remove from ready set as it's now in progress\n            }\n            \n            // Break conditions: if all free members have been assigned OR all remaining tasks are assigned\n            if (assignments_today.size() == current_free_members.size() || \n                total_tasks_completed + assignments_today.size() == N) {\n                break; \n            }\n        }\n\n        // Output assignments for the day\n        std::cout << assignments_today.size();\n        for (const auto& p : assignments_today) {\n            std::cout << \" \" << p.first << \" \" << p.second;\n        }\n        std::cout << std::endl;\n        flush_stdout(); // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc006":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <set>\n#include <unordered_set>\n#include <tuple> // For std::tie\n\n// --- Structs ---\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id; // 1-indexed original ID\n    Point p; // pickup\n    Point d; // delivery\n};\n\nenum NodeType {\n    PICKUP_TYPE = 0,\n    DELIVERY_TYPE = 1\n};\n\nstruct RouteNode {\n    int order_id;\n    NodeType type;\n    Point coord;\n};\n\n// --- Global Constants ---\nconst Point OFFICE = {400, 400};\nconst int NUM_TOTAL_ORDERS = 1000;\nconst int NUM_DELIVERIES_QUOTA = 50;\n\n// --- Random Number Generator ---\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\nlong long manhattan_dist(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\n// Calculate total distance for a route represented by a sequence of RouteNodes\nlong long calculate_total_route_distance(const std::vector<RouteNode>& route_nodes) {\n    long long total_dist = 0;\n    if (route_nodes.empty()) {\n        return manhattan_dist(OFFICE, OFFICE);\n    }\n\n    total_dist += manhattan_dist(OFFICE, route_nodes[0].coord);\n    for (size_t i = 0; i < route_nodes.size() - 1; ++i) {\n        total_dist += manhattan_dist(route_nodes[i].coord, route_nodes[i+1].coord);\n    }\n    total_dist += manhattan_dist(route_nodes.back().coord, OFFICE);\n    return total_dist;\n}\n\n// Generates an initial route using a greedy Nearest Neighbor heuristic.\nstd::vector<RouteNode> generate_nearest_neighbor_route(const std::vector<int>& selected_order_ids, \n                                                       const std::map<int, Order>& all_orders_map) {\n    std::vector<RouteNode> route;\n    std::unordered_set<int> unpicked_order_ids(selected_order_ids.begin(), selected_order_ids.end());\n    std::unordered_set<int> un_delivered_order_ids;\n\n    Point current_pos = OFFICE;\n\n    while (!unpicked_order_ids.empty() || !un_delivered_order_ids.empty()) {\n        std::vector<std::pair<long long, RouteNode>> candidates; \n\n        for (int order_id : unpicked_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.p), {order_id, PICKUP_TYPE, order.p}});\n        }\n\n        for (int order_id : un_delivered_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.d), {order_id, DELIVERY_TYPE, order.d}});\n        }\n\n        if (candidates.empty()) break;\n\n        long long min_dist = candidates[0].first;\n        for (size_t i = 1; i < candidates.size(); ++i) {\n            if (candidates[i].first < min_dist) {\n                min_dist = candidates[i].first;\n            }\n        }\n\n        std::vector<RouteNode> best_candidates_nodes;\n        for (const auto& cand : candidates) {\n            if (cand.first == min_dist) {\n                best_candidates_nodes.push_back(cand.second);\n            }\n        }\n        \n        std::uniform_int_distribution<int> dist_cand_idx(0, best_candidates_nodes.size() - 1);\n        RouteNode chosen_node = best_candidates_nodes[dist_cand_idx(rng)];\n\n        route.push_back(chosen_node);\n        current_pos = chosen_node.coord;\n\n        if (chosen_node.type == PICKUP_TYPE) {\n            unpicked_order_ids.erase(chosen_node.order_id);\n            un_delivered_order_ids.insert(chosen_node.order_id);\n        } else { // DELIVERY_TYPE\n            un_delivered_order_ids.erase(chosen_node.order_id);\n        }\n    }\n    return route;\n}\n\n// Calculates delta cost for removing a node at `idx` from `current_route`.\n// The points before and after `idx` will be connected.\nlong long calculate_removal_delta(const std::vector<RouteNode>& current_route, int idx) {\n    Point p_before = (idx == 0) ? OFFICE : current_route[idx - 1].coord;\n    Point p_node = current_route[idx].coord;\n    Point p_after = (idx == current_route.size() - 1) ? OFFICE : current_route[idx + 1].coord;\n    \n    long long dist_removed_segment = manhattan_dist(p_before, p_node) + manhattan_dist(p_node, p_after);\n    long long dist_merged_segment = manhattan_dist(p_before, p_after);\n    return dist_merged_segment - dist_removed_segment;\n}\n\n// Calculates delta cost for inserting a node at `insert_idx` into `current_route`.\n// The node will be inserted between `current_route[insert_idx-1]` and `current_route[insert_idx]`.\nlong long calculate_insertion_delta(const std::vector<RouteNode>& current_route, int insert_idx, const RouteNode& node_to_insert) {\n    Point p_before = (insert_idx == 0) ? OFFICE : current_route[insert_idx - 1].coord;\n    Point p_after = (insert_idx == current_route.size()) ? OFFICE : current_route[insert_idx].coord;\n    \n    long long dist_new_segment = manhattan_dist(p_before, node_to_insert.coord) + manhattan_dist(node_to_insert.coord, p_after);\n    long long dist_old_at_insert_point = manhattan_dist(p_before, p_after);\n    return dist_new_segment - dist_old_at_insert_point;\n}\n\n\n// Applies a node relocation local search operator.\n// Returns the new route and the new total distance.\nstd::pair<std::vector<RouteNode>, long long> relocate_node_and_calculate_delta(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist) {\n\n    if (current_route.empty()) return {current_route, current_total_dist}; // No nodes to relocate\n\n    std::uniform_int_distribution<int> dist_move_idx(0, current_route.size() - 1);\n    int move_idx = dist_move_idx(rng);\n    RouteNode node_to_move = current_route[move_idx];\n\n    long long delta_from_removal = calculate_removal_delta(current_route, move_idx);\n\n    // Create a temporary route with the node removed\n    std::vector<RouteNode> new_route_temp;\n    new_route_temp.reserve(current_route.size() - 1);\n    for (size_t i = 0; i < current_route.size(); ++i) {\n        if (i == (size_t)move_idx) continue;\n        new_route_temp.push_back(current_route[i]);\n    }\n    \n    int min_insert_idx = 0;\n    int max_insert_idx = new_route_temp.size(); // Default: can insert anywhere\n\n    if (node_to_move.type == PICKUP_TYPE) {\n        int Di_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == DELIVERY_TYPE) {\n                Di_pos = i;\n                break;\n            }\n        }\n        if (Di_pos != -1) { \n            max_insert_idx = Di_pos;\n        }\n    } else { // DELIVERY_TYPE\n        int Pi_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == PICKUP_TYPE) {\n                Pi_pos = i;\n                break;\n            }\n        }\n        if (Pi_pos != -1) { \n            min_insert_idx = Pi_pos + 1;\n        }\n    }\n    \n    if (min_insert_idx > max_insert_idx) { // Safety check. Should not happen if original route was valid.\n         min_insert_idx = 0; \n         max_insert_idx = new_route_temp.size();\n    }\n    if (new_route_temp.empty()) { // Special case: current_route had only 1 node. After removal, it's empty.\n        min_insert_idx = 0;\n        max_insert_idx = 0;\n    }\n\n    std::uniform_int_distribution<int> dist_insert_pos(min_insert_idx, max_insert_idx);\n    int insert_pos = dist_insert_pos(rng); \n    \n    long long delta_from_insertion = calculate_insertion_delta(new_route_temp, insert_pos, node_to_move);\n\n    new_route_temp.insert(new_route_temp.begin() + insert_pos, node_to_move);\n\n    long long new_total_dist = current_total_dist + delta_from_removal + delta_from_insertion;\n\n    return {new_route_temp, new_total_dist};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // --- Input Reading ---\n    std::vector<Order> all_orders_orig(NUM_TOTAL_ORDERS); // Store original orders to easily access by id-1\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        all_orders_orig[i].id = i + 1; // 1-indexed\n        std::cin >> all_orders_orig[i].p.x >> all_orders_orig[i].p.y >> all_orders_orig[i].d.x >> all_orders_orig[i].d.y;\n    }\n\n    // --- Initial Selection (Greedy based on standalone cost) ---\n    std::vector<std::pair<long long, int>> order_costs(NUM_TOTAL_ORDERS); // {cost, original_id}\n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        long long cost = manhattan_dist(OFFICE, all_orders_orig[i].p) +\n                         manhattan_dist(all_orders_orig[i].p, all_orders_orig[i].d) +\n                         manhattan_dist(all_orders_orig[i].d, OFFICE);\n        order_costs[i] = {cost, all_orders_orig[i].id};\n    }\n    std::sort(order_costs.begin(), order_costs.end());\n\n    std::vector<int> current_selected_order_ids_vec;\n    std::map<int, Order> current_selected_orders_map; // Stores selected orders for quick lookup\n    std::vector<int> unselected_order_ids_vec;\n\n    for (int i = 0; i < NUM_DELIVERIES_QUOTA; ++i) {\n        int order_id = order_costs[i].second;\n        current_selected_order_ids_vec.push_back(order_id);\n        current_selected_orders_map[order_id] = all_orders_orig[order_id - 1]; // Store 1-indexed\n    }\n    for (int i = NUM_DELIVERIES_QUOTA; i < NUM_TOTAL_ORDERS; ++i) {\n        unselected_order_ids_vec.push_back(order_costs[i].second);\n    }\n\n    // --- Initial Route Generation ---\n    std::vector<RouteNode> current_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n    long long current_total_dist = calculate_total_route_distance(current_route_nodes);\n\n    // --- Best Solution Tracking ---\n    long long best_total_dist = current_total_dist;\n    std::vector<RouteNode> best_route_nodes = current_route_nodes;\n    std::vector<int> best_selected_order_ids = current_selected_order_ids_vec;\n\n    // --- Simulated Annealing Parameters ---\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SEC = 1.95; // Slightly increased time limit\n    const double T_START = 5000.0;     // Initial temperature\n    const double T_END = 1.0;          // Final temperature\n    const double PROB_ORDER_SWAP = 0.05; // Probability of performing an order swap\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_selected_idx(0, NUM_DELIVERIES_QUOTA - 1);\n    \n    // --- Simulated Annealing Loop ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_sec = std::chrono::duration<double>(current_time - start_time).count();\n\n        if (elapsed_sec >= TIME_LIMIT_SEC) {\n            break;\n        }\n\n        double progress = elapsed_sec / TIME_LIMIT_SEC;\n        double current_T = T_START * std::pow(T_END / T_START, progress);\n\n        long long new_total_dist;\n        std::vector<RouteNode> new_route_nodes;\n        bool orders_swapped_this_iter = false; \n\n        // Declare swap related indices outside the if block for scope\n        int out_vec_idx = -1; \n        int in_vec_idx = -1;\n        \n        if (dist_0_1(rng) < PROB_ORDER_SWAP && !unselected_order_ids_vec.empty()) {\n            // --- Order Swap Operation (Optimized) ---\n            orders_swapped_this_iter = true;\n            out_vec_idx = dist_selected_idx(rng);\n            int order_out_id = current_selected_order_ids_vec[out_vec_idx];\n\n            std::uniform_int_distribution<int> dist_unselected_idx(0, unselected_order_ids_vec.size() - 1);\n            in_vec_idx = dist_unselected_idx(rng);\n            int order_in_id = unselected_order_ids_vec[in_vec_idx];\n\n            // 1. Create a temporary route by removing order_out_id's nodes\n            std::vector<RouteNode> temp_route_after_removal;\n            temp_route_after_removal.reserve(current_route_nodes.size() - 2);\n            for(const auto& node : current_route_nodes) {\n                if(node.order_id != order_out_id) {\n                    temp_route_after_removal.push_back(node);\n                }\n            }\n            long long dist_after_removal = calculate_total_route_distance(temp_route_after_removal);\n\n            // 2. Insert order_in_id's nodes (P_in, D_in) greedily\n            const Order& order_in = all_orders_orig[order_in_id - 1];\n            RouteNode p_in_node = {order_in_id, PICKUP_TYPE, order_in.p};\n            RouteNode d_in_node = {order_in_id, DELIVERY_TYPE, order_in.d};\n\n            // Find best insertion for P_in\n            std::vector<RouteNode> route_working_copy = temp_route_after_removal;\n            long long dist_working_copy = dist_after_removal;\n            int best_p_in_insert_pos = 0;\n            long long min_p_in_delta = -1; // Placeholder for a very large value, or use LLONG_MAX\n\n            for (int i = 0; i <= route_working_copy.size(); ++i) {\n                long long current_delta = calculate_insertion_delta(route_working_copy, i, p_in_node);\n                if (min_p_in_delta == -1 || current_delta < min_p_in_delta) {\n                    min_p_in_delta = current_delta;\n                    best_p_in_insert_pos = i;\n                }\n            }\n            route_working_copy.insert(route_working_copy.begin() + best_p_in_insert_pos, p_in_node);\n            dist_working_copy += min_p_in_delta;\n            \n            // Find P_in's exact position in the modified route_working_copy (it's best_p_in_insert_pos if no other elements were inserted)\n            // But we need to be robust. It's guaranteed to be at this spot due to the `insert` call.\n            int p_in_actual_pos = best_p_in_insert_pos;\n\n            // Find best insertion for D_in (after P_in's actual position)\n            int best_d_in_insert_pos = p_in_actual_pos + 1; // Default to immediately after P_in\n            long long min_d_in_delta = -1; // Placeholder for a very large value\n\n            for (int i = p_in_actual_pos + 1; i <= route_working_copy.size(); ++i) {\n                 long long current_delta = calculate_insertion_delta(route_working_copy, i, d_in_node);\n                if (min_d_in_delta == -1 || current_delta < min_d_in_delta) {\n                    min_d_in_delta = current_delta;\n                    best_d_in_insert_pos = i;\n                }\n            }\n            \n            new_route_nodes = route_working_copy; // This will be the new route for the SA state\n            new_route_nodes.insert(new_route_nodes.begin() + best_d_in_insert_pos, d_in_node);\n            new_total_dist = dist_working_copy + min_d_in_delta;\n            \n            // --- Temporarily Apply the swap to current_selected_order_ids_vec and current_selected_orders_map for acceptance check ---\n            // If the move is accepted, these temporary changes become permanent. If rejected, they are reverted.\n            current_selected_order_ids_vec[out_vec_idx] = order_in_id;\n            unselected_order_ids_vec[in_vec_idx] = order_out_id;\n            current_selected_orders_map.erase(order_out_id);\n            current_selected_orders_map[order_in_id] = all_orders_orig[order_in_id - 1];\n\n        } else {\n            // --- Route Relocation Operation ---\n            std::tie(new_route_nodes, new_total_dist) = relocate_node_and_calculate_delta(current_route_nodes, current_total_dist);\n        }\n\n        // --- Acceptance Criteria ---\n        if (new_total_dist < current_total_dist) {\n            current_total_dist = new_total_dist;\n            current_route_nodes = new_route_nodes;\n        } else {\n            double prob_acceptance = std::exp((double)(current_total_dist - new_total_dist) / current_T);\n            if (dist_0_1(rng) < prob_acceptance) {\n                current_total_dist = new_total_dist;\n                current_route_nodes = new_route_nodes;\n            } else {\n                // Reject: if orders were swapped, revert them\n                if (orders_swapped_this_iter) {\n                    // Revert the last swap using the stored indices\n                    int order_in_id_to_revert = current_selected_order_ids_vec[out_vec_idx]; // This is the new order at the old position\n                    int order_out_id_to_revert = unselected_order_ids_vec[in_vec_idx];     // This is the old order at the new position in unselected\n\n                    current_selected_order_ids_vec[out_vec_idx] = order_out_id_to_revert;\n                    unselected_order_ids_vec[in_vec_idx] = order_in_id_to_revert;\n                    \n                    current_selected_orders_map.erase(order_in_id_to_revert);\n                    current_selected_orders_map[order_out_id_to_revert] = all_orders_orig[order_out_id_to_revert - 1];\n                }\n            }\n        }\n\n        // --- Update Best Solution ---\n        if (current_total_dist < best_total_dist) {\n            best_total_dist = current_total_dist;\n            best_route_nodes = current_route_nodes;\n            // IMPORTANT: best_selected_order_ids must reflect the order selection that generated best_route_nodes\n            // The current current_selected_order_ids_vec is always up-to-date with current_route_nodes.\n            best_selected_order_ids = current_selected_order_ids_vec; \n        }\n    }\n\n    // --- Output ---\n    std::cout << NUM_DELIVERIES_QUOTA;\n    for (int id : best_selected_order_ids) {\n        std::cout << \" \" << id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_route_nodes.size() + 2; // +2 for start and end office points\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (const auto& node : best_route_nodes) {\n        std::cout << \" \" << node.coord.x << \" \" << node.coord.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric> \n#include <iomanip>\n#include <algorithm>\n\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    long long d; // Precomputed rounded Euclidean distance\n};\n\n// Global constants for problem size\nconst int N_NODES = 400;\nconst int M_EDGES = 1995;\n\n// Function to calculate rounded Euclidean distance\nlong long calculate_d(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    // dx*dx + dy*dy can be up to 800^2 + 800^2 = 1,280,000. Fits in long long.\n    // sqrt of 1,280,000 is approx 1131.\n    return std::round(std::sqrt(static_cast<double>(dx * dx + dy * dy)));\n}\n\n// Heuristic parameters for tuning\n// TAU_MIN: Initial strictness for cost ratio l_i / d_i\n// Decreased from 1.3 to 1.2 to be more selective early on.\nconst double TAU_MIN = 1.2; \n// TAU_MAX: Final leniency for cost ratio l_i / d_i when close to connecting all nodes\n// Kept at 3.0 to ensure connectivity at the very end.\nconst double TAU_MAX = 3.0; \n\n// BASE_REDUNDANCY_FACTOR: M_EDGES / (N_NODES - 1) is the factual average redundancy.\n// For N=400, M=1995, this is 1995 / 399 = 5.0.\nconst double BASE_REDUNDANCY_FACTOR = static_cast<double>(M_EDGES) / (N_NODES - 1.0);\n\n// EFFECTIVE_REDUNDANCY_DENOMINATOR: A tuning parameter. Lowering this makes\n// `potential_useful_remaining` larger, delaying the urgency trigger.\n// Decreased from 6.0 to 5.5 to be less aggressive with urgency (more cost-sensitive).\nconst double EFFECTIVE_REDUNDANCY_DENOMINATOR = 5.5; \n\n// URGENCY_SAFETY_MARGIN: A small buffer for the urgency condition.\n// Kept at 0.0 to ensure strict urgency when it does trigger.\nconst double URGENCY_SAFETY_MARGIN = 0.0; \n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    std::vector<Point> vertices(N_NODES);\n    for (int i = 0; i < N_NODES; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<EdgeInfo> edges(M_EDGES);\n    for (int i = 0; i < M_EDGES; ++i) {\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].d = calculate_d(vertices[edges[i].u], vertices[edges[i].v]);\n    }\n\n    atcoder::dsu dsu(N_NODES);\n    int edges_taken_count = 0;\n\n    for (int i = 0; i < M_EDGES; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        long long d_val = edges[i].d;\n\n        long long l_val;\n        std::cin >> l_val;\n\n        int decision = 0; // Default: reject\n\n        if (!dsu.same(u, v)) {\n            int needed_to_connect = dsu.groups().size() - 1; \n            int remaining_candidates = M_EDGES - (i + 1);\n            double cost_ratio = static_cast<double>(l_val) / d_val;\n\n            double potential_useful_remaining = 0.0;\n            // Guard against division by zero. EFFECTIVE_REDUNDANCY_DENOMINATOR is constant > 0.\n            if (EFFECTIVE_REDUNDANCY_DENOMINATOR > 0) { \n                 potential_useful_remaining = static_cast<double>(remaining_candidates) / EFFECTIVE_REDUNDANCY_DENOMINATOR;\n            }\n            \n            // --- Urgency Check ---\n            // If the number of merges needed is greater than or equal to the (pessimistic)\n            // estimate of useful edges remaining, then we must take this edge.\n            if (needed_to_connect >= potential_useful_remaining - URGENCY_SAFETY_MARGIN) {\n                decision = 1;\n            } else {\n                // --- Adaptive Threshold Check ---\n                // progress_ratio_taken is (edges_taken_count / (N_NODES - 1.0)), which is also\n                // equivalent to ((N_NODES - dsu.groups().size()) / (N_NODES - 1.0)),\n                // measuring how much of the MST has been completed.\n                double progress_ratio_taken = static_cast<double>(edges_taken_count) / (N_NODES - 1.0);\n                // current_tau interpolates between TAU_MIN (at start) and TAU_MAX (at completion).\n                double current_tau = TAU_MIN + (TAU_MAX - TAU_MIN) * progress_ratio_taken;\n\n                if (cost_ratio <= current_tau) {\n                    decision = 1;\n                }\n            }\n        }\n\n        if (decision == 1) {\n            dsu.merge(u, v);\n            edges_taken_count++;\n        }\n\n        std::cout << decision << std::endl;\n    }\n\n    return 0;\n}\n","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <set>\n#include <algorithm>\n#include <tuple> // For std::tie\n#include <map>   // For BFS path reconstruction\n\nusing namespace std;\n\n// Global constants\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: U, D, L, R\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    // Overload operators for use in sets/maps and comparisons\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    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// Game state variables\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type; // Not used for movement prediction in this solution\nvector<Point> human_pos;\n\n// Board state: 0=passable, 1=impassable (wall)\nvector<vector<int>> board(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n\n// Global BFS data structures (re-used each time BFS is called)\nvector<vector<int>> dist_bfs;\nvector<vector<Point>> parent_bfs;\n\n// Function to check if a point is within grid boundaries\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// BFS to find shortest path distance from start to target_dest_for_human.\n// Also stores parent pointers to reconstruct the first step of the path.\n// `start`: The starting point for BFS (human's current position).\n// `target_dest_for_human`: The specific cell the human wants to move to.\n// `current_blocked_this_turn`: Set of cells that will become walls this turn by other humans.\n// `current_moved_to_this_turn_targets`: Set of cells that other humans are planning to move to this turn.\n// `all_human_current_pos`: Current positions of all humans (to avoid pathfinding through other humans' current spots).\n// `self_idx`: Index of the human for whom BFS is being run (to allow passing through its own start cell).\nint bfs(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n        const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    dist_bfs.assign(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    parent_bfs.assign(GRID_SIZE, vector<Point>(GRID_SIZE, {-1, -1}));\n    queue<Point> q;\n\n    q.push(start);\n    dist_bfs[start.r][start.c] = 0;\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        if (curr == target_dest_for_human) {\n            return dist_bfs[curr.r][curr.c]; // Target reached\n        }\n\n        // Explore 4 cardinal neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.r + DR[i];\n            int nc = curr.c + DC[i];\n            Point next = {nr, nc};\n\n            // Basic checks: within bounds, not visited yet\n            if (!is_valid(nr, nc) || dist_bfs[nr][nc] != -1) continue;\n\n            // Check if 'next' cell is impassable due to existing walls or planned blocks\n            if (board[nr][nc] == 1) continue; // Existing permanent wall\n            if (current_blocked_this_turn.count(next)) continue; // Blocked by another human this turn\n\n            // Check if 'next' cell is a target for another human's move this turn\n            if (current_moved_to_this_turn_targets.count(next)) continue;\n            \n            // Check if 'next' cell is currently occupied by another human (who isn't moving out of it)\n            bool is_other_human_current_pos = false;\n            for(int h_idx_other = 0; h_idx_other < M; ++h_idx_other) {\n                if (h_idx_other == self_idx) continue; // Current human can pass through its own start\n                if (all_human_current_pos[h_idx_other] == next) {\n                    is_other_human_current_pos = true;\n                    break;\n                }\n            }\n            if (is_other_human_current_pos) continue; // Impassable if another human is currently there\n\n            // If all checks pass, 'next' is a valid step\n            dist_bfs[nr][nc] = dist_bfs[curr.r][curr.c] + 1;\n            parent_bfs[nr][nc] = curr;\n            q.push(next);\n        }\n    }\n    return -1; // Target not reachable\n}\n\n// Reconstructs the character for the first move from 'start' to 'target_dest_for_human' based on BFS path.\nchar get_move_char(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n                   const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    if (bfs(start, target_dest_for_human, current_blocked_this_turn, current_moved_to_this_turn_targets, all_human_current_pos, self_idx) == -1) {\n        return '.'; // No path found\n    }\n\n    // Path reconstruction: find the first step from 'start' towards 'target_dest_for_human'\n    Point curr = target_dest_for_human;\n    // Walk back from target until we find the child of 'start'\n    while (parent_bfs[curr.r][curr.c] != start) {\n        curr = parent_bfs[curr.r][curr.c];\n        if (curr.r == -1 || curr.c == -1) return '.'; // Safety break for invalid parent\n    }\n\n    // 'curr' is now the first step from 'start'\n    for (int i = 0; i < 4; ++i) {\n        if (start.r + DR[i] == curr.r && start.c + DC[i] == curr.c) {\n            return MOVE_CHARS[i]; // Return corresponding move character\n        }\n    }\n    return '.'; // Should not be reached if BFS found a path\n}\n\n// Structure to represent a rectangle (inclusive coordinates, 0-indexed)\nstruct Rect {\n    int r1, c1, r2, c2;\n    int area() const { \n        if (r1 < 0 || c1 < 0 || r2 >= GRID_SIZE || c2 >= GRID_SIZE || r1 > r2 || c1 > c2) return 0; // Handle invalid rectangles\n        return (r2 - r1 + 1) * (c2 - c1 + 1); \n    }\n    // Check if a point is inside the rectangle\n    bool contains(Point p) const {\n        return p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2;\n    }\n};\n\nRect target_rect = {0, 0, 0, 0}; // The main region humans will try to enclose\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read initial pet information\n    cin >> N;\n    pet_pos.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i];\n        pet_pos[i].r--; // Convert to 0-indexed\n        pet_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // Read initial human information\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].r >> human_pos[i].c;\n        human_pos[i].r--; // Convert to 0-indexed\n        human_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // --- Initialization Phase: Find the best target rectangle ---\n    long long max_heuristic_score = -2e18; // Initialize with a very small number\n    Rect best_initial_rect = {-1, -1, -1, -1}; // Initialize with an invalid rectangle\n\n    // Brute force search for the best pet-free rectangle\n    for (int r1 = 0; r1 < GRID_SIZE; ++r1) {\n        for (int c1 = 0; c1 < GRID_SIZE; ++c1) {\n            for (int r2 = r1; r2 < GRID_SIZE; ++r2) {\n                for (int c2 = c1; c2 < GRID_SIZE; ++c2) {\n                    Rect current_rect = {r1, c1, r2, c2};\n                    bool is_pet_free = true;\n                    // Check if any pet is inside the current rectangle\n                    for (int i = 0; i < N; ++i) {\n                        if (current_rect.contains(pet_pos[i])) {\n                            is_pet_free = false;\n                            break;\n                        }\n                    }\n\n                    if (is_pet_free) {\n                        long long current_area = current_rect.area();\n                        if (current_area == 0) continue; // Skip 0-area rectangles\n                        \n                        // 1. Calculate sum of Manhattan distances from humans to perimeter of current_rect itself\n                        long long dist_sum_to_human_perimeter = 0;\n                        vector<Point> perimeter_of_rect_itself;\n                        for (int c = c1; c <= c2; ++c) {\n                            perimeter_of_rect_itself.push_back({r1, c});\n                            if (r1 != r2) perimeter_of_rect_itself.push_back({r2, c});\n                        }\n                        for (int r = r1 + 1; r < r2; ++r) { // Start from r1+1 to avoid double-counting corners with top/bottom rows\n                            perimeter_of_rect_itself.push_back({r, c1});\n                            if (c1 != c2) perimeter_of_rect_itself.push_back({r, c2});\n                        }\n                        \n                        if (!perimeter_of_rect_itself.empty()) {\n                            for (int i = 0; i < M; ++i) {\n                                int min_dist = 100000; \n                                for (const auto& p_cell : perimeter_of_rect_itself) {\n                                    min_dist = min(min_dist, abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c));\n                                }\n                                dist_sum_to_human_perimeter += min_dist;\n                            }\n                        } else { \n                            dist_sum_to_human_perimeter = 100000 * M; // High penalty for unapproachable/empty perimeter\n                        }\n\n                        // 2. Calculate initial \"vulnerability\" (number of unblockable wall cells around it)\n                        int vulnerability_score = 0;\n                        // Find potential wall cells (adjacent to current_rect, outside it)\n                        for (int r_outer = 0; r_outer < GRID_SIZE; ++r_outer) {\n                            for (int c_outer = 0; c_outer < GRID_SIZE; ++c_outer) {\n                                Point p_outer = {r_outer, c_outer};\n                                if (current_rect.contains(p_outer)) continue; // Can't block inside target rect\n                                bool adjacent_to_rect_internal = false;\n                                for (int d = 0; d < 4; ++d) {\n                                    Point neighbor_internal = {r_outer + DR[d], c_outer + DC[d]};\n                                    if (current_rect.contains(neighbor_internal)) {\n                                        adjacent_to_rect_internal = true;\n                                        break;\n                                    }\n                                }\n                                if (adjacent_to_rect_internal) { // p_outer is a candidate wall cell\n                                    // Check if this wall cell is initially unblockable due to pets\n                                    bool is_unblockable_by_pet_influence = false;\n                                    for (int p_idx = 0; p_idx < N; ++p_idx) {\n                                        Point pet = pet_pos[p_idx];\n                                        if (pet == p_outer) { // Pet is on the wall cell itself\n                                            is_unblockable_by_pet_influence = true;\n                                            break;\n                                        }\n                                        for (int d_pet = 0; d_pet < 4; ++d_pet) {\n                                            Point pet_neighbor = {pet.r + DR[d_pet], pet.c + DC[d_pet]};\n                                            if (pet_neighbor == p_outer) { // Wall cell is adjacent to a pet\n                                                is_unblockable_by_pet_influence = true;\n                                                break;\n                                            }\n                                        }\n                                        if (is_unblockable_by_pet_influence) break;\n                                    }\n                                    if (is_unblockable_by_pet_influence) {\n                                        vulnerability_score++;\n                                    }\n                                }\n                            }\n                        }\n                        \n                        // Heuristic score: Area - W1 * Sum_of_Distances - W2 * Vulnerability_Score\n                        // W1 = 1 to value proximity to humans\n                        // W2 = 10 to strongly penalize walls that are hard to build initially due to pets\n                        long long current_heuristic_score = current_area - dist_sum_to_human_perimeter * 1 - (long long)vulnerability_score * 10; \n\n                        if (current_heuristic_score > max_heuristic_score) {\n                            max_heuristic_score = current_heuristic_score;\n                            best_initial_rect = current_rect;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback: If no good pet-free rectangle found or area is too small.\n    // Use an arbitrary threshold of 25 cells for \"too small\" for M=5 humans.\n    if (best_initial_rect.area() == 0 || best_initial_rect.area() < (long long)M * 5) { \n        target_rect = {5, 5, 24, 24}; // Default to 20x20 central square (0-indexed)\n        // Ensure this fallback is also pet-free, if not, then the entire score will be zero anyway.\n        // It's assumed inputs guarantee at least some viable region.\n    } else {\n        target_rect = best_initial_rect;\n    }\n\n    // Generate the set of actual target wall cells that humans will block\n    // These are cells adjacent to target_rect, but outside target_rect.\n    set<Point> wall_target_cells_set;\n    for (int r_cell = 0; r_cell < GRID_SIZE; ++r_cell) {\n        for (int c_cell = 0; c_cell < GRID_SIZE; ++c_cell) {\n            Point p = {r_cell, c_cell};\n            if (target_rect.contains(p)) continue; // Cannot block inside the target rect\n            bool is_adjacent_to_target_rect_internal = false;\n            for (int d = 0; d < 4; ++d) {\n                Point neighbor = {r_cell + DR[d], c_cell + DC[d]};\n                if (target_rect.contains(neighbor)) {\n                    is_adjacent_to_target_rect_internal = true;\n                    break;\n                }\n            }\n            if (is_adjacent_to_target_rect_internal) {\n                wall_target_cells_set.insert(p);\n            }\n        }\n    }\n    // Convert to vector for easier iteration with indices.\n    vector<Point> target_wall_goals_vector(wall_target_cells_set.begin(), wall_target_cells_set.end());\n    \n    // `human_target_wall_goals[i]` stores the specific wall cell that human 'i' is trying to block.\n    vector<Point> human_target_wall_goals(M, {-1,-1}); \n\n    // --- Main Loop: 300 turns of human actions and pet movements ---\n    for (int turn = 0; turn < MAX_TURNS; ++turn) {\n        // 1. Determine `can_block_grid`: which cells are valid to block this turn.\n        // Initialize to true, then mark invalid ones.\n        vector<vector<bool>> can_block_grid(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n        // Pets make cells unblockable\n        for (int i = 0; i < N; ++i) {\n            Point p = pet_pos[i];\n            // Cell containing pet is unblockable\n            if(is_valid(p.r, p.c)) can_block_grid[p.r][p.c] = false; \n            // Cells adjacent to a pet are unblockable\n            for (int d = 0; d < 4; ++d) { \n                int nr = p.r + DR[d];\n                int nc = p.c + DC[d];\n                if (is_valid(nr, nc)) {\n                    can_block_grid[nr][nc] = false;\n                }\n            }\n        }\n        // Humans make cells unblockable (their own position)\n        for (int i = 0; i < M; ++i) {\n            Point h = human_pos[i];\n            if(is_valid(h.r, h.c)) can_block_grid[h.r][h.c] = false; \n        }\n\n        // 2. Human Action Planning\n        vector<char> actions_output(M, '.'); // Stores the final action character for each human\n        vector<Point> next_human_pos_candidates(M); // Stores each human's position AFTER actions\n        for(int i=0; i<M; ++i) next_human_pos_candidates[i] = human_pos[i]; // Default: stay put\n\n        set<Point> current_blocked_this_turn;       // Cells chosen to be blocked by humans THIS turn\n        set<Point> current_moved_to_this_turn_targets; // Cells chosen to be moved into by humans THIS turn\n\n        // 2.1. Update each human's block goal\n        // Humans greedily pick the best available wall target cell based on a score.\n        for (int i = 0; i < M; ++i) {\n            // Re-assign goal if current goal is completed, invalid, or already blocked\n            if (human_target_wall_goals[i].r == -1 || \n                !is_valid(human_target_wall_goals[i].r, human_target_wall_goals[i].c) ||\n                board[human_target_wall_goals[i].r][human_target_wall_goals[i].c] == 1) { \n                \n                Point best_goal = {-1,-1};\n                long long max_current_cell_score_for_human = -2e18; // Initialize with a very small number\n\n                // Temporarily track goals assigned to other humans (within this turn's assignment phase)\n                set<Point> temp_assigned_goals;\n                for(int j=0; j<M; ++j) {\n                    if (j != i && human_target_wall_goals[j].r != -1) {\n                        temp_assigned_goals.insert(human_target_wall_goals[j]);\n                    }\n                }\n\n                for (const auto& p_cell : target_wall_goals_vector) { // Iterate over actual wall target cells\n                    // Check if the wall target cell is currently:\n                    //   1. Passable (not already a permanent wall)\n                    //   2. Blockable (no pets nearby, not occupied by human/pet)\n                    //   3. Not already being blocked by another human this turn (from current_blocked_this_turn)\n                    //   4. Not already assigned as a goal to another human (for current goal assignment phase)\n                    if (board[p_cell.r][p_cell.c] == 0 && can_block_grid[p_cell.r][p_cell.c] && \n                        !current_blocked_this_turn.count(p_cell) && !temp_assigned_goals.count(p_cell)) {\n                        \n                        long long current_cell_score = 0;\n                        int dist_to_human = abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c); \n                        \n                        // Penalty for distance from human (lower dist is better, so subtract dist)\n                        current_cell_score -= (long long)dist_to_human * 1; \n\n                        // Bonus for blocking cells that are near pets (higher danger is better to block)\n                        int pet_danger_score = 0;\n                        for (int p_idx = 0; p_idx < N; ++p_idx) {\n                            Point pet = pet_pos[p_idx];\n                            if (target_rect.contains(pet)) continue; // Only consider pets outside target_rect\n                            \n                            int pet_dist = abs(pet.r - p_cell.r) + abs(pet.c - p_cell.c);\n                            if (pet_dist == 1) { // Manhattan dist 1 means adjacent\n                                pet_danger_score += 100; // Significant bonus for blocking a cell directly adjacent to a pet\n                            } else if (pet_dist == 2) { // Manhattan dist 2\n                                pet_danger_score += 10; // Moderate bonus\n                            } else if (pet_dist == 3) {\n                                pet_danger_score += 1; // Small bonus\n                            }\n                        }\n                        current_cell_score += pet_danger_score;\n\n                        if (current_cell_score > max_current_cell_score_for_human) {\n                            max_current_cell_score_for_human = current_cell_score;\n                            best_goal = p_cell;\n                        }\n                    }\n                }\n                human_target_wall_goals[i] = best_goal; // Assign the new best goal\n            }\n        }\n        \n        // 2.2. Phase 1: Determine BLOCK actions\n        // Humans who are adjacent to their block goal perform the block action.\n        for (int i = 0; i < M; ++i) {\n            if (human_target_wall_goals[i].r != -1) {\n                Point goal_to_block = human_target_wall_goals[i]; // This is the cell to make impassable\n                for (int d = 0; d < 4; ++d) { // Check if human is adjacent to this goal_to_block\n                    if (human_pos[i].r + DR[d] == goal_to_block.r && human_pos[i].c + DC[d] == goal_to_block.c) { \n                        // Human is adjacent to goal_to_block. Can they block it?\n                        if (board[goal_to_block.r][goal_to_block.c] == 0 && can_block_grid[goal_to_block.r][goal_to_block.c] && !current_blocked_this_turn.count(goal_to_block)) {\n                            actions_output[i] = BLOCK_CHARS[d]; // Set block action\n                            current_blocked_this_turn.insert(goal_to_block); // Mark as blocked for this turn\n                            board[goal_to_block.r][goal_to_block.c] = 1; // Temporarily update board for pathfinding in Phase 2\n                            human_target_wall_goals[i] = {-1,-1}; // Goal achieved, reset\n                        }\n                        break; // A human can only perform one action (block or move)\n                    }\n                }\n            }\n        }\n        \n        // 2.3. Phase 2: Determine MOVE actions for humans who did not block.\n        // Use a priority queue to resolve conflicts for moving to the same cell.\n        struct MoveCandidate {\n            int human_idx;\n            Point next_pos; // The cell human will move TO\n            char move_char;\n            int priority; // Higher priority (e.g., closer to goal) is better\n            bool operator<(const MoveCandidate& other) const {\n                return priority < other.priority; // Min-priority queue for default, so this makes it max-priority.\n            }\n        };\n        priority_queue<MoveCandidate> move_queue;\n\n        for (int i = 0; i < M; ++i) {\n            if (actions_output[i] == '.') { // Only if human didn't block in Phase 1\n                Point wall_cell_to_block = human_target_wall_goals[i];\n                if (wall_cell_to_block.r != -1) { // If there's still a wall target to move towards\n                    // Find the best position for the human to *stand* in order to block 'wall_cell_to_block'.\n                    // This means finding a cell adjacent to 'wall_cell_to_block' that is pathable for the human.\n                    Point target_human_stand_pos = {-1,-1};\n                    int min_dist_to_stand_pos = 100000;\n\n                    for(int d=0; d<4; ++d) {\n                        Point candidate_stand_pos = {wall_cell_to_block.r + DR[d], wall_cell_to_block.c + DC[d]};\n                        \n                        // Preliminary checks for a valid 'stand_pos' (more thorough check in BFS)\n                        if (is_valid(candidate_stand_pos.r, candidate_stand_pos.c) &&\n                            board[candidate_stand_pos.r][candidate_stand_pos.c] == 0 && // Not existing wall\n                            !current_blocked_this_turn.count(candidate_stand_pos)) { // Not blocked this turn\n                            \n                            int dist = abs(human_pos[i].r - candidate_stand_pos.r) + abs(human_pos[i].c - candidate_stand_pos.c); // Manhattan distance\n                            if (dist < min_dist_to_stand_pos) {\n                                min_dist_to_stand_pos = dist;\n                                target_human_stand_pos = candidate_stand_pos;\n                            }\n                        }\n                    }\n\n                    if (target_human_stand_pos.r != -1 && target_human_stand_pos != human_pos[i]) { // Found a valid stand position, and it's not current position\n                        // Use BFS to get the first move character towards target_human_stand_pos\n                        char move_c = get_move_char(human_pos[i], target_human_stand_pos, \n                                                    current_blocked_this_turn, current_moved_to_this_turn_targets, \n                                                    human_pos, i); \n                        if (move_c != '.') { // If a path was found\n                            Point first_step = human_pos[i]; // Will be updated\n                            for (int d_idx = 0; d_idx < 4; ++d_idx) {\n                                if (MOVE_CHARS[d_idx] == move_c) {\n                                    first_step = {human_pos[i].r + DR[d_idx], human_pos[i].c + DC[d_idx]};\n                                    break;\n                                }\n                            }\n                            // Priority is based on negative distance to target_human_stand_pos. Smaller distance means higher priority\n                            move_queue.push({i, first_step, move_c, -min_dist_to_stand_pos}); \n                        }\n                    }\n                }\n            }\n        }\n\n        // Process the move_queue to resolve conflicts (multiple humans wanting to move to the same cell)\n        while (!move_queue.empty()) {\n            MoveCandidate mc = move_queue.top();\n            move_queue.pop();\n\n            if (actions_output[mc.human_idx] == '.') { // If human hasn't been assigned an action yet\n                // Check if the target cell for this move is free (not blocked or targeted by another human)\n                if (!current_blocked_this_turn.count(mc.next_pos) && !current_moved_to_this_turn_targets.count(mc.next_pos)) {\n                    actions_output[mc.human_idx] = mc.move_char; // Assign the move action\n                    next_human_pos_candidates[mc.human_idx] = mc.next_pos; // Update planned position\n                    current_moved_to_this_turn_targets.insert(mc.next_pos); // Mark as targeted\n                }\n                // Else: Conflict occurred, the human stays put (action remains '.')\n            }\n        }\n\n        // 3. Output actions for all humans\n        for (int i = 0; i < M; ++i) {\n            cout << actions_output[i];\n        }\n        cout << endl; // Newline after all actions\n        fflush(stdout); // Crucial for interactive problems\n\n        // 4. Update game state (board and human_pos) based on actions\n        for (int i = 0; i < M; ++i) {\n            // If the action was a block, update the board state permanently\n            // Check if it's not a '.' and not one of the move characters ('U', 'D', 'L', 'R')\n            if (actions_output[i] != '.' && string(MOVE_CHARS).find(actions_output[i]) == string::npos) {\n                Point blocked_cell = human_pos[i]; // Default value\n                char block_char = actions_output[i];\n                for(int d=0; d<4; ++d) {\n                    if (BLOCK_CHARS[d] == block_char) {\n                        blocked_cell = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                        break;\n                    }\n                }\n                if (is_valid(blocked_cell.r, blocked_cell.c)) { // Sanity check for blocked_cell\n                    board[blocked_cell.r][blocked_cell.c] = 1; // Mark cell as impassable\n                }\n            }\n            human_pos[i] = next_human_pos_candidates[i]; // Update human positions\n        }\n\n        // 5. Read pet movements and update pet positions\n        string pet_moves_str;\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves_str;\n            if (pet_moves_str == \".\") continue; // Pet did not move\n            \n            for (char move_char : pet_moves_str) {\n                for (int d = 0; d < 4; ++d) {\n                    if (MOVE_CHARS[d] == move_char) {\n                        pet_pos[i].r += DR[d];\n                        pet_pos[i].c += DC[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int H = 20;\nconst int W = 20;\nconst int MAX_PATH_LENGTH = 200;\n\n// Global variables for problem input\nint start_r, start_c, target_r, target_c;\ndouble p_forget_val;\nbool has_wall_right[H][W - 1]; // wall between (r,c) and (r,c+1)\nbool has_wall_down[H - 1][W];  // wall between (r,c) and (r+1,c)\n\n// Directions for movement\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar move_chars[] = {'U', 'D', 'L', 'R'};\n\n// Helper function to calculate next position, staying if wall or boundary\npair<int, int> get_next_pos(int r, int c, char move_char) {\n    int nr = r, nc = c; // Default to staying\n    if (move_char == 'U') {\n        if (r > 0 && !has_wall_down[r - 1][c]) {\n            nr = r - 1;\n        }\n    } else if (move_char == 'D') {\n        if (r < H - 1 && !has_wall_down[r][c]) {\n            nr = r + 1;\n        }\n    } else if (move_char == 'L') {\n        if (c > 0 && !has_wall_right[r][c - 1]) {\n            nc = c - 1;\n        }\n    } else if (move_char == 'R') {\n        if (c < W - 1 && !has_wall_right[r][c]) {\n            nc = c + 1;\n        }\n    }\n    return {nr, nc};\n}\n\n// DP states (declared globally to avoid reallocations and for performance)\nvector<vector<double>> current_dp_state(H, vector<double>(W));\nvector<vector<double>> next_dp_state(H, vector<double>(W));\n\n// Evaluates a given path string\ndouble evaluate(const string& path) {\n    // Reset initial state for a new path evaluation\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_dp_state[i][j] = 0.0;\n        }\n    }\n    current_dp_state[start_r][start_c] = 1.0;\n\n    double total_expected_score = 0.0;\n\n    for (int k = 0; k < path.length(); ++k) {\n        // Clear next_dp_state for this turn's calculations\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                next_dp_state[i][j] = 0.0;\n            }\n        }\n\n        double prob_reach_this_turn = 0.0;\n        char move_char = path[k];\n\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                // Use a small epsilon for double comparison\n                if (current_dp_state[r][c] < 1e-18) continue; \n\n                // Option 1: Forgets char (prob p_forget_val), stays at (r,c)\n                next_dp_state[r][c] += current_dp_state[r][c] * p_forget_val;\n\n                // Option 2: Remembers char (prob 1-p_forget_val), moves according to move_char\n                pair<int, int> next_pos = get_next_pos(r, c, move_char);\n                int nr = next_pos.first;\n                int nc = next_pos.second;\n\n                if (nr == target_r && nc == target_c) {\n                    // Reached target at turn k+1\n                    prob_reach_this_turn += current_dp_state[r][c] * (1.0 - p_forget_val);\n                } else {\n                    // Did not reach target\n                    next_dp_state[nr][nc] += current_dp_state[r][c] * (1.0 - p_forget_val);\n                }\n            }\n        }\n\n        total_expected_score += prob_reach_this_turn * (401.0 - (k + 1));\n        current_dp_state.swap(next_dp_state); // Efficiently update current_dp_state\n    }\n    return total_expected_score;\n}\n\n// BFS to find the shortest path\nstring get_bfs_path() {\n    vector<vector<int>> dist(H, vector<int>(W, -1));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> move_to_parent(H, vector<char>(W, ' '));\n    queue<pair<int, int>> q;\n\n    q.push({start_r, start_c});\n    dist[start_r][start_c] = 0;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        if (r == target_r && c == target_c) break; // Found target\n\n        for (int i = 0; i < 4; ++i) { // For each direction (U, D, L, R)\n            int potential_nr = r + dr[i];\n            int potential_nc = c + dc[i];\n            char move_char = move_chars[i];\n\n            bool can_move = true;\n            if (move_char == 'U') {\n                if (r == 0 || has_wall_down[r - 1][c]) can_move = false;\n            } else if (move_char == 'D') {\n                if (r == H - 1 || has_wall_down[r][c]) can_move = false;\n            } else if (move_char == 'L') {\n                if (c == 0 || has_wall_right[r][c - 1]) can_move = false;\n            } else if (move_char == 'R') {\n                if (c == W - 1 || has_wall_right[r][c]) can_move = false;\n            }\n\n            if (!can_move) continue;\n            \n            // If can_move, the next valid position is (potential_nr, potential_nc)\n            if (dist[potential_nr][potential_nc] == -1) { // If not visited\n                dist[potential_nr][potential_nc] = dist[r][c] + 1;\n                parent[potential_nr][potential_nc] = {r, c};\n                move_to_parent[potential_nr][potential_nc] = move_char;\n                q.push({potential_nr, potential_nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path_str = \"\";\n    int curr_r = target_r;\n    int curr_c = target_c;\n    \n    // Problem guarantees start and target are different and reachable.\n    while (curr_r != start_r || curr_c != start_c) {\n        path_str += move_to_parent[curr_r][curr_c];\n        pair<int, int> p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read input\n    cin >> start_r >> start_c >> target_r >> target_c >> p_forget_val;\n\n    for (int i = 0; i < H; ++i) {\n        string row_h;\n        cin >> row_h;\n        for (int j = 0; j < W - 1; ++j) {\n            has_wall_right[i][j] = (row_h[j] == '1');\n        }\n    }\n    for (int i = 0; i < H - 1; ++i) {\n        string row_v;\n    cin >> row_v;\n        for (int j = 0; j < W; ++j) {\n            has_wall_down[i][j] = (row_v[j] == '1');\n        }\n    }\n\n    // Timer setup\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0; // Use 1.95 seconds to be safe\n\n    // Initial path (BFS shortest path)\n    string best_path_str = get_bfs_path();\n    double best_score = evaluate(best_path_str);\n    string current_path_str = best_path_str;\n    double current_score = best_score;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    // SA parameters: Reverted T_start to the initial value that performed better.\n    double T_start = 2000.0; \n    double T_end = 1.0;     \n\n    // Cache BFS path length for mutation probability calculation\n    int bfs_path_length = best_path_str.length();\n\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) break;\n\n        double T = T_start * pow(T_end / T_start, elapsed_ms / TIME_LIMIT_MS);\n        \n        string new_path_str = current_path_str;\n        \n        // Revised Adaptive Operation Selection Probabilities\n        double current_len = new_path_str.length();\n        \n        // Base weights for different operations\n        double change_char_weight = 2.0;\n        double insert_char_weight = 1.0;\n        double delete_char_weight = 1.0;\n        double duplicate_segment_weight = 1.0; // New mutation type\n\n        // Scale p_forget_val from [0.1, 0.5] to [0, 1]\n        double p_scaled = (p_forget_val - 0.1) / (0.5 - 0.1); \n\n        // Adjust weights based on p_forget_val:\n        // Higher p_forget_val -> more need for redundancy (insert/duplicate)\n        duplicate_segment_weight += p_scaled * 2.0; \n        insert_char_weight += p_scaled * 1.0; \n        delete_char_weight -= p_scaled * 0.8; \n\n        // Estimate an \"optimal\" path length:\n        // Multiplier 3.0 gives an ideal length 1.3x to 2.5x longer than BFS.\n        double estimated_optimal_len = min((double)MAX_PATH_LENGTH, (double)bfs_path_length * (1.0 + p_forget_val * 3.0));\n        \n        // Adjust weights based on current path length relative to estimated optimal\n        // Use a continuous adjustment based on normalized length difference\n        double len_diff_normalized = (current_len - estimated_optimal_len) / (MAX_PATH_LENGTH - bfs_path_length + 1e-9); // +1e-9 to prevent div by zero\n        len_diff_normalized = max(-1.0, min(1.0, len_diff_normalized)); // Clamp to [-1, 1]\n\n        insert_char_weight -= len_diff_normalized * 1.5; // If too long, decrease insert/dup weight\n        duplicate_segment_weight -= len_diff_normalized * 1.5;\n        delete_char_weight += len_diff_normalized * 2.0; // If too long, increase delete weight\n\n        // Apply floor to weights to ensure they are at least a small positive value\n        // This prevents an operation from having zero probability\n        change_char_weight = max(0.01, change_char_weight);\n        insert_char_weight = max(0.01, insert_char_weight);\n        delete_char_weight = max(0.01, delete_char_weight);\n        duplicate_segment_weight = max(0.01, duplicate_segment_weight);\n        \n        // Calculate total weight and normalize to probabilities\n        double total_weight = change_char_weight + insert_char_weight + delete_char_weight + duplicate_segment_weight;\n        double p_change = change_char_weight / total_weight;\n        double p_insert = insert_char_weight / total_weight;\n        double p_delete = delete_char_weight / total_weight;\n        double p_duplicate = duplicate_segment_weight / total_weight;\n\n        // Cumulative probabilities for random choice\n        double cum_p_change = p_change;\n        double cum_p_insert = cum_p_change + p_insert;\n        double cum_p_delete = cum_p_insert + p_delete;\n        // cum_p_duplicate is 1.0 (implicitly, or after explicit re-normalization)\n        \n        double op_choice_rand = prob_dist(rng);\n\n        if (op_choice_rand < cum_p_change) { \n            // --- Operation 1: Change character ---\n            if (new_path_str.empty()) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            char original_char = new_path_str[idx];\n            \n            char new_char;\n            do {\n                uniform_int_distribution<int> char_dist(0, 3);\n                new_char = move_chars[char_dist(rng)];\n            } while (new_char == original_char); \n            \n            new_path_str[idx] = new_char;\n        } else if (op_choice_rand < cum_p_insert) {\n            // --- Operation 2: Insert character ---\n            if (new_path_str.length() >= MAX_PATH_LENGTH) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length()); \n            int idx = idx_dist(rng);\n            uniform_int_distribution<int> char_dist(0, 3);\n            char char_to_insert = move_chars[char_dist(rng)];\n            \n            new_path_str.insert(idx, 1, char_to_insert);\n        } else if (op_choice_rand < cum_p_delete) { \n            // --- Operation 3: Delete character ---\n            if (new_path_str.empty() || new_path_str.length() == 1) continue; \n\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            \n            new_path_str.erase(idx, 1);\n        } else {\n            // --- Operation 4: Duplicate/Repeat Segment ---\n            // Need a path with at least 2 characters to pick a segment of length >= 2\n            // And room to insert a segment.\n            if (new_path_str.length() < 2 || new_path_str.length() >= MAX_PATH_LENGTH - 2) continue; \n\n            uniform_int_distribution<int> seg_start_idx_dist(0, (int)new_path_str.length() - 2); \n            int seg_start_idx = seg_start_idx_dist(rng);\n            \n            uniform_int_distribution<int> seg_len_dist(2, (int)new_path_str.length() - seg_start_idx); // Segment length must be at least 2\n            int seg_len = seg_len_dist(rng);\n            \n            string segment = new_path_str.substr(seg_start_idx, seg_len);\n\n            if (new_path_str.length() + segment.length() > MAX_PATH_LENGTH) {\n                // If segment insertion would exceed MAX_PATH_LENGTH, truncate the segment\n                segment = segment.substr(0, MAX_PATH_LENGTH - new_path_str.length());\n                if (segment.empty()) continue; // If no room for even a single char, skip\n            }\n\n            uniform_int_distribution<int> insert_idx_dist(0, (int)new_path_str.length()); \n            int insert_idx = insert_idx_dist(rng);\n            \n            new_path_str.insert(insert_idx, segment);\n        }\n\n        // Evaluate new path\n        double new_score = evaluate(new_path_str);\n\n        // SA acceptance criterion\n        if (new_score > current_score || prob_dist(rng) < exp((new_score - current_score) / T)) {\n            current_score = new_score;\n            current_path_str = new_path_str;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path_str = current_path_str;\n            }\n        }\n    }\n\n    cout << best_path_str << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple> // For std::tuple\n\n// Define grid dimensions\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0=Left, 1=Up, 2=Right, 3=Down\n// di, dj: changes in row and column for each direction\nconst int di[] = {0, -1, 0, 1};\n// FIX: Corrected square brackets [] to curly braces {} for array initialization.\nconst int dj[] = {-1, 0, 1, 0};\n\n// initial_to[tile_type][entry_direction] -> exit_direction\n// Provided by problem statement\nconst int initial_to[8][4] = {\n    {1, 0, -1, -1}, // Type 0: L-U curve (0-1)\n    {-1, 2, 1, -1}, // Type 1: U-R curve (1-2)\n    {-1, -1, 3, 2}, // Type 2: R-D curve (2-3)\n    {3, -1, -1, 0}, // Type 3: D-L curve (3-0)\n    {1, 0, 3, 2},   // Type 4: L-U and R-D (0-1, 2-3)\n    {3, 2, 1, 0},   // Type 5: U-R and D-L (1-2, 3-0)\n    {2, -1, 0, -1}, // Type 6: horizontal straight (0-2)\n    {-1, 3, -1, 1}  // Type 7: vertical straight (1-3)\n};\n\n// Stores the initial tile types read from input\nstd::vector<std::vector<int>> initial_tiles(H, std::vector<int>(W));\n// Stores the current rotation for each tile (0-3)\nstd::vector<std::vector<int>> current_rotations(H, std::vector<int>(W));\n\n// Precompute effective_to table for faster lookup\n// effective_to[initial_tile_type][rotation_count][entry_direction] -> exit_direction\nint effective_to[8][4][4];\n\nvoid precompute_effective_to() {\n    for (int t_initial = 0; t_initial < 8; ++t_initial) {\n        for (int r_rot = 0; r_rot < 4; ++r_rot) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // 1. Convert absolute entry direction to tile's original orientation\n                // If a tile is rotated `r_rot` times counter-clockwise,\n                // an absolute entry `d_entry` corresponds to `(d_entry - r_rot + 4) % 4`\n                // in the tile's original, unrotated reference frame.\n                int d_base = (d_entry - r_rot + 4) % 4;\n                \n                // 2. Find exit direction in tile's original orientation\n                int exit_base = initial_to[t_initial][d_base];\n                \n                // 3. If broken, mark as -1\n                if (exit_base == -1) {\n                    effective_to[t_initial][r_rot][d_entry] = -1;\n                } else {\n                    // 4. Convert exit direction back to absolute orientation\n                    // The exit direction is also rotated by `r_rot` times CCW.\n                    effective_to[t_initial][r_rot][d_entry] = (exit_base + r_rot) % 4;\n                }\n            }\n        }\n    }\n}\n\n// Function to calculate the exit direction for a given tile and entry\ninline int get_exit_dir(int r, int c, int d_entry) {\n    return effective_to[initial_tiles[r][c]][current_rotations[r][c]][d_entry];\n}\n\nstruct VisitedState {\n    int id;  // Unique ID for the current calculate_score() call or active path\n    int len; // Path length when this state was first visited in current active path\n};\n// Use static to initialize once to {0,0} for all entries\nstatic VisitedState visited_tracking[H][W][4];\nstatic int current_search_id = 0; // Incremented for each calculate_score() call\n\n// Global/static vector to avoid repeated allocations in calculate_score\nstatic std::vector<std::tuple<int, int, int>> nodes_in_current_path_segment_global;\n\nlong long calculate_score() {\n    std::vector<long long> loop_lengths;\n    current_search_id++; // New unique ID for this score calculation\n\n    // `active_path_id` is used to mark nodes *currently in the path exploration*.\n    // `current_search_id` is used to mark nodes that have been *fully processed*\n    // (either part of a completed cycle or a path that dead-ended/merged into an already processed segment).\n    int active_path_id = current_search_id + 1; // Unique ID for current path traversal\n\n    for (int r = 0; r < H; ++r) {\n        for (int c = 0; c < W; ++c) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // Skip if this state has already been part of a fully processed path/cycle\n                if (visited_tracking[r][c][d_entry].id == current_search_id) {\n                    continue; \n                }\n\n                int curr_r = r;\n                int curr_c = c;\n                int curr_d_entry = d_entry;\n                long long path_len = 0;\n                \n                nodes_in_current_path_segment_global.clear(); // Clear for current path exploration\n\n                while (true) {\n                    // Check if current node is out of bounds\n                    if (curr_r < 0 || curr_r >= H || curr_c < 0 || curr_c >= W) {\n                        break; // Out of bounds, path broken\n                    }\n                    \n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == active_path_id) {\n                        // Cycle detected! Current node was visited in this active path.\n                        // The length of the loop is the current path length minus the length\n                        // when this node was first visited in this active path.\n                        long long cycle_start_len = visited_tracking[curr_r][curr_c][curr_d_entry].len;\n                        loop_lengths.push_back(path_len - cycle_start_len);\n                        break;\n                    }\n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == current_search_id) {\n                        // Merged into an already processed path/cycle. This means this path segment\n                        // doesn't form a new distinct loop starting from `(r,c,d_entry)`.\n                        break;\n                    }\n\n                    // Mark current node as 'in active path' and record its length\n                    visited_tracking[curr_r][curr_c][curr_d_entry] = {active_path_id, (int)path_len};\n                    nodes_in_current_path_segment_global.emplace_back(curr_r, curr_c, curr_d_entry); // Store nodes for later global marking\n\n                    int d_exit = get_exit_dir(curr_r, curr_c, curr_d_entry);\n                    if (d_exit == -1) {\n                        break; // Broken line\n                    }\n\n                    int next_r = curr_r + di[d_exit];\n                    int next_c = curr_c + dj[d_exit];\n                    // The train enters the next tile from the opposite direction it exited.\n                    int next_d_entry = (d_exit + 2) % 4; \n                    path_len++;\n\n                    curr_r = next_r;\n                    curr_c = next_c;\n                    curr_d_entry = next_d_entry;\n                }\n\n                // After path ends (break from loop), mark all nodes visited in `nodes_in_current_path_segment_global`\n                // as 'processed for current_search_id'. This ensures they are not re-evaluated as starting points\n                // for new paths within the same `calculate_score` call.\n                for (const auto& node : nodes_in_current_path_segment_global) {\n                    visited_tracking[std::get<0>(node)][std::get<1>(node)][std::get<2>(node)].id = current_search_id;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) {\n        return 0; // Score is 0 if less than two loop lines\n    }\n\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend()); // Sort descending\n    return loop_lengths[0] * loop_lengths[1]; // Product of two longest loops\n}\n\n// Random number generator\nstd::mt19937 mt;\n\nvoid solve() {\n    auto start_time = std::chrono::high_resolution_clock::now();\n\n    // Read initial tile types\n    for (int i = 0; i < H; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < W; ++j) {\n            initial_tiles[i][j] = row_str[j] - '0';\n        }\n    }\n\n    precompute_effective_to();\n\n    // Initialize random number generator using current time\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\n    mt.seed(seed);\n\n    // Initial solution: assign random rotations to all tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_rotations[i][j] = mt() % 4;\n        }\n    }\n\n    std::vector<std::vector<int>> best_rotations = current_rotations;\n    long long current_score = calculate_score();\n    long long best_score = current_score;\n\n    // Simulated Annealing parameters\n    // T_START adjusted to allow more exploration, especially for larger delta_scores.\n    // This value is based on considering potential score changes and desired early acceptance probabilities.\n    double T_START = 10000.0; \n    double TIME_LIMIT_MS = 1900.0; // Run for 1.9 seconds out of 2.0s total\n\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) { \n            break; // Time limit exceeded, terminate SA\n        }\n\n        // Linear cooling schedule: temperature decreases over time\n        double T = T_START * (1.0 - elapsed_ms / TIME_LIMIT_MS);\n        if (T < 0.1) T = 0.1; // Prevent T from becoming too small, avoiding `exp()` issues or division by zero\n\n        // Generate neighbor state: randomly pick one tile and change its rotation\n        int r_idx = mt() % H;\n        int c_idx = mt() % W;\n        int old_rot = current_rotations[r_idx][c_idx];\n        // Ensure the new rotation is different from the old one\n        int new_rot = (old_rot + (mt() % 3) + 1) % 4; \n\n        current_rotations[r_idx][c_idx] = new_rot;\n        long long neighbor_score = calculate_score();\n        \n        long long delta_score = neighbor_score - current_score;\n\n        // Acceptance criteria based on Metropolis-Hastings:\n        // Always accept if score improves (delta_score > 0).\n        // Otherwise, accept with probability exp(delta_score / T).\n        if (delta_score > 0 || std::uniform_real_distribution<double>(0.0, 1.0)(mt) < std::exp(delta_score / T)) {\n            current_score = neighbor_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations; // Update overall best solution\n            }\n        } else {\n            // Revert to old rotation if new state is not accepted\n            current_rotations[r_idx][c_idx] = old_rot;\n        }\n    }\n\n    // Output the rotations corresponding to the best score found\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            std::cout << best_rotations[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\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 <random>\n#include <chrono>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <limits> // For numeric_limits\n\nusing namespace std;\n\n// --- Constants and Global Variables ---\nconst long long TIME_LIMIT_MS = 2800; // 2.8 seconds for computation\nconst double T_START = 200.0;        // Initial temperature for Simulated Annealing\nconst double T_END = 0.01;           // Final temperature for Simulated Annealing\n\nint N;               // Board size\nint MAX_S_VALUE;     // Maximum possible S value (N*N - 1)\nlong long MAX_MOVES; // Maximum allowed operations (T = 2 * N^3)\n\n// Energy function weights\nlong double W_S_CRITICAL; // Huge weight for (MAX_S_VALUE - S) when S < MAX_S_VALUE\nlong double W_K = 1.0;    // Weight for K when S = MAX_S_VALUE, or small weight when S < MAX_S_VALUE\n\n// Directions for empty square movement\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_char[] = {'U', 'D', 'L', 'R'};\nint opposite_dir[] = {1, 0, 3, 2}; // e.g., opposite of U(0) is D(1)\n\n// Global random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- DSU Structure for Score Calculation ---\nstruct DSU {\n    vector<int> parent;\n    vector<int> comp_size;\n    vector<int> num_edges;\n    vector<bool> has_cycle;\n    int num_cells;\n\n    DSU(int n_squared) : num_cells(n_squared) {\n        parent.resize(num_cells);\n        iota(parent.begin(), parent.end(), 0); // Initialize parent[i] = i\n        comp_size.assign(num_cells, 1);        // Each cell starts as a component of size 1\n        num_edges.assign(num_cells, 0);        // Each component starts with 0 edges\n        has_cycle.assign(num_cells, false);    // No cycles initially\n    }\n\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\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            // Union by size/rank: attach smaller tree to larger tree\n            if (comp_size[root_i] < comp_size[root_j])\n                swap(root_i, root_j);\n            parent[root_j] = root_i;\n            comp_size[root_i] += comp_size[root_j];\n            num_edges[root_i] += num_edges[root_j]; // Add edges from merged component\n            num_edges[root_i]++;                     // Add the new edge\n            has_cycle[root_i] = has_cycle[root_i] || has_cycle[root_j]; // Propagate cycle info\n        } else {\n            num_edges[root_i]++;         // Edge added within the same component\n            has_cycle[root_i] = true;    // This implies a cycle\n        }\n    }\n};\n\n// --- BoardState Structure ---\nstruct BoardState {\n    vector<vector<int>> board;\n    int empty_r, empty_c;\n    string moves;\n    int last_move_idx; // Index of the last move (0:U, 1:D, 2:L, 3:R), -1 if no previous move\n\n    BoardState(int n_val) : board(n_val, vector<int>(n_val)), empty_r(-1), empty_c(-1), last_move_idx(-1) {}\n\n    // Calculate the score S for the current board configuration\n    // S is the number of vertices in the largest tree component (connected and acyclic)\n    int calculate_S() const {\n        DSU dsu(N * N);\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // The empty cell is not part of the graph formed by tiles\n                if (r == empty_r && c == empty_c) continue;\n\n                int current_tile = board[r][c];\n                int current_idx = r * N + c;\n\n                // Check downward connection with (r+1, c)\n                if (r + 1 < N) {\n                    if (!(r + 1 == empty_r && c == empty_c)) { \n                        int neighbor_tile = board[r+1][c];\n                        int neighbor_idx = (r+1) * N + c;\n                        if ((current_tile & 8) && (neighbor_tile & 2)) { // Down line on current, Up line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n                // Check rightward connection with (r, c+1)\n                if (c + 1 < N) {\n                    if (!(r == empty_r && c + 1 == empty_c)) {\n                        int neighbor_tile = board[r][c+1];\n                        int neighbor_idx = r * N + (c+1);\n                        if ((current_tile & 4) && (neighbor_tile & 1)) { // Right line on current, Left line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n            }\n        }\n\n        int max_S = 0;\n        for (int i = 0; i < N * N; ++i) {\n            if (i == empty_r * N + empty_c) continue; // Skip empty square\n\n            if (dsu.parent[i] == i) { // If 'i' is the root of a component\n                if (!dsu.has_cycle[i]) {\n                    max_S = max(max_S, dsu.comp_size[i]);\n                }\n            }\n        }\n        return max_S;\n    }\n};\n\n// --- Main Function ---\nint main() {\n    ios_base::sync_with_stdio(false); // Faster I/O\n    cin.tie(NULL);\n\n    cin >> N >> MAX_MOVES;\n\n    MAX_S_VALUE = N * N - 1; // Total number of tiles, excluding the empty one\n    W_S_CRITICAL = (long double)MAX_MOVES + 1.0; // Set critical weight\n\n    BoardState current_state(N);\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            current_state.board[i][j] = stoi(string(1, row_str[j]), nullptr, 16);\n            if (current_state.board[i][j] == 0) { // Found the empty square\n                current_state.empty_r = i;\n                current_state.empty_c = j;\n            }\n        }\n    }\n\n    // Initialize best state with the initial state\n    BoardState best_state = current_state;\n    int current_S = current_state.calculate_S();\n    int current_K = 0; // Number of operations starts at 0\n\n    int best_S = current_S;\n    int best_K = current_K;\n\n    auto start_time = chrono::steady_clock::now();\n    long long iter_count = 0;\n\n    uniform_real_distribution<long double> dist_prob(0.0, 1.0); // For acceptance probability\n\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() < TIME_LIMIT_MS) {\n        iter_count++;\n\n        // Calculate current temperature based on elapsed time\n        long double progress = (long double)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / TIME_LIMIT_MS;\n        long double temp = T_START * pow(T_END / T_START, progress);\n        \n        if (temp < 1e-12) temp = 1e-12; // Safety net for extremely low temperatures\n\n        // Calculate energy for the current state (used for SA acceptance)\n        long double current_energy;\n        if (current_S == MAX_S_VALUE) {\n            current_energy = (long double)current_K * W_K;\n        } else {\n            current_energy = (long double)(MAX_S_VALUE - current_S) * W_S_CRITICAL + (long double)current_K * W_K;\n        }\n\n        // Determine possible moves\n        vector<int> possible_moves_indices;\n        for (int i = 0; i < 4; ++i) {\n            int next_empty_r = current_state.empty_r + dr[i];\n            int next_empty_c = current_state.empty_c + dc[i];\n\n            if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                if (current_state.last_move_idx == -1 || i != opposite_dir[current_state.last_move_idx]) {\n                    possible_moves_indices.push_back(i);\n                }\n            }\n        }\n        \n        if (possible_moves_indices.empty()) { // Fallback: if no non-reverting moves are available\n            for (int i = 0; i < 4; ++i) {\n                int next_empty_r = current_state.empty_r + dr[i];\n                int next_empty_c = current_state.empty_c + dc[i];\n                if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                     possible_moves_indices.push_back(i);\n                }\n            }\n            if (possible_moves_indices.empty()) { \n                 continue; // Should not happen for N >= 2\n            }\n        }\n\n        uniform_int_distribution<int> dist_valid_dir(0, possible_moves_indices.size() - 1);\n        int move_idx = possible_moves_indices[dist_valid_dir(rng)];\n\n        int prev_empty_r = current_state.empty_r;\n        int prev_empty_c = current_state.empty_c;\n        int moved_tile_r = prev_empty_r + dr[move_idx];\n        int moved_tile_c = prev_empty_c + dc[move_idx];\n        \n        BoardState next_state = current_state;\n        \n        next_state.board[prev_empty_r][prev_empty_c] = next_state.board[moved_tile_r][moved_tile_c];\n        next_state.board[moved_tile_r][moved_tile_c] = 0;\n        next_state.empty_r = moved_tile_r;\n        next_state.empty_c = moved_tile_c;\n        next_state.moves += dir_char[move_idx];\n        next_state.last_move_idx = move_idx;\n\n        int next_K = next_state.moves.length();\n        if (next_K > MAX_MOVES) {\n            continue; \n        }\n\n        int next_S = next_state.calculate_S();\n        long double next_energy;\n        if (next_S == MAX_S_VALUE) {\n            next_energy = (long double)next_K * W_K;\n        } else {\n            next_energy = (long double)(MAX_S_VALUE - next_S) * W_S_CRITICAL + (long double)next_K * W_K;\n        }\n\n        long double delta_E = next_energy - current_energy;\n\n        if (delta_E < 0 || dist_prob(rng) < exp(-delta_E / temp)) {\n            current_state = next_state;\n            current_S = next_S;\n            current_K = next_K;\n            // current_energy is implicitly updated for the next iteration when current_S and current_K are used.\n            \n            // Update the best solution found so far\n            if (current_S > best_S) {\n                best_S = current_S;\n                best_K = current_K;\n                best_state = current_state;\n            } else if (current_S == best_S && current_K < best_K) { \n                best_K = current_K;\n                best_state = current_state;\n            }\n        }\n    }\n\n    // Output debug information to stderr\n    cerr << \"Iterations: \" << iter_count << endl;\n    cerr << \"Best S: \" << best_S << \" / \" << MAX_S_VALUE << endl;\n    cerr << \"Best K: \" << best_K << \" / \" << MAX_MOVES << endl;\n    \n    // Calculate final score for the best found state based on problem formula\n    long long final_score;\n    if (best_S == MAX_S_VALUE) {\n        final_score = round(500000.0 * (2.0 - (long double)best_K / MAX_MOVES));\n    } else {\n        final_score = round(500000.0 * ((long double)best_S / MAX_S_VALUE));\n    }\n    cerr << \"Final Score: \" << final_score << endl;\n\n    cout << best_state.moves << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // For std::gcd\n#include <algorithm> // For std::min, std::max\n#include <unordered_map>\n#include <bitset>    // For std::bitset\n#include <cassert>   // For debugging assertions\n#include <set>       // For tracking used strawberry pairs\n\n// Using long long for coordinates and intermediate calculations for lines\n// Max value for Ax + By + C can be large but fits in long long.\n\nusing namespace std;\n\n// --- Constants and Type Definitions ---\nconst int K_MAX_CUTS_CONST = 100; // K is fixed at 100\nconst long long MAX_INITIAL_LINE_COORD = 100000LL; // Range for line points (10x cake radius)\nconst long long MAX_PERTURB_MAG = 50000LL; // Max perturbation magnitude (5x cake radius)\n\n// --- Random Number Generator ---\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<long long> dist_line_coord(-MAX_INITIAL_LINE_COORD, MAX_INITIAL_LINE_COORD); \nuniform_int_distribution<int> dist_k_idx(0, K_MAX_CUTS_CONST - 1); \nuniform_int_distribution<int> dist_coord_choice(0, 3); // 0=px, 1=py, 2=qx, 3=qy\nuniform_real_distribution<double> dist_01(0.0, 1.0); // For SA acceptance probability\nuniform_int_distribution<int> dist_strawberry_idx; // Will be initialized with N_strawberries\n\n// --- Global variables ---\nint N_strawberries;\nint K_max_cuts; \nvector<int> a_attendees(11); // a_d for d=1 to 10. a_attendees[0] unused.\nlong long total_attendees_demand = 0; // Sum of a_d\n\nstruct Strawberry {\n    long long x, y;\n};\nvector<Strawberry> strawberries;\n\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C; // Line equation Ax + By + C = 0\n\n    Line(long long p1x, long long p1y, long long p2x, long long p2y) :\n        px(p1x), py(p1y), qx(p2x), qy(p2y) {\n        // Points (p1x, p1y) and (p2x, p2y) are guaranteed to be distinct by the caller.\n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n        \n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero, points were identical or other issue.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        \n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n    Line() : px(0), py(0), qx(1), qy(0), A(0), B(-1), C(0) {} // Default horizontal line y=0\n\n    void perturb(double decrease_factor) { // decrease_factor goes from 1.0 to 0.0 over time\n        long long perturb_magnitude = (long long)(MAX_PERTURB_MAG * decrease_factor) + 1; \n        \n        long long old_px = px, old_py = py, old_qx = qx, old_qy = qy; \n        \n        long long *coord_ptr;\n        switch (dist_coord_choice(rng)) {\n            case 0: coord_ptr = &px; break;\n            case 1: coord_ptr = &py; break;\n            case 2: coord_ptr = &qx; break;\n            default: coord_ptr = &qy; break;\n        }\n        long long new_coord_val = *coord_ptr + uniform_int_distribution<long long>(-perturb_magnitude, perturb_magnitude)(rng);\n        *coord_ptr = max(-MAX_INITIAL_LINE_COORD, min(MAX_INITIAL_LINE_COORD, new_coord_val));\n\n        if (px == qx && py == qy) { // If perturbation makes points identical, revert to original.\n            px = old_px; py = old_py; qx = old_qx; qy = old_qy;\n        }\n        \n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n\n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero after perturbation.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n};\n\n// Using std::bitset for piece signatures. Faster hashing and comparison than std::vector<char>.\n// A 'true' bit represents a positive side, 'false' a negative side.\nusing PieceSignature = std::bitset<K_MAX_CUTS_CONST>;\n\n// Custom hash for std::bitset (using std::hash for bitset)\nstruct BitsetHash {\n    std::size_t operator()(const PieceSignature& b) const {\n        return std::hash<std::bitset<K_MAX_CUTS_CONST>>{}(b);\n    }\n};\n\n// State variables for Simulated Annealing\nvector<PieceSignature> strawberry_line_sides_current_bits; \nvector<short> num_lines_passing_through_strawberry_current; \nunordered_map<PieceSignature, int, BitsetHash> piece_strawberry_counts_current; \nvector<long long> b_d_current(11, 0); \nlong long current_score = 0; \nvector<Line> current_lines; \n\n// Function to calculate the score based on a given b_d vector.\nlong long calculate_score(const vector<long long>& b_d_vec) {\n    long long actual_distributed = 0;\n    for (int d = 1; d <= 10; ++d) {\n        actual_distributed += min(a_attendees[d], (int)b_d_vec[d]);\n    }\n    if (total_attendees_demand == 0) return 0; // Should not happen given problem constraints (N > 0).\n    return round(1e6 * (double)actual_distributed / total_attendees_demand);\n}\n\n// Function to generate a purely random line\nLine generate_random_line() {\n    long long p1x, p1y, p2x, p2y;\n    do {\n        p1x = dist_line_coord(rng);\n        p1y = dist_line_coord(rng);\n        p2x = dist_line_coord(rng);\n        p2y = dist_line_coord(rng);\n    } while (p1x == p2x && p1y == p2y); \n    return Line(p1x, p1y, p2x, p2y);\n}\n\n// Function to generate a line passing through two specific strawberries\nLine generate_line_through_strawberries(int idx1, int idx2) {\n    return Line(strawberries[idx1].x, strawberries[idx1].y, strawberries[idx2].x, strawberries[idx2].y);\n}\n\n\n// Performs a full evaluation of the given set of lines.\nvoid full_evaluate(const vector<Line>& lines) {\n    strawberry_line_sides_current_bits.assign(N_strawberries, PieceSignature());\n    num_lines_passing_through_strawberry_current.assign(N_strawberries, 0); \n    piece_strawberry_counts_current.clear();\n    fill(b_d_current.begin(), b_d_current.end(), 0);\n\n    for (int j = 0; j < N_strawberries; ++j) {\n        for (int i = 0; i < K_max_cuts; ++i) {\n            long long val = lines[i].A * strawberries[j].x + lines[i].B * strawberries[j].y + lines[i].C;\n            if (val == 0) {\n                num_lines_passing_through_strawberry_current[j]++;\n                strawberry_line_sides_current_bits[j].set(i, true); // Arbitrary: set to true if on line\n            } else {\n                strawberry_line_sides_current_bits[j].set(i, val > 0); // true for >0, false for <0\n            }\n        }\n        if (num_lines_passing_through_strawberry_current[j] == 0) { \n            piece_strawberry_counts_current[strawberry_line_sides_current_bits[j]]++;\n        }\n    }\n\n    for (const auto& pair : piece_strawberry_counts_current) {\n        if (pair.second > 0 && pair.second <= 10) { \n            b_d_current[pair.second]++;\n        }\n    }\n    current_score = calculate_score(b_d_current);\n}\n\nvoid solve() {\n    cin >> N_strawberries >> K_max_cuts;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a_attendees[d];\n        total_attendees_demand += a_attendees[d];\n    }\n    strawberries.resize(N_strawberries);\n    dist_strawberry_idx = uniform_int_distribution<int>(0, N_strawberries - 1); // Initialize distribution for strawberry indices\n    num_lines_passing_through_strawberry_current.resize(N_strawberries); \n    for (int i = 0; i < N_strawberries; ++i) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n\n    current_lines.resize(K_max_cuts);\n    \n    // --- Smarter Initial Line Generation ---\n    // Generate K/2 lines connecting two random strawberries, K - K/2 purely random.\n    int num_strategic_lines = K_max_cuts / 2;\n    set<pair<int, int>> used_strawberry_pairs; // To avoid duplicate lines or lines through same strawberry pair\n    \n    for (int i = 0; i < num_strategic_lines; ++i) {\n        int idx1, idx2;\n        int attempts = 0;\n        do { // Ensure unique, distinct strawberry pair\n            idx1 = dist_strawberry_idx(rng);\n            idx2 = dist_strawberry_idx(rng);\n            if (idx1 > idx2) swap(idx1, idx2);\n            attempts++;\n            if (attempts > 1000 && N_strawberries < 200) { // If N_strawberries is small, can run out of unique pairs.\n                // Fallback to random if too hard to find unique pair\n                current_lines[i] = generate_random_line(); \n                idx1 = -1; idx2 = -1; // Mark as non-strawberry line\n                break;\n            }\n        } while (idx1 == idx2 || used_strawberry_pairs.count({idx1, idx2}));\n        \n        if (idx1 != -1) { // If a valid strawberry pair was found\n            current_lines[i] = generate_line_through_strawberries(idx1, idx2);\n            used_strawberry_pairs.insert({idx1, idx2});\n        }\n    }\n\n    for (int i = num_strategic_lines; i < K_max_cuts; ++i) {\n        current_lines[i] = generate_random_line();\n    }\n    // --- End Smarter Initial Line Generation ---\n    \n    full_evaluate(current_lines);\n\n    vector<Line> best_lines = current_lines;\n    long long best_score = current_score;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.95; \n\n    double T_start = 1e7; \n    double T_end = 1e-1;   \n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double temp_ratio = elapsed_time / TIME_LIMIT; \n        double T = T_start * pow(T_end / T_start, temp_ratio); \n\n        int line_idx_to_perturb = dist_k_idx(rng);\n        Line original_line_at_idx = current_lines[line_idx_to_perturb];\n        Line candidate_line = original_line_at_idx;\n\n        // --- Perturbation Strategy: Local adjustment OR Full replacement ---\n        if (dist_01(rng) < 0.05) { // 5% chance to completely replace the line\n            candidate_line = generate_random_line();\n        } else { // 95% chance for local adjustment\n            candidate_line.perturb(1.0 - temp_ratio); \n        }\n        // --- End Perturbation Strategy ---\n\n        vector<long long> temp_b_d = b_d_current;\n        unordered_map<PieceSignature, int, BitsetHash> temp_piece_strawberry_counts = piece_strawberry_counts_current;\n        \n        vector<bool> next_line_side_values_at_idx_bit(N_strawberries);\n        vector<short> next_num_lines_passing_through_commit(N_strawberries);\n\n\n        for (int j = 0; j < N_strawberries; ++j) {\n            long long val_original_line_k = original_line_at_idx.A * strawberries[j].x + original_line_at_idx.B * strawberries[j].y + original_line_at_idx.C;\n            long long val_candidate_line_k = candidate_line.A * strawberries[j].x + candidate_line.B * strawberries[j].y + candidate_line.C;\n\n            bool was_on_original_line_k = (val_original_line_k == 0);\n            bool is_on_candidate_line_k = (val_candidate_line_k == 0);\n\n            short temp_num_lines_passing_for_j = num_lines_passing_through_strawberry_current[j];\n            if (was_on_original_line_k && !is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j--;\n            } else if (!was_on_original_line_k && is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j++;\n            }\n            next_num_lines_passing_through_commit[j] = temp_num_lines_passing_for_j; \n\n            bool was_lost_j = (num_lines_passing_through_strawberry_current[j] > 0);\n            bool is_lost_j_candidate = (temp_num_lines_passing_for_j > 0);\n\n            bool new_side_k_value_for_key = (val_candidate_line_k > 0);\n            if (is_on_candidate_line_k) { \n                 new_side_k_value_for_key = true; \n            }\n            next_line_side_values_at_idx_bit[j] = new_side_k_value_for_key; \n            \n            // --- Update temp_b_d and temp_piece_strawberry_counts ---\n            \n            // Step 1: Remove strawberry j from its previous piece (if it was in one).\n            if (!was_lost_j) {\n                PieceSignature old_piece_key = strawberry_line_sides_current_bits[j];\n                int count_in_old_piece = temp_piece_strawberry_counts[old_piece_key]; \n                \n                temp_piece_strawberry_counts[old_piece_key]--;\n                if (count_in_old_piece >= 1 && count_in_old_piece <= 10) {\n                    temp_b_d[count_in_old_piece]--; \n                }\n                if (count_in_old_piece - 1 >= 1 && count_in_old_piece - 1 <= 10) { \n                    temp_b_d[count_in_old_piece - 1]++; \n                }\n            }\n\n            // Step 2: Add strawberry j to its new piece (if it will be in one).\n            if (!is_lost_j_candidate) {\n                PieceSignature new_piece_key = strawberry_line_sides_current_bits[j]; \n                new_piece_key.set(line_idx_to_perturb, new_side_k_value_for_key); \n                \n                int count_in_new_piece_before_add = temp_piece_strawberry_counts[new_piece_key];\n                temp_piece_strawberry_counts[new_piece_key]++;\n                \n                if (count_in_new_piece_before_add >= 1 && count_in_new_piece_before_add <= 10) {\n                    temp_b_d[count_in_new_piece_before_add]--;\n                }\n                if (count_in_new_piece_before_add + 1 >= 1 && count_in_new_piece_before_add + 1 <= 10) {\n                    temp_b_d[count_in_new_piece_before_add + 1]++;\n                }\n            }\n        } // End of strawberry loop\n        \n        long long new_score = calculate_score(temp_b_d);\n\n        if (new_score > current_score || dist_01(rng) < exp((double)(new_score - current_score) / T)) {\n            // Accept the change\n            current_lines[line_idx_to_perturb] = candidate_line;\n            b_d_current = temp_b_d;\n            piece_strawberry_counts_current = temp_piece_strawberry_counts;\n            current_score = new_score;\n\n            // Commit changes to global strawberry state variables.\n            for (int j = 0; j < N_strawberries; ++j) {\n                num_lines_passing_through_strawberry_current[j] = next_num_lines_passing_through_commit[j];\n                strawberry_line_sides_current_bits[j].set(line_idx_to_perturb, next_line_side_values_at_idx_bit[j]);\n            }\n\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_lines = current_lines;\n            }\n        }\n    }\n\n    cout << K_max_cuts << endl;\n    for (const auto& line : best_lines) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << endl;\n    }\n}\n\n// Main function to run the solution.\nint main() {\n    ios_base::sync_with_stdio(false); \n    cin.tie(NULL); \n    solve();\n    return 0;\n}\n","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set> \n#include <chrono>\n\n// To manage execution time\nstd::chrono::high_resolution_clock::time_point start_time;\ndouble time_limit_ms = 4900.0; // 4.9 seconds to be safe\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        return !(*this == other);\n    }\n    // For sorting in set/map, etc. Not strictly needed for this solution.\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\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\nstruct RectangleOp {\n    Point p1, p2, p3, p4; // p1 is the new dot, p2, p3, p4 are existing dots\n};\n\nint N_global;\nint center_x_coord; \nint center_y_coord; \nstd::vector<std::vector<bool>> has_dot;\n\n// For condition 3: tracking drawn segments\n// horizontal_drawn[y][x]: segment (x,y)-(x+1,y)\nstd::vector<std::vector<bool>> horizontal_drawn;\n// vertical_drawn[x][y]: segment (x,y)-(x,y+1)\n// Corrected sizing: x from 0 to N-1, y from 0 to N-2\nstd::vector<std::vector<bool>> vertical_drawn;\n// diag_up_drawn[x][y]: segment (x,y)-(x+1,y+1) (slope +1)\nstd::vector<std::vector<bool>> diag_up_drawn;\n// diag_down_drawn[x][y]: segment (x,y+1)-(x+1,y) (slope -1)\nstd::vector<std::vector<bool>> diag_down_drawn;\n\n// Weights precomputation\nstd::vector<std::vector<double>> point_weights;\n\n// Moved `is_in_bounds` definition here, before its usage in `get_weight`\nbool is_in_bounds(Point p) {\n    return p.x >= 0 && p.x < N_global && p.y >= 0 && p.y < N_global;\n}\n\n// Precompute weights for all points\nvoid precompute_weights() {\n    point_weights.resize(N_global, std::vector<double>(N_global));\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            // Using long long for intermediate products to prevent potential overflow, then cast to double\n            point_weights[i][j] = (double)((long long)(i - center_x_coord) * (i - center_x_coord) + \n                                           (long long)(j - center_y_coord) * (j - center_y_coord) + 1);\n        }\n    }\n}\n\ndouble get_weight(Point p) {\n    if (!is_in_bounds(p)) return -1.0; \n    return point_weights[p.x][p.y];\n}\n\n\n// Helper to check if a point on perimeter is an allowed dot (one of p2,p3,p4)\n// p1 (new point) is allowed to be empty. This function checks for other unexpected dots.\nbool is_allowed_dot(Point p, Point p2, Point p3, Point p4) {\n    return p == p2 || p == p3 || p == p4;\n}\n\n// Function to check condition 2 (no other dots on perimeter)\n// Iterates grid points on each segment.\nbool check_perimeter_dots(Point p1_new, Point p2, Point p3, Point p4) {\n    auto check_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        int steps = std::max(std::abs(dx), std::abs(dy));\n\n        if (steps == 0) return true; // Degenerate segment, no intermediate points\n\n        // Iterate intermediate points on the segment (excluding endpoints)\n        for (int i = 1; i < steps; ++i) {\n            Point p = {start.x + dx * i / steps, start.y + dy * i / steps};\n            \n            // Check if there is a dot at p that is NOT p2, p3, or p4\n            if (has_dot[p.x][p.y] && !is_allowed_dot(p, p2, p3, p4)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    if (!check_segment(p1_new, p2)) return false;\n    if (!check_segment(p2, p3)) return false;\n    if (!check_segment(p3, p4)) return false;\n    if (!check_segment(p4, p1_new)) return false;\n    return true;\n}\n\n// Function to check condition 3 (no shared segment with positive length)\n// dry_run = true only checks, dry_run = false marks the segments\nbool check_shared_segments(Point p1_new, Point p2, Point p3, Point p4, bool dry_run) {\n    auto process_segment = [&](Point start, Point end, bool dry_run_local) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        // Condition 3: \"common segment of positive length\"\n        // So, if dx=0, dy=0, it's a point, not a segment of positive length.\n        if (dx == 0 && dy == 0) return true;\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                if (dry_run_local) {\n                    if (vertical_drawn[x][y]) return false;\n                } else {\n                    vertical_drawn[x][y] = true;\n                }\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                if (dry_run_local) {\n                    if (horizontal_drawn[y][x]) return false;\n                } else {\n                    horizontal_drawn[y][x] = true;\n                }\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                if (dry_run_local) {\n                    if (diag_up_drawn[min_x + i][min_y + i]) return false;\n                } else {\n                    diag_up_drawn[min_x + i][min_y + i] = true;\n                }\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end); // Ensure start.x <= end.x\n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                // For a unit segment (x_curr, y_curr+1)-(x_curr+1, y_curr), its bottom-left is (x_curr, y_curr)\n                int x_curr = current_start.x + i;\n                int y_curr = current_start.y - i - 1; \n\n                if (dry_run_local) {\n                    if (diag_down_drawn[x_curr][y_curr]) return false;\n                } else {\n                    diag_down_drawn[x_curr][y_curr] = true;\n                }\n            }\n        }\n        return true;\n    };\n\n    if (!process_segment(p1_new, p2, dry_run)) return false;\n    if (!process_segment(p2, p3, dry_run)) return false;\n    if (!process_segment(p3, p4, dry_run)) return false;\n    if (!process_segment(p4, p1_new, dry_run)) return false;\n\n    return true; // All checks passed for dry run or successfully marked\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    start_time = std::chrono::high_resolution_clock::now();\n\n    int M;\n    std::cin >> N_global >> M;\n\n    center_x_coord = (N_global - 1) / 2; \n    center_y_coord = (N_global - 1) / 2; \n\n    has_dot.resize(N_global, std::vector<bool>(N_global, false));\n    horizontal_drawn.resize(N_global, std::vector<bool>(N_global - 1, false));\n    vertical_drawn.resize(N_global, std::vector<bool>(N_global - 1, false)); \n    diag_up_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n    diag_down_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n\n    std::vector<Point> current_dots_list;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        std::cin >> x >> y;\n        current_dots_list.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    precompute_weights();\n\n    std::vector<RectangleOp> operations;\n    int loop_count = 0;\n    const int max_loops = 5000; // Cap the total main loop iterations\n\n    while (loop_count < max_loops) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n\n        double best_P1_weight = -1.0;\n        RectangleOp best_op;\n        bool found_op = false;\n\n        // Iterate over pairs of existing dots p_adj1 and p_adj2.\n        // These will be p_{i,2} and p_{i,4} in the problem's notation (opposite vertices in the (x,y) plane).\n        // p_{i,3} is then derived such that it is also an existing dot.\n        // p_{i,1} (p1_new) is derived as the empty point.\n        for (size_t i = 0; i < current_dots_list.size(); ++i) {\n            Point p_adj1 = current_dots_list[i]; // Corresponds to p_{i,2}\n            for (size_t j = 0; j < current_dots_list.size(); ++j) {\n                if (i == j) continue; // p_adj1 and p_adj2 must be distinct\n                Point p_adj2 = current_dots_list[j]; // Corresponds to p_{i,4}\n\n                // --- Try Axis-aligned rectangle ---\n                // p1_new_aa = (p_adj1.x, p_adj2.y)\n                // p_opp_aa = (p_adj2.x, p_adj1.y)\n                // These four points form a rectangle: (p1_new_aa, p_adj1, p_opp_aa, p_adj2) in order\n                Point p1_new_aa = {p_adj1.x, p_adj2.y};\n                Point p_opp_aa = {p_adj2.x, p_adj1.y}; // Corresponds to p_{i,3}\n\n                // Check for degenerate rectangle (zero width or height)\n                if (p_adj1.x == p_adj2.x || p_adj1.y == p_adj2.y) continue; \n\n                if (is_in_bounds(p1_new_aa) && !has_dot[p1_new_aa.x][p1_new_aa.y] && // p1_new must be empty\n                    is_in_bounds(p_opp_aa) && has_dot[p_opp_aa.x][p_opp_aa.y] &&    // p_opp must have a dot\n                    p1_new_aa != p_adj1 && p1_new_aa != p_opp_aa && p1_new_aa != p_adj2) // All 4 points distinct\n                {\n                    if (check_perimeter_dots(p1_new_aa, p_adj1, p_opp_aa, p_adj2) &&\n                        check_shared_segments(p1_new_aa, p_adj1, p_opp_aa, p_adj2, true)) { // dry_run = true\n                        double current_weight = get_weight(p1_new_aa);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_aa, p_adj1, p_opp_aa, p_adj2};\n                            found_op = true;\n                        }\n                    }\n                }\n\n                // --- Try 45-degree inclined rectangle (general case) ---\n                // Transform to (U,V) coordinates where U = x+y, V = x-y\n                int u_adj1 = p_adj1.x + p_adj1.y;\n                int v_adj1 = p_adj1.x - p_adj1.y;\n                int u_adj2 = p_adj2.x + p_adj2.y;\n                int v_adj2 = p_adj2.x - p_adj2.y;\n\n                // Check for degenerate rectangle in (U,V) space (zero width or height)\n                if (u_adj1 == u_adj2 || v_adj1 == v_adj2) continue;\n                \n                // Derived U,V for p1_new and p_opp\n                int u1_new = u_adj1;\n                int v1_new = v_adj2;\n                int u3_opp = u_adj2;\n                int v3_opp = v_adj1;\n\n                // Check parity for integer coordinates after inverse transform: (U+V)/2, (U-V)/2\n                if ((u1_new + v1_new) % 2 != 0 || (u1_new - v1_new) % 2 != 0 ||\n                    (u3_opp + v3_opp) % 2 != 0 || (u3_opp - v3_opp) % 2 != 0) {\n                    continue; // Points would not be on integer grid\n                }\n\n                Point p1_new_45 = {(u1_new + v1_new) / 2, (u1_new - v1_new) / 2};\n                Point p_opp_45 = {(u3_opp + v3_opp) / 2, (u3_opp - v3_opp) / 2};\n\n                if (is_in_bounds(p1_new_45) && !has_dot[p1_new_45.x][p1_new_45.y] &&\n                    is_in_bounds(p_opp_45) && has_dot[p_opp_45.x][p_opp_45.y] &&\n                    p1_new_45 != p_adj1 && p1_new_45 != p_opp_45 && p1_new_45 != p_adj2) {\n                    if (check_perimeter_dots(p1_new_45, p_adj1, p_opp_45, p_adj2) &&\n                        check_shared_segments(p1_new_45, p_adj1, p_opp_45, p_adj2, true)) { // dry_run = true\n                        double current_weight = get_weight(p1_new_45);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_45, p_adj1, p_opp_45, p_adj2};\n                            found_op = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found_op) {\n            break; // No more valid operations\n        }\n\n        // Perform the best operation\n        operations.push_back(best_op);\n        has_dot[best_op.p1.x][best_op.p1.y] = true;\n        current_dots_list.push_back(best_op.p1); // Add new dot to list for future operations\n        check_shared_segments(best_op.p1, best_op.p2, best_op.p3, best_op.p4, false); // dry_run = false to mark\n        loop_count++;\n    }\n\n    std::cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        std::cout << op.p1.x << \" \" << op.p1.y << \" \"\n                  << op.p2.x << \" \" << op.p2.y << \" \"\n                  << op.p3.x << \" \" << op.p3.y << \" \"\n                  << op.p4.x << \" \" << op.p4.y << \"\\n\";\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#include <queue> // For BFS in component calculation\n\n// Using std namespace for convenience in competitive programming context\nusing namespace std;\n\n// Constants for board size\nconst int N = 10; \n\n// Global board state\nvector<vector<int>> board(N, vector<int>(N, 0)); // 0: empty, 1,2,3: flavors\n\n// Stores the flavors of candies in the order they are received (f_1 to f_100)\nvector<int> flavors_data(100);\n\n// For the tie-breaker heuristic:\n// Maps original flavor index (1,2,3) to its assigned region index (0,1,2)\nmap<int, int> flavor_to_region_idx;\n// Maps assigned region index (0,1,2) back to its original flavor index (1,2,3)\nvector<int> region_idx_to_flavor(3); \n// Stores start and end rows for each assigned region (0,1,2)\nvector<int> region_rows_start(3); \nvector<int> region_rows_end(3);   \n\n// Directions for BFS\nconst int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\nconst int dc[] = {0, 0, -1, 1};\n\n\n// Function to find the (r, c) coordinates of the p-th empty cell\npair<int, int> get_coords_from_p_idx(int p_idx) {\n    int count = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) {\n                count++;\n                if (count == p_idx) {\n                    return {r, c};\n                }\n            }\n        }\n    }\n    return {-1, -1}; // Should not happen in a valid problem scenario\n}\n\n// Function to apply a tilt operation to a given board\nvoid apply_tilt(vector<vector<int>>& current_board, char dir) {\n    if (dir == 'F') { // Forward (up, towards row 0)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = 0; r < N; ++r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = 0; r < N; ++r) {\n                if (r < candies_in_col.size()) {\n                    current_board[r][c] = candies_in_col[r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'B') { // Backward (down, towards row N-1)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = N - 1; r >= 0; --r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = N - 1; r >= 0; --r) {\n                if ((N - 1 - r) < candies_in_col.size()) { // Fill from bottom up\n                    current_board[r][c] = candies_in_col[N - 1 - r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'L') { // Left (towards col 0)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = 0; c < N; ++c) {\n                if (c < candies_in_row.size()) {\n                    current_board[r][c] = candies_in_row[c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'R') { // Right (towards col N-1)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = N - 1; c >= 0; --c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = N - 1; c >= 0; --c) {\n                if ((N - 1 - c) < candies_in_row.size()) { // Fill from right to left\n                    current_board[r][c] = candies_in_row[N - 1 - c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    }\n}\n\n// Helper function to calculate the sum of n_i^2 for a given board state\nlong long calculate_sum_n_sq(const vector<vector<int>>& current_board) {\n    long long total_n_sq = 0;\n    \n    for (int flavor_to_check = 1; flavor_to_check <= 3; ++flavor_to_check) {\n        vector<vector<bool>> visited_for_flavor(N, vector<bool>(N, false));\n        \n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] == flavor_to_check && !visited_for_flavor[r][c]) {\n                    int current_component_size = 0;\n                    queue<pair<int, int>> q; \n                    q.push({r, c});\n                    visited_for_flavor[r][c] = true;\n                    \n                    while(!q.empty()){\n                        pair<int, int> curr = q.front();\n                        q.pop();\n                        current_component_size++;\n\n                        for (int i = 0; i < 4; ++i) {\n                            int nr = curr.first + dr[i];\n                            int nc = curr.second + dc[i];\n\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                                current_board[nr][nc] == flavor_to_check && !visited_for_flavor[nr][nc]) {\n                                visited_for_flavor[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                    total_n_sq += (long long)current_component_size * current_component_size;\n                }\n            }\n        }\n    }\n    return total_n_sq;\n}\n\n// Function to get the target flavor for a given cell (r, c) based on region partitioning\n// This function is for the tie-breaker heuristic\nint get_target_flavor_for_pos(int r, int c) {\n    int assigned_region_idx;\n    if (r >= region_rows_start[0] && r <= region_rows_end[0]) {\n        assigned_region_idx = 0;\n    } else if (r >= region_rows_start[1] && r <= region_rows_end[1]) {\n        assigned_region_idx = 1;\n    } else { // r must be in region 2\n        assigned_region_idx = 2;\n    }\n    return region_idx_to_flavor[assigned_region_idx];\n}\n\n// Function to calculate the number of candies in their assigned regions for a tie-breaker\ndouble calculate_regional_match_score(const vector<vector<int>>& current_board) {\n    double match_score = 0.0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (current_board[r][c] != 0) { // If there's a candy in this cell\n                int candy_flavor = current_board[r][c];\n                int target_flavor = get_target_flavor_for_pos(r, c); // Get the flavor intended for this region\n                if (candy_flavor == target_flavor) {\n                    match_score += 1.0; \n                }\n            }\n        }\n    }\n    return match_score;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read all candy flavors (f_1 to f_100)\n    vector<int> d_counts(4, 0); // d_counts[0] unused, d_counts[1,2,3] for flavors 1,2,3\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors_data[i];\n        d_counts[flavors_data[i]]++;\n    }\n\n    // Determine region assignment based on flavor counts (for tie-breaker)\n    vector<pair<int, int>> flavor_data_sorted; \n    flavor_data_sorted.push_back({d_counts[1], 1});\n    flavor_data_sorted.push_back({d_counts[2], 2});\n    flavor_data_sorted.push_back({d_counts[3], 3});\n\n    sort(flavor_data_sorted.rbegin(), flavor_data_sorted.rend()); \n\n    for (int i = 0; i < 3; ++i) {\n        flavor_to_region_idx[flavor_data_sorted[i].second] = i;\n        region_idx_to_flavor[i] = flavor_data_sorted[i].second;\n    }\n\n    vector<int> row_counts(3);\n    int assigned_total_rows = 0;\n    for (int i = 0; i < 2; ++i) { \n        row_counts[i] = round(flavor_data_sorted[i].first * static_cast<double>(N) / 100.0);\n        row_counts[i] = max(1, row_counts[i]); \n        assigned_total_rows += row_counts[i];\n    }\n    row_counts[2] = max(1, N - assigned_total_rows); \n\n    int current_sum_row_counts = row_counts[0] + row_counts[1] + row_counts[2];\n    int diff = current_sum_row_counts - N;\n    if (diff > 0) { \n        for (int i = 0; i < 3 && diff > 0; ++i) {\n            if (row_counts[i] > 1) { \n                int decrement_val = min(diff, row_counts[i] - 1);\n                row_counts[i] -= decrement_val;\n                diff -= decrement_val;\n            }\n        }\n    }\n\n    int current_row_idx = 0;\n    for (int i = 0; i < 3; ++i) {\n        region_rows_start[i] = current_row_idx;\n        region_rows_end[i] = current_row_idx + row_counts[i] - 1;\n        current_row_idx += row_counts[i];\n    }\n    \n    // Main loop: process each candy one by one\n    char directions[] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p_t;\n        cin >> p_t; // Read the index of the empty cell for the current candy\n\n        // Find coordinates for the new candy\n        pair<int, int> new_candy_coords = get_coords_from_p_idx(p_t);\n        int r_new = new_candy_coords.first;\n        int c_new = new_candy_coords.second;\n\n        // Place the new candy on the board\n        board[r_new][c_new] = flavors_data[t];\n\n        long long best_tilt_score_n_sq = -1; // Initialize with a small number, scores are non-negative\n        double best_tie_breaker_score = -1.0; // Initialize tie-breaker score\n        char best_dir = ' ';\n\n        // Evaluate each of the four possible tilt directions\n        for (char dir : directions) {\n            vector<vector<int>> temp_board = board; // Create a copy of the board for simulation\n            apply_tilt(temp_board, dir); // Simulate the tilt\n\n            // Primary metric: sum of n_i^2\n            long long current_tilt_score_n_sq = calculate_sum_n_sq(temp_board);\n            \n            // Secondary metric (for tie-breaking): number of candies in their assigned regions\n            double current_tie_breaker_score = calculate_regional_match_score(temp_board);\n\n            // Update best direction if current tilt yields a higher primary score,\n            // or if primary scores are equal and secondary score is higher.\n            if (current_tilt_score_n_sq > best_tilt_score_n_sq) {\n                best_tilt_score_n_sq = current_tilt_score_n_sq;\n                best_tie_breaker_score = current_tie_breaker_score;\n                best_dir = dir;\n            } else if (current_tilt_score_n_sq == best_tilt_score_n_sq) {\n                if (current_tie_breaker_score > best_tie_breaker_score) {\n                    best_tie_breaker_score = current_tie_breaker_score;\n                    best_dir = dir;\n                }\n            }\n        }\n\n        // Apply the chosen best tilt to the actual board\n        apply_tilt(board, best_dir);\n\n        // Output the chosen direction and flush stdout\n        cout << best_dir << endl;\n    }\n\n    return 0;\n}\n","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <map>\n#include <iomanip>\n#include <cmath> // For std::round, std::abs, std::pow\n\n// Adjacency matrix representation\nusing AdjMatrix = std::vector<std::vector<bool>>;\n\n// Function to convert adjacency matrix to string representation\nstd::string graph_to_string(const AdjMatrix& adj, int N) {\n    std::string s = \"\";\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Function to convert string representation to adjacency matrix\nAdjMatrix string_to_graph(const std::string& s, int N) {\n    AdjMatrix adj(N, std::vector<bool>(N, false));\n    int k_str = 0; // Index for the string s\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[k_str] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            k_str++;\n        }\n    }\n    return adj;\n}\n\n// Computes WL refinement color histogram (fingerprint) of a graph\nstd::map<int, int> compute_wl_fingerprint(const AdjMatrix& adj, int N, int wl_iters) {\n    std::vector<int> colors(N);\n    // Initial colors based on degrees\n    for (int i = 0; i < N; ++i) {\n        int degree = 0;\n        for (int j = 0; j < N; ++j) {\n            if (adj[i][j]) {\n                degree++;\n            }\n        }\n        colors[i] = degree;\n    }\n\n    // If wl_iters is 0, just return the degree distribution as fingerprint\n    if (wl_iters == 0) {\n        std::map<int, int> histogram;\n        for (int c : colors) {\n            histogram[c]++;\n        }\n        return histogram;\n    }\n\n    // For WL iterations > 0\n    // Use a unique color_map for each iteration to avoid global state issues.\n    // Or, more efficiently, reset/clear the map for each graph's WL computation.\n    // However, the current structure means 'color_map' is local to compute_wl_fingerprint,\n    // so it's fresh for each graph processed. The 'next_color_idx' ensures unique IDs within one graph's WL processing.\n    std::map<std::vector<int>, int> color_map; // Maps unique (current_color, sorted_neighbor_colors) to a new integer color\n    int next_color_idx = 0; // Counter for assigning new unique colors for this iteration\n\n    for (int iter = 0; iter < wl_iters; ++iter) {\n        // Clear color_map and reset next_color_idx for each iteration for distinctness\n        // No, this is incorrect. The colors are global for all N vertices within ONE graph.\n        // It's 'colors' (the vector) that holds the current iteration's state.\n        // `color_map` is used to map combinations of old_color+neighbor_colors to NEW_color.\n        // This mapping has to be consistent within one iteration for all vertices.\n        // The implementation already correctly uses a single color_map and next_color_idx for a full WL computation for one graph.\n        std::vector<int> new_colors(N);\n        for (int i = 0; i < N; ++i) {\n            std::vector<int> neighbor_colors;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    neighbor_colors.push_back(colors[j]);\n                }\n            }\n            std::sort(neighbor_colors.begin(), neighbor_colors.end());\n\n            // Construct key for color_map: current color + sorted list of neighbor colors\n            std::vector<int> current_key = {colors[i]};\n            current_key.insert(current_key.end(), neighbor_colors.begin(), neighbor_colors.end());\n            \n            // Assign a new unique color if this key hasn't been seen before\n            if (color_map.find(current_key) == color_map.end()) {\n                color_map[current_key] = next_color_idx++;\n            }\n            new_colors[i] = color_map[current_key];\n        }\n        colors = new_colors; // Update colors for the next iteration\n    }\n\n    // Compute histogram of final colors\n    std::map<int, int> histogram;\n    for (int c : colors) {\n        histogram[c]++;\n    }\n    return histogram;\n}\n\n// Calculates squared Euclidean distance between two color histograms\ndouble histogram_distance(const std::map<int, int>& h1, const std::map<int, int>& h2) {\n    double dist_sq = 0;\n    \n    // Collect all unique colors present in either histogram\n    std::vector<int> all_colors_keys;\n    for(const auto& pair : h1) all_colors_keys.push_back(pair.first);\n    for(const auto& pair : h2) all_colors_keys.push_back(pair.first);\n    std::sort(all_colors_keys.begin(), all_colors_keys.end());\n    all_colors_keys.erase(std::unique(all_colors_keys.begin(), all_colors_keys.end()), all_colors_keys.end());\n\n    for (int color : all_colors_keys) {\n        int count1 = h1.count(color) ? h1.at(color) : 0;\n        int count2 = h2.count(color) ? h2.at(color) : 0;\n        dist_sq += (double)(count1 - count2) * (count1 - count2);\n    }\n    return dist_sq;\n}\n\n// Global variables for problem parameters and generated graphs\nint M_param;\ndouble EPSILON_param;\nint N_chosen;\nstd::vector<AdjMatrix> G_graphs;\nstd::vector<std::map<int, int>> G_fingerprints; // Precomputed fingerprints for G_graphs\nstd::vector<int> G_edge_counts; // Precomputed edge counts for G_graphs\nint WL_ITERS_chosen; // Number of WL iterations to use\nint E_total_possible; // Total possible edges for N_chosen vertices\n\n// Function to precompute N and all M graphs G_k\nvoid precompute_graphs() {\n    // Determine N based on M and epsilon. Refined heuristic choice.\n    // Aims for a smaller N to minimize score penalty, while still providing enough capacity.\n    N_chosen = std::min(100, std::max(4, (int)(M_param * 0.3 + 10 + EPSILON_param * 20))); // Adjusted factors\n\n    // Determine WL_ITERS based on epsilon. Heuristic choice.\n    // Fewer iterations for higher epsilon to prevent noise from propagating too much.\n    // wl_iters can be 0, meaning only initial degree distribution is used.\n    WL_ITERS_chosen = std::max(0, 3 - (int)(EPSILON_param * 5));\n\n    E_total_possible = N_chosen * (N_chosen - 1) / 2; // Total possible edges\n    \n    G_graphs.resize(M_param);\n    G_fingerprints.resize(M_param);\n    G_edge_counts.resize(M_param);\n\n    // List all possible edges to facilitate random selection\n    std::vector<std::pair<int, int>> all_possible_edges;\n    for (int i = 0; i < N_chosen; ++i) {\n        for (int j = i + 1; j < N_chosen; ++j) {\n            all_possible_edges.push_back({i, j});\n        }\n    }\n\n    for (int k = 0; k < M_param; ++k) {\n        AdjMatrix current_G(N_chosen, std::vector<bool>(N_chosen, false));\n        \n        // Target number of edges for G_k.\n        // Distributed from 0 to E_total across M graphs.\n        int target_edges_count = std::round((double)k / (M_param - 1) * E_total_possible);\n        if (M_param == 1) target_edges_count = 0; // Special case for M=1 to avoid division by zero\n        \n        // Generate edges using a pseudo-random approach.\n        // A fixed seed 'k' ensures G_k is deterministic and distinct for each k.\n        std::mt19937 rng(k); \n        std::vector<std::pair<int, int>> shuffled_edges = all_possible_edges;\n        std::shuffle(shuffled_edges.begin(), shuffled_edges.end(), rng);\n\n        // Add the target number of edges\n        int actual_edges = 0;\n        for (int i = 0; i < target_edges_count; ++i) {\n            auto edge = shuffled_edges[i];\n            current_G[edge.first][edge.second] = true;\n            current_G[edge.second][edge.first] = true;\n            actual_edges++;\n        }\n        G_graphs[k] = current_G;\n        G_edge_counts[k] = actual_edges; // Store precomputed edge count\n        \n        // Precompute fingerprint for efficiency\n        G_fingerprints[k] = compute_wl_fingerprint(current_G, N_chosen, WL_ITERS_chosen);\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read M and epsilon\n    std::cin >> M_param >> EPSILON_param;\n\n    // Perform precomputation (determine N, generate G_k graphs and their fingerprints)\n    precompute_graphs();\n\n    // Output N and the M generated graphs\n    std::cout << N_chosen << std::endl;\n    for (int k = 0; k < M_param; ++k) {\n        std::cout << graph_to_string(G_graphs[k], N_chosen) << std::endl;\n    }\n    std::cout << std::flush; // Crucial for interactive problems\n\n    // Calculate normalization factor for WL distance. Max possible squared difference in a histogram of N vertices.\n    // If N is very small (e.g., N=4), 2.0 * N_chosen * N_chosen could be too large relative to max actual diff.\n    // For N_chosen vertices, the sum of counts in a histogram is N_chosen.\n    // Max diff for any single bucket is N_chosen. Max sum of squared diffs is 2*N_chosen^2.\n    // This value seems okay for normalization.\n    double wl_norm_factor = 2.0 * N_chosen * N_chosen;\n    if (N_chosen <= 1) wl_norm_factor = 1.0; // Defensive check, N_chosen >= 4\n\n    // Calculate weight alpha for combining distances.\n    // Alpha scales from 0 (pure WL) to 1 (pure edge count diff) as epsilon goes from 0 to 0.4.\n    // Using a square root power ensures edge_diff becomes relevant more quickly for intermediate epsilon.\n    double alpha_weight_base = EPSILON_param / 0.4;\n    double alpha_weight = std::pow(alpha_weight_base, 0.5); // Using sqrt to adjust weighting curve\n    \n    // Clamp alpha_weight to [0, 1] for robustness against floating point errors or edge cases.\n    alpha_weight = std::max(0.0, std::min(1.0, alpha_weight));\n\n    // For very small epsilon, ensure alpha_weight is 0 to prioritize WL.\n    if (EPSILON_param < 0.001) alpha_weight = 0.0;\n    // For very large epsilon, ensure alpha_weight is 1 to prioritize edge count.\n    if (EPSILON_param > 0.399) alpha_weight = 1.0;\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str; // Read the received graph H_k\n        \n        // Compute fingerprint for H_k\n        AdjMatrix H_adj = string_to_graph(H_str, N_chosen);\n        std::map<int, int> H_fingerprint = compute_wl_fingerprint(H_adj, N_chosen, WL_ITERS_chosen);\n        \n        // Count edges in H_k\n        int H_edge_count = 0;\n        for (char c : H_str) {\n            if (c == '1') {\n                H_edge_count++;\n            }\n        }\n\n        double min_total_dist = -1.0;\n        int best_t = -1;\n\n        // Compare H_k's fingerprint and edge count with all precomputed G_t\n        for (int t = 0; t < M_param; ++t) {\n            // WL distance\n            double wl_dist = histogram_distance(H_fingerprint, G_fingerprints[t]);\n            double normalized_wl_dist = wl_dist / wl_norm_factor;\n\n            // Edge count difference distance\n            double edge_diff = std::abs((double)H_edge_count - G_edge_counts[t]);\n            double normalized_edge_diff = edge_diff / (double)E_total_possible;\n            if (E_total_possible == 0) normalized_edge_diff = 0.0; // Should not happen with N_chosen>=4, but for safety.\n\n            // Combined distance\n            double current_total_dist = (1.0 - alpha_weight) * normalized_wl_dist + alpha_weight * normalized_edge_diff;\n            \n            if (best_t == -1 || current_total_dist < min_total_dist) {\n                min_total_dist = current_total_dist;\n                best_t = t;\n            }\n        }\n        std::cout << best_t << std::endl; // Output the prediction\n        std::cout << std::flush; // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <limits>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <map>\n#include <iomanip> // For setprecision\n#include <random>\n\nusing namespace std;\n\n// Using long long for distances to avoid overflow for sums\nconst long long INF = numeric_limits<long long>::max() / 2; // A sufficiently large value that avoids overflow when added to\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Node {\n    long long dist;\n    int u;\n    bool operator>(const Node& other) const {\n        return dist > other.dist;\n    }\n};\n\nstruct EdgeInfo {\n    int u, v, w, id;\n    long double val; // combined importance score: extra_dist * edge_betweenness\n};\n\nvector<vector<pair<int, int>>> adj; // adj[u] = list of {v, edge_id}\nvector<Edge> edges_data;\nint N_global, M_global, D_global, K_global;\n\n// Dijkstra's algorithm to find shortest paths from a source s\n// Optionally excludes a specific edge for extra_dist calculation\n// Returns a vector of distances from s to all other vertices.\nvector<long long> dijkstra(int s, const vector<vector<pair<int, int>>>& current_adj, int excluded_edge_id = -1) {\n    vector<long long> dist(N_global, INF);\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n    dist[s] = 0;\n    pq.push({0, s});\n\n    while (!pq.empty()) {\n        long long d = pq.top().dist;\n        int u = pq.top().u;\n        pq.pop();\n\n        if (d > dist[u]) continue; // Already found a shorter path\n\n        for (auto& edge_pair : current_adj[u]) {\n            int v = edge_pair.first;\n            int edge_id = edge_pair.second;\n\n            if (edge_id == excluded_edge_id) continue;\n\n            long long weight = edges_data[edge_id].w;\n            if (dist[u] != INF && dist[u] + weight < dist[v]) { // dist[u] != INF check to prevent overflow\n                dist[v] = dist[u] + weight;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Brandes' algorithm for Edge Betweenness Centrality\n// Returns a vector where element i is the betweenness centrality of edge_data[i]\nvector<long double> calculate_edge_betweenness() {\n    vector<long double> edge_betweenness(M_global, 0.0);\n\n    for (int s = 0; s < N_global; ++s) {\n        vector<long long> dist(N_global, INF);\n        vector<long long> num_shortest_paths(N_global, 0); // Count of shortest paths from s to v\n        vector<vector<int>> predecessors(N_global); // For each v, a list of vertices u that precede v on shortest paths from s\n        vector<int> stack; // To process vertices in decreasing order of distance\n\n        priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n        dist[s] = 0;\n        num_shortest_paths[s] = 1;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            long long d = pq.top().dist;\n            int u = pq.top().u;\n            pq.pop();\n\n            if (d > dist[u]) continue; \n            \n            stack.push_back(u); // Add to stack for processing in reverse order of distance\n\n            for (auto& edge_pair : adj[u]) {\n                int v = edge_pair.first;\n                int edge_id = edge_pair.second;\n                long long weight = edges_data[edge_id].w;\n\n                if (dist[u] != INF) { // Only consider paths from reachable u\n                    if (dist[u] + weight < dist[v]) {\n                        dist[v] = dist[u] + weight;\n                        num_shortest_paths[v] = num_shortest_paths[u];\n                        predecessors[v].clear();\n                        predecessors[v].push_back(u);\n                        pq.push({dist[v], v});\n                    } else if (dist[u] + weight == dist[v]) {\n                        num_shortest_paths[v] += num_shortest_paths[u];\n                        predecessors[v].push_back(u);\n                    }\n                }\n            }\n        }\n\n        vector<long double> delta(N_global, 0.0); // Dependency of s on v\n        while (!stack.empty()) {\n            int v = stack.back();\n            stack.pop_back();\n\n            for (int u_pred : predecessors[v]) {\n                // Fraction of shortest paths from s to v that pass through u_pred\n                // num_shortest_paths[v] must be > 0 here, because v is reachable from s\n                long double path_fraction = (long double)num_shortest_paths[u_pred] / num_shortest_paths[v];\n                long double contribution = path_fraction * (1.0 + delta[v]);\n                \n                // Find edge_id for (u_pred, v)\n                int found_edge_id = -1;\n                for(const auto& edge_pair : adj[u_pred]) {\n                    if (edge_pair.first == v) {\n                        found_edge_id = edge_pair.second;\n                        break; \n                    }\n                }\n                \n                if (found_edge_id != -1) { // Should always be found for edges on shortest paths\n                    edge_betweenness[found_edge_id] += contribution;\n                }\n                delta[u_pred] += contribution;\n            }\n        }\n    }\n    return edge_betweenness;\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    cin >> N_global >> M_global >> D_global >> K_global;\n\n    adj.resize(N_global);\n    edges_data.resize(M_global);\n\n    for (int i = 0; i < M_global; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v; // 0-indexed\n        edges_data[i] = {u, v, w, i};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i}); // Add edge for both directions\n    }\n\n    // Skip coordinates input as they are not used in this solution\n    for (int i = 0; i < N_global; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge betweenness centrality for each edge\n    vector<long double> edge_betweenness = calculate_edge_betweenness();\n\n    // 2. Precompute extra_dist for each edge (d'(u,v) - w when edge (u,v) is removed)\n    vector<long long> extra_dist(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        int u = edges_data[i].u;\n        int v = edges_data[i].v;\n        int w = edges_data[i].w;\n        vector<long long> dist_from_u_without_edge = dijkstra(u, adj, i);\n        // If u and v become disconnected, consider the path effectively infinite (10^9 from problem)\n        // Ensure extra_dist is non-negative\n        extra_dist[i] = (dist_from_u_without_edge[v] == INF) ? (1000000000LL - w) : (dist_from_u_without_edge[v] - w);\n        if (extra_dist[i] < 0) extra_dist[i] = 0; \n    }\n    \n    // 3. Combine scores: val[e_idx] = extra_dist[e_idx] * edge_betweenness[e_idx]\n    vector<EdgeInfo> edge_infos(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        edge_infos[i] = {edges_data[i].u, edges_data[i].v, edges_data[i].w, i, (long double)extra_dist[i] * edge_betweenness[i]};\n    }\n    \n    // 4. Initial assignment (r[M]): Sort edges by combined importance (val) and assign round-robin\n    sort(edge_infos.begin(), edge_infos.end(), [](const EdgeInfo& a, const EdgeInfo& b) {\n        return a.val > b.val;\n    });\n\n    vector<int> r(M_global); // repair day for each edge (1-indexed)\n    vector<int> day_load(D_global + 1, 0); // Number of edges assigned to each day\n    vector<long double> current_sum_val(D_global + 1, 0.0); // Sum of val for edges assigned to each day\n\n    for (int i = 0; i < M_global; ++i) {\n        int edge_id = edge_infos[i].id;\n        int day = (i % D_global) + 1; // Round-robin assignment based on sorted importance\n        r[edge_id] = day;\n        day_load[day]++;\n        current_sum_val[day] += edge_infos[i].val;\n    }\n    \n    // Calculate initial estimated frustration score (sum of average vals per day)\n    long double current_total_approx_score = 0.0;\n    for (int k = 1; k <= D_global; ++k) {\n        if (day_load[k] > 0) {\n            current_total_approx_score += current_sum_val[k] / day_load[k];\n        }\n    }\n\n    vector<int> best_r = r;\n    long double best_total_approx_score = current_total_approx_score;\n\n    // Simulated Annealing parameters\n    double time_limit_sec = 5.9; // Allocate 5.9 seconds for SA\n    long double T_start = 1e12; // Starting temperature\n    long double T_end = 1e-4;   // Ending temperature\n    \n    // Random number generation setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_edge(0, M_global - 1);\n    uniform_int_distribution<int> dist_day(1, D_global);\n    uniform_real_distribution<long double> dist_01(0.0, 1.0);\n\n    // SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time_sec = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time_sec > time_limit_sec) {\n            break;\n        }\n\n        // Linear cooling schedule\n        long double current_T = T_start * (1.0 - elapsed_time_sec / time_limit_sec);\n        if (current_T < T_end) current_T = T_end;\n\n        int edge_idx = dist_edge(rng); // Randomly pick an edge to move\n        int day_from = r[edge_idx];\n        int day_to = dist_day(rng); // Randomly pick a target day\n\n        // Check feasibility and efficiency constraints\n        if (day_from == day_to || day_load[day_to] >= K_global) {\n            continue; // Cannot move to same day or to an already full day\n        }\n\n        long double val_e = edge_infos[edge_idx].val; // Importance value of the edge being moved\n\n        // Calculate old average frustration for affected days\n        long double old_f_from = current_sum_val[day_from] / day_load[day_from];\n        long double old_f_to = (day_load[day_to] > 0) ? (current_sum_val[day_to] / day_load[day_to]) : 0.0; // If day_to is empty, old frustration is 0\n\n        // Calculate new average frustration if move is accepted\n        long double new_f_from = (day_load[day_from] > 1) ? ((current_sum_val[day_from] - val_e) / (day_load[day_from] - 1.0)) : 0.0; // If day_from becomes empty, new frustration is 0\n        long double new_f_to = (current_sum_val[day_to] + val_e) / (day_load[day_to] + 1.0);\n        \n        long double delta_score = (new_f_from - old_f_from) + (new_f_to - old_f_to);\n\n        // Acceptance criteria for Simulated Annealing\n        if (delta_score < 0 || dist_01(rng) < exp(-delta_score / current_T)) {\n            // Accept the move\n            r[edge_idx] = day_to;\n            day_load[day_from]--;\n            day_load[day_to]++;\n            current_sum_val[day_from] -= val_e;\n            current_sum_val[day_to] += val_e;\n            current_total_approx_score += delta_score;\n\n            // Update best solution found so far\n            if (current_total_approx_score < best_total_approx_score) {\n                best_total_approx_score = current_total_approx_score;\n                best_r = r;\n            }\n        }\n    }\n\n    // Output the best assignment found\n    for (int i = 0; i < M_global; ++i) {\n        cout << best_r[i] << (i == M_global - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}\n","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <queue>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\n// Global D for convenience\nint D;\n\n// Struct for 3D point\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& 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 Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\n// Represents a polycube shape as a vector of relative points\nusing Shape = vector<Point>;\n\n// Function to apply a rotation to a point relative to its origin (0,0,0)\nPoint rotate_point(const Point& p, int rot_idx) {\n    // This defines the 24 unique rotations\n    // Each case maps (x,y,z) to a permutation of (+/-x, +/-y, +/-z)\n    switch (rot_idx) {\n        case 0: return {p.x, p.y, p.z};\n        case 1: return {p.x, p.z, -p.y};\n        case 2: return {p.x, -p.y, -p.z};\n        case 3: return {p.x, -p.z, p.y};\n        \n        case 4: return {-p.x, -p.y, p.z};\n        case 5: return {-p.x, -p.z, -p.y};\n        case 6: return {-p.x, p.y, -p.z};\n        case 7: return {-p.x, p.z, p.y};\n\n        case 8: return {p.y, p.x, -p.z};\n        case 9: return {p.y, p.z, p.x};\n        case 10: return {p.y, -p.x, p.z};\n        case 11: return {p.y, -p.z, -p.x};\n\n        case 12: return {-p.y, p.x, p.z};\n        case 13: return {-p.y, p.z, -p.x};\n        case 14: return {-p.y, -p.x, -p.z};\n        case 15: return {-p.y, -p.z, p.x};\n        \n        case 16: return {p.z, p.x, p.y};\n        case 17: return {p.z, p.y, -p.x};\n        case 18: return {p.z, -p.x, -p.y};\n        case 19: return {p.z, -p.y, p.x};\n        \n        case 20: return {-p.z, p.x, p.y};\n        case 21: return {-p.z, p.y, -p.x};\n        case 22: return {-p.z, -p.x, -p.y};\n        case 23: return {-p.z, -p.y, p.x};\n    }\n    return p; // Should not be reached\n}\n\n// Function to canonicalize a shape (vector of relative points)\nShape get_canonical_form(const Shape& shape) {\n    if (shape.empty()) return {};\n\n    Shape canonical_shape = shape;\n    sort(canonical_shape.begin(), canonical_shape.end()); // Initial sort\n\n    for (int rot_idx = 0; rot_idx < 24; ++rot_idx) {\n        Shape rotated_shape_temp;\n        for (const auto& p : shape) {\n            rotated_shape_temp.push_back(rotate_point(p, rot_idx));\n        }\n\n        // Translate to (0,0,0) origin\n        int min_x = D, min_y = D, min_z = D;\n        for (const auto& p : rotated_shape_temp) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated_shape_temp) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n\n        sort(rotated_shape_temp.begin(), rotated_shape_temp.end());\n        if (rotated_shape_temp < canonical_shape) {\n            canonical_shape = rotated_shape_temp;\n        }\n    }\n    return canonical_shape;\n}\n\n// BFS to find a connected component and return its absolute points.\n// Also modifies `grid_to_search` by setting visited cells to 0.\n// Returns a pair: {vector of absolute points, relative shape}\npair<vector<Point>, Shape> find_and_extract_component(vector<vector<vector<int>>>& grid_to_search, int start_x, int start_y, int start_z) {\n    vector<Point> absolute_points;\n    Shape relative_shape;\n\n    if (start_x < 0 || start_x >= D || start_y < 0 || start_y >= D || start_z < 0 || start_z >= D || grid_to_search[start_x][start_y][start_z] == 0) {\n        return {absolute_points, relative_shape};\n    }\n\n    queue<Point> q;\n    q.push({start_x, start_y, start_z});\n    grid_to_search[start_x][start_y][start_z] = 0; // Mark as visited and remove from current grid\n    absolute_points.push_back({start_x, start_y, start_z});\n\n    int dx[] = {0, 0, 0, 0, 1, -1};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {1, -1, 0, 0, 0, 0};\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            int nz = curr.z + dz[i];\n\n            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D && grid_to_search[nx][ny][nz] == 1) {\n                grid_to_search[nx][ny][nz] = 0; // Mark as visited\n                q.push({nx, ny, nz});\n                absolute_points.push_back({nx, ny, nz});\n            }\n        }\n    }\n    \n    // Translate the component points to be relative to their bounding box min corner\n    if (absolute_points.empty()) return {absolute_points, relative_shape};\n\n    int min_x = D, min_y = D, min_z = D;\n    for (const auto& p : absolute_points) {\n        min_x = min(min_x, p.x);\n        min_y = min(min_y, p.y);\n        min_z = min(min_z, p.z);\n    }\n    \n    for (const auto& p : absolute_points) {\n        relative_shape.push_back({p.x - min_x, p.y - min_y, p.z - min_z});\n    }\n    sort(relative_shape.begin(), relative_shape.end());\n    \n    return {absolute_points, relative_shape};\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D;\n\n    vector<string> f1_str(D), r1_str(D), f2_str(D), r2_str(D);\n    for (int i = 0; i < D; ++i) cin >> f1_str[i];\n    for (int i = 0; i < D; ++i) cin >> r1_str[i];\n    for (int i = 0; i < D; ++i) cin >> f2_str[i];\n    for (int i = 0; i < D; ++i) cin >> r2_str[i];\n\n    // U_i_grid_initial[x][y][z] == 1 if (x,y,z) can be occupied based on silhouettes\n    // These grids are the \"ground truth\" and are not modified during component extraction.\n    vector<vector<vector<int>>> U1_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U2_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (f1_str[z][x] == '1' && r1_str[z][y] == '1') U1_grid_initial[x][y][z] = 1;\n                if (f2_str[z][x] == '1' && r2_str[z][y] == '1') U2_grid_initial[x][y][z] = 1;\n            }\n        }\n    }\n\n    // b_raw grids store temporary IDs for blocks discovered for each object independently.\n    // They are populated to fully cover U_grid_initial for their respective objects.\n    vector<vector<vector<int>>> b1_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Stores (canonical_shape, volume) for each temporary block in b1_raw and b2_raw\n    // 1-indexed, so push a dummy element at index 0.\n    vector<tuple<Shape, int>> b1_temp_blocks_info; \n    b1_temp_blocks_info.emplace_back(Shape{}, 0); \n    vector<tuple<Shape, int>> b2_temp_blocks_info; \n    b2_temp_blocks_info.emplace_back(Shape{}, 0); \n    \n    int current_temp_id_b1 = 1;\n    int current_temp_id_b2 = 1;\n\n    // Phase 1: Fill b1_raw completely based on U1_grid_initial\n    // Use a mutable copy for BFS, as it modifies the grid by setting visited cells to 0.\n    vector<vector<vector<int>>> U1_grid_mutable = U1_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U1_grid_mutable[x][y][z] == 1) { \n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U1_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n\n                    if (!absolute_points.empty()) { \n                        int temp_id = current_temp_id_b1++;\n                        for (const auto& p_abs : absolute_points) {\n                            b1_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b1_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Fill b2_raw completely based on U2_grid_initial\n    // Similar to Phase 1, but for object 2.\n    vector<vector<vector<int>>> U2_grid_mutable = U2_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U2_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U2_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int temp_id = current_temp_id_b2++;\n                        for (const auto& p_abs : absolute_points) {\n                            b2_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b2_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n\n    // Phase 3: Consolidate temporary blocks into final block set and IDs\n    vector<int> map_b1_to_final_id(current_temp_id_b1, 0); // Maps b1_raw temp_id to final_id\n    vector<int> map_b2_to_final_id(current_temp_id_b2, 0); // Maps b2_raw temp_id to final_id\n    \n    int current_final_id = 1; // Start final block IDs from 1\n    \n    // These vectors store info about the *final* set of unique blocks.\n    // They are not directly used for output, but for score calculation logic.\n    // Kept for clarity and potential future optimizations.\n    vector<Shape> final_block_shapes;\n    vector<int> final_block_volumes;\n    vector<bool> final_block_used_in_1;\n    vector<bool> final_block_used_in_2;\n\n    // Dummy entries for 1-indexed final_ids\n    final_block_shapes.push_back({});\n    final_block_volumes.push_back(0);\n    final_block_used_in_1.push_back(false);\n    final_block_used_in_2.push_back(false);\n\n    // Group temporary blocks by their canonical shape\n    map<Shape, vector<int>> temp_ids_b1_by_shape; // canonical_shape -> list of b1_raw temp_id\n    map<Shape, vector<int>> temp_ids_b2_by_shape; // canonical_shape -> list of b2_raw temp_id\n\n    for (int i = 1; i < b1_temp_blocks_info.size(); ++i) {\n        temp_ids_b1_by_shape[get<0>(b1_temp_blocks_info[i])].push_back(i);\n    }\n    for (int i = 1; i < b2_temp_blocks_info.size(); ++i) {\n        temp_ids_b2_by_shape[get<0>(b2_temp_blocks_info[i])].push_back(i);\n    }\n\n    set<Shape> processed_shapes; // To avoid processing same shape twice (from b1 and b2 loops)\n\n    // First, process shapes that appear in b1_raw. Try to match them with b2_raw blocks.\n    for (auto const& [shape, b1_raw_ids_for_shape] : temp_ids_b1_by_shape) {\n        processed_shapes.insert(shape); // Mark this shape as processed\n        \n        auto it_b2 = temp_ids_b2_by_shape.find(shape);\n        vector<int> b2_raw_ids_for_shape;\n        if (it_b2 != temp_ids_b2_by_shape.end()) {\n            b2_raw_ids_for_shape = it_b2->second;\n        }\n\n        // Match as many b1 blocks with b2 blocks of the same shape as possible\n        int num_to_match = min(b1_raw_ids_for_shape.size(), b2_raw_ids_for_shape.size());\n        for (int i = 0; i < num_to_match; ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n            \n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]])); // Volume is same for same shape\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(true);\n        }\n\n        // Remaining b1_raw blocks (only used in Object 1)\n        for (int i = num_to_match; i < b1_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(false);\n        }\n\n        // Remaining b2_raw blocks (only used in Object 2), for this shape\n        for (int i = num_to_match; i < b2_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n\n    // Process shapes that were only present in b2_raw (not in b1_raw)\n    for (auto const& [shape, b2_raw_ids_for_shape] : temp_ids_b2_by_shape) {\n        if (processed_shapes.count(shape)) continue; // Already handled if present in b1_raw\n        \n        for (int b2_id : b2_raw_ids_for_shape) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_id] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_id]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n    \n    // Phase 4: Populate final b1 and b2 grids with assigned final IDs\n    vector<vector<vector<int>>> b1_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (b1_raw[x][y][z] != 0) {\n                    b1_final_output[x][y][z] = map_b1_to_final_id[b1_raw[x][y][z]];\n                }\n                if (b2_raw[x][y][z] != 0) {\n                    b2_final_output[x][y][z] = map_b2_to_final_id[b2_raw[x][y][z]];\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << current_final_id - 1 << endl; // Total number of unique final blocks\n\n    // Output b1_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b1_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    // Output b2_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b2_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\nconst long long INF_LL = 4e18; // Sufficiently large infinity for long long\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\nstruct Edge {\n    int id; // original edge index (0 to M-1)\n    int u, v;\n    long long w;\n};\n\nstruct EdgeInfo { // For adjacency list\n    int to_node;\n    long long weight;\n    int original_edge_idx;\n};\n\n// For Dijkstra\nstruct State {\n    long long cost;\n    int u;\n\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\nint N, M, K;\nvector<Point> nodes;\nvector<Edge> edges_data;\nvector<Point> residents;\nvector<vector<EdgeInfo>> adj; // adjacency list for graph\n\n// Precomputed distances\nvector<vector<long long>> dist_res_node_sq; // dist_res_node_sq[k][i] = squared Euclidean distance from resident k to node i\nvector<long long> dist_from_1; // Shortest path cost from node 1 to node i\nvector<int> parent_on_spt_node; // parent_on_spt_node[i] = parent node in SPT from node 1\nvector<int> parent_on_spt_edge_idx; // parent_on_spt_edge_idx[i] = original edge index of (parent[i], i)\n\n// Global random generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to calculate squared Euclidean distance\nlong long distSq(Point p1, 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\n// Calculate rounded Euclidean distance\nint round_dist_val(long long dist_sq) {\n    return static_cast<int>(round(sqrt((long double)dist_sq))); // Cast to long double for sqrt for precision\n}\n\n// Dijkstra from node 1\nvoid run_dijkstra() {\n    dist_from_1.assign(N + 1, INF_LL);\n    parent_on_spt_node.assign(N + 1, -1);\n    parent_on_spt_edge_idx.assign(N + 1, -1);\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist_from_1[1] = 0;\n    pq.push({0, 1});\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        long long d = current.cost;\n        int u = current.u;\n\n        if (d > dist_from_1[u]) continue;\n\n        for (auto& edge_info : adj[u]) {\n            int v = edge_info.to_node;\n            long long weight = edge_info.weight;\n            int edge_idx = edge_info.original_edge_idx;\n\n            if (dist_from_1[u] + weight < dist_from_1[v]) {\n                dist_from_1[v] = dist_from_1[u] + weight;\n                parent_on_spt_node[v] = u;\n                parent_on_spt_edge_idx[v] = edge_idx;\n                pq.push({dist_from_1[v], v});\n            }\n        }\n    }\n}\n\n// Recalculates edge cost for a given set of active stations\nlong long calculate_edge_cost_from_active_stations(const set<int>& active_stations, vector<int>& B_output_temp) {\n    set<int> edges_on_idx_set;\n    long long current_edge_cost = 0;\n\n    for (int u : active_stations) {\n        if (dist_from_1[u] == INF_LL) { \n            return INF_LL; // Should not happen if `active_stations` are already filtered or cost is set to INF_LL\n        }\n        if (u == 1) continue; \n        \n        int curr = u;\n        while (curr != 1 && parent_on_spt_node[curr] != -1) {\n            int edge_idx = parent_on_spt_edge_idx[curr];\n            if (edges_on_idx_set.find(edge_idx) == edges_on_idx_set.end()) {\n                edges_on_idx_set.insert(edge_idx);\n                current_edge_cost += edges_data[edge_idx].w;\n            }\n            curr = parent_on_spt_node[curr];\n        }\n    }\n    \n    // Populate B_output_temp\n    B_output_temp.assign(M, 0);\n    for (int j = 0; j < M; ++j) {\n        if (edges_on_idx_set.count(j)) {\n            B_output_temp[j] = 1;\n        }\n    }\n\n    return current_edge_cost;\n}\n\n\nvoid solve() {\n    // Precomputation (read input, run Dijkstra, calculate resident-node distances)\n    nodes.resize(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        cin >> nodes[i].x >> nodes[i].y;\n        nodes[i].id = i;\n    }\n\n    adj.resize(N + 1);\n    edges_data.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges_data[j].u >> edges_data[j].v >> edges_data[j].w;\n        edges_data[j].id = j;\n        adj[edges_data[j].u].push_back({edges_data[j].v, edges_data[j].w, j});\n        adj[edges_data[j].v].push_back({edges_data[j].u, edges_data[j].w, j});\n    }\n\n    residents.resize(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n\n    run_dijkstra();\n\n    dist_res_node_sq.resize(K, vector<long long>(N + 1));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            dist_res_node_sq[k][i] = distSq(residents[k], nodes[i]);\n        }\n    }\n    \n    // Initial solution (Greedy approach)\n    vector<int> P_current(N + 1, 0);\n    \n    // For each resident, assign it to its closest reachable station (within 5000 radius).\n    // Then combine P values for stations.\n    for (int k = 0; k < K; ++k) {\n        int best_station_for_k = -1;\n        long long min_dist_sq_for_k = (long long)5001 * 5001; // Max guaranteed distance is 5000\n        for (int i = 1; i <= N; ++i) {\n            if (dist_from_1[i] == INF_LL) continue; // Station must be reachable from 1\n            if (dist_res_node_sq[k][i] <= (long long)5000 * 5000) {\n                if (dist_res_node_sq[k][i] < min_dist_sq_for_k) {\n                    min_dist_sq_for_k = dist_res_node_sq[k][i];\n                    best_station_for_k = i;\n                }\n            }\n        }\n        if (best_station_for_k != -1) {\n            P_current[best_station_for_k] = max(P_current[best_station_for_k], round_dist_val(min_dist_sq_for_k));\n        } else {\n             // This indicates a problem as per problem statement guarantee. Should not happen.\n        }\n    }\n    // Cap all P values at 5000\n    for(int i=1; i<=N; ++i) {\n        P_current[i] = min(P_current[i], 5000);\n    }\n    \n    vector<int> B_best(M);\n    long long best_S = INF_LL;\n    vector<int> P_best = P_current;\n\n    // State variables for SA (to allow incremental updates)\n    long long current_P_cost_SA = 0;\n    set<int> active_stations_SA;\n    vector<int> num_covering_stations_for_resident(K, 0);\n    int num_residents_fully_covered = 0;\n\n    // Initialize SA state variables from P_current\n    for (int i = 1; i <= N; ++i) {\n        if (P_current[i] > 0 && dist_from_1[i] == INF_LL) { // If an initially active station is unreachable\n            current_P_cost_SA = INF_LL; // Mark initial state as invalid\n            break;\n        }\n        current_P_cost_SA += (long long)P_current[i] * P_current[i];\n        if (P_current[i] > 0) {\n            active_stations_SA.insert(i);\n        }\n    }\n    if (current_P_cost_SA != INF_LL) { // If initial P cost is valid (all active stations reachable)\n        for (int k = 0; k < K; ++k) {\n            for (int i = 1; i <= N; ++i) {\n                if (P_current[i] > 0) {\n                    if (dist_res_node_sq[k][i] <= (long long)P_current[i] * P_current[i]) {\n                        num_covering_stations_for_resident[k]++;\n                    }\n                }\n            }\n            if (num_covering_stations_for_resident[k] > 0) {\n                num_residents_fully_covered++;\n            }\n        }\n    }\n    \n    long long current_edge_cost_SA = 0;\n    if (current_P_cost_SA != INF_LL && num_residents_fully_covered == K) {\n        vector<int> temp_B(M); // Placeholder for calculate_edge_cost_from_active_stations\n        current_edge_cost_SA = calculate_edge_cost_from_active_stations(active_stations_SA, temp_B);\n        best_S = current_P_cost_SA + current_edge_cost_SA;\n        P_best = P_current;\n    }\n\n\n    // Simulated Annealing\n    chrono::high_resolution_clock::time_point start_time = chrono::high_resolution_clock::now();\n    long double current_temp;\n    if (best_S == INF_LL) { \n        current_temp = 1e9; \n    } else {\n        current_temp = (long double)best_S / 100.0; // Dynamic initial temperature\n    }\n    long double end_temp = 1.0;\n    long double time_limit = 1.95; // seconds\n    \n    // Parameters for SA moves\n    const int P_ADJUST_RANGE = 500; \n    \n    long long iter_count = 0;\n    while (true) {\n        chrono::high_resolution_clock::time_point current_time = chrono::high_resolution_clock::now();\n        long double elapsed_time = chrono::duration_cast<chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        if (elapsed_time > time_limit) {\n            break;\n        }\n        \n        current_temp = end_temp + (current_temp - end_temp) * (1.0 - elapsed_time / time_limit);\n        \n        vector<int> P_next = P_current; // P_next is a copy for perturbation\n        long long next_P_cost = current_P_cost_SA;\n        set<int> next_active_stations = active_stations_SA;\n        vector<int> next_num_covering_stations = num_covering_stations_for_resident;\n        int next_num_residents_fully_covered = num_residents_fully_covered;\n\n        int target_node = rng() % N + 1;\n        int old_P_val = P_current[target_node]; // Use P_current for old P value\n\n        if (dist_from_1[target_node] == INF_LL) { // Don't bother with unreachable nodes\n            continue;\n        }\n\n        int move_type = rng() % 100;\n\n        if (move_type < 60) { // Type 0: Adjust P_i for a random station i (60% chance)\n            int rand_delta = (rng() % (2 * P_ADJUST_RANGE + 1)) - P_ADJUST_RANGE;\n            int new_P_val = old_P_val + rand_delta;\n            new_P_val = max(0, min(5000, new_P_val));\n            P_next[target_node] = new_P_val;\n\n            // Update incremental costs\n            next_P_cost -= (long long)old_P_val * old_P_val;\n            next_P_cost += (long long)new_P_val * new_P_val;\n\n            if (old_P_val == 0 && new_P_val > 0) { // Station became active\n                next_active_stations.insert(target_node);\n            } else if (old_P_val > 0 && new_P_val == 0) { // Station became inactive\n                next_active_stations.erase(target_node);\n            }\n\n            // Update coverage counts incrementally for O(K) complexity\n            for (int k = 0; k < K; ++k) {\n                bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                if (old_covered_by_target && !new_covered_by_target) {\n                    next_num_covering_stations[k]--;\n                    if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                } else if (!old_covered_by_target && new_covered_by_target) {\n                    next_num_covering_stations[k]++;\n                    if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                }\n            }\n\n        } else { // Type 1: Try to turn off a station and re-assign coverage (40% chance)\n            \n            // If target_node is currently OFF, try turning it ON (random P)\n            if (old_P_val == 0) { \n                int new_P_val = rng() % 5001; // Random P between 0 and 5000\n                P_next[target_node] = new_P_val;\n\n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_P_cost += (long long)new_P_val * new_P_val;\n\n                if (new_P_val > 0) {\n                    next_active_stations.insert(target_node);\n                }\n\n                // Update coverage counts incrementally\n                for (int k = 0; k < K; ++k) {\n                    bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                    bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                    if (old_covered_by_target && !new_covered_by_target) {\n                        next_num_covering_stations[k]--;\n                        if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                    } else if (!old_covered_by_target && new_covered_by_target) {\n                        next_num_covering_stations[k]++;\n                        if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                    }\n                }\n\n            } else { // If target_node is currently ON, try turning it OFF and re-assign\n                // Temporarily remove target_node's coverage from next_num_covering_stations\n                // This makes it easy to find truly uncovered residents for re-assignment\n                for(int k=0; k<K; ++k){\n                    if(dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val){\n                        next_num_covering_stations[k]--;\n                        if(next_num_covering_stations[k] == 0){\n                            next_num_residents_fully_covered--;\n                        }\n                    }\n                }\n\n                P_next[target_node] = 0; \n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_active_stations.erase(target_node);\n\n                // For each resident that became uncovered, find the best station to cover it\n                for(int k=0; k<K; ++k){\n                    if(next_num_covering_stations[k] == 0){ // This resident is now uncovered\n                        int best_alt_station = -1;\n                        long long min_dist_sq = INF_LL; \n                        for(int i=1; i<=N; ++i){ \n                            if(dist_from_1[i] == INF_LL) continue; // Only consider reachable stations\n                            if(dist_res_node_sq[k][i] < min_dist_sq){\n                                min_dist_sq = dist_res_node_sq[k][i];\n                                best_alt_station = i;\n                            }\n                        }\n                        if(best_alt_station != -1){\n                            int old_alt_P = P_next[best_alt_station]; // Use P_next (which might already be updated)\n                            long long required_P_sq = min_dist_sq;\n                            int required_P = round_dist_val(required_P_sq);\n                            int new_alt_P = max(old_alt_P, min(5000, required_P));\n                            \n                            // Apply change to P_next and update costs incrementally\n                            P_next[best_alt_station] = new_alt_P;\n                            next_P_cost -= (long long)old_alt_P * old_alt_P;\n                            next_P_cost += (long long)new_alt_P * new_alt_P;\n                            if (old_alt_P == 0 && new_alt_P > 0) {\n                                next_active_stations.insert(best_alt_station);\n                            }\n                            // Update coverage for this resident 'k' by best_alt_station\n                            // (Only for k, not all residents affected by best_alt_station's P change)\n                            if (dist_res_node_sq[k][best_alt_station] <= (long long)new_alt_P * new_alt_P) {\n                                next_num_covering_stations[k]++;\n                                if(next_num_covering_stations[k] == 1) { // It just became covered again\n                                    next_num_residents_fully_covered++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        long long S_current_val = current_P_cost_SA + current_edge_cost_SA;\n        long long S_next = INF_LL;\n\n        if (next_num_residents_fully_covered == K) {\n            vector<int> B_temp(M);\n            long long next_edge_cost = calculate_edge_cost_from_active_stations(next_active_stations, B_temp);\n            S_next = next_P_cost + next_edge_cost;\n        }\n\n        if (S_next < best_S) {\n            P_current = P_next;\n            current_P_cost_SA = next_P_cost;\n            active_stations_SA = next_active_stations;\n            num_covering_stations_for_resident = next_num_covering_stations;\n            num_residents_fully_covered = next_num_residents_fully_covered;\n            current_edge_cost_SA = S_next - current_P_cost_SA; // derive edge cost from S_next and P_cost\n            best_S = S_next;\n            P_best = P_next;\n        } else if (S_next != INF_LL) {\n            long double prob = exp((S_current_val - S_next) / current_temp);\n            if (uniform_real_distribution<long double>(0.0, 1.0)(rng) < prob) {\n                P_current = P_next;\n                current_P_cost_SA = next_P_cost;\n                active_stations_SA = next_active_stations;\n                num_covering_stations_for_resident = next_num_covering_stations;\n                num_residents_fully_covered = next_num_residents_fully_covered;\n                current_edge_cost_SA = S_next - current_P_cost_SA;\n            }\n        }\n        \n        iter_count++;\n    }\n\n    // Final calculation for output\n    vector<int> B_final(M);\n    calculate_edge_cost_from_active_stations(active_stations_SA, B_final); \n\n    // Output\n    for (int i = 1; i <= N; ++i) {\n        cout << P_best[i] << (i == N ? \"\" : \" \");\n    }\n    cout << endl;\n    for (int j = 0; j < M; ++j) {\n        cout << B_final[j] << (j == M - 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 >> K;\n    solve();\n\n    return 0;\n}\n","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <tuple>   // For std::tuple\n\n// N is fixed to 30 for all inputs.\n// The problem defines N as the number of tiers.\n// Tiers are 0-indexed from 0 to N-1.\n// Ball coordinates are (x,y) where 0 <= x <= N-1 and 0 <= y <= x.\nconst int N = 30;\n\n// Global data structures for the pyramid state and operations.\n// The pyramid itself, storing the ball numbers.\nstd::vector<std::vector<int>> pyramid(N);\n\n// To quickly find the coordinates of a ball given its number.\n// `current_pos_of_value[ball_number]` stores `{x, y}`.\nstd::vector<std::pair<int, int>> current_pos_of_value(N * (N + 1) / 2);\n\n// Stores the sequence of swap operations.\n// Each operation is a tuple `{x1, y1, x2, y2}`.\nstd::vector<std::tuple<int, int, int, int>> operations;\n\n/**\n * @brief Performs a swap between two balls at given coordinates and records the operation.\n *\n * This function updates the `pyramid` and `current_pos_of_value` data structures\n * to reflect the swap, and adds the operation to the `operations` list.\n * The coordinates (r1, c1) and (r2, c2) must refer to adjacent balls.\n *\n * @param r1 Row coordinate of the first ball.\n * @param c1 Column coordinate of the first ball.\n * @param r2 Row coordinate of the second ball.\n * @param c2 Column coordinate of the second ball.\n */\nvoid perform_swap(int r1, int c1, int r2, int c2) {\n    int val1 = pyramid[r1][c1];\n    int val2 = pyramid[r2][c2];\n\n    // Swap values in the pyramid grid\n    pyramid[r1][c1] = val2;\n    pyramid[r2][c2] = val1;\n\n    // Update the mapping from value to its current position\n    current_pos_of_value[val1] = {r2, c2};\n    current_pos_of_value[val2] = {r1, c1};\n\n    // Record the swap operation\n    operations.emplace_back(r1, c1, r2, c2);\n}\n\n/**\n * @brief Sifts down an element at (r, c) to satisfy the min-pyramid property.\n *\n * This function repeatedly compares the ball at (r, c) with its two children\n * ((r+1, c) and (r+1, c+1)). If the parent ball is larger than either child,\n * it swaps the parent with the smallest child. This process continues until\n * the parent ball is smaller than or equal to both its children, or it reaches\n * the bottom tier.\n * This is an iterative implementation of the sift-down (or heapify-down) process.\n *\n * @param r Row coordinate of the ball to sift down.\n * @param c Column coordinate of the ball to sift down.\n */\nvoid sift_down(int r, int c) {\n    while (true) {\n        int parent_val = pyramid[r][c];\n        int min_val = parent_val; // Initialize min_val with parent's value\n        int target_r = r;         // Initialize target_r and target_c to parent's position\n        int target_c = c;\n\n        // Check left child: (r+1, c)\n        // Ensure that (r,c) is not in the last tier (N-1)\n        if (r + 1 < N) {\n            int child1_val = pyramid[r+1][c];\n            if (child1_val < min_val) {\n                min_val = child1_val;\n                target_r = r + 1;\n                target_c = c;\n            }\n        }\n\n        // Check right child: (r+1, c+1)\n        // Ensure (r,c) is not in the last tier AND (r+1, c+1) is a valid coordinate.\n        // For a tier x, valid column indices are from 0 to x.\n        // So for tier r+1, column c+1 must satisfy c+1 <= r+1.\n        if (r + 1 < N && c + 1 <= r + 1) {\n            int child2_val = pyramid[r+1][c+1];\n            // Crucially, compare against `min_val` (which might be child1_val already),\n            // not directly `parent_val`, to find the smallest among parent and both children.\n            if (child2_val < min_val) {\n                min_val = child2_val;\n                target_r = r + 1;\n                target_c = c + 1;\n            }\n        }\n\n        // If no child was smaller than the parent (or if it's a leaf node),\n        // the element is in its correct position relative to its children.\n        if (target_r == r && target_c == c) {\n            break; // Sifting process complete for this element\n        } else {\n            // Swap the current ball with the smallest child\n            perform_swap(r, c, target_r, target_c);\n\n            // Continue sifting down from the new position of the swapped element\n            r = target_r;\n            c = target_c;\n        }\n    }\n}\n\n\nint main() {\n    // Optimize C++ standard streams for competitive programming.\n    // This unties cin from cout and disables synchronization with C stdio,\n    // speeding up input/output operations.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read the initial state of the pyramid from standard input.\n    // Each row 'i' has 'i+1' balls.\n    for (int i = 0; i < N; ++i) {\n        pyramid[i].resize(i + 1); // Allocate space for balls in tier 'i'\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> pyramid[i][j];\n            // Store the initial position of each ball number.\n            current_pos_of_value[pyramid[i][j]] = {i, j};\n        }\n    }\n\n    // Apply the bottom-up heapify algorithm to satisfy the min-pyramid property.\n    // We iterate from the second-to-last tier (N-2) up to the top tier (0).\n    // For each ball in these tiers, we call sift_down to ensure it's smaller\n    // than its children. Since we process tiers bottom-up, when we sift down\n    // an element, its children's sub-pyramids are already correctly heapified.\n    for (int r = N - 2; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            sift_down(r, c);\n        }\n    }\n\n    // Output the total number of operations performed.\n    std::cout << operations.size() << std::endl;\n    // Output each swap operation in the specified format.\n    for (const auto& op : operations) {\n        std::cout << std::get<0>(op) << \" \"\n                  << std::get<1>(op) << \" \"\n                  << std::get<2>(op) << \" \"\n                  << std::get<3>(op) << std::endl;\n    }\n\n    return 0;\n}\n","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::abs\n\n// Global constants\nconst int D = 9;\nconst int DR[] = {-1, 1, 0, 0}; // delta row for neighbors (up, down, left, right)\nconst int DC[] = {0, 0, -1, 1}; // delta col for neighbors\n\n// Grid cell states\nconst int EMPTY = -1;\nconst int OBSTACLE = -2;\nconst int ENTRANCE_CELL = -3; // Renamed to avoid conflict with function entrance_r/c\nconst int UNVISITED = -1; // For BFS distance arrays\n\n// Global variables for the warehouse state\nint grid[D][D]; // Stores container ID (0 to M-1), or EMPTY/OBSTACLE/ENTRANCE_CELL\nbool is_obstacle[D][D];\nint static_dist[D][D]; // BFS distance from entrance on an empty grid\nstd::vector<std::pair<int, int>> static_ranked_squares; // Sorted by static_dist\nstd::map<std::pair<int, int>, int> square_to_static_rank; // Maps (r,c) to its rank in static_ranked_squares\n\nstd::pair<int, int> container_pos[D * D]; // Maps container ID to its (r,c) location\nint M; // Total number of containers\n\n// Coordinates of the entrance\nint entrance_r, entrance_c;\n\n// BFS utility function\n// Returns a vector of reachable empty squares (for placement phase)\n// Also populates reachable_container_ids_ptr if provided (for transport-out phase)\nstd::vector<std::pair<int, int>> bfs_reachable_info(\n    int (&current_grid)[D][D],\n    int (&current_dist)[D][D], // Output: distances from entrance\n    const bool* extracted_containers_mask_ptr, // Pointer to mask for extracted containers (nullptr for placement)\n    std::set<int>* reachable_container_ids_ptr // Output: reachable container IDs (nullptr for placement)\n) {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            current_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    current_dist[entrance_r][entrance_c] = 0;\n\n    std::vector<std::pair<int, int>> reachable_empty_squares_candidates;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue; // Out of bounds\n            if (is_obstacle[nr][nc]) continue; // Obstacle\n\n            if (current_dist[nr][nc] == UNVISITED) { // Not visited yet\n                if (current_grid[nr][nc] == EMPTY) {\n                    current_dist[nr][nc] = current_dist[r][c] + 1;\n                    q.push({nr, nc});\n                    reachable_empty_squares_candidates.push_back({nr, nc});\n                } else if (current_grid[nr][nc] == ENTRANCE_CELL) { \n                    // Entrance is traversable and starting point, already visited at dist 0.\n                    // No need to push again or add to reachable_empty_squares_candidates.\n                } else if (current_grid[nr][nc] >= 0) { // Contains a container\n                    int container_id = current_grid[nr][nc];\n                    if (extracted_containers_mask_ptr && extracted_containers_mask_ptr[container_id]) { \n                        // Container already extracted, treat as empty and traversable\n                        current_dist[nr][nc] = current_dist[r][c] + 1;\n                        q.push({nr, nc});\n                        reachable_empty_squares_candidates.push_back({nr, nc}); // Add as an available \"empty\" path square\n                    } else { \n                        // Container still present, cannot traverse, but is reachable for extraction\n                        if (reachable_container_ids_ptr) {\n                            reachable_container_ids_ptr->insert(container_id);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return reachable_empty_squares_candidates;\n}\n\n// Precomputes static distances from the entrance on an empty grid\nvoid precompute_static_distances() {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            static_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    static_dist[entrance_r][entrance_c] = 0;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (is_obstacle[nr][nc]) continue;\n\n            if (static_dist[nr][nc] == UNVISITED) {\n                static_dist[nr][nc] = static_dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Collect all valid container squares and sort them by static distance\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (!is_obstacle[i][j] && (i != entrance_r || j != entrance_c)) {\n                static_ranked_squares.push_back({i, j});\n            }\n        }\n    }\n\n    // Sort by static_dist, then row, then column for consistent ranking\n    std::sort(static_ranked_squares.begin(), static_ranked_squares.end(), [](const auto& a, const auto& b) {\n        if (static_dist[a.first][a.second] != static_dist[b.first][b.second]) {\n            return static_dist[a.first][a.second] < static_dist[b.first][b.second];\n        }\n        if (a.first != b.first) {\n            return a.first < b.first;\n        }\n        return a.second < b.second;\n    });\n\n    for (int i = 0; i < static_ranked_squares.size(); ++i) {\n        square_to_static_rank[static_ranked_squares[i]] = i;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_obstacles;\n    std::cin >> D >> N_obstacles; // D is fixed at 9, but read for generality\n\n    entrance_r = 0;\n    entrance_c = (D - 1) / 2;\n\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            grid[i][j] = EMPTY;\n            is_obstacle[i][j] = false;\n        }\n    }\n    grid[entrance_r][entrance_c] = ENTRANCE_CELL;\n\n    for (int k = 0; k < N_obstacles; ++k) {\n        int r_obs, c_obs;\n        std::cin >> r_obs >> c_obs;\n        is_obstacle[r_obs][c_obs] = true;\n        grid[r_obs][c_obs] = OBSTACLE;\n    }\n\n    M = D * D - 1 - N_obstacles; // Total number of containers\n\n    precompute_static_distances();\n\n    // Placement Phase\n    int current_dist[D][D]; // Temporary array for BFS distances in current state\n    bool dummy_extracted_mask[D*D] = {false}; // Placeholder, not used in placement phase BFS\n\n    for (int d = 0; d < M; ++d) {\n        int t_d; // Container ID\n        std::cin >> t_d;\n\n        std::vector<std::pair<int, int>> reachable_empty_squares =\n            bfs_reachable_info(grid, current_dist, dummy_extracted_mask, nullptr); // Nullptr for transport-out specific parameters\n\n        int best_score_diff = M + 1; // Max possible diff is M-1, so M+1 is a safe initial high value\n        std::pair<int, int> best_pos = {-1, -1};\n\n        for (const auto& p : reachable_empty_squares) {\n            int r = p.first;\n            int c = p.second;\n            int static_rank = square_to_static_rank[p];\n            int score_diff = std::abs(t_d - static_rank);\n\n            if (score_diff < best_score_diff) {\n                best_score_diff = score_diff;\n                best_pos = p;\n            } else if (score_diff == best_score_diff) {\n                // Tie-breaking rules for placement:\n                // 1. Prefer smaller current_dist (currently closer to entrance)\n                if (current_dist[r][c] < current_dist[best_pos.first][best_pos.second]) {\n                    best_pos = p;\n                }\n                // 2. If current_dist is also tied, prefer smaller static_dist (inherently closer)\n                else if (current_dist[r][c] == current_dist[best_pos.first][best_pos.second]) {\n                    if (static_dist[r][c] < static_dist[best_pos.first][best_pos.second]) {\n                        best_pos = p;\n                    }\n                    // 3. If static_dist is also tied, prefer smaller row, then smaller column (lexicographical)\n                    else if (static_dist[r][c] == static_dist[best_pos.first][best_pos.second]) {\n                        if (r < best_pos.first) {\n                            best_pos = p;\n                        } else if (r == best_pos.first) {\n                            if (c < best_pos.second) {\n                                best_pos = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        grid[best_pos.first][best_pos.second] = t_d;\n        container_pos[t_d] = best_pos;\n\n        std::cout << best_pos.first << \" \" << best_pos.second << std::endl;\n    }\n\n    // Transport-Out Phase\n    std::vector<int> b_sequence(M);\n    bool extracted_containers_mask[D*D]; // Tracks which containers have been extracted\n    for(int i = 0; i < D*D; ++i) extracted_containers_mask[i] = false;\n\n    for (int k = 0; k < M; ++k) {\n        std::set<int> reachable_containers;\n        // BFS to find all reachable containers given current grid state and extracted_containers_mask\n        bfs_reachable_info(grid, current_dist, extracted_containers_mask, &reachable_containers);\n\n        int min_reachable_id = -1;\n        if (!reachable_containers.empty()) {\n            min_reachable_id = *reachable_containers.begin(); // std::set keeps elements sorted, so begin() is the smallest\n        } else {\n            // This case should ideally not be reached if the problem guarantees connectivity\n            // and we always place containers in reachable spots.\n            // As a fallback, this would mean searching for the smallest unextracted ID,\n            // but this indicates a problem with logic or problem constraints.\n            // For now, assume a container is always reachable.\n            for (int id = 0; id < M; ++id) {\n                if (!extracted_containers_mask[id]) {\n                    min_reachable_id = id;\n                    break;\n                }\n            }\n        }\n\n        b_sequence[k] = min_reachable_id;\n        extracted_containers_mask[min_reachable_id] = true; // Mark container as extracted\n    }\n\n    for (int k = 0; k < M; ++k) {\n        std::pair<int, int> pos = container_pos[b_sequence[k]];\n        std::cout << pos.first << \" \" << pos.second << std::endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>   // For tracking affected pairs in adjacency check\n#include <tuple> // For std::tie\n\nusing namespace std;\n\n// Fixed grid size and number of wards\nconst int N = 50;\nconst int M = 100;\n\n// Original map from input\nint c[N][N];\n// Created map (modified during SA)\nint d[N][N];\n\n// Required adjacencies: adj_req[u][v] is true if u and v must be adjacent\nbool adj_req[M + 1][M + 1];\n\n// Current adjacencies in 'd' map: adj_count[u][v] stores number of edges between color u and color v\nint adj_count[M + 1][M + 1];\n\n// Number of cells for each color in 'd' map\nint num_cells[M + 1];\n\n// Stores coordinates of cells for each color\nvector<pair<int, int>> ward_cells[M + 1];\n// Stores the index of a cell (r,c) within ward_cells[d[r][c]].\n// This allows O(1) removal from ward_cells by swapping with the last element.\nint cell_idx_in_ward_cells[N][N];\n\n// Directions for neighbors (up, down, left, right)\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\n\n// Check if coordinates (r, c_val) are within the grid bounds\ninline bool is_valid_coord(int r, int c_val) {\n    return r >= 0 && r < N && c_val >= 0 && c_val < N;\n}\n\n// Check if a color 'k' is connected in the 'd' map.\n// If (excluded_r, excluded_c) is specified, that cell is temporarily ignored for connectivity.\nbool check_color_connectivity(int k, int excluded_r = -1, int excluded_c = -1) {\n    int current_num_k_cells = num_cells[k];\n    if (excluded_r != -1 && d[excluded_r][excluded_c] == k) {\n        current_num_k_cells--; // If the excluded cell has color k, reduce the count\n    }\n\n    if (current_num_k_cells == 0) return true; // Empty ward is trivially connected\n\n    // Find a starting point for BFS for color k\n    int start_r = -1, start_c = -1;\n    // Iterate through ward_cells to find a valid starting point that is not the excluded cell\n    for (auto p : ward_cells[k]) {\n        if (p.first == excluded_r && p.second == excluded_c) continue;\n        start_r = p.first;\n        start_c = p.second;\n        break;\n    }\n\n    if (start_r == -1) { // No cells of color k left after exclusion, but current_num_k_cells > 0. This shouldn't happen if num_cells is accurate.\n        return current_num_k_cells == 0;\n    }\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_count = 0;\n\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    reachable_count++;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == k && !visited[nr][nc]) {\n                if (nr == excluded_r && nc == excluded_c) continue; // Skip the excluded cell\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_count++;\n            }\n        }\n    }\n    return reachable_count == current_num_k_cells;\n}\n\n// Check if color 0 is connected (to the outside) in the 'd' map\nbool check_zero_connectivity() {\n    int current_zero_count = num_cells[0];\n    if (current_zero_count == 0) return true; // No 0s, trivially connected\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_zeros = 0;\n\n    // Add all boundary cells that are color 0 to the queue\n    for (int r = 0; r < N; ++r) {\n        if (d[r][0] == 0 && !visited[r][0]) {\n            q.push({r, 0});\n            visited[r][0] = true;\n            reachable_zeros++;\n        }\n        if (d[r][N - 1] == 0 && !visited[r][N - 1]) {\n            q.push({r, N - 1});\n            visited[r][N - 1] = true;\n            reachable_zeros++;\n        }\n    }\n    for (int c_val = 1; c_val < N - 1; ++c_val) { // Avoid double counting corners\n        if (d[0][c_val] == 0 && !visited[0][c_val]) {\n            q.push({0, c_val});\n            visited[0][c_val] = true;\n            reachable_zeros++;\n        }\n        if (d[N - 1][c_val] == 0 && !visited[N - 1][c_val]) {\n            q.push({N - 1, c_val});\n            visited[N - 1][c_val] = true;\n            reachable_zeros++;\n        }\n    }\n\n    // If no boundary '0' cells, but there are other '0' cells, they are disconnected.\n    if (current_zero_count > 0 && reachable_zeros == 0) return false;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == 0 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_zeros++;\n            }\n        }\n    }\n    return reachable_zeros == current_zero_count;\n}\n\nvoid solve() {\n    // Read input\n    int n_val, m_val;\n    cin >> n_val >> m_val; // N, M are fixed, but read them\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> c[i][j];\n        }\n    }\n\n    // Initialize d with c, and calculate initial state metrics\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            d[i][j] = c[i][j];\n            num_cells[d[i][j]]++;\n            // Add to ward_cells and record its index for O(1) removal later\n            cell_idx_in_ward_cells[i][j] = ward_cells[d[i][j]].size();\n            ward_cells[d[i][j]].push_back({i, j});\n        }\n    }\n\n    // Precompute required adjacencies (adj_req) from original map 'c'\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = c[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_req[curr_color][0] = adj_req[0][curr_color] = true;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = c[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_req[curr_color][neighbor_color] = adj_req[neighbor_color][curr_color] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initialize current adjacencies (adj_count) from 'd' (which is initially 'c')\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = d[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_count[min(curr_color, 0)][max(curr_color, 0)]++;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = d[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_count[min(curr_color, neighbor_color)][max(curr_color, neighbor_color)]++;\n                    }\n                }\n            }\n        }\n    }\n\n    // Each edge between two non-zero colors (u,v) where u,v > 0 is counted twice.\n    // So, divide by 2 for pairs (u,v) where u,v > 0.\n    // Pairs involving 0 (boundary adjacencies) are only counted once (when processing the non-zero cell).\n    // So for u=0 or v=0, we should not divide.\n    for (int u = 1; u <= M; ++u) { // Iterate only non-zero colors for u\n        for (int v = u; v <= M; ++v) { // Iterate only non-zero colors for v, ensuring u <= v\n            adj_count[u][v] /= 2;\n        }\n    }\n\n    // Store best map and score. Score is number of non-zero cells (maximize this).\n    vector<vector<int>> best_d(N, vector<int>(N));\n    int current_score = N * N - num_cells[0];\n    int best_score = current_score;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            best_d[i][j] = d[i][j];\n        }\n    }\n\n    // --- Simulated Annealing parameters ---\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95; // seconds (slightly less than 2s to allow for output)\n    double T_start = 2000.0;        // Initial temperature\n    double T_end = 1.0;             // Final temperature\n    long long iter_count = 0;       // Iteration counter\n\n    // Distributions for random selection\n    uniform_int_distribution<int> dist_rc(0, N - 1); // For random row/col\n    uniform_int_distribution<int> dist_color_m(1, M); // For random ward color (1 to M)\n    uniform_real_distribution<double> dist_real(0.0, 1.0); // For acceptance probability\n\n    // Main SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int r = dist_rc(rng);       // Random row\n        int c_val = dist_rc(rng);   // Random column\n        int old_color = d[r][c_val]; // Current color of the cell\n        int new_color;              // Proposed new color\n\n        // Strategy to pick new_color:\n        // Prioritize reducing 0s, then explore other moves\n        if (old_color == 0) {\n            // Try to fill this 0 cell with a neighboring ward's color\n            vector<int> non_zero_neighbors;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] != 0) {\n                    non_zero_neighbors.push_back(d[nr][nc]);\n                }\n            }\n\n            if (!non_zero_neighbors.empty()) {\n                // Pick a random non-zero neighbor's color\n                uniform_int_distribution<int> dist_neighbor_idx(0, non_zero_neighbors.size() - 1);\n                new_color = non_zero_neighbors[dist_neighbor_idx(rng)];\n            } else {\n                // If no non-zero neighbors, pick a random ward color (less effective, might create isolated components)\n                new_color = dist_color_m(rng);\n            }\n        } else { // Current cell is a ward color (1 to M)\n            // Option 1: Change to 0 (might fix forbidden adjacencies, but increases 0s)\n            // Option 2: Change to another non-zero color (assimilation/swap with neighbor)\n            if (dist_real(rng) < 0.5) { // 50% chance to try changing to 0\n                new_color = 0;\n            } else { // 50% chance to try changing to a neighbor's color\n                vector<int> neighbor_colors;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc)) {\n                        neighbor_colors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!neighbor_colors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, neighbor_colors.size() - 1);\n                    new_color = neighbor_colors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); // Random if no neighbors, fallback\n                }\n            }\n        }\n\n        if (new_color == old_color) continue; // No effective change, skip\n\n        // --- Prepare for tentative move and checks ---\n        // Store original state to revert if move is invalid/rejected\n        int original_d_rc_val = d[r][c_val];\n\n        vector<tuple<int, int, int>> temp_adj_count_deltas; // {u, v, delta}\n        set<pair<int, int>> affected_adj_pairs; // Track unique (u,v) pairs affected\n\n        // Update adj_count based on (r,c_val) -> (new_color)\n        // This is done before changing d[r][c_val] to correctly reflect adjacencies with neighbors.\n        // Neighbors of (r,c_val) are still in their original colors.\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c_val + DC[i];\n            if (is_valid_coord(nr, nc)) {\n                int neighbor_color = d[nr][nc]; // Neighbor's current color\n\n                // Remove old_color's adjacency with neighbor_color\n                if (old_color != neighbor_color) {\n                    int u = min(old_color, neighbor_color);\n                    int v = max(old_color, neighbor_color);\n                    adj_count[u][v]--;\n                    temp_adj_count_deltas.emplace_back(u, v, 1); // For reverting: add 1\n                    affected_adj_pairs.insert({u, v});\n                }\n                // Add new_color's adjacency with neighbor_color\n                if (new_color != neighbor_color) {\n                    int u = min(new_color, neighbor_color);\n                    int v = max(new_color, neighbor_color);\n                    adj_count[u][v]++;\n                    temp_adj_count_deltas.emplace_back(u, v, -1); // For reverting: subtract 1\n                    affected_adj_pairs.insert({u, v});\n                }\n            }\n        }\n        // Handle boundary adjacencies with color 0\n        if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n            if (old_color != 0) {\n                int u = min(old_color, 0);\n                int v = max(old_color, 0);\n                adj_count[u][v]--;\n                temp_adj_count_deltas.emplace_back(u, v, 1);\n                affected_adj_pairs.insert({u, v});\n            }\n            if (new_color != 0) {\n                int u = min(new_color, 0);\n                int v = max(new_color, 0);\n                adj_count[u][v]++;\n                temp_adj_count_deltas.emplace_back(u, v, -1);\n                affected_adj_pairs.insert({u, v});\n            }\n        }\n\n        // Tentatively apply d[r][c_val] = new_color;\n        d[r][c_val] = new_color;\n\n        // --- Perform validity checks ---\n        bool move_is_valid = true;\n\n        // 1. Local Adjacency Check: No required adjacencies broken, no forbidden ones created\n        for (auto p : affected_adj_pairs) {\n            int u = p.first;\n            int v = p.second;\n            bool current_adj_exists = (adj_count[u][v] > 0);\n            if (current_adj_exists != adj_req[u][v]) {\n                move_is_valid = false;\n                break;\n            }\n        }\n        if (!move_is_valid) {\n            // Revert d[r][c_val] and adj_count immediately\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue; // Skip to next iteration\n        }\n\n        // 2. Connectivity check for old_color (if it's not 0 and shrinking)\n        // A move can cause an old_color to split only if num_cells[old_color] > 1.\n        // If it becomes 0 after this change (num_cells[old_color] == 1 initially), it's trivially connected.\n        // The adjacency check ensures that if the only cell of old_color is removed, its required adjacencies\n        // are not broken.\n        if (old_color != 0 && num_cells[old_color] > 1) {\n            // Heuristic: If (r,c_val) had 0 or 1 neighbor of old_color, connectivity is likely fine.\n            // Only perform BFS if (r,c_val) was connected to multiple old_color cells\n            int old_color_neighbors_count = 0;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == old_color) {\n                    old_color_neighbors_count++;\n                }\n            }\n            // If it had multiple connections, removal might split the component\n            if (old_color_neighbors_count >= 2) {\n                if (!check_color_connectivity(old_color, r, c_val)) {\n                    move_is_valid = false;\n                }\n            }\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 3. Connectivity check for new_color (if it's not 0 and expanding/connecting)\n        // If num_cells[new_color] was 0, and now it becomes 1 (i.e. this is the first cell), it's connected.\n        // If num_cells[new_color] > 0, the new cell must connect to existing new_color cells.\n        if (new_color != 0) {\n            if (num_cells[new_color] > 0) { // new_color already exists, so (r,c_val) must connect to it\n                bool connected_to_new_color_region = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc) && d[nr][nc] == new_color) {\n                        connected_to_new_color_region = true;\n                        break;\n                    }\n                }\n                if (!connected_to_new_color_region) {\n                    // If no new_color neighbors, it forms an isolated component, which is invalid\n                    move_is_valid = false;\n                }\n            }\n            // If num_cells[new_color] was 0 (now becomes 1), it is trivially connected. No need to check.\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 4. Connectivity check for color 0 (expensive but crucial)\n        if (!check_zero_connectivity()) {\n            move_is_valid = false;\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // --- Move is valid, now decide on acceptance ---\n        // Update num_cells first\n        num_cells[old_color]--;\n        num_cells[new_color]++;\n\n        int new_score = N * N - num_cells[0]; // Score is number of non-zero cells\n\n        // Simulated Annealing acceptance logic\n        if (new_score > current_score || dist_real(rng) < exp((new_score - current_score) / T)) {\n            // Accept the move: update ward_cells permanently (O(1) with indexed swap)\n            // Remove (r,c_val) from old_color's ward_cells\n            int old_idx = cell_idx_in_ward_cells[r][c_val];\n            pair<int, int> last_cell_of_old_color = ward_cells[old_color].back();\n            ward_cells[old_color][old_idx] = last_cell_of_old_color;\n            cell_idx_in_ward_cells[last_cell_of_old_color.first][last_cell_of_old_color.second] = old_idx;\n            ward_cells[old_color].pop_back();\n\n            // Add (r,c_val) to new_color's ward_cells\n            cell_idx_in_ward_cells[r][c_val] = ward_cells[new_color].size();\n            ward_cells[new_color].push_back({r, c_val});\n\n            current_score = new_score;\n\n            if (new_score > best_score) {\n                best_score = new_score;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        best_d[i][j] = d[i][j];\n                    }\n                }\n            }\n        } else {\n            // Reject the move: revert changes to d, adj_count, num_cells\n            num_cells[old_color]++;\n            num_cells[new_color]--;\n            d[r][c_val] = original_d_rc_val; // Revert d[r][c_val]\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n        }\n    } // End of SA loop\n\n    // Output the best map found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_d[i][j] << (j == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n#include <map>\n\n// DSU structure\nstruct DSU {\n    std::vector<int> parent;\n    std::vector<int> sz; // Stores size of component for root\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    // Returns true if i and j were in different sets and are now united.\n    // comp_estimated_weight must be provided to update the new root's estimated weight.\n    bool unite(int i, int j, std::vector<double>& comp_estimated_weight) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            // Union by size\n            if (sz[root_i] < sz[root_j]) std::swap(root_i, root_j);\n            \n            // Weighted average for the new component's estimated weight\n            // This averages the estimated weights of all items in the two combined components.\n            double new_weight = (comp_estimated_weight[root_i] * sz[root_i] + comp_estimated_weight[root_j] * sz[root_j]) / (sz[root_i] + sz[root_j]);\n\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            comp_estimated_weight[root_i] = new_weight;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global random number generator\nstd::mt19937 mt;\n\n// Function to perform a query\nstd::string query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int item_idx : L) {\n        std::cout << \" \" << item_idx;\n    }\n    for (int item_idx : R) {\n        std::cout << \" \" << item_idx;\n    }\n    std::cout << std::endl; // Flush output\n    \n    std::string result;\n    std::cin >> result;\n    return result;\n}\n\n// Function to calculate variance for the partitioning\ndouble calculate_variance(int D, const std::vector<double>& group_sums) {\n    if (D == 0) return 0.0;\n    double sum_t = 0.0;\n    for (double t : group_sums) {\n        sum_t += t;\n    }\n    double mean_t = sum_t / D;\n    double variance = 0.0;\n    for (double t : group_sums) {\n        variance += (t - mean_t) * (t - mean_t);\n    }\n    return variance / D;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Use current time as seed for random number generator\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N, D, Q;\n    std::cin >> N >> D >> Q;\n\n    DSU dsu(N);\n    std::vector<double> comp_estimated_weight(N);\n    for (int i = 0; i < N; ++i) {\n        comp_estimated_weight[i] = 1.0; // Initial estimated weight for each component root\n    }\n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TOTAL_TIME_LIMIT = 1.9; // seconds\n\n    // Query parameters\n    const double initial_learning_rate = 0.05;\n    const double final_learning_rate = 0.001;\n    const int max_group_query_size = 5;\n\n    for (int q_idx = 0; q_idx < Q; ++q_idx) {\n        double current_learning_rate = initial_learning_rate - (initial_learning_rate - final_learning_rate) * q_idx / Q;\n\n        std::vector<int> active_roots;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.parent[i] == i) { // Check if 'i' is a root\n                active_roots.push_back(i);\n            }\n        }\n\n        std::vector<int> L_items, R_items;\n        int root_L_comp = -1, root_R_comp = -1; // Roots of components chosen for L and R\n\n        bool picked_from_distinct_roots = false;\n        if (active_roots.size() >= 2) {\n            std::shuffle(active_roots.begin(), active_roots.end(), mt);\n            root_L_comp = active_roots[0];\n            root_R_comp = active_roots[1];\n            picked_from_distinct_roots = true;\n        } else { // All items are already in one DSU component, or N < 2\n            // If all items are merged, we can still query, but roots will be the same.\n            // This primarily happens if all items are estimated as equal, so further comparisons may not yield much new info.\n            int item1 = mt() % N;\n            int item2 = mt() % N;\n            while (item1 == item2) {\n                item2 = mt() % N;\n            }\n            L_items.push_back(item1);\n            R_items.push_back(item2);\n            root_L_comp = dsu.find(item1);\n            root_R_comp = dsu.find(item2);\n        }\n\n        if (picked_from_distinct_roots) {\n            std::vector<int> items_in_root1_comp;\n            std::vector<int> items_in_root2_comp;\n            for (int i = 0; i < N; ++i) {\n                if (dsu.find(i) == root_L_comp) items_in_root1_comp.push_back(i);\n                if (dsu.find(i) == root_R_comp) items_in_root2_comp.push_back(i);\n            }\n            \n            int L_size = 1 + mt() % max_group_query_size;\n            int R_size = 1 + mt() % max_group_query_size;\n\n            L_size = std::min((int)items_in_root1_comp.size(), L_size);\n            R_size = std::min((int)items_in_root2_comp.size(), R_size);\n\n            if (L_size == 0 && !items_in_root1_comp.empty()) L_size = 1;\n            if (R_size == 0 && !items_in_root2_comp.empty()) R_size = 1;\n\n            if (items_in_root1_comp.empty() || items_in_root2_comp.empty()) { // Fallback, should rarely happen\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else {\n                std::shuffle(items_in_root1_comp.begin(), items_in_root1_comp.end(), mt);\n                std::shuffle(items_in_root2_comp.begin(), items_in_root2_comp.end(), mt);\n\n                for (int k = 0; k < L_size; ++k) L_items.push_back(items_in_root1_comp[k]);\n                for (int k = 0; k < R_size; ++k) R_items.push_back(items_in_root2_comp[k]);\n            }\n        }\n\n        // Safety check: ensure L and R are non-empty before query\n        if (L_items.empty() || R_items.empty()) {\n            if (N > 1) { \n                 L_items.clear(); R_items.clear();\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else { \n                continue; // Cannot query with N=1\n            }\n        }\n        // Ensure root_L_comp and root_R_comp are updated to their latest roots\n        root_L_comp = dsu.find(L_items[0]);\n        root_R_comp = dsu.find(R_items[0]);\n\n        // If roots are the same, it means we compare items already believed to be equal.\n        // Such queries might not provide new information if our model is perfect,\n        // but could help refine. For now, we only update if roots are distinct for inequalities.\n        // For equality, 1-1 comparison of items from same root yields no change.\n        // Group comparison of items from same root yields no change.\n\n        std::string result = query(L_items, R_items);\n\n        // Calculate current estimated sums based on component representatives\n        double sum_L_est = 0.0;\n        for (int item_idx : L_items) sum_L_est += comp_estimated_weight[dsu.find(item_idx)];\n        double sum_R_est = 0.0;\n        for (int item_idx : R_items) sum_R_est += comp_estimated_weight[dsu.find(item_idx)];\n\n        if (result == \"=\") {\n            if (root_L_comp != root_R_comp) { // Only adjust if they are distinct components\n                if (L_items.size() == 1 && R_items.size() == 1) {\n                    // Direct merge for 1-vs-1 equality\n                    dsu.unite(L_items[0], R_items[0], comp_estimated_weight);\n                } else { // Group equality for distinct components (e.g., A+B = C+D)\n                    // Softly adjust component weights to make their estimated sums equal\n                    // Target sum per side is the average of current estimated sums\n                    double target_sum_per_side = (sum_L_est + sum_R_est) / 2.0;\n                    \n                    double target_w_L = target_sum_per_side / L_items.size();\n                    double target_w_R = target_sum_per_side / R_items.size();\n\n                    comp_estimated_weight[root_L_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_L_comp] + current_learning_rate * target_w_L;\n                    comp_estimated_weight[root_R_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_R_comp] + current_learning_rate * target_w_R;\n                }\n            }\n        } else { // Inequality: L is lighter (<) or heavier (>) than R\n            if (root_L_comp != root_R_comp) { // Only adjust if distinct components\n                if (result == \"<\") { // Actual L < Actual R\n                    comp_estimated_weight[root_L_comp] *= (1.0 - current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 + current_learning_rate);\n                } else { // Actual L > Actual R (result == \">\")\n                    comp_estimated_weight[root_L_comp] *= (1.0 + current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 - current_learning_rate);\n                }\n            }\n        }\n\n        // Ensure weights are positive. Minimum actual weight is 1.0, but allowing estimates slightly lower might help explore.\n        comp_estimated_weight[root_L_comp] = std::max(0.1, comp_estimated_weight[root_L_comp]);\n        comp_estimated_weight[root_R_comp] = std::max(0.1, comp_estimated_weight[root_R_comp]);\n    }\n\n    // Phase 2: Partitioning using Simulated Annealing\n    std::vector<double> final_weights(N);\n    for (int i = 0; i < N; ++i) {\n        final_weights[i] = comp_estimated_weight[dsu.find(i)];\n    }\n\n    std::vector<int> item_to_group(N);\n    std::vector<int> item_indices(N);\n    std::iota(item_indices.begin(), item_indices.end(), 0);\n\n    // Initial greedy assignment: sort items by estimated weight descending\n    std::sort(item_indices.begin(), item_indices.end(), [&](int a, int b) {\n        return final_weights[a] > final_weights[b];\n    });\n\n    std::vector<double> group_sums(D, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int item_idx = item_indices[i];\n        int min_group = 0;\n        for (int d = 1; d < D; ++d) {\n            if (group_sums[d] < group_sums[min_group]) {\n                min_group = d;\n            }\n        }\n        item_to_group[item_idx] = min_group;\n        group_sums[min_group] += final_weights[item_idx];\n    }\n    \n    // Simulated Annealing parameters\n    // Estimate initial variance for T_start scaling\n    double initial_variance = calculate_variance(D, group_sums);\n    // T_start should be large enough to allow many uphill moves, scaled by initial variance magnitude.\n    double T_start = initial_variance * 10.0; \n    if (T_start < 1.0) T_start = 1.0; // Ensure a reasonable minimum T_start to prevent division by zero or too-small steps\n    double T_end = 0.01;      // Ending temperature, low enough to allow fine convergence\n\n    auto current_time = std::chrono::high_resolution_clock::now();\n    double elapsed_time_at_sa_start = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n    \n    // Time available for SA. Ensure at least a small amount of time.\n    double sa_duration_limit = std::max(0.05, TOTAL_TIME_LIMIT - elapsed_time_at_sa_start); \n\n    double current_variance = initial_variance;\n\n    while (true) {\n        current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time_total = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        \n        if (elapsed_time_total > TOTAL_TIME_LIMIT) break;\n\n        // Progress through the SA phase (0 to 1)\n        double progress = (elapsed_time_total - elapsed_time_at_sa_start) / sa_duration_limit;\n        if (progress < 0) progress = 0; // Should not happen with correct logic\n        if (progress > 1) progress = 1; // Cap progress at 1 for calculation stability\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        int item_to_move_idx = mt() % N;\n        int current_group = item_to_group[item_to_move_idx];\n        int new_group = mt() % D;\n        \n        if (new_group == current_group) {\n            continue; \n        }\n\n        // Temporarily adjust group sums to calculate next_variance\n        double old_group_sum_current = group_sums[current_group];\n        double old_group_sum_new = group_sums[new_group];\n        \n        group_sums[current_group] -= final_weights[item_to_move_idx];\n        group_sums[new_group] += final_weights[item_to_move_idx];\n        \n        double next_variance = calculate_variance(D, group_sums);\n\n        if (next_variance < current_variance) {\n            current_variance = next_variance;\n            item_to_group[item_to_move_idx] = new_group;\n        } else {\n            // Accept worse solution with probability\n            double prob = std::exp((current_variance - next_variance) / T);\n            if (std::uniform_real_distribution<double>(0.0, 1.0)(mt) < prob) {\n                current_variance = next_variance;\n                item_to_group[item_to_move_idx] = new_group;\n            } else {\n                // Revert changes if not accepted\n                group_sums[current_group] = old_group_sum_current;\n                group_sums[new_group] = old_group_sum_new;\n            }\n        }\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        std::cout << item_to_group[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <algorithm> // For std::min_element, std::min, std::max\n#include <limits>    // For std::numeric_limits\n\n// Fixed constants for N and M as per problem statement\nconst int N_BOXES = 200;\nconst int M_STACKS = 10;\nconst int SENTINEL_MIN_VAL = N_BOXES + 1; // Used for min_val_in_stack for empty stacks\n\n// Structure to hold the state of a box\nstruct BoxInfo {\n    int stack_idx;  // 0-indexed stack number (0 to M_STACKS-1)\n    int height_idx; // 0-indexed height from bottom (0 to stack.size()-1)\n};\n\n// Helper function to calculate min_val for a stack\nint calculate_min_in_stack(const std::deque<int>& stack) {\n    if (stack.empty()) {\n        return SENTINEL_MIN_VAL;\n    }\n    return *std::min_element(stack.begin(), stack.end());\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n_input, m_input; // Read N and M, though they are fixed\n    std::cin >> n_input >> m_input;\n\n    // stacks[i] is a deque representing stack i, from bottom to top\n    std::vector<std::deque<int>> stacks(M_STACKS);\n    // box_location[v] stores BoxInfo for box v (1-indexed box_id)\n    std::vector<BoxInfo> box_location(N_BOXES + 1);\n    // min_val_in_stack[i] stores the minimum box ID currently in stack i\n    std::vector<int> min_val_in_stack(M_STACKS);\n\n    // Initialize stacks and box_location from input\n    for (int i = 0; i < M_STACKS; ++i) {\n        for (int j = 0; j < N_BOXES / M_STACKS; ++j) {\n            int box_id;\n            std::cin >> box_id;\n            stacks[i].push_back(box_id);\n            box_location[box_id] = {i, j};\n        }\n    }\n\n    // Initialize min_val_in_stack for all stacks\n    for (int i = 0; i < M_STACKS; ++i) {\n        min_val_in_stack[i] = calculate_min_in_stack(stacks[i]);\n    }\n\n    std::vector<std::pair<int, int>> operations;\n    // long long total_energy_expended = 0; // For debugging/local testing, not required for output\n\n    // Weights for scoring function (heuristic for destination stack selection)\n    const int W1_TOP_BOX = 100;        // Weight for stack.back()\n    const int W2_MIN_BOX = 10;         // Weight for min_val_in_stack[d]\n    const int W3_STACK_SIZE = 5;       // Weight for stack.size() (negative contribution)\n    const int K_LOOKAHEAD = 10;        // Number of future boxes to check for burial penalty\n    const int W4_BADNESS = 1000;       // Weight for burying a soon-needed box\n    const int EMPTY_STACK_SCORE = 2000000; // A score higher than any possible non-empty stack score\n\n    // Iterate for each box from 1 to N_BOXES in ascending order\n    for (int v = 1; v <= N_BOXES; ++v) {\n        int current_stack_idx = box_location[v].stack_idx;\n        int current_height_idx = box_location[v].height_idx;\n\n        // If box v is already carried out, skip (this check is mostly for robustness/debugging)\n        if (current_stack_idx == -1) {\n            continue;\n        }\n\n        // Store min_val of current_stack_idx before any modifications\n        int old_min_val_src_stack = min_val_in_stack[current_stack_idx];\n\n        // Check if box v is at the top of its stack\n        if (current_height_idx == (int)stacks[current_stack_idx].size() - 1) {\n            // Box v is at the top, can be carried out\n            operations.push_back({v, 0}); // Operation 2: (v, 0)\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n\n            // Update min_val_in_stack for the source stack\n            if (v == old_min_val_src_stack) { // If v was the minimum, recalculate\n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        } else {\n            // Box v is not at the top, need to move boxes above it\n\n            // Identify the bottom-most box of the block to be moved\n            // These are boxes from current_height_idx + 1 up to the top\n            int block_bottom_box_id = stacks[current_stack_idx][current_height_idx + 1];\n            // Calculate number of boxes to move (k in problem statement)\n            // int num_boxes_to_move = stacks[current_stack_idx].size() - (current_height_idx + 1);\n            // total_energy_expended += (long long)num_boxes_to_move + 1; // Add cost (k+1)\n\n            // Choose destination stack for Operation 1 based on heuristic scoring\n            int dest_stack_idx = -1;\n            long long best_score = std::numeric_limits<long long>::min(); // Use long long for score to avoid overflow with large penalties\n\n            for (int d = 0; d < M_STACKS; ++d) {\n                if (d == current_stack_idx) continue; // Cannot move to the same stack\n\n                long long current_score;\n                if (stacks[d].empty()) {\n                    current_score = EMPTY_STACK_SCORE;\n                } else {\n                    current_score = (long long)stacks[d].back() * W1_TOP_BOX + \n                                    (long long)min_val_in_stack[d] * W2_MIN_BOX - \n                                    (long long)stacks[d].size() * W3_STACK_SIZE;\n\n                    long long badness_penalty = 0;\n                    for (int future_v = v + 1; future_v <= std::min(N_BOXES, v + K_LOOKAHEAD); ++future_v) {\n                        // Check if future_v is in stack 'd' and would be buried deeper by this move\n                        if (box_location[future_v].stack_idx == d && box_location[future_v].height_idx < (int)stacks[d].size()) {\n                            // Higher penalty for boxes needed sooner (smaller future_v)\n                            badness_penalty += (N_BOXES - future_v + 1); \n                        }\n                    }\n                    current_score -= badness_penalty * W4_BADNESS;\n                }\n\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    dest_stack_idx = d;\n                }\n            }\n            \n            // This should always find a valid dest_stack_idx since M > 1.\n\n            // Perform Operation 1: move block_bottom_box_id and boxes above it to dest_stack_idx\n            // Output stack_idx as 1-indexed, so dest_stack_idx + 1\n            operations.push_back({block_bottom_box_id, dest_stack_idx + 1});\n\n            // Temporarily store boxes that will be moved\n            std::vector<int> boxes_to_move;\n            // Iterate from the box above v up to the current top of the stack\n            for (size_t i = current_height_idx + 1; i < stacks[current_stack_idx].size(); ++i) {\n                boxes_to_move.push_back(stacks[current_stack_idx][i]);\n            }\n            \n            // Resize the original stack to remove the moved boxes\n            stacks[current_stack_idx].resize(current_height_idx + 1);\n\n            // Add the moved boxes to the destination stack and update their locations\n            for (int box_id : boxes_to_move) {\n                box_location[box_id] = {dest_stack_idx, (int)stacks[dest_stack_idx].size()};\n                stacks[dest_stack_idx].push_back(box_id);\n            }\n            \n            // Update min_val_in_stack for the destination stack\n            // If dest_stack_idx was empty, its min_val_in_stack was SENTINEL_MIN_VAL,\n            // so any box_id will be smaller and correctly set the new minimum.\n            for (int box_id : boxes_to_move) {\n                min_val_in_stack[dest_stack_idx] = std::min(min_val_in_stack[dest_stack_idx], box_id);\n            }\n\n            // After moving, box v is now at the top of its original stack.\n            // Update v's height_idx to reflect its new top position\n            box_location[v].height_idx = (int)stacks[current_stack_idx].size() - 1;\n\n            // Perform Operation 2: carry out box v\n            operations.push_back({v, 0});\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n\n            // Update min_val_in_stack for the source stack after v is removed\n            if (v == old_min_val_src_stack) { // If v was the minimum, recalculate\n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        }\n    }\n\n    // Output the sequence of operations\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip> // For setprecision\n#include <functional> // For std::function\n\nusing namespace std;\n\nint N;\nvector<string> H_walls; // h[i][j] wall between (i,j) and (i+1,j)\nvector<string> V_walls; // v[i][j] wall between (i,j) and (i,j+1)\nvector<vector<int>> D_values; // d[i][j] dirt susceptibility\n\n// Directions: D, R, U, L\nint DR[] = {1, 0, -1, 0};\nint DC[] = {0, 1, 0, -1};\nchar DIR_CHARS[] = {'D', 'R', 'U', 'L'};\nchar REV_DIR_CHARS[] = {'U', 'L', 'D', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Get next position after moving in a given direction\nPos get_next_pos(Pos current, int dir_idx) {\n    return {current.r + DR[dir_idx], current.c + DC[dir_idx]};\n}\n\n// Check if move is valid (within bounds and no wall)\nbool is_valid_move(Pos current, int dir_idx) {\n    int nr = current.r + DR[dir_idx];\n    int nc = current.c + DC[dir_idx];\n\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n        return false; // Out of bounds\n    }\n\n    // Check for walls\n    if (dir_idx == 0) { // Down: from (r,c) to (r+1,c)\n        return H_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 1) { // Right: from (r,c) to (r,c+1)\n        return V_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 2) { // Up: from (r,c) to (r-1,c)\n        // Wall between (r-1,c) and (r,c) is H_walls[r-1][c]\n        return H_walls[nr][nc] == '0'; \n    } else if (dir_idx == 3) { // Left: from (r,c) to (r,c-1)\n        // Wall between (r,c-1) and (r,c) is V_walls[r][c-1]\n        return V_walls[nr][nc] == '0';\n    }\n    return false; // Should not happen\n}\n\n// Calculate exact score based on path_moves and visits\ndouble calculate_exact_score(int L, const vector<vector<int>>& visits_data, const vector<vector<int>>& d_values) {\n    double total_S_sum_terms = 0.0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int sq_idx = i * N + j;\n            const auto& cell_visits = visits_data[sq_idx];\n\n            if (cell_visits.empty()) {\n                // This means an illegal path (square not visited)\n                return 1e18; // Very high penalty\n            }\n\n            double sum_term_for_cell = 0.0;\n            int N_ij = cell_visits.size();\n\n            for (int k = 0; k < N_ij - 1; ++k) {\n                long long T = cell_visits[k+1] - cell_visits[k];\n                sum_term_for_cell += (double)T * (T - 1) / 2.0;\n            }\n            // For the last interval that wraps around\n            long long T_last = L - cell_visits[N_ij-1] + cell_visits[0];\n            sum_term_for_cell += (double)T_last * (T_last - 1) / 2.0;\n\n            total_S_sum_terms += d_values[i][j] * sum_term_for_cell;\n        }\n    }\n    return total_S_sum_terms / L;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    H_walls.resize(N - 1);\n    V_walls.resize(N);\n    D_values.resize(N, vector<int>(N));\n\n    for (int i = 0; i < N - 1; ++i) cin >> H_walls[i];\n    for (int i = 0; i < N; ++i) cin >> V_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D_values[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    string current_path_moves_str;\n    \n    // Initial DFS path generation\n    vector<bool> dfs_visited_cells(N * N, false);\n    \n    // Lambda function for DFS path building\n    function<void(Pos)> build_dfs_path = \n        [&](Pos current) {\n        int current_idx = current.r * N + current.c;\n        dfs_visited_cells[current_idx] = true;\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            int next_idx = next.r * N + next.c;\n\n            if (next.r < 0 || next.r >= N || next.c < 0 || next.c >= N) continue; // Out of bounds check\n            if (!is_valid_move(current, dir_idx)) continue; // Wall check\n            if (dfs_visited_cells[next_idx]) continue; // Already visited\n\n            current_path_moves_str += DIR_CHARS[dir_idx];\n            build_dfs_path(next);\n            current_path_moves_str += REV_DIR_CHARS[dir_idx];\n        }\n    };\n    \n    build_dfs_path({0,0});\n    string initial_dfs_path_moves = current_path_moves_str; // Store initial path as a fallback\n    int current_L = current_path_moves_str.length();\n\n    // Build visits list from the initial DFS path\n    vector<vector<int>> current_visits(N * N);\n    Pos temp_pos = {0,0};\n    for (int t = 0; t < current_L; ++t) {\n        char move_char = current_path_moves_str[t];\n        int dir_idx = -1;\n        for(int i=0; i<4; ++i) if(DIR_CHARS[i] == move_char) dir_idx = i;\n        temp_pos = get_next_pos(temp_pos, dir_idx);\n        current_visits[temp_pos.r * N + temp_pos.c].push_back(t + 1); // t+1 because 1-indexed time\n    }\n\n    double current_score = calculate_exact_score(current_L, current_visits, D_values);\n    double best_score = current_score;\n    string best_path_moves = current_path_moves_str; // Initialize best path\n\n    // Set up random number generators for Simulated Annealing\n    mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double T_start = 1000.0; // Initial temperature (can be related to max D_value)\n    double T_end = 0.1;     // Final temperature, tuned lower\n    long long max_iterations_for_temp = 1000000; // Reference for cooling schedule progression, tuned higher\n\n    int iter_count = 0;\n    // Iterate for a maximum of 1.95 seconds (leaving some margin for output/cleanup)\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1950) {\n        iter_count++;\n        // Linear cooling schedule\n        double T = T_start + (T_end - T_start) * ((double)iter_count / max_iterations_for_temp);\n        if (T < T_end) T = T_end; // Ensure temp doesn't drop below T_end\n\n        // Try adding a 2-move loop from (0,0) to an adjacent cell and back\n        Pos zero_zero_pos = {0,0};\n        \n        int dir_idx = rng() % 4; // Random direction for neighbor of (0,0)\n        Pos next_loop_pos = get_next_pos(zero_zero_pos, dir_idx);\n        \n        // Check if the loop is valid (within bounds, no walls for both moves)\n        if (next_loop_pos.r < 0 || next_loop_pos.r >= N || next_loop_pos.c < 0 || next_loop_pos.c >= N) continue;\n        if (!is_valid_move(zero_zero_pos, dir_idx)) continue;\n        int rev_dir_idx = (dir_idx + 2) % 4; // Direction to move back to (0,0)\n        if (!is_valid_move(next_loop_pos, rev_dir_idx)) continue;\n\n        string added_moves = string(1, DIR_CHARS[dir_idx]) + string(1, REV_DIR_CHARS[rev_dir_idx]);\n        string temp_path_moves = current_path_moves_str + added_moves;\n        int temp_L = current_L + 2;\n        \n        if (temp_L > 100000) continue; // Path length limit\n\n        vector<vector<int>> temp_visits = current_visits; // Create a copy of current visits data\n        \n        // Add new visit times for the two cells involved in the loop\n        // The first new visit is for `next_loop_pos` at `current_L + 1`\n        // The second new visit is for `zero_zero_pos` at `current_L + 2`\n        int next_loop_idx = next_loop_pos.r * N + next_loop_pos.c;\n        int zero_zero_idx = zero_zero_pos.r * N + zero_zero_pos.c;\n\n        // Use lower_bound and insert to maintain sorted order efficiently (O(k) where k is vector size)\n        auto it_next = lower_bound(temp_visits[next_loop_idx].begin(), temp_visits[next_loop_idx].end(), current_L + 1);\n        temp_visits[next_loop_idx].insert(it_next, current_L + 1);\n\n        auto it_zero = lower_bound(temp_visits[zero_zero_idx].begin(), temp_visits[zero_zero_idx].end(), current_L + 2);\n        temp_visits[zero_zero_idx].insert(it_zero, current_L + 2);\n        \n        double temp_score = calculate_exact_score(temp_L, temp_visits, D_values);\n        \n        double delta_score = temp_score - current_score;\n\n        if (delta_score < 0 || (T > 0 && dist_real(rng) < exp(-delta_score / T))) {\n            current_path_moves_str = temp_path_moves;\n            current_L = temp_L;\n            current_visits = temp_visits;\n            current_score = temp_score;\n\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_path_moves = current_path_moves_str;\n            }\n        }\n    }\n\n    // Final check for the best_path_moves: ensure it truly ends at (0,0)\n    Pos final_pos_check = {0,0};\n    for (char move_char : best_path_moves) {\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        final_pos_check = get_next_pos(final_pos_check, dir_idx);\n    }\n\n    if (!(final_pos_check == Pos{0,0})) {\n        // Fallback to the initial DFS path if the best_path_moves somehow became invalid.\n        // This is a safety measure to avoid WA on \"does not return to (0,0)\".\n        // It indicates a very subtle bug in the SA path update logic that wasn't identified.\n        // Outputting initial_dfs_path_moves guarantees valid path.\n        cerr << \"WARNING: best_path_moves does not end at (0,0). Falling back to initial DFS path.\" << endl;\n        cout << initial_dfs_path_moves << endl;\n    } else {\n        cout << best_path_moves << endl;\n    }\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm> \n#include <tuple>     \n#include <cmath>     \n\n// Aho-Corasick Node definition\nstruct ACNode {\n    std::array<int, 26> go_direct; // Stores ONLY direct transitions from this node\n    int fail;                      // Failure link\n    std::vector<int> pattern_indices; // Indices of patterns ending at this node (or via failure links)\n    int depth;                     // Length of string represented by this node\n\n    ACNode() : fail(0), depth(0) {\n        go_direct.fill(0); // Initialize all direct transitions to 0\n    }\n};\n\nstd::vector<ACNode> ac_trie;         // The Aho-Corasick automaton trie\nstd::vector<char> global_found_tks; // Tracks which of the M patterns have been found\nint M_val;                          // Stores the total number of patterns (M)\n\n// Get the next state in the Aho-Corasick automaton (dynamic traversal using fail links)\n// This is the more robust, but potentially slower, way\nint get_next_ac_state_dynamic(int current_node, char ch) {\n    int c_idx = ch - 'A';\n    // Repeatedly follow failure links until a direct transition is found or root is reached\n    while (current_node != 0 && ac_trie[current_node].go_direct[c_idx] == 0) {\n        current_node = ac_trie[current_node].fail;\n    }\n    // If a direct transition from current_node (or its fail-link ancestor) exists, take it.\n    // If not (e.g., current_node is 0 and no direct transition), stay at root (0).\n    if (ac_trie[current_node].go_direct[c_idx] != 0) {\n        return ac_trie[current_node].go_direct[c_idx];\n    }\n    return 0; // Return root if no match\n}\n\n// Builds the Aho-Corasick automaton from the given patterns\nvoid build_ac(const std::vector<std::string>& patterns) {\n    ac_trie.clear();\n    ac_trie.emplace_back(); // Root node (node 0)\n    M_val = patterns.size();\n    global_found_tks.assign(M_val, 0); // Initialize all patterns as not found (0 for false)\n\n    // 1. Build Trie structure: Insert all patterns into the trie\n    for (int p_idx = 0; p_idx < M_val; ++p_idx) {\n        int curr = 0; // Start from the root\n        for (char ch : patterns[p_idx]) {\n            int c_idx = ch - 'A';\n            if (ac_trie[curr].go_direct[c_idx] == 0) { // If direct transition doesn't exist, create a new node\n                ac_trie[curr].go_direct[c_idx] = ac_trie.size(); // Assign new node ID\n                ac_trie.emplace_back();                   // Add new node to the trie\n                ac_trie.back().depth = ac_trie[curr].depth + 1; // Set its depth\n            }\n            curr = ac_trie[curr].go_direct[c_idx]; // Move to the next node\n        }\n        ac_trie[curr].pattern_indices.push_back(p_idx); // Mark this node as an end point for pattern p_idx\n    }\n\n    // 2. Build Failure Links and propagate output patterns using BFS\n    std::queue<int> q;\n    // For all direct children of the root, their failure link points to the root (0)\n    for (int i = 0; i < 26; ++i) {\n        if (ac_trie[0].go_direct[i] != 0) {\n            ac_trie[ac_trie[0].go_direct[i]].fail = 0; // Set fail link\n            q.push(ac_trie[0].go_direct[i]);           // Add to BFS queue\n        }\n    }\n\n    while (!q.empty()) {\n        int u = q.front(); // Current node\n        q.pop();\n\n        // Propagate pattern_indices from the failure link:\n        // Any patterns found via `u`'s failure link are also considered found when at `u`\n        int f = ac_trie[u].fail;\n        for (int p_idx : ac_trie[f].pattern_indices) {\n            ac_trie[u].pattern_indices.push_back(p_idx);\n        }\n        \n        // For each character in the alphabet\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            if (ac_trie[u].go_direct[c_idx] != 0) { // If a direct child `v` exists for char `c_idx`\n                int v = ac_trie[u].go_direct[c_idx];\n                // The fail link of `v` is found by dynamically traversing from `u`'s fail link\n                ac_trie[v].fail = get_next_ac_state_dynamic(ac_trie[u].fail, 'A' + c_idx);\n                q.push(v); // Add `v` to the BFS queue\n            }\n            // Note: No `else` branch to precompute shortcuts here.\n            // `get_next_ac_state_dynamic` handles traversal dynamically.\n        }\n    }\n}\n\n// Checks for newly found patterns at the given node and updates the global_found_tks array.\nvoid check_and_update_patterns(int node_id) {\n    for (int p_idx : ac_trie[node_id].pattern_indices) {\n        if (!global_found_tks[p_idx]) { // If this pattern hasn't been marked as found yet\n            global_found_tks[p_idx] = 1; // Mark it as found (1 for true)\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_grid, M_patterns;\n    std::cin >> N_grid >> M_patterns;\n\n    int s_i, s_j; // Initial finger position\n    std::cin >> s_i >> s_j;\n\n    std::vector<std::string> A_grid(N_grid);\n    std::vector<std::vector<std::pair<int, int>>> char_to_coords(26);\n    for (int i = 0; i < N_grid; ++i) {\n        std::cin >> A_grid[i];\n        for (int j = 0; j < N_grid; ++j) {\n            char_to_coords[A_grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    std::vector<std::string> t_patterns(M_patterns);\n    for (int k = 0; k < M_patterns; ++k) {\n        std::cin >> t_patterns[k];\n    }\n\n    build_ac(t_patterns); // Build the Aho-Corasick automaton\n\n    std::pair<int, int> current_pos = {s_i, s_j}; // Current finger position\n    int current_ac_node = 0; // Current state in the Aho-Corasick automaton (starts at root)\n    std::vector<std::pair<int, int>> operations; // List to store the sequence of operations\n\n    check_and_update_patterns(0); // Check for patterns found by empty string (usually none)\n\n    // Main greedy loop\n    while (true) {\n        int found_count = 0;\n        for (char b : global_found_tks) {\n            if (b) found_count++;\n        }\n\n        if (found_count == M_patterns) {\n            break; \n        }\n        if (operations.size() >= 5000) {\n            break; \n        }\n\n        int best_nr = -1, best_nc = -1; \n        char best_char_to_append = ' '; \n\n        // Metric for choosing the best next operation (maximize new patterns, then depth, then minimize cost)\n        std::tuple<int, int, int> best_metric = {-1, -1, 1}; \n\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            char c = 'A' + c_idx;\n            for (auto [nr, nc] : char_to_coords[c_idx]) { \n                int current_move_cost = std::abs(nr - current_pos.first) + std::abs(nc - current_pos.second) + 1;\n                // Use the dynamic state traversal\n                int next_node = get_next_ac_state_dynamic(current_ac_node, c); \n\n                int temp_new_tks_count = 0;\n                for (int p_idx : ac_trie[next_node].pattern_indices) {\n                    if (!global_found_tks[p_idx]) { \n                        temp_new_tks_count++;\n                    }\n                }\n                \n                std::tuple<int, int, int> current_metric = {temp_new_tks_count, ac_trie[next_node].depth, -current_move_cost};\n\n                if (current_metric > best_metric) { \n                    best_metric = current_metric;\n                    best_nr = nr;\n                    best_nc = nc;\n                    best_char_to_append = c;\n                }\n            }\n        }\n\n        if (best_nr == -1) { // Should not happen if patterns are not all found and ops < 5000\n            break;\n        }\n\n        operations.push_back({best_nr, best_nc});\n        current_pos = {best_nr, best_nc}; \n        current_ac_node = get_next_ac_state_dynamic(current_ac_node, best_char_to_append); \n        check_and_update_patterns(current_ac_node); \n    }\n\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <map>\n#include <set> // Added include for std::set\n#include <chrono>\n\n// Global variables for problem parameters\nint N, M;\ndouble EPS;\nstd::vector<std::vector<std::pair<int, int>>> poly_shapes; // M polyomino shapes, relative coordinates\n\n// Time limit management\nauto start_time = std::chrono::high_resolution_clock::now(); // Use high_resolution_clock\nlong long TIME_LIMIT_MS = 2800; // 2.8 seconds for safety, total time limit is 3.0 sec\n\nbool check_time() {\n    auto current_time = std::chrono::high_resolution_clock::now();\n    auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n    return elapsed_ms < TIME_LIMIT_MS;\n}\n\n// Coordinate struct\nstruct Coord {\n    int r, c;\n    bool operator<(const Coord& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Polyomino bounds (max_r, max_c) relative to (0,0)\nstd::vector<Coord> poly_bounds; // Store max_r, max_c for each poly shape\n\n// Helper to flush output\nvoid flush_output() {\n    std::cout << std::flush;\n}\n\n// Query 1 (drill)\nint query_1(int r, int c) {\n    std::cout << \"q 1 \" << r << \" \" << c << std::endl;\n    flush_output();\n    int v_val;\n    std::cin >> v_val;\n    return v_val;\n}\n\n// Query k (divine)\nint query_k(const std::vector<Coord>& coords) {\n    // This function assumes coords.size() >= 2 as per problem statement\n    std::cout << \"q \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int approx_v_sum;\n    std::cin >> approx_v_sum;\n    return approx_v_sum;\n}\n\n// Answer (guess)\nbool answer(const std::vector<Coord>& coords) {\n    std::cout << \"a \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int response;\n    std::cin >> response;\n    return response == 1;\n}\n\n// Cumulative distribution function for normal distribution\n// M_SQRT2 is from <cmath>, represents sqrt(2)\ndouble normalCDF(double x, double mean, double stddev) {\n    if (stddev < 1e-9) { // Handle very small standard deviation (effectively 0)\n        return x >= mean ? 1.0 : 0.0;\n    }\n    return 0.5 * (1.0 + std::erf((x - mean) / (stddev * M_SQRT2)));\n}\n\n// Particle structure\nstruct Particle {\n    std::vector<Coord> oil_field_positions; // (min_r, min_c) for each of M fields\n    std::vector<std::vector<int>> v_grid; // N x N grid for this particle's configuration\n    double weight;\n\n    Particle() : v_grid(N, std::vector<int>(N, 0)), weight(1.0) {}\n\n    void calculate_v_grid() {\n        for (int i = 0; i < N; ++i) {\n            std::fill(v_grid[i].begin(), v_grid[i].end(), 0);\n        }\n\n        for (int k = 0; k < M; ++k) {\n            const Coord& pos = oil_field_positions[k];\n            for (const auto& rel_coord : poly_shapes[k]) {\n                int r = pos.r + rel_coord.first;\n                int c = pos.c + rel_coord.second;\n                // Coordinates are guaranteed to be within N x N due to placement generation\n                v_grid[r][c]++;\n            }\n        }\n    }\n\n    int get_v_S_sum(const std::vector<Coord>& query_coords) const {\n        int sum = 0;\n        for (const auto& p : query_coords) {\n            sum += v_grid[p.r][p.c];\n        }\n        return sum;\n    }\n};\n\n// Global random number generator\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> EPS;\n\n    poly_shapes.resize(M);\n    poly_bounds.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d_k;\n        std::cin >> d_k;\n        poly_shapes[k].resize(d_k);\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d_k; ++i) {\n            std::cin >> poly_shapes[k][i].first >> poly_shapes[k][i].second;\n            max_r = std::max(max_r, poly_shapes[k][i].first);\n            max_c = std::max(max_c, poly_shapes[k][i].second);\n        }\n        poly_bounds[k] = {max_r, max_c};\n    }\n\n    // Precompute all possible top-left placements for each polyomino\n    std::vector<std::vector<Coord>> possible_poly_placements(M);\n    for (int k = 0; k < M; ++k) {\n        for (int r = 0; r <= N - 1 - poly_bounds[k].r; ++r) {\n            for (int c = 0; c <= N - 1 - poly_bounds[k].c; ++c) {\n                possible_poly_placements[k].push_back({r, c});\n            }\n        }\n    }\n\n    int NUM_PARTICLES = 5000; \n    if (N > 15) NUM_PARTICLES = 10000; // More particles for larger N\n    if (N <= 12) NUM_PARTICLES = 2000; // Fewer for smaller N\n    if (M >= 10 && N > 15) NUM_PARTICLES = 15000; // More for many polyominos on larger N\n\n    std::vector<Particle> particles(NUM_PARTICLES);\n\n    // Initialize particles: random positions, calculate v_grid, set uniform weights\n    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n        particles[p_idx].oil_field_positions.resize(M);\n        for (int k = 0; k < M; ++k) {\n            std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n            particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n        }\n        particles[p_idx].calculate_v_grid();\n        particles[p_idx].weight = 1.0 / NUM_PARTICLES; \n    }\n\n    int ops_count = 0;\n    int MAX_OPS = 2 * N * N;\n\n    // Keep track of drilled squares and their true values\n    std::map<Coord, int> drilled_actual_v;\n\n    // ---- Initial broad queries (q N*N) ----\n    // Cheap queries for the whole grid to quickly refine the total oil count.\n    int initial_broad_queries_count = std::min(15, MAX_OPS / 20); \n    if (N < 15) initial_broad_queries_count = std::min(8, MAX_OPS/20);\n\n    for (int iter = 0; iter < initial_broad_queries_count; ++iter) {\n        if (!check_time() || ops_count >= MAX_OPS - 2) break; \n\n        std::vector<Coord> all_squares;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                all_squares.push_back({r, c});\n            }\n        }\n\n        int observed_sum = query_k(all_squares); // all_squares will always have N*N elements, so k >= 2 is guaranteed.\n        ops_count++;\n\n        double total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            int particle_v_sum = particles[p_idx].get_v_S_sum(all_squares);\n            \n            double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)N * N * EPS;\n            double sigma_sq = (double)N * N * EPS * (1.0 - EPS);\n            double stddev = std::sqrt(sigma_sq);\n\n            double likelihood;\n            if (observed_sum == 0) {\n                likelihood = normalCDF(0.5, mu, stddev);\n            } else {\n                likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n            }\n            if (likelihood < 1e-10) likelihood = 1e-10; \n\n            particles[p_idx].weight *= likelihood;\n            total_weight += particles[p_idx].weight;\n        }\n\n        // Resampling\n        if (total_weight > 1e-10) { // If there's still some weight\n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx]; \n                new_particles[i].weight = 1.0 / NUM_PARTICLES; \n            }\n            particles = new_particles;\n        } else {\n            // All weights became zero, reinitialize. This means current model is inconsistent.\n            std::cout << \"#c All particle weights zero, re-initializing!\\n\"; // Changed to '\\n'\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                for (int k = 0; k < M; ++k) {\n                    std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                    particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                }\n                particles[p_idx].calculate_v_grid();\n                particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n            }\n            // Re-apply previously drilled facts to the reinitialized particles\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            // Re-normalize and resample after re-applying drilled data\n            total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) total_weight += particles[p_idx].weight;\n            if (total_weight > 1e-10) { \n                 std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else {\n                std::cout << \"#c Still no particles after re-applying drilled data. Filter effectively failed.\\n\"; // Changed to '\\n'\n                break; // Give up on particle filter, fallback will handle it\n            }\n        }\n    }\n\n\n    // ---- Main particle filter loop with targeted queries ----\n    int drill_budget = N*N / 20; \n    int k_query_budget = N*N / 20; \n    \n    // Adjust budget for smaller N or more M\n    if (N <= 15) {\n        drill_budget = N*N / 15;\n        k_query_budget = N*N / 15;\n    }\n    if (M > 10) { // For cases with many polyominos, more exploration might be needed\n        drill_budget = N*N / 10;\n        k_query_budget = N*N / 10;\n    }\n    \n    int drills_done = 0;\n    int k_queries_done = 0;\n\n    int loop_iterations = 0;\n    const int MAX_LOOP_ITERS = MAX_OPS - initial_broad_queries_count - 2; \n    \n    // Store which cells have been queried by q k (to avoid immediate duplicates)\n    std::vector<std::vector<bool>> queried_mask(N, std::vector<bool>(N, false));\n\n    while (ops_count < MAX_OPS - 2 && loop_iterations < MAX_LOOP_ITERS && check_time()) {\n        loop_iterations++;\n        \n        // Calculate P(v>0) and E[v] for all cells based on current particle weights\n        std::vector<std::vector<double>> P_has_oil(N, std::vector<double>(N, 0.0));\n        std::vector<std::vector<double>> E_v(N, std::vector<double>(N, 0.0));\n        double current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight < 1e-10) { \n            std::cout << \"#c Current total weight too small in main loop, breaking.\\n\"; // Changed to '\\n'\n            break;\n        }\n\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            double normalized_weight = particles[p_idx].weight / current_total_weight;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (particles[p_idx].v_grid[r][c] > 0) {\n                        P_has_oil[r][c] += normalized_weight;\n                    }\n                    E_v[r][c] += normalized_weight * particles[p_idx].v_grid[r][c];\n                }\n            }\n        }\n        \n        // Query selection logic\n        bool queried_this_iter = false;\n\n        // Try to drill high-uncertainty cells or cells with high expected value\n        if (drills_done < drill_budget) {\n            double max_uncertainty = -1.0;\n            Coord best_drill_coord_uncertainty = {-1, -1};\n            double max_E_v = -1.0;\n            Coord best_drill_coord_Ev = {-1, -1};\n\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { // Not yet drilled\n                        double uncertainty = P_has_oil[r][c] * (1.0 - P_has_oil[r][c]); \n                        if (uncertainty > max_uncertainty) {\n                            max_uncertainty = uncertainty;\n                            best_drill_coord_uncertainty = current_coord;\n                        }\n                        if (E_v[r][c] > max_E_v) {\n                            max_E_v = E_v[r][c];\n                            best_drill_coord_Ev = current_coord;\n                        }\n                    }\n                }\n            }\n            \n            // Prioritize drilling if high uncertainty exists\n            if (best_drill_coord_uncertainty.r != -1 && max_uncertainty > 0.05) { \n                 int actual_v = query_1(best_drill_coord_uncertainty.r, best_drill_coord_uncertainty.c);\n                 drilled_actual_v[best_drill_coord_uncertainty] = actual_v;\n                 ops_count++;\n                 drills_done++;\n                 queried_this_iter = true;\n                 for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                     if (particles[p_idx].v_grid[best_drill_coord_uncertainty.r][best_drill_coord_uncertainty.c] != actual_v) {\n                         particles[p_idx].weight = 0;\n                     }\n                 }\n            } else if (best_drill_coord_Ev.r != -1 && max_E_v > 0.2) { // If high E_v exists and uncertainty is low\n                int actual_v = query_1(best_drill_coord_Ev.r, best_drill_coord_Ev.c);\n                drilled_actual_v[best_drill_coord_Ev] = actual_v;\n                ops_count++;\n                drills_done++;\n                queried_this_iter = true;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[best_drill_coord_Ev.r][best_drill_coord_Ev.c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n        }\n        \n        // If no drill happened or drill budget exhausted, try q k\n        if (!queried_this_iter && k_queries_done < k_query_budget) {\n            std::vector<std::pair<double, Coord>> uncertainty_list;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && !queried_mask[r][c]) {\n                        // Use uncertainty + expected value for qk query selection\n                        uncertainty_list.push_back({P_has_oil[r][c] * (1.0 - P_has_oil[r][c]) + E_v[r][c] / M, current_coord});\n                    }\n                }\n            }\n            std::sort(uncertainty_list.rbegin(), uncertainty_list.rend()); \n\n            // Only proceed with q k if we have at least 2 candidate squares\n            if (uncertainty_list.size() >= 2) { // FIX: Ensure at least 2 candidates\n                int k_val = std::min((int)uncertainty_list.size(), N * N / 16); // Dynamic K value\n                if (k_val < 2) k_val = 2; // Minimum 2 squares for q k, now safe as size >= 2\n\n                std::vector<Coord> query_coords;\n                for (int i = 0; i < k_val; ++i) {\n                    query_coords.push_back(uncertainty_list[i].second);\n                    queried_mask[uncertainty_list[i].second.r][uncertainty_list[i].second.c] = true; \n                }\n                \n                int observed_sum = query_k(query_coords);\n                ops_count++;\n                k_queries_done++;\n                queried_this_iter = true;\n\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    int particle_v_sum = particles[p_idx].get_v_S_sum(query_coords);\n                    double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)query_coords.size() * EPS;\n                    double sigma_sq = (double)query_coords.size() * EPS * (1.0 - EPS);\n                    double stddev = std::sqrt(sigma_sq);\n\n                    double likelihood;\n                    if (observed_sum == 0) {\n                        likelihood = normalCDF(0.5, mu, stddev);\n                    } else {\n                        likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n                    }\n                    if (likelihood < 1e-10) likelihood = 1e-10;\n\n                    particles[p_idx].weight *= likelihood;\n                }\n            } // End of if (uncertainty_list.size() >= 2)\n        }\n\n        // Resample after each operation\n        current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight > 1e-10) {\n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / current_total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx];\n                new_particles[i].weight = 1.0 / NUM_PARTICLES;\n            }\n            particles = new_particles;\n        } else {\n            // All weights became zero, reinitialize and re-apply known data\n            std::cout << \"#c All particle weights zero in main loop, re-initializing!\\n\"; // Changed to '\\n'\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                for (int k = 0; k < M; ++k) {\n                    std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                    particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                }\n                particles[p_idx].calculate_v_grid();\n                particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n            }\n            // Re-apply known drilled data\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            // Resample again after re-applying drilled data\n            current_total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) current_total_weight += particles[p_idx].weight;\n            if (current_total_weight > 1e-10) { \n                std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / current_total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else { \n                break;\n            }\n        }\n\n        // Clear queried mask for next iteration periodically to allow re-querying different cells\n        if (loop_iterations % (N) == 0) { \n            for (int r = 0; r < N; ++r) std::fill(queried_mask[r].begin(), queried_mask[r].end(), false);\n        }\n    }\n\n\n    // Final guess attempt\n    std::set<Coord> potential_oil_squares_set;\n    for(const auto& entry : drilled_actual_v) { \n        if (entry.second > 0) {\n            potential_oil_squares_set.insert(entry.first);\n        }\n    }\n\n    double final_total_weight = 0.0;\n    for(const auto& p : particles) final_total_weight += p.weight;\n    \n    if (final_total_weight > 1e-10) { // Only use particle beliefs if filter didn't collapse\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                Coord current_coord = {r, c};\n                if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { // If not drilled\n                    double P_val = 0.0;\n                    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                        if (particles[p_idx].v_grid[r][c] > 0) {\n                            P_val += particles[p_idx].weight;\n                        }\n                    }\n                    P_val /= final_total_weight;\n                    if (P_val > 0.5) { // If probability of having oil is high\n                        potential_oil_squares_set.insert(current_coord);\n                    }\n                }\n            }\n        }\n    } else { // Particle filter failed, rely on drilled data for final guess (will still be incorrect if not all oil fields are covered)\n        std::cout << \"#c Particle filter collapsed before final guess. Relying on drilled data only.\\n\"; // Changed to '\\n'\n    }\n\n\n    std::vector<Coord> final_oil_squares_vec(potential_oil_squares_set.begin(), potential_oil_squares_set.end());\n    std::sort(final_oil_squares_vec.begin(), final_oil_squares_vec.end()); // Ensure consistent order\n\n    if (answer(final_oil_squares_vec)) {\n        return 0; \n    }\n    ops_count++;\n\n    // Fallback: If guess was incorrect, drill all remaining unknown squares.\n    std::cout << \"#c Initial guess incorrect. Falling back to drilling all remaining squares.\\n\"; // Changed to '\\n'\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            Coord current_coord = {r, c};\n            if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && ops_count < MAX_OPS -1) { \n                int actual_v = query_1(r, c);\n                drilled_actual_v[current_coord] = actual_v;\n                ops_count++;\n            }\n        }\n    }\n\n    // Final answer after drilling everything\n    std::vector<Coord> final_fallback_squares;\n    for (const auto& entry : drilled_actual_v) {\n        if (entry.second > 0) {\n            final_fallback_squares.push_back(entry.first);\n        }\n    }\n    std::sort(final_fallback_squares.begin(), final_fallback_squares.end()); \n\n    if (!answer(final_fallback_squares)) {\n        std::cout << \"#c Fallback guess incorrect. This should not happen!\\n\"; // Changed to '\\n'\n    }\n\n    return 0;\n}\n","ahc031":"long long calculate_delta_cost(int d, const Rect& old_r, const Rect& new_r, int k_id,\n                                 const bool H_prev_day[W+1][W], const bool V_prev_day[W][W+1],\n                                 GridManager& gm, long long current_total_cost) {\n    // 1. Calculate delta area cost:\n    long long delta_area_cost = 0;\n    // Remove old_r's contribution\n    if (old_r.area() < a_global[d][k_id]) delta_area_cost -= 100LL * (a_global[d][k_id] - old_r.area());\n    // Add new_r's contribution\n    if (new_r.area() < a_global[d][k_id]) delta_area_cost += 100LL * (a_global[d][k_id] - new_r.area());\n\n    // 2. Calculate delta partition cost:\n    long long delta_partition_cost = 0;\n    \n    // Temporarily revert the placed_rects entry for k_id to old_r\n    // (since gm.place(new_r, k_id) was already called for validation)\n    // We need the state *before* gm.place(new_r, k_id) to figure out diffs.\n    // The safest way is to manage `H_curr` and `V_curr` arrays incrementally.\n    \n    // Instead of directly calculating delta, calculate new total cost based on `gm.placed_rects`\n    // (which now includes new_r) and then subtract `current_total_cost`.\n    // This implies `calculate_day_cost` is called directly, but its performance needs to be improved\n    // beyond `O(W^2)`.\n\n    // Optimized `calculate_day_cost` for incremental SA updates:\n    // Store `H_current_sum` and `V_current_sum` (total active partitions)\n    // When `is_occupied[r][c]` changes, it affects 4 segments.\n    // For each affected segment `s = (i,j)-(i',j')`:\n    //  `old_H_curr_s = is_segment_a_border_before_change(s)`\n    //  `new_H_curr_s = is_segment_a_border_after_change(s)`\n    //  If `(old_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    //  If `(new_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    // This is the $O(Area)$ bottleneck.\n    // To implement `is_segment_a_border`, you need `is_occupied` state.\n\n    // A simpler way:\n    // Copy `is_occupied` state to a temporary `is_occupied_temp`\n    // Then `gm.remove(k_id, from_is_occupied_temp)`\n    // Compute `old_local_partition_status` using `is_occupied_temp` within `old_r`'s perimeter + 1 cell buffer.\n    // `gm.place(new_r, to_is_occupied_temp)`\n    // Compute `new_local_partition_status` using `is_occupied_temp` within `new_r`'s perimeter + 1 cell buffer.\n    // Then calculate the `delta_partition_cost` within these local affected regions.\n\n    // For simplicity of implementation (and hoping that AvgArea is small enough on average)\n    // just call the full `calculate_day_cost` after updating `gm.placed_rects`.\n    // With `SA_ITERATIONS` around 1000 per day, total $5 \\times 10^7$ iterations for `calculate_day_cost`.\n    // AvgArea $20000 \\approx 0.02 W^2$.\n    // If average $W^2$ operations is $2 \\times 10^4$, then $5 \\times 10^7 \\times 2 \\times 10^4 = 10^{12}$. Still too much.\n    // This is why `calculate_day_cost` *must* be O(Perimeter) in SA.\n    \n    // Let's go with the O(Perimeter) approach for SA iterations.\n    // Need to precompute `H_curr` and `V_curr` from `is_occupied` once per day.\n    // Then when a rectangle `R_k` changes, we update only the segments around its perimeter.\n    // This implies `H_curr_global[W+1][W]` and `V_curr_global[W][W+1]` must be updated incrementally.\n    \n    // `current_H_states[W+1][W]` and `current_V_states[W][W+1]` (booleans)\n    // `current_H_count`, `current_V_count` (total partition lengths)\n    // On a move:\n    //  `old_r_perimeter_segs = get_perimeter_segments(old_r)`\n    //  `new_r_perimeter_segs = get_perimeter_segments(new_r)`\n    //  For `s` in `old_r_perimeter_segs` and `new_r_perimeter_segs` (union):\n    //    `was_border = is_segment_a_border(s, is_occupied_before_change)`\n    //    `is_border = is_segment_a_border(s, is_occupied_after_change)`\n    //    If `was_border != is_border`:\n    //      if `was_border != global_H_prev[s]`: `delta_cost--`\n    //      if `is_border != global_H_prev[s]`: `delta_cost++`\n    // This `is_segment_a_border` checks `is_occupied` for neighbors of `s`, which means `O(1)` per segment.\n    // Total `O(Perimeter)` for partition cost delta. Area update is $O(Area)$.\n    // So the move is $O(Area + Perimeter)$, which becomes $O(Area)$ in worst case.\n    // Let's assume avg Area is small enough on average for $N=50$ given $W=1000$.\n    // If $W^2/N = 20000$, $Area \\sim 20000$. This is the largest factor.\n    // $50 \\times 1000 \\times 20000 = 10^9$. Maybe SA_ITERATIONS must be smaller, say 1000.\n    // $50 \\times 1000 \\times 20000 = 10^9$. This would be close to 1 second.\n    // $SA\\_ITERATIONS=1000$ per day. Total $50000$ iterations.\n    // Each is $O(Area)$, `20000`. So $50000 \\times 20000 = 10^9$. This will be slow for 3s.\n    // The input generation suggests `a_d,k` sum is around $W^2-E$. Smallest $E$ is $W^2 \\times 0.0025 = 2500$.\n    // So average desired area is typically $W^2/N \\approx 20000$.\n    // Maybe `Area` updates are sparse?\n}\n\nFinal decision: I will implement `calculate_day_cost` with `O(W^2)` per call, and reduce `SA_ITERATIONS` to a very small number (e.g., 50 per day). This makes total operations $D \\times SA\\_ITERATIONS \\times W^2 = 50 \\times 50 \\times 10^6 = 2.5 \\times 10^9$. This might barely pass, or be too slow. A hybrid: `O(Area)` based delta computation during SA, and full `O(W^2)` only once at the end of each day for `global_H_prev` update.\n","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric> // Potentially for std::accumulate, though not strictly used with the new scoring approach\n#include <algorithm> // For std::sort, std::min\n#include <limits>    // For std::numeric_limits\n#include <chrono>    // For high_resolution_clock and duration\n#include <random>    // For mt19937, uniform_int_distribution\n\n// Define MOD constant\nconst int MOD = 998244353;\n\n// Structure to store an performed operation\nstruct Operation {\n    int m, p, q;\n};\n\n// Helper struct to store an option with its gain\nstruct Option {\n    long long gain;\n    int m, p, q;\n\n    // For sorting: higher gain comes first\n    bool operator<(const Option& other) const {\n        return gain > other.gain; // Sort in descending order of gain\n    }\n};\n\n// Function to calculate the total score for a given board state\n// This is used for initial score and comparing final scores of different runs.\nlong long calculate_board_score(const std::vector<std::vector<int>>& board, int N) {\n    long long total_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            total_score += board[i][j];\n        }\n    }\n    return total_score;\n}\n\n\nint main() {\n    // Optimize C++ standard streams for faster input/output.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N, M, K;\n    std::cin >> N >> M >> K;\n\n    // Read initial board values.\n    std::vector<std::vector<int>> initial_board(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_board[i][j]; // a_i,j are guaranteed to be < MOD\n        }\n    }\n\n    // Read all stamp configurations `s_m,i,j`.\n    std::vector<std::vector<std::vector<int>>> s(M, std::vector<std::vector<int>>(3, std::vector<int>(3)));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> s[m][i][j]; // s_m,i,j are guaranteed to be < MOD\n            }\n        }\n    }\n\n    // Initialize random number generator using current time for varied seeds across runs.\n    std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Best overall score found and the sequence of operations that produced it.\n    long long max_overall_score = calculate_board_score(initial_board, N);\n    std::vector<Operation> best_overall_operations;\n\n    // Set a time limit for the iterative process (e.g., 1.95 seconds out of 2.0s total).\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 1.95; // Tunable parameter for time allocation\n\n    // Loop for multiple attempts (Iterated Randomly Perturbed Greedy).\n    // The loop continues as long as there is time remaining.\n    while (true) {\n        auto current_chrono_time = std::chrono::high_resolution_clock::now();\n        double elapsed_seconds = std::chrono::duration<double>(current_chrono_time - start_time).count();\n        if (elapsed_seconds >= TIME_LIMIT_SECONDS) {\n            break; // Stop if time limit is reached.\n        }\n\n        // Start a new greedy run with a fresh copy of the initial board.\n        std::vector<std::vector<int>> current_board = initial_board;\n        std::vector<Operation> current_operations;\n        long long current_run_score = calculate_board_score(current_board, N);\n\n        // Perform up to K operations for this specific run.\n        for (int k_idx = 0; k_idx < K; ++k_idx) {\n            std::vector<Option> possible_options; // List to store all potential operations and their gains.\n\n            // Evaluate all M * (N-2)^2 possible operations.\n            for (int m_idx = 0; m_idx < M; ++m_idx) {\n                for (int p_idx = 0; p_idx <= N - 3; ++p_idx) {\n                    for (int q_idx = 0; q_idx <= N - 3; ++q_idx) {\n                        long long current_gain = 0; // Accumulated gain for the current stamp application.\n\n                        // Calculate the score change if this stamp is applied.\n                        for (int i_s = 0; i_s < 3; ++i_s) {\n                            for (int j_s = 0; j_s < 3; ++j_s) {\n                                int r = p_idx + i_s; // Row on the board\n                                int c = q_idx + j_s; // Column on the board\n\n                                int old_val_mod = current_board[r][c];\n                                // Calculate new value modulo MOD. Use long long for addition to prevent overflow.\n                                int new_val_mod = (int)(((long long)old_val_mod + s[m_idx][i_s][j_s]) % MOD);\n                                \n                                current_gain += (new_val_mod - old_val_mod);\n                            }\n                        }\n                        \n                        // Only consider operations that provide a strict positive gain.\n                        if (current_gain > 0) {\n                             possible_options.push_back({current_gain, m_idx, p_idx, q_idx});\n                        }\n                    }\n                }\n            }\n            \n            // If no operation can increase the score, this run stops early.\n            if (possible_options.empty()) {\n                break;\n            }\n\n            // Sort options by gain in descending order.\n            std::sort(possible_options.begin(), possible_options.end());\n\n            // Define how many top options to consider for random selection.\n            // Using a constant like 10, 15, or 20 is often a good heuristic for N=9, M=20, K=81.\n            // This allows some exploration beyond the absolute best, but still prioritizes good options.\n            const int TOP_X = 15; // Tunable parameter\n            int actual_top_x_count = std::min((int)possible_options.size(), TOP_X);\n\n            // Randomly pick one operation from the top `actual_top_x_count` options.\n            // This distribution is safe even if actual_top_x_count is 1.\n            std::uniform_int_distribution<int> dist(0, actual_top_x_count - 1);\n            int chosen_idx = dist(rng);\n            Option chosen_option = possible_options[chosen_idx];\n\n            // Apply the chosen operation to update the board state for this run.\n            for (int i_s = 0; i_s < 3; ++i_s) {\n                for (int j_s = 0; j_s < 3; ++j_s) {\n                    int r = chosen_option.p + i_s;\n                    int c = chosen_option.q + j_s;\n                    current_board[r][c] = (int)(((long long)current_board[r][c] + s[chosen_option.m][i_s][j_s]) % MOD);\n                }\n            }\n            // Update the score for the current run incrementally.\n            current_run_score += chosen_option.gain;\n            // Record the operation performed.\n            current_operations.push_back({chosen_option.m, chosen_option.p, chosen_option.q});\n        } // End of k_idx loop for one greedy run\n\n        // After completing one full greedy run (or breaking early), check if it's the best so far.\n        if (current_run_score > max_overall_score) {\n            max_overall_score = current_run_score;\n            best_overall_operations = current_operations;\n        }\n    } // End of time-limited loop for multiple runs\n\n    // Output the number of operations in the best sequence found.\n    std::cout << best_overall_operations.size() << std::endl;\n    // Output each operation's details (stamp index, top-left row, top-left column).\n    for (const auto& op : best_overall_operations) {\n        std::cout << op.m << \" \" << op.p << \" \" << op.q << std::endl;\n    }\n\n    return 0;\n}\n","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map> \n#include <set>\n#include <algorithm>\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 { // For map keys (container_locations still uses map)\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint DR[] = {-1, 1, 0, 0}; // U, D, L, R\nint DC[] = {0, 0, -1, 1};\n\n// Correct way to get char from dr,dc\nchar get_dir_char(int dr, int dc) {\n    if (dr == -1 && dc == 0) return 'U';\n    if (dr == 1 && dc == 0) return 'D';\n    if (dr == 0 && dc == -1) return 'L';\n    if (dr == 0 && dc == 1) return 'R';\n    return '.'; // Should not happen for a valid move\n}\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int holding_container_id; // -1 if not holding\n    bool is_large;\n    bool is_bombed;\n};\n\nstruct State {\n    vector<vector<int>> board; // container ID, -1 if empty\n    vector<Crane> cranes;\n    vector<int> incoming_idx; // next container index for each receiving gate (row)\n    vector<int> next_dispatch_val; // next container ID expected at each dispatch gate (row)\n    vector<vector<int>> A; // initial incoming container sequence\n    map<int, Pos> container_locations; // Map container_id to its (r,c) position or {-1,-1} if in crane's hand\n};\n\n// BFS to find the next step (dr, dc) and path cost\n// Returns {dr, dc} for the next step. {0,0} if no path or already at target.\n// path_cost_out will be set to the cost of the path, or -1 if no path.\nPos get_next_step(const State& current_state, int crane_id, Pos start_pos, Pos target_pos,\n                  bool is_holding_container, bool is_large_crane,\n                  const vector<Pos>& other_crane_current_pos_snapshot, // Snapshot of all crane positions before planning\n                  const vector<Pos>& target_next_crane_pos_planned, // Planned next positions for higher priority cranes (j < crane_id)\n                  int& path_cost_out) {\n\n    if (start_pos == target_pos) {\n        path_cost_out = 0;\n        return {0,0};\n    }\n\n    // Optimized BFS: use 2D array for distance and parent tracking\n    vector<vector<int>> dist_grid(N, vector<int>(N, -1)); // -1 means unvisited\n    vector<vector<Pos>> parent_grid(N, vector<Pos>(N, {-1,-1})); // Stores parent position to reconstruct path\n    queue<Pos> q;\n\n    q.push(start_pos);\n    dist_grid[start_pos.r][start_pos.c] = 0;\n\n    Pos next_step_dir = {0,0};\n    path_cost_out = -1; // Default to no path found\n\n    Pos found_target_pos = {-1,-1}; // To store the actual target_pos if found\n\n    while (!q.empty()) {\n        Pos u = q.front();\n        q.pop();\n\n        if (u == target_pos) {\n            found_target_pos = u;\n            break; // Path found\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos v = {u.r + DR[i], u.c + DC[i]};\n\n            if (v.r < 0 || v.r >= N || v.c < 0 || v.c >= N) continue; // Out of bounds\n\n            // If already visited, skip (or if new path isn't shorter)\n            if (dist_grid[v.r][v.c] != -1) continue;\n\n            // Check for container on destination square (for small cranes holding cargo)\n            // Small crane carrying container cannot move to occupied square.\n            // Large crane carrying container CAN move to occupied square, so this check is skipped for large cranes.\n            if (!is_large_crane && is_holding_container && current_state.board[v.r][v.c] != -1) {\n                continue; \n            }\n\n            bool collision = false;\n            for (int j = 0; j < N; ++j) {\n                if (j == crane_id || current_state.cranes[j].is_bombed) continue; // Skip self or bombed cranes\n\n                Pos other_curr_j = other_crane_current_pos_snapshot[j]; \n                \n                if (j < crane_id) { // Higher priority crane, its next position is already planned\n                    Pos other_next_j_planned = target_next_crane_pos_planned[j];\n                    \n                    if (v == other_next_j_planned) { // Target collision\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == other_next_j_planned) { // Swap collision\n                        collision = true; break;\n                    }\n                } else { // Lower priority crane, it hasn't planned its move yet. Consider its current position as blocked.\n                    if (v == other_curr_j) { // Target collision\n                        collision = true; break;\n                    }\n                    // For j > k, we don't attempt to detect swap collision here. \n                    // Lower priority cranes will handle avoiding this crane's planned `v` position when they plan their own moves.\n                }\n            }\n            if (collision) continue;\n\n            dist_grid[v.r][v.c] = dist_grid[u.r][u.c] + 1;\n            parent_grid[v.r][v.c] = u; // Store parent for path reconstruction\n            q.push(v);\n        }\n    }\n\n    if (found_target_pos.r != -1) { // Path found\n        path_cost_out = dist_grid[found_target_pos.r][found_target_pos.c];\n        \n        // Reconstruct the first step\n        Pos curr = found_target_pos;\n        while (parent_grid[curr.r][curr.c] != start_pos) {\n            curr = parent_grid[curr.r][curr.c];\n        }\n        next_step_dir = {curr.r - start_pos.r, curr.c - start_pos.c};\n    }\n    return next_step_dir;\n}\n\n\nvoid solve() {\n    State current_state;\n    current_state.board.assign(N, vector<int>(N, -1));\n    current_state.A.assign(N, vector<int>(N));\n    current_state.incoming_idx.assign(N, 0);\n    \n    // FIX 1: Initialize next_dispatch_val correctly\n    current_state.next_dispatch_val.resize(N);\n    for(int i = 0; i < N; ++i) {\n        current_state.next_dispatch_val[i] = N * i;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> current_state.A[i][j];\n        }\n    }\n\n    current_state.cranes.resize(N);\n    for (int i = 0; i < N; ++i) {\n        current_state.cranes[i].id = i;\n        current_state.cranes[i].pos = {i, 0};\n        current_state.cranes[i].holding_container_id = -1;\n        current_state.cranes[i].is_large = (i == 0);\n        current_state.cranes[i].is_bombed = false;\n    }\n\n    int turns = 0;\n    int dispatched_count = 0;\n\n    vector<string> all_crane_actions(N, \"\");\n\n    while (dispatched_count < N*N && turns < MAX_TURNS) {\n        turns++;\n        \n        // 0. Store current crane positions for BFS collision detection\n        vector<Pos> other_crane_current_pos_snapshot(N);\n        for(int i=0; i<N; ++i) other_crane_current_pos_snapshot[i] = current_state.cranes[i].pos;\n\n        // Initialize planned positions and holding status to current state\n        vector<Pos> target_next_crane_pos_planned(N);\n        vector<int> target_next_crane_holding_planned(N);\n        for (int k = 0; k < N; ++k) {\n            target_next_crane_pos_planned[k] = current_state.cranes[k].pos;\n            target_next_crane_holding_planned[k] = current_state.cranes[k].holding_container_id;\n        }\n\n        // 1. Incoming containers (Before crane planning so cranes can react to them)\n        for (int i = 0; i < N; ++i) {\n            if (current_state.incoming_idx[i] < N) {\n                bool gate_has_container = (current_state.board[i][0] != -1);\n                bool gate_has_crane = false;\n                for(int k=0; k<N; ++k) {\n                    // Check actual crane positions from current_state before they move\n                    if (!current_state.cranes[k].is_bombed && current_state.cranes[k].pos.r == i && current_state.cranes[k].pos.c == 0) {\n                        gate_has_crane = true;\n                        break;\n                    }\n                }\n                if (!gate_has_container && !gate_has_crane) {\n                    int container_id = current_state.A[i][current_state.incoming_idx[i]];\n                    current_state.board[i][0] = container_id;\n                    current_state.container_locations[container_id] = {i,0};\n                    current_state.incoming_idx[i]++;\n                }\n            }\n        }\n\n        // 2. Crane actions planning (prioritized by crane ID 0 to N-1)\n        vector<char> current_turn_actions_char(N, '.');\n        \n        for (int k = 0; k < N; ++k) { \n            if (current_state.cranes[k].is_bombed) {\n                current_turn_actions_char[k] = '.';\n                continue;\n            }\n\n            Pos crane_curr_pos = current_state.cranes[k].pos;\n            int holding_id = current_state.cranes[k].holding_container_id;\n\n            // Priority 1: Deliver if holding the correct container at the dispatch gate\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                // FIX 2: Check if target square is empty for 'Q' action\n                if (is_next_dispatch && crane_curr_pos.r == target_row && crane_curr_pos.c == N - 1 && current_state.board[crane_curr_pos.r][crane_curr_pos.c] == -1) {\n                    current_turn_actions_char[k] = 'Q';\n                    target_next_crane_holding_planned[k] = -1; // Released\n                    continue;\n                }\n            }\n\n            // If holding a container, move it towards its destination\n            if (holding_id != -1) {\n                int target_row = holding_id / N;\n                bool is_next_dispatch = (holding_id == current_state.next_dispatch_val[target_row]);\n                Pos actual_target_dest = {target_row, (is_next_dispatch ? N - 1 : N - 2)};\n                \n                // Small crane handling for cross-row moves with cargo (drop at N/2 column)\n                if (!current_state.cranes[k].is_large && crane_curr_pos.r != target_row) {\n                    Pos release_mid_pos = {crane_curr_pos.r, N/2};\n                    // FIX 2: Check if target square is empty for 'Q' action\n                    if (crane_curr_pos == release_mid_pos && current_state.board[release_mid_pos.r][release_mid_pos.c] == -1) {\n                        current_turn_actions_char[k] = 'Q';\n                        target_next_crane_holding_planned[k] = -1; // Released\n                        current_state.container_locations[holding_id] = release_mid_pos; // Mark container's new location\n                    } else {\n                        // Move towards release_mid_pos\n                        int cost;\n                        Pos dir = get_next_step(current_state, k, crane_curr_pos, release_mid_pos, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                        if (cost != -1) {\n                            current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                            target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                        } else {\n                            current_turn_actions_char[k] = '.';\n                        }\n                    }\n                } else { // Large crane, or small crane already in correct row\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, actual_target_dest, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n                continue; // Crane has a container, its action is determined\n            }\n\n            // If not holding a container, find a task\n            int best_cost = MAX_TURNS + 1; // High value\n            Pos best_pick_pos = {-1,-1};\n            int best_item_id = -1;\n\n            // FIX 4: Move lambda definition here\n            auto calculate_cost = [&](Pos target_for_pickup) {\n                int cost;\n                get_next_step(current_state, k, crane_curr_pos, target_for_pickup, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                return cost;\n            };\n            \n            // Check if a container is already targeted by a higher-priority crane or held\n            auto is_container_busy = [&](int container_id) {\n                if (container_id == -1) return true;\n                for (int j = 0; j < N; ++j) {\n                    if (current_state.cranes[j].id != k && target_next_crane_holding_planned[j] == container_id) return true;\n                }\n                return false;\n            };\n\n            // Task search priorities (high to low):\n\n            // Option 1: Pick up 'next_dispatch_val'\n            for (int i = 0; i < N; ++i) {\n                int C = current_state.next_dispatch_val[i];\n                if (current_state.container_locations.count(C) && current_state.container_locations[C].r != -1) { // Container exists on board\n                    Pos c_pos = current_state.container_locations[C];\n                    // FIX 3: Exclude if it's already at the dispatch gate and ready to be dispatched\n                    if (c_pos.r == i && c_pos.c == N - 1) continue; \n                    \n                    if (is_container_busy(C)) continue;\n                    \n                    // Small crane can only pick up if container is in its row. Large crane can pick up anything.\n                    if (!current_state.cranes[k].is_large && c_pos.r != k) continue;\n\n                    int cost = calculate_cost(c_pos);\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = c_pos;\n                        best_item_id = C;\n                    }\n                }\n            }\n            \n            // Option 2: Clear receiving gate (row i, col 0)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.incoming_idx[i] < N && current_state.board[i][0] != -1) {\n                    int C = current_state.board[i][0];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,0});\n                    if (cost != -1 && cost < best_cost) { \n                        best_cost = cost;\n                        best_pick_pos = {i,0};\n                        best_item_id = C;\n                    }\n                }\n            }\n\n            // Option 3: Clear dispatch gate (row i, col N-1)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != current_state.next_dispatch_val[i]) {\n                    int C = current_state.board[i][N-1];\n                    if (is_container_busy(C)) continue;\n\n                    // Small crane can only pick up from its own row's gate\n                    if (!current_state.cranes[k].is_large && i != k) continue;\n\n                    int cost = calculate_cost({i,N-1});\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = {i,N-1};\n                        best_item_id = C;\n                    }\n                }\n            }\n            \n            // Option 4: Move container to its staging area (row, N-2) if in correct row but too far left\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N-2; ++c) { // Check cells to the left of N-2\n                    int C = current_state.board[r][c];\n                    if (C != -1 && C/N == r && C != current_state.next_dispatch_val[r]) {\n                        if (is_container_busy(C)) continue;\n\n                        // Small crane can only pick up if container is in its row\n                        if (!current_state.cranes[k].is_large && r != k) continue;\n\n                        int cost = calculate_cost({r,c});\n                        if (cost != -1 && cost < best_cost) {\n                            best_cost = cost;\n                            best_pick_pos = {r,c};\n                            best_item_id = C;\n                        }\n                    }\n                }\n            }\n\n            // Option 5: Move container to its row's middle column (C/N, N/2) - for cross-row moves (Large crane only).\n            if (current_state.cranes[k].is_large) { // Only large crane handles cross-row pickups\n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        int C = current_state.board[r][c];\n                        if (C != -1 && C/N != r) { // Container in wrong row\n                            if (is_container_busy(C)) continue;\n                            int cost = calculate_cost({r,c});\n                            if (cost != -1 && cost < best_cost) {\n                                best_cost = cost;\n                                best_pick_pos = {r,c};\n                                best_item_id = C;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Execute the chosen task\n            if (best_cost != MAX_TURNS + 1) { // A task was found\n                if (crane_curr_pos == best_pick_pos) {\n                    current_turn_actions_char[k] = 'P';\n                    target_next_crane_holding_planned[k] = best_item_id;\n                    current_state.container_locations[best_item_id] = {-1,-1}; // In crane's hand (not on board)\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, best_pick_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.'; // Should ideally not happen if best_cost was valid\n                    }\n                }\n            } else { // No urgent task, move to a parking spot\n                Pos parking_pos = current_state.cranes[k].is_large ? Pos{0, N/2} : Pos{k, 1}; // Large crane at center-top, small cranes at their row's column 1\n                if (crane_curr_pos == parking_pos) {\n                    current_turn_actions_char[k] = '.';\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, parking_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n            }\n        }\n\n        // Apply all planned actions simultaneously\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) continue;\n\n            char action = current_turn_actions_char[k];\n            all_crane_actions[k] += action;\n\n            if (action == 'P') {\n                int container_id = current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c];\n                current_state.cranes[k].holding_container_id = container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = -1;\n            } else if (action == 'Q') {\n                int container_id = current_state.cranes[k].holding_container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = container_id;\n                current_state.cranes[k].holding_container_id = -1;\n                current_state.container_locations[container_id] = current_state.cranes[k].pos; // Container back on board\n            } else if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n                current_state.cranes[k].pos = target_next_crane_pos_planned[k];\n            }\n        }\n        \n        // 3. Dispatch containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] == current_state.next_dispatch_val[i]) {\n                int dispatched_id = current_state.board[i][N-1];\n                current_state.board[i][N-1] = -1;\n                current_state.container_locations.erase(dispatched_id); // Container removed from the game\n                current_state.next_dispatch_val[i]++; // Advance expectation for this gate\n                dispatched_count++;\n            }\n        }\n    }\n\n    // Output results\n    for (int i = 0; i < N; ++i) {\n        cout << all_crane_actions[i] << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <limits> // Required for std::numeric_limits\n\n// N is fixed at 20 for this problem\nconst int N = 20;\n\n// Global variables to store the current state\nint H[N][N]; // Current heights of the grid cells\nint current_r = 0; // Current row of the dump truck\nint current_c = 0; // Current column of the dump truck\nlong long truck_load = 0; // Current amount of soil loaded on the truck\nstd::vector<std::string> ops; // Stores the sequence of operations\n\n// Calculates Manhattan distance between two cells\nlong long manhattan_dist(int r1, int c1, int r2, int c2) {\n    return std::abs(r1 - r2) + std::abs(c1 - c2);\n}\n\n// Moves the truck to the target coordinates and records the movement operations\nvoid move_truck_to(int target_r, int target_c) {\n    while (current_r < target_r) {\n        ops.push_back(\"D\");\n        current_r++;\n    }\n    while (current_r > target_r) {\n        ops.push_back(\"U\");\n        current_r--;\n    }\n    while (current_c < target_c) {\n        ops.push_back(\"R\");\n        current_c++;\n    }\n    while (current_c > target_c) {\n        ops.push_back(\"L\");\n        current_c--;\n    }\n}\n\n// Structure to hold cell coordinates and a calculated distance, used for sorting candidates\nstruct CandidateCell {\n    int r, c;\n    long long dist;\n\n    // Operator< for sorting by distance\n    bool operator<(const CandidateCell& other) const {\n        return dist < other.dist;\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int dummy_N; // Read N, but it's fixed at 20\n    std::cin >> dummy_N;\n\n    long long total_initial_positive_soil = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> H[i][j];\n            if (H[i][j] > 0) {\n                total_initial_positive_soil += H[i][j];\n            }\n        }\n    }\n\n    long long soil_moved_to_level_sinks = 0; // Tracks the total soil moved to fulfill negative heights\n    const int K_CANDIDATES = 30; // Increased number of closest sources/sinks to consider (from 20 to 30)\n\n    // Timer for execution time limit\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds to be safe (total limit is 2.0 sec)\n\n    // Main loop: continues until all soil is leveled or operation/time limits are reached\n    while (soil_moved_to_level_sinks < total_initial_positive_soil) {\n        if (ops.size() >= 99000) { // Max 100000 turns, stop early to avoid exceeding\n            break;\n        }\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) {\n            break;\n        }\n\n        std::vector<CandidateCell> all_sources; // List of all cells with H > 0\n        std::vector<CandidateCell> all_sinks;   // List of all cells with H < 0\n\n        // Populate sources and sinks lists\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (H[i][j] > 0) {\n                    // For sources, calculate distance from current truck position\n                    all_sources.push_back({i, j, manhattan_dist(current_r, current_c, i, j)});\n                } else if (H[i][j] < 0) {\n                    all_sinks.push_back({i, j, 0}); // Distance for sinks will be calculated later from a potential source\n                }\n            }\n        }\n\n        // If no sources or sinks remain, the leveling is complete (or stuck)\n        if (all_sources.empty() || all_sinks.empty()) {\n            break;\n        }\n\n        // Partially sort sources by their distance from the current truck position\n        int num_source_candidates_to_process = std::min((int)all_sources.size(), K_CANDIDATES);\n        if (num_source_candidates_to_process > 0) {\n            std::partial_sort(all_sources.begin(), all_sources.begin() + num_source_candidates_to_process, all_sources.end());\n        }\n\n        // Variables to track the best transfer based on MINIMUM ABSOLUTE TOTAL COST\n        long long min_total_cost = std::numeric_limits<long long>::max(); \n\n        int best_sr = -1, best_sc = -1, best_dr = -1, best_dc = -1; // Coordinates of the best source/sink\n        long long best_D_value = 0; // Amount of soil for the best transfer\n\n        // Iterate through a limited number of closest source candidates\n        for (int i = 0; i < num_source_candidates_to_process; ++i) {\n            int sr = all_sources[i].r;\n            int sc = all_sources[i].c;\n\n            // Create a temporary list of sinks, calculating their distance from the current source candidate\n            std::vector<CandidateCell> current_sink_candidates;\n            for (const auto& sink : all_sinks) {\n                current_sink_candidates.push_back({sink.r, sink.c, manhattan_dist(sr, sc, sink.r, sink.c)});\n            }\n            \n            // Partially sort these sinks by their distance from the current source candidate\n            int num_sink_candidates_to_process = std::min((int)current_sink_candidates.size(), K_CANDIDATES);\n            if (num_sink_candidates_to_process > 0) {\n                std::partial_sort(current_sink_candidates.begin(), current_sink_candidates.begin() + num_sink_candidates_to_process, current_sink_candidates.end());\n            }\n\n            // Iterate through a limited number of closest sink candidates for this source\n            for (int j = 0; j < num_sink_candidates_to_process; ++j) {\n                int dr = current_sink_candidates[j].r;\n                int dc = current_sink_candidates[j].c;\n\n                // Calculate the amount of soil to transfer: min of available at source and needed at sink\n                long long D = std::min((long long)H[sr][sc], -(long long)H[dr][dc]);\n                if (D <= 0) continue; // No actual transfer possible\n\n                // Calculate the total cost for this specific (source, sink, amount) transfer\n                long long cost_to_source = manhattan_dist(current_r, current_c, sr, sc) * 100LL;\n                long long cost_source_to_sink = manhattan_dist(sr, sc, dr, dc) * (100LL + D);\n                long long current_total_cost = cost_to_source + cost_source_to_sink + 2LL * D;\n\n                // Update if this transfer is cheaper based on MINIMUM ABSOLUTE TOTAL COST\n                if (current_total_cost < min_total_cost) {\n                    min_total_cost = current_total_cost;\n                    best_sr = sr; best_sc = sc;\n                    best_dr = dr; best_dc = dc;\n                    best_D_value = D;\n                }\n            }\n        }\n\n        // If no valid transfer was found in this iteration (min_total_cost is still its initial max value), break the loop\n        if (min_total_cost == std::numeric_limits<long long>::max()) {\n            break;\n        }\n\n        // Execute the operations for the chosen best transfer\n        \n        // 1. Move truck to the best source\n        move_truck_to(best_sr, best_sc);\n        \n        // 2. Load soil\n        ops.push_back(\"+\" + std::to_string(best_D_value));\n        truck_load += best_D_value;\n        H[best_sr][best_sc] -= best_D_value; // Update source cell's height\n        \n        // 3. Move truck to the best sink\n        move_truck_to(best_dr, best_dc);\n        \n        // 4. Unload soil\n        ops.push_back(\"-\" + std::to_string(best_D_value));\n        truck_load -= best_D_value;\n        H[best_dr][best_dc] += best_D_value; // Update sink cell's height\n        soil_moved_to_level_sinks += best_D_value; // Increment total soil leveled\n    }\n\n    // Output all recorded operations\n    for (const std::string& op : ops) {\n        std::cout << op << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <cmath>   // For std::exp\n\n// --- Global variables for N, M, T and X_seeds ---\nint N_global, M_global, T_global;\nstd::vector<std::vector<int>> X_seeds_global; // Current seeds available for planting\nstd::vector<int> initial_X_max_global;       // Max value for each criterion from initial seeds\n\n// --- RNG ---\n// Use std::mt19937_64 for potentially better randomness and larger range.\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper function to calculate potential for a pair ---\n// Returns the sum of max values for each criterion between two seeds.\n// seed_idx1 and seed_idx2 are indices into X_seeds_global.\nlong long calculate_pair_potential(int seed_idx1, int seed_idx2) {\n    long long potential = 0;\n    for (int l = 0; l < M_global; ++l) {\n        potential += std::max(X_seeds_global[seed_idx1][l], X_seeds_global[seed_idx2][l]);\n    }\n    return potential;\n}\n\n// --- Helper function to get adjacent coordinates ---\n// Returns a vector of {row, col} pairs for direct neighbors of (r, c).\n// For N=6, this will return at most 4 pairs.\nstd::vector<std::pair<int, int>> get_adjacent_coords(int r, int c) {\n    std::vector<std::pair<int, int>> adj;\n    adj.reserve(4); // Reserve capacity to avoid reallocations, N is small and fixed\n    int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n    int dc[] = {0, 0, -1, 1};\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_global && nc >= 0 && nc < N_global) {\n            adj.push_back({nr, nc});\n        }\n    }\n    return adj;\n}\n\n// --- Function to calculate total score for a grid configuration ---\n// Sum of potential values for all adjacent pairs in the grid.\nlong long calculate_grid_score(const std::vector<std::vector<int>>& A) {\n    long long total_score = 0;\n    // Horizontal adjacencies\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global - 1; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i][j+1]);\n        }\n    }\n    // Vertical adjacencies\n    for (int i = 0; i < N_global - 1; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i+1][j]);\n        }\n    }\n    return total_score;\n}\n\nvoid solve() {\n    std::cin >> N_global >> M_global >> T_global;\n\n    int seed_count = 2 * N_global * (N_global - 1); // For N=6, this is 2*6*5 = 60 seeds\n    X_seeds_global.resize(seed_count, std::vector<int>(M_global));\n    initial_X_max_global.resize(M_global, 0);\n\n    // Read initial seeds and compute initial_X_max_global\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M_global; ++j) {\n            std::cin >> X_seeds_global[i][j];\n            initial_X_max_global[j] = std::max(initial_X_max_global[j], X_seeds_global[i][j]);\n        }\n    }\n\n    // Main simulation loop for T turns\n    for (int turn = 0; turn < T_global; ++turn) {\n        // 1. Select seeds for planting:\n        // Calculate a combined score for all current seeds and pick the top N*N.\n        // The combined score considers V_k + a bonus for carrying initial global max traits.\n        std::vector<std::pair<long long, int>> seed_scores(seed_count); // {combined_score, seed_idx}\n        for (int i = 0; i < seed_count; ++i) {\n            long long current_Vk = 0;\n            int trait_count = 0;\n            for (int l = 0; l < M_global; ++l) {\n                current_Vk += X_seeds_global[i][l];\n                if (X_seeds_global[i][l] == initial_X_max_global[l]) {\n                    trait_count++;\n                }\n            }\n            // TUNING: Increased alpha to 300LL. This weights seeds carrying global max traits\n            // even more heavily, encouraging their rapid propagation and combination.\n            long long combined_score = current_Vk + 300LL * trait_count; \n            seed_scores[i] = {combined_score, i};\n        }\n        std::sort(seed_scores.rbegin(), seed_scores.rend()); // Sort descending by combined_score\n\n        std::vector<int> selected_seeds_indices(N_global * N_global); // N*N = 36 seeds\n        for (int i = 0; i < N_global * N_global; ++i) {\n            selected_seeds_indices[i] = seed_scores[i].second;\n        }\n\n        // 2. Determine placement using Simulated Annealing\n        std::vector<std::vector<int>> current_A(N_global, std::vector<int>(N_global));\n        \n        // Initial placement for SA: random permutation of selected seeds\n        std::shuffle(selected_seeds_indices.begin(), selected_seeds_indices.end(), rng);\n        int k_idx = 0;\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                current_A[i][j] = selected_seeds_indices[k_idx++];\n            }\n        }\n\n        long long current_score = calculate_grid_score(current_A);\n        std::vector<std::vector<int>> best_A = current_A;\n        long long best_score = current_score;\n\n        // SA parameters (tuned for AHC035 constraints)\n        // TUNING: Increased start_temp to 30000.0 for even more aggressive initial exploration.\n        double start_temp = 30000.0; \n        double end_temp = 100.0;    \n        long long max_iterations = 250000; // Safety upper bound, time budget is primary control\n        \n        // Time budget for SA loop (e.g., 180ms per turn for T=10 turns, 1.8s total SA time)\n        auto start_time = std::chrono::high_resolution_clock::now();\n        std::chrono::milliseconds time_budget(180); \n\n        std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        std::uniform_int_distribution<int> dist_rc(0, N_global - 1); // For random row/col\n\n        for (long long iter = 0; iter < max_iterations; ++iter) {\n            // Check time budget\n            auto current_time = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time) > time_budget) {\n                break; \n            }\n\n            // Calculate current temperature with exponential decay\n            double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / max_iterations);\n\n            // Pick two random distinct cells to swap\n            int r1 = dist_rc(rng);\n            int c1 = dist_rc(rng);\n            int r2 = dist_rc(rng);\n            int c2 = dist_rc(rng);\n            while (r1 == r2 && c1 == c2) { // Ensure distinct cells\n                r2 = dist_rc(rng);\n                c2 = dist_rc(rng);\n            }\n\n            int seed1_idx = current_A[r1][c1]; // Original seed at (r1,c1)\n            int seed2_idx = current_A[r2][c2]; // Original seed at (r2,c2)\n\n            // Calculate change in score (delta_score) efficiently\n            long long old_adj_contrib = 0;\n            std::vector<std::pair<int, int>> neighbors_r1c1 = get_adjacent_coords(r1, c1);\n            std::vector<std::pair<int, int>> neighbors_r2c2 = get_adjacent_coords(r2, c2);\n\n            for (auto p : neighbors_r1c1) {\n                // If the other swapped cell is a neighbor, exclude it.\n                // The direct edge contribution (P(seed1, seed2)) is symmetric and\n                // does not change when the seeds are swapped, so it's not part of delta_score calculation.\n                if (!(p.first == r2 && p.second == c2)) { \n                    old_adj_contrib += calculate_pair_potential(seed1_idx, current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    old_adj_contrib += calculate_pair_potential(seed2_idx, current_A[p.first][p.second]);\n                }\n            }\n\n            // Temporarily perform the swap\n            current_A[r1][c1] = seed2_idx;\n            current_A[r2][c2] = seed1_idx;\n\n            long long new_adj_contrib = 0;\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r1][c1], current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r2][c2], current_A[p.first][p.second]);\n                }\n            }\n            \n            long long delta_score = new_adj_contrib - old_adj_contrib;\n            long long new_score = current_score + delta_score;\n\n            // Metropolis criterion for acceptance\n            if (new_score > current_score || dist_prob(rng) < std::exp(static_cast<double>(new_score - current_score) / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_A = current_A;\n                }\n            } else {\n                // Revert the swap if not accepted\n                current_A[r1][c1] = seed1_idx;\n                current_A[r2][c2] = seed2_idx;\n            }\n        }\n        \n        // Output the best placement found for this turn\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                std::cout << best_A[i][j];\n                if (j < N_global - 1) {\n                    std::cout << \" \";\n                } else {\n                    std::cout << std::endl;\n                }\n            }\n        }\n        std::cout.flush(); // Flush output to interactive judge\n\n        // 3. Read the new seeds for the next turn\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M_global; ++j) {\n                std::cin >> X_seeds_global[i][j];\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    solve();\n    \n    return 0;\n}\n","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for grid and problem parameters\nint N, M, V_MAX;\n\n// Current state of takoyaki (sources and targets)\nset<pair<int, int>> current_s_takoyaki; // Takoyaki that need to be picked up\nset<pair<int, int>> current_t_empty;    // Target squares that need takoyaki\n\n// Robotic arm state\nstruct Vec2 {\n    int x, y; // x for row, y for col\n    Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }\n    Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }\n    long long dist_sq(const Vec2& other) const { return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y); }\n};\n\nVec2 root_pos;\nvector<Vec2> rel_vecs; // relative position of vertex u to its parent p_u\nvector<int> orient_idx; // 0:right, 1:down, 2:left, 3:up (problem's definition)\n\n// For positions calculation\nvector<Vec2> abs_pos;\nvector<bool> is_fingertip;\nvector<int> parent_map; // parent_map[u] gives parent of u\nvector<int> L_map; // L_map[u] gives length of (parent[u], u)\n\nvector<bool> fingertip_holding; // Whether each fingertip is holding a takoyaki\n\n// PROBLEM_REL_DX, PROBLEM_REL_DY for cardinal directions (0:R, 1:D, 2:L, 3:U)\n// These define the (row_diff, col_diff) for a segment pointing in that direction.\n// R: (0,1)\n// D: (1,0)\n// L: (0,-1)\n// U: (-1,0)\nconst int PROBLEM_REL_DX[] = {0, 1, 0, -1}; \nconst int PROBLEM_REL_DY[] = {1, 0, -1, 0};\n\n// Rotate a vector (dr, dc) 90 degrees clockwise (dr -> dc, dc -> -dr)\n// Example from problem: (0,L) -> (L,0)\nVec2 rotate_cw_problem(const Vec2& v) { return {v.y, -v.x}; }\n// Rotate a vector (dr, dc) 90 degrees counter-clockwise (dr -> -dc, dc -> dr)\n// Example: (0,L) -> (-L,0)\nVec2 rotate_ccw_problem(const Vec2& v) { return {-v.y, v.x}; }\n\n// Update absolute positions of all vertices\nvoid update_abs_pos() {\n    abs_pos[0] = root_pos;\n    for (size_t i = 1; i < abs_pos.size(); ++i) {\n        abs_pos[i] = abs_pos[parent_map[i]] + rel_vecs[i];\n    }\n}\n\n// Calculate centroid of a set of points\nVec2 calculate_centroid(const set<pair<int, int>>& points) {\n    if (points.empty()) {\n        return {-1, -1}; // Invalid centroid\n    }\n    long long sum_x = 0, sum_y = 0;\n    for (const auto& p : points) {\n        sum_x += p.first;\n        sum_y += p.second;\n    }\n    return {(int)round((double)sum_x / points.size()), (int)round((double)sum_y / points.size())};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> V_MAX;\n\n    set<pair<int, int>> initial_sources_raw; // To store original sources\n    set<pair<int, int>> target_goals_raw; // To store original targets\n\n    // Read initial takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                initial_sources_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Read target takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                target_goals_raw.insert({i, j});\n            }\n        }\n    }\n\n    // Initialize current_s_takoyaki and current_t_empty by removing already satisfied takoyaki\n    current_s_takoyaki = initial_sources_raw;\n    current_t_empty = target_goals_raw;\n\n    for (auto it = current_t_empty.begin(); it != current_t_empty.end(); ) {\n        if (current_s_takoyaki.count(*it)) {\n            current_s_takoyaki.erase(*it);\n            it = current_t_empty.erase(it);\n        } else {\n            ++it;\n        }\n    }\n\n    // Design the robotic arm (V' = V_MAX, star graph, all edges length 1)\n    int V_prime = V_MAX; // Number of vertices in the arm\n    cout << V_prime << endl;\n\n    parent_map.resize(V_prime);\n    L_map.resize(V_prime);\n    is_fingertip.resize(V_prime, false);\n    \n    // Root is 0. Children 1 to V_prime-1 are fingertips.\n    for (int u = 1; u < V_prime; ++u) {\n        // Parent of u is 0, length 1\n        cout << 0 << \" \" << 1 << endl;\n        parent_map[u] = 0;\n        L_map[u] = 1; // All fingertips are length 1 away from root\n        is_fingertip[u] = true;\n    }\n\n    // Initial root position (center of the grid)\n    root_pos = {N / 2, N / 2};\n    cout << root_pos.x << \" \" << root_pos.y << endl;\n\n    // Initialize arm state\n    abs_pos.resize(V_prime);\n    rel_vecs.resize(V_prime);\n    orient_idx.resize(V_prime, 0); // All edges initially point right (direction 0)\n\n    for (int u = 1; u < V_prime; ++u) {\n        rel_vecs[u] = {L_map[u] * PROBLEM_REL_DX[0], L_map[u] * PROBLEM_REL_DY[0]}; // (L,0) for parent-child edge\n    }\n\n    fingertip_holding.resize(V_prime, false); // No fingertip holds takoyaki initially\n\n    // Operation loop\n    for (int turn = 0; turn < 100000; ++turn) {\n        if (current_t_empty.empty()) {\n            break; // All takoyaki delivered\n        }\n\n        // 1. Calculate absolute positions based on current root_pos and relative vectors\n        update_abs_pos();\n\n        // 2. Determine root movement\n        string command_root_move = \".\";\n        Vec2 target_centroid = {-1, -1};\n\n        int holding_count = 0;\n        for(int i=0; i<V_prime; ++i) if(is_fingertip[i] && fingertip_holding[i]) holding_count++;\n\n        if (holding_count > 0) { // If holding takoyaki, prioritize moving to target empty spots\n            target_centroid = calculate_centroid(current_t_empty);\n        } else { // If no takoyaki held, prioritize moving to source takoyaki\n            target_centroid = calculate_centroid(current_s_takoyaki);\n        }\n        \n        // If no target or source left, break or idle\n        if (target_centroid.x == -1) { \n            break; \n        }\n\n        int next_rx = root_pos.x;\n        int next_ry = root_pos.y;\n\n        int dx_diff = target_centroid.x - root_pos.x;\n        int dy_diff = target_centroid.y - root_pos.y;\n\n        // Prioritize moving along the larger difference axis\n        if (abs(dx_diff) >= abs(dy_diff)) {\n            if (dx_diff > 0) { // Move Down (increase row index)\n                if (root_pos.x + 1 < N) {\n                    next_rx = root_pos.x + 1;\n                    command_root_move = \"D\";\n                }\n            } else if (dx_diff < 0) { // Move Up (decrease row index)\n                if (root_pos.x - 1 >= 0) {\n                    next_rx = root_pos.x - 1;\n                    command_root_move = \"U\";\n                }\n            }\n        } \n        \n        // If no movement determined yet, or movement on X axis was impossible, try the Y axis\n        if (command_root_move == \".\" || (abs(dx_diff) < abs(dy_diff) && abs(dy_diff) > 0)) { // Only try if Y diff is larger or X move was skipped\n            if (dy_diff > 0) { // Move Right (increase col index)\n                if (root_pos.y + 1 < N) {\n                    next_ry = root_pos.y + 1;\n                    command_root_move = \"R\";\n                }\n            } else if (dy_diff < 0) { // Move Left (decrease col index)\n                if (root_pos.y - 1 >= 0) {\n                    next_ry = root_pos.y - 1;\n                    command_root_move = \"L\";\n                }\n            }\n        }\n\n        // Apply root movement\n        root_pos.x = next_rx;\n        root_pos.y = next_ry;\n        \n        // Update positions after root move (needed for rotation logic)\n        update_abs_pos();\n\n        // 3. Determine rotations\n        string command_rotations_str(V_prime - 1, '.'); // For non-root vertices (1 to V_prime-1)\n        vector<int> desired_orient_idx(V_prime, -1); // -1 means no specific rotation desired for this turn\n\n        // Prioritize placing takoyaki\n        // Try to assign holding fingertips to target squares\n        for (int d = 0; d < 4; ++d) { // For each cardinal direction (0:R, 1:D, 2:L, 3:U)\n            // Target cell one unit away from root in direction d\n            Vec2 target_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (target_cell.x >= 0 && target_cell.x < N && target_cell.y >= 0 && target_cell.y < N &&\n                current_t_empty.count({target_cell.x, target_cell.y})) {\n                \n                // Find a holding fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n\n        // Then assign empty fingertips to source squares\n        for (int d = 0; d < 4; ++d) {\n            // Source cell one unit away from root in direction d\n            Vec2 source_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[1], PROBLEM_REL_DY[d] * L_map[1]};\n\n            if (source_cell.x >= 0 && source_cell.x < N && source_cell.y >= 0 && source_cell.y < N &&\n                current_s_takoyaki.count({source_cell.x, source_cell.y})) {\n                \n                // Find an empty fingertip that is not yet assigned a target for this turn\n                int best_fingertip_id = -1;\n                for (int u = 1; u < V_prime; ++u) { // Iterate fingertips\n                    if (is_fingertip[u] && !fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                        best_fingertip_id = u;\n                        break;\n                    }\n                }\n                if (best_fingertip_id != -1) {\n                    desired_orient_idx[best_fingertip_id] = d;\n                }\n            }\n        }\n        \n        // Apply rotations based on desired_orient_idx\n        for (int u = 1; u < V_prime; ++u) { // Only non-root vertices can rotate (fingertips in this design)\n            if (desired_orient_idx[u] != -1) {\n                int current_d = orient_idx[u];\n                int target_d = desired_orient_idx[u];\n\n                if (current_d == target_d) {\n                    command_rotations_str[u - 1] = '.'; // No rotation needed\n                } else {\n                    // Calculate shortest rotation path (1 step CW vs 1 step CCW)\n                    int cw_diff = (target_d - current_d + 4) % 4;\n                    int ccw_diff = (current_d - target_d + 4) % 4;\n\n                    if (cw_diff == 1) { // 90 deg CW\n                        command_rotations_str[u - 1] = 'R';\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else if (ccw_diff == 1) { // 90 deg CCW\n                        command_rotations_str[u - 1] = 'L';\n                        orient_idx[u] = (orient_idx[u] + 3) % 4;\n                        rel_vecs[u] = rotate_ccw_problem(rel_vecs[u]);\n                    } else if (cw_diff == 2) { // 180 deg, takes 2 turns. Pick one direction (CW).\n                        command_rotations_str[u - 1] = 'R'; \n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else { // Should not happen for 0-3 directions, but for safety\n                         command_rotations_str[u - 1] = '.';\n                    }\n                }\n            } else {\n                command_rotations_str[u - 1] = '.'; // No specific target, no rotation\n            }\n        }\n        \n        // Update positions after rotations\n        update_abs_pos();\n\n        // 4. Determine grab/release actions\n        // String to store P/'.' for each vertex 0 to V_prime-1.\n        // command_P_actions_part[i] will store the action for vertex i.\n        string command_P_actions_part(V_prime, '.'); \n        \n        // Process fingertips in order of ID (1 to V_prime-1) as problem states vertex order.\n        // Vertex 0 (root) is not a fingertip, so command_P_actions_part[0] remains '.'\n        for (int u = 1; u < V_prime; ++u) { \n            Vec2 current_tip_pos = abs_pos[u];\n\n            // Check if fingertip is within grid boundaries\n            if (current_tip_pos.x < 0 || current_tip_pos.x >= N || current_tip_pos.y < 0 || current_tip_pos.y >= N) {\n                continue; // Fingertip outside grid, cannot act\n            }\n\n            if (fingertip_holding[u]) { // If currently holding a takoyaki\n                if (current_t_empty.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Place takoyaki on target square\n                    command_P_actions_part[u] = 'P'; // Action for vertex 'u' is stored at index 'u'\n                    current_t_empty.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = false;\n                }\n            } else { // If not holding a takoyaki\n                if (current_s_takoyaki.count({current_tip_pos.x, current_tip_pos.y})) {\n                    // Pick up takoyaki from source square\n                    command_P_actions_part[u] = 'P';\n                    current_s_takoyaki.erase({current_tip_pos.x, current_tip_pos.y});\n                    fingertip_holding[u] = true;\n                }\n            }\n        }\n        \n        // Output combined command string\n        // Format: [root_move_char][V_prime-1 rotation_chars][V_prime P_chars]\n        cout << command_root_move << command_rotations_str << command_P_actions_part << endl;\n    }\n\n    return 0;\n}\n","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <set>\n// #include <optional> // optional is no longer strictly needed for 'hole' but can be kept if desired\n\nusing namespace std;\n\n// Timer utility\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    double time_limit_ms;\n\n    Timer(double limit_ms) : time_limit_ms(limit_ms) {\n        start_time = chrono::high_resolution_clock::now();\n    }\n\n    bool is_time_up() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() >= time_limit_ms;\n    }\n\n    double get_elapsed_time_ms() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n    }\n};\n\n// Point structure\nstruct Point {\n    int x, y;\n};\n\n// Rectangle structure\nstruct Rect {\n    int x_min, y_min, x_max, y_max;\n    long long length() const {\n        // Degenerate rectangle (width or height is 0 or negative) has 0 length\n        if (x_min >= x_max || y_min >= y_max) return 0; \n        return 2LL * (x_max - x_min) + 2LL * (y_max - y_min);\n    }\n};\n\n// Fenwick Tree (BIT) for 2D range sum queries\ntemplate <typename T>\nstruct FenwickTree2D {\n    int max_x_idx, max_y_idx;\n    vector<vector<T>> bit;\n\n    FenwickTree2D(int mx_idx, int my_idx) : max_x_idx(mx_idx), max_y_idx(my_idx) {\n        // Fenwick tree indices are 1-based, so size mx_idx+1, my_idx+1\n        bit.assign(max_x_idx + 1, vector<T>(max_y_idx + 1, 0));\n    }\n\n    void update(int x, int y, T delta) { // x, y are 0-based compressed indices\n        for (int i = x + 1; i <= max_x_idx; i += i & -i) {\n            for (int j = y + 1; j <= max_y_idx; j += j & -j) {\n                bit[i][j] += delta;\n            }\n        }\n    }\n\n    T query(int x, int y) { // query sum from (0,0) to (x,y) inclusive (0-based compressed indices)\n        T sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i) {\n            for (int j = y + 1; j > 0; j -= j & -j) {\n                sum += bit[i][j];\n            }\n        }\n        return sum;\n    }\n\n    // query sum for rectangle [x1, x2] x [y1, y2] (0-based compressed indices)\n    T query_rect_sum(int x1, int y1, int x2, int y2) { \n        // If the rectangle is inverted or empty in terms of compressed indices, it contains no points\n        if (x1 > x2 || y1 > y2) return 0;\n\n        T sum = query(x2, y2);\n        if (x1 > 0) sum -= query(x1 - 1, y2);\n        if (y1 > 0) sum -= query(x2, y1 - 1);\n        if (x1 > 0 && y1 > 0) sum += query(x1 - 1, y1 - 1);\n        return sum;\n    }\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nvector<int> unique_xs, unique_ys;\nmap<int, int> x_to_idx, y_to_idx;\nFenwickTree2D<int>* ft_ptr = nullptr; // Pointer to FenwickTree2D\n\n// Score calculation wrapper for real coordinates using compressed FT\nlong long calculate_rect_score(const Rect& rect) {\n    // If the rectangle is degenerate (width or height is 0 or negative), it cannot contain any points.\n    if (rect.x_min >= rect.x_max || rect.y_min >= rect.y_max) return 0; \n\n    // Find compressed indices for the given real coordinate rectangle\n    auto it_x1 = lower_bound(unique_xs.begin(), unique_xs.end(), rect.x_min);\n    if (it_x1 == unique_xs.end()) return 0; // rect.x_min is beyond all unique x-coordinates\n    int x1_idx = distance(unique_xs.begin(), it_x1);\n\n    auto it_x2 = upper_bound(unique_xs.begin(), unique_xs.end(), rect.x_max);\n    if (it_x2 == unique_xs.begin()) return 0; // rect.x_max is smaller than all unique x-coordinates\n    int x2_idx = distance(unique_xs.begin(), it_x2) - 1; // Largest unique_x_coord <= rect.x_max\n\n    auto it_y1 = lower_bound(unique_ys.begin(), unique_ys.end(), rect.y_min);\n    if (it_y1 == unique_ys.end()) return 0; \n    int y1_idx = distance(unique_ys.begin(), it_y1);\n\n    auto it_y2 = upper_bound(unique_ys.begin(), unique_ys.end(), rect.y_max);\n    if (it_y2 == unique_ys.begin()) return 0; \n    int y2_idx = distance(unique_ys.begin(), it_y2) - 1;\n\n    // Check if the compressed index range itself is valid (x1_idx <= x2_idx and y1_idx <= y2_idx)\n    // This handles cases where rect.x_min > rect.x_max (after compression logic)\n    if (x1_idx > x2_idx || y1_idx > y2_idx) return 0; \n\n    return ft_ptr->query_rect_sum(x1_idx, y1_idx, x2_idx, y2_idx);\n}\n\n// Polygon state for SA: now only a single rectangle\nstruct PolygonState {\n    Rect outer;\n    long long value; // Score (mackerels - sardines)\n    long long total_len; // Total length of edges\n    vector<Point> vertices; // Actual vertices for output\n\n    PolygonState() : value(0), total_len(0), outer({0,0,0,0}) {} // Default empty state\n\n    void calculate_polygon_data() {\n        // Outer rect must be valid (x_min < x_max and y_min < y_max)\n        if (outer.x_min >= outer.x_max || outer.y_min >= outer.y_max) { \n            value = -1; // Indicate invalid state (negative value for invalid)\n            total_len = 0;\n            vertices.clear();\n            return;\n        }\n        \n        value = calculate_rect_score(outer);\n        total_len = outer.length();\n\n        vertices.clear();\n        // Generate vertices for output if score is non-negative\n        // For a valid, non-degenerate rectangle, these 4 points are always distinct.\n        // The output polygon will be a simple rectangle with 4 vertices.\n        vertices.push_back({outer.x_min, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_max});\n        vertices.push_back({outer.x_min, outer.y_max});\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer(1900); // 1.9 seconds time limit for main SA loop\n\n    cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    set<int> x_coords_set, y_coords_set;\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        x_coords_set.insert(mackerels[i].x);\n        y_coords_set.insert(mackerels[i].y);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        x_coords_set.insert(sardines[i].x);\n        y_coords_set.insert(sardines[i].y);\n    }\n\n    // Coordinate compression\n    unique_xs.assign(x_coords_set.begin(), x_coords_set.end());\n    unique_ys.assign(y_coords_set.begin(), y_coords_set.end());\n\n    // Ensure 0 and 100000 are in unique_xs/ys as potential boundaries for rectangles.\n    // This is important because a rectangle might span these boundaries even if no points are exactly on them.\n    if (unique_xs.empty() || unique_xs.front() != 0) { unique_xs.insert(unique_xs.begin(), 0); }\n    if (unique_xs.back() != 100000) { unique_xs.push_back(100000); }\n    if (unique_ys.empty() || unique_ys.front() != 0) { unique_ys.insert(unique_ys.begin(), 0); }\n    if (unique_ys.back() != 100000) { unique_ys.push_back(100000); }\n    \n    // Re-sort if necessary (std::set keeps elements sorted, so unique_xs.assign copies them in order. \n    // Manual insert at begin/end might break this if elements are not at the extrema, but 0 and 100000 are extrema.)\n    // However, it's safer to ensure they are sorted if inserts were made. std::set properties ensure this is usually fine.\n    // With `insert` and `push_back` as written for 0 and 100000, `unique_xs` and `unique_ys` remain sorted.\n\n    // Populate maps for fast lookup from real coordinate to compressed index\n    for (int i = 0; i < unique_xs.size(); ++i) x_to_idx[unique_xs[i]] = i;\n    for (int i = 0; i < unique_ys.size(); ++i) y_to_idx[unique_ys[i]] = i;\n\n    // Initialize 2D Fenwick Tree using compressed indices\n    FenwickTree2D<int> ft(unique_xs.size(), unique_ys.size());\n    ft_ptr = &ft;\n\n    for (int i = 0; i < N; ++i) { // Mackerels contribute +1\n        ft.update(x_to_idx[mackerels[i].x], y_to_idx[mackerels[i].y], 1);\n    }\n    for (int i = 0; i < N; ++i) { // Sardines contribute -1\n        ft.update(x_to_idx[sardines[i].x], y_to_idx[sardines[i].y], -1);\n    }\n\n    // Initialize random number generator\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_idx_x(0, unique_xs.size() - 1);\n    uniform_int_distribution<int> rand_idx_y(0, unique_ys.size() - 1);\n    uniform_real_distribution<double> rand_prob(0.0, 1.0);\n    \n    // Initial solution: a large rectangle covering the entire possible area\n    PolygonState best_polygon;\n    best_polygon.outer = {0, 0, 100000, 100000};\n    best_polygon.calculate_polygon_data(); // Calculate score and vertices for initial state\n    \n    // If the initial full map rectangle is degenerate, invalid, or yields a negative score\n    // (meaning a score of 1 in the contest, effectively), initialize with a minimal valid rectangle.\n    // The current calculate_polygon_data sets value=-1 for invalid, and total_len=0.\n    // So, if best_polygon.value is -1, it implies an invalid rectangle, or actual score < 0.\n    if (best_polygon.value < 0 || best_polygon.total_len > 400000) {\n        best_polygon.outer = {0,0,1,1}; // A minimal 1x1 rectangle at origin. Valid, length 4, 4 vertices.\n        best_polygon.calculate_polygon_data();\n    }\n\n    PolygonState current_polygon = best_polygon; // Start SA from this point\n\n    double T_start = 2000.0; // Initial temperature: A heuristic, roughly the maximum possible (mackerel - sardine) difference\n    double T_end = 1.0;      // Final temperature: Low enough to favor improvements but still allow small worsening moves\n    long long iter_count = 0;\n    long long max_iterations = 500000; // Increase iterations as calculations are faster now\n\n    while (!timer.is_time_up() && iter_count < max_iterations) {\n        iter_count++;\n        PolygonState next_polygon = current_polygon;\n\n        // Only modify the outer rectangle's boundaries\n        int dim_to_change = uniform_int_distribution<int>(0, 3)(rng); // 0:x_min, 1:y_min, 2:x_max, 3:y_max\n        int new_val_idx;\n        \n        if (dim_to_change == 0) { // Modify x_min\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max); // Ensure x_min <= x_max\n        } else if (dim_to_change == 1) { // Modify y_min\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max); // Ensure y_min <= y_max\n        } else if (dim_to_change == 2) { // Modify x_max\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min); // Ensure x_max >= x_min\n        } else { // Modify y_max\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min); // Ensure y_max >= y_min\n        }\n        \n        next_polygon.calculate_polygon_data(); // Recalculate score and other data for the new state\n        \n        // Validity check: Must result in a valid polygon (value >= 0, length within limits)\n        if (next_polygon.value < 0 || next_polygon.total_len > 400000) {\n            continue; // This move is invalid, discard and try again\n        }\n\n        // Simulated Annealing acceptance criteria\n        double current_temp = T_start * pow(T_end / T_start, timer.get_elapsed_time_ms() / timer.time_limit_ms);\n        double acceptance_prob = 1.0;\n        if (next_polygon.value < current_polygon.value) {\n            // If the new solution is worse, accept it with a probability that decreases with temperature\n            acceptance_prob = exp((double)(next_polygon.value - current_polygon.value) / current_temp);\n        }\n\n        if (rand_prob(rng) < acceptance_prob) {\n            current_polygon = next_polygon; // Accept the new solution\n            if (current_polygon.value > best_polygon.value) {\n                best_polygon = current_polygon; // Update overall best solution found\n            }\n        }\n    }\n\n    // Output the best polygon found\n    // If best_polygon.value is negative (which shouldn't happen with the fallback {0,0,1,1} initialization, \n    // but as a safeguard), output the minimal 1x1 polygon for a score of 1.\n    if (best_polygon.value < 0) {\n        cout << 4 << endl;\n        cout << \"0 0\" << endl;\n        cout << \"1 0\" << endl;\n        cout << \"1 1\" << endl;\n        cout << \"0 1\" << endl;\n    } else {\n        cout << best_polygon.vertices.size() << endl;\n        for (const auto& v : best_polygon.vertices) {\n            cout << v.x << \" \" << v.y << endl;\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <map>\n#include <iomanip> // For std::fixed, std::setprecision\n#include <chrono> // For timing\n#include <cmath> // For std::exp, std::pow, std::sqrt\n\n// Random number generator\nstd::mt19937 rng;\n\n// Global parameters from input\nint N_GLOBAL;\nint T_TOTAL_GLOBAL;\nlong long SIGMA_GLOBAL;\nstd::vector<long long> W_PRIME_GLOBAL, H_PRIME_GLOBAL; // Initial observed dimensions\n\n// Current estimates for true widths and heights, using double for precision\nstd::vector<double> current_estimated_w, current_estimated_h;\n\n// Struct to represent a single placement operation\nstruct Operation {\n    int p;     // Rectangle index (0 to N-1)\n    int r;     // Rotation (0: no, 1: 90-deg)\n    char d;    // Direction ('U' or 'L')\n    int b;     // Reference rectangle index (-1 for origin or 0 to p-1)\n};\n\n// Struct to store details of a rectangle after it's been placed\nstruct PlacedRectInfo {\n    long long x, y, w, h; // Coordinates and dimensions\n    int p_idx;             // Original index of the rectangle\n    bool rotated;          // True if rotated\n};\n\n// Helper function for random integer generation\nint random_int(int min, int max) {\n    std::uniform_int_distribution<int> dist(min, max);\n    return dist(rng);\n}\n\n// Helper function for random char selection\nchar random_char(char c1, char c2) {\n    return (random_int(0, 1) == 0) ? c1 : c2;\n}\n\n// Helper for random double in range [0, 1)\ndouble random_double_01() {\n    std::uniform_real_distribution<double> dist(0.0, 1.0);\n    return dist(rng);\n}\n\n// Simulates the placement of rectangles given a set of operations and current dimension estimates.\n// Returns the predicted bounding box (W, H) and the detailed info of placed rectangles.\nstd::pair<std::pair<long long, long long>, std::vector<PlacedRectInfo>>\nsimulate_placement(const std::vector<Operation>& ops,\n                   const std::vector<double>& est_w,\n                   const std::vector<double>& est_h) {\n    \n    std::vector<PlacedRectInfo> placed_rect_infos;\n    std::map<int, PlacedRectInfo> p_idx_to_info; // Map from original rectangle index to its PlacedRectInfo\n\n    long long max_X = 0;\n    long long max_Y = 0;\n\n    for (const auto& op : ops) {\n        // Get estimated dimensions and apply rotation\n        long long current_w = static_cast<long long>(est_w[op.p]);\n        long long current_h = static_cast<long long>(est_h[op.p]);\n        \n        if (op.r == 1) { // Rotate 90 degrees\n            std::swap(current_w, current_h);\n        }\n\n        // Clamp dimensions to problem constraints [1, 10^9]\n        current_w = std::max(1LL, std::min(1000000000LL, current_w));\n        current_h = std::max(1LL, std::min(1000000000LL, current_h));\n\n        long long new_x = 0;\n        long long new_y = 0;\n\n        if (op.d == 'U') {\n            // Determine the x-coordinate of the left edge\n            long long target_x_left = 0;\n            if (op.b != -1) {\n                // Ensure op.b is a valid index and present in p_idx_to_info\n                // op.b ranges from -1 to p-1, so if op.b >= 0, it must be in p_idx_to_info\n                if (p_idx_to_info.count(op.b)) { \n                    target_x_left = p_idx_to_info[op.b].x + p_idx_to_info[op.b].w;\n                }\n            }\n            new_x = target_x_left;\n\n            // Find the highest point (max y + h) that the new rectangle would sit on\n            long long y_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for horizontal overlap with placed_r\n                if (placed_r.x < new_x + current_w && placed_r.x + placed_r.w > new_x) {\n                    y_stop_level = std::max(y_stop_level, placed_r.y + placed_r.h);\n                }\n            }\n            new_y = y_stop_level;\n\n        } else { // op.d == 'L'\n            // Determine the y-coordinate of the top edge\n            long long target_y_top = 0;\n            if (op.b != -1) {\n                // Ensure op.b is a valid index and present in p_idx_to_info\n                if (p_idx_to_info.count(op.b)) {\n                    target_y_top = p_idx_to_info[op.b].y + p_idx_to_info[op.b].h;\n                }\n            }\n            new_y = target_y_top;\n\n            // Find the rightmost point (max x + w) that the new rectangle would push against\n            long long x_stop_level = 0;\n            for (const auto& entry : p_idx_to_info) {\n                const auto& placed_r = entry.second;\n                // Check for vertical overlap with placed_r\n                if (placed_r.y < new_y + current_h && placed_r.y + placed_r.h > new_y) {\n                    x_stop_level = std::max(x_stop_level, placed_r.x + placed_r.w);\n                }\n            }\n            new_x = x_stop_level;\n        }\n\n        // Store info for the newly placed rectangle\n        PlacedRectInfo info = {new_x, new_y, current_w, current_h, op.p, (op.r == 1)};\n        placed_rect_infos.push_back(info); // For tracking order of placement\n        p_idx_to_info[op.p] = info;      // For quick lookup by original index\n\n        // Update overall bounding box dimensions\n        max_X = std::max(max_X, new_x + current_w);\n        max_Y = std::max(max_Y, new_y + current_h);\n    }\n\n    return {{max_X, max_Y}, placed_rect_infos};\n}\n\n// Generates an initial random placement strategy\nstd::vector<Operation> generate_random_strategy(int N) {\n    std::vector<Operation> ops(N);\n    for (int i = 0; i < N; ++i) {\n        ops[i].p = i; // Always place rectangles in ascending order of their original indices\n        ops[i].r = random_int(0, 1);\n        ops[i].d = random_char('U', 'L');\n        ops[i].b = random_int(-1, i - 1); // Reference rectangle must be -1 or a previously placed index\n    }\n    return ops;\n}\n\n// Main solution function\nvoid solve() {\n    // Read initial N, T, sigma and rectangle measurements\n    std::cin >> N_GLOBAL >> T_TOTAL_GLOBAL >> SIGMA_GLOBAL;\n\n    W_PRIME_GLOBAL.resize(N_GLOBAL);\n    H_PRIME_GLOBAL.resize(N_GLOBAL);\n    current_estimated_w.resize(N_GLOBAL);\n    current_estimated_h.resize(N_GLOBAL);\n\n    for (int i = 0; i < N_GLOBAL; ++i) {\n        std::cin >> W_PRIME_GLOBAL[i] >> H_PRIME_GLOBAL[i];\n        current_estimated_w[i] = static_cast<double>(W_PRIME_GLOBAL[i]);\n        current_estimated_h[i] = static_cast<double>(H_PRIME_GLOBAL[i]);\n    }\n\n    // Initialize the best strategy found so far across all turns\n    std::vector<Operation> overall_best_ops = generate_random_strategy(N_GLOBAL);\n    auto initial_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n    long long overall_best_score_predicted = initial_sim_result.first.first + initial_sim_result.first.second;\n\n    // Time management for local search\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 2.9; // Allow some buffer for I/O and final calculations\n\n    // Simulated Annealing temperature parameters\n    // T_GLOBAL_START determines the initial temperature for SA in the first turn.\n    // Adjusted based on average estimated rectangle side lengths to be more robust.\n    double T_GLOBAL_START = 0;\n    for(int i=0; i<N_GLOBAL; ++i) T_GLOBAL_START += (current_estimated_w[i] + current_estimated_h[i]);\n    T_GLOBAL_START /= N_GLOBAL; // Average side length sum per rectangle\n    T_GLOBAL_START *= 10.0;     // Scale up for initial temperature, arbitrary tuning.\n    T_GLOBAL_START = std::max(T_GLOBAL_START, 100000.0); // Minimum temp to ensure it's not too small.\n\n    const double T_GLOBAL_END_RATIO = 0.01; // Global temp decays to T_GLOBAL_START * T_GLOBAL_END_RATIO over all turns.\n    const double T_INNER_END_RATIO = 0.001; // Inner temp decays to T_TURN_START * T_INNER_END_RATIO over local search iterations.\n    const int NUM_LOCAL_SEARCH_ATTEMPTS = 50; \n    \n    for (int turn = 0; turn < T_TOTAL_GLOBAL; ++turn) {\n        // Calculate the current global temperature for this turn.\n        double turn_progress = (double)turn / T_TOTAL_GLOBAL;\n        double T_turn_start = T_GLOBAL_START * std::pow(T_GLOBAL_END_RATIO, turn_progress);\n\n        // Keep track of the best solution found during this SA run for this turn\n        std::vector<Operation> current_ops_SA = overall_best_ops; // Start SA from the current overall best\n        long long current_score_SA = overall_best_score_predicted;\n        \n        std::vector<Operation> best_ops_in_SA = overall_best_ops;\n        long long best_score_in_SA = overall_best_score_predicted;\n\n        for (int iter = 0; iter < NUM_LOCAL_SEARCH_ATTEMPTS; ++iter) {\n            std::vector<Operation> candidate_ops = current_ops_SA; // Start from current SA state\n            int p_idx_to_change = random_int(0, N_GLOBAL - 1); // Pick a random rectangle to perturb\n\n            // Randomly choose one parameter to mutate\n            int mutate_type = random_int(0, 2); // 0: r (rotation), 1: d (direction), 2: b (reference)\n\n            if (mutate_type == 0) { // Mutate rotation\n                candidate_ops[p_idx_to_change].r = 1 - candidate_ops[p_idx_to_change].r;\n            } else if (mutate_type == 1) { // Mutate direction\n                candidate_ops[p_idx_to_change].d = (candidate_ops[p_idx_to_change].d == 'U' ? 'L' : 'U');\n            } else { // Mutate reference rectangle (b_i)\n                candidate_ops[p_idx_to_change].b = random_int(-1, p_idx_to_change - 1);\n            }\n\n            // Simulate the candidate strategy and evaluate its score\n            auto sim_result = simulate_placement(candidate_ops, current_estimated_w, current_estimated_h);\n            long long candidate_score = sim_result.first.first + sim_result.first.second;\n\n            // Simulated Annealing acceptance condition\n            double inner_iter_progress = (double)iter / NUM_LOCAL_SEARCH_ATTEMPTS;\n            double temp_for_this_iter = T_turn_start * std::pow(T_INNER_END_RATIO, inner_iter_progress);\n            \n            // Prevent division by zero if temp becomes extremely small, or other numerical issues\n            if (temp_for_this_iter < 1.0) temp_for_this_iter = 1.0; \n\n            if (candidate_score < current_score_SA) {\n                current_ops_SA = candidate_ops;\n                current_score_SA = candidate_score;\n                // If this is better than the overall best found in this SA run, update it\n                if (current_score_SA < best_score_in_SA) {\n                    best_ops_in_SA = current_ops_SA;\n                    best_score_in_SA = current_score_SA;\n                }\n            } else {\n                // Accept worse solutions with a probability\n                double acceptance_prob = std::exp(-(double)(candidate_score - current_score_SA) / temp_for_this_iter);\n                if (random_double_01() < acceptance_prob) {\n                    current_ops_SA = candidate_ops;\n                    current_score_SA = candidate_score;\n                }\n            }\n        } // End of NUM_LOCAL_SEARCH_ATTEMPTS loop (inner SA)\n\n        // After SA, update overall_best_ops if a better solution was found\n        // `best_score_in_SA` is used as `current_score_SA` might be a worse accepted state.\n        if (best_score_in_SA < overall_best_score_predicted) {\n            overall_best_ops = best_ops_in_SA;\n            overall_best_score_predicted = best_score_in_SA;\n        }\n\n        // Output the chosen (overall best) strategy for this turn\n        std::cout << N_GLOBAL << std::endl;\n        for (const auto& op : overall_best_ops) {\n            std::cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << std::endl;\n        }\n        std::cout << std::flush; // Crucial for interactive problems\n\n        // Read observed W' and H' from the judge\n        long long W_observed, H_observed;\n        std::cin >> W_observed >> H_observed;\n\n        // --- Update dimension estimates based on feedback ---\n        // Simulate overall_best_ops with current_estimated_w/h to get W_predicted, H_predicted\n        auto sim_result_for_update = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        long long W_predicted = sim_result_for_update.first.first;\n        long long H_predicted = sim_result_for_update.first.second;\n\n        // Calculate scaling ratios. Predicted W/H should not be zero since min_w/h is 1.\n        double W_ratio = static_cast<double>(W_observed) / W_predicted;\n        double H_ratio = static_cast<double>(H_observed) / H_predicted;\n\n        // Learning rate decreases over turns to stabilize estimates\n        double learn_rate = 0.05 / std::sqrt(turn + 1.0); \n        // Regularization rate to pull estimates back towards initial observations\n        double initial_reversion_rate = 0.01 / std::sqrt(turn + 1.0); \n\n        for (int i = 0; i < N_GLOBAL; ++i) {\n            // Adjust estimates based on observed vs. predicted global dimensions\n            current_estimated_w[i] = current_estimated_w[i] * (1.0 + learn_rate * (W_ratio - 1.0));\n            current_estimated_h[i] = current_estimated_h[i] * (1.0 + learn_rate * (H_ratio - 1.0));\n\n            // Regularize towards the initial noisy measurements w'_i, h'_i\n            current_estimated_w[i] = (1.0 - initial_reversion_rate) * current_estimated_w[i] + initial_reversion_rate * W_PRIME_GLOBAL[i];\n            current_estimated_h[i] = (1.0 - initial_reversion_rate) * current_estimated_h[i] + initial_reversion_rate * H_PRIME_GLOBAL[i];\n\n            // Clamp estimates within reasonable bounds (problem implies these max values)\n            current_estimated_w[i] = std::max(1.0, std::min(1000000000.0, current_estimated_w[i]));\n            current_estimated_h[i] = std::max(1.0, std::min(1000000000.0, current_estimated_h[i]));\n        }\n\n        // Re-calculate the overall best predicted score with the new estimates\n        // This is important because the estimation of dimensions has changed.\n        // It ensures `overall_best_score_predicted` is always based on current estimates\n        // and is ready for the next turn's SA.\n        overall_best_score_predicted = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.first + \n                                       simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h).first.second;\n\n        // Check if remaining time is too low to continue effectively\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT_SECONDS) {\n            // std::cerr << \"# Time out at turn \" << turn << std::endl; // Comment for visualizer\n            break; \n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for speed\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Seed the random number generator\n    rng.seed(std::chrono::system_clock::now().time_since_epoch().count());\n\n    // Call the solver function\n    solve();\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <queue>\n#include <chrono>\n#include <random>\n#include <cmath> // For std::exp\n\n// Global random number generator\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Structure to hold graph and problem data\nstruct ProblemData {\n    int N, M, H_limit;\n    std::vector<int> A;\n    std::vector<std::vector<int>> adj; // Adjacency list for the original graph\n    std::vector<long long> A_prefix_sum; // For biased node selection based on A_v\n};\n\n// Structure to hold a solution candidate (parent array, score, heights)\nstruct Solution {\n    std::vector<int> parent;\n    long long score;\n    std::vector<int> heights; // Heights for current parent configuration\n\n    Solution(int N_val) : parent(N_val, -1), score(0), heights(N_val, -1) {}\n};\n\n// Function to evaluate a given parent array and compute heights\n// Returns score, and populates heights_out. Returns -1 for invalid states.\n// Invalid states include cycles or height constraint violations.\nlong long eval_score(const ProblemData& pd, const std::vector<int>& p, std::vector<int>& heights_out) {\n    int N = pd.N;\n    int H_limit = pd.H_limit;\n    const std::vector<int>& A = pd.A;\n\n    std::vector<std::vector<int>> children_lists(N);\n    std::vector<char> is_root(N, 1); // Using char for boolean (1 for true, 0 for false)\n                                     // to avoid std::vector<bool> specialization issues.\n\n    for (int v = 0; v < N; ++v) {\n        if (p[v] != -1) {\n            // Basic validity check for parent index\n            if (p[v] < 0 || p[v] >= N || p[v] == v) { \n                return -1; // Invalid parent reference (e.g., self-loop or out of bounds)\n            }\n            children_lists[p[v]].push_back(v);\n            is_root[v] = 0; // Node v is not a root\n        }\n    }\n\n    std::fill(heights_out.begin(), heights_out.end(), -1); // Initialize heights to -1 (unvisited)\n    long long current_total_score = 0;\n    \n    std::queue<int> q; // Queue for BFS\n\n    // Iterate through all nodes to find roots and process trees\n    for (int r = 0; r < N; ++r) {\n        // If 'r' is a root and has not been visited yet (i.e., not part of another tree)\n        if (is_root[r] == 1 && heights_out[r] == -1) { \n            q.push(r);\n            heights_out[r] = 0; // Root has height 0\n            current_total_score += (1LL * (heights_out[r] + 1) * A[r]);\n\n            while (!q.empty()) {\n                int u = q.front();\n                q.pop();\n\n                if (heights_out[u] > H_limit) { // Height constraint violation\n                    return -1; \n                }\n\n                for (int v_child : children_lists[u]) {\n                    if (heights_out[v_child] == -1) { // If v_child has not yet been visited in this tree\n                        heights_out[v_child] = heights_out[u] + 1;\n                        if (heights_out[v_child] > H_limit) { // Height constraint violation for v_child\n                            return -1;\n                        }\n                        current_total_score += (1LL * (heights_out[v_child] + 1) * A[v_child]);\n                        q.push(v_child);\n                    } else {\n                        // Cycle or structural inconsistency detected (e.g., v_child visited in same tree via different path)\n                        return -1; \n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure all nodes have been assigned a height (i.e., are part of some tree).\n    for(int v = 0; v < N; ++v){\n        if(heights_out[v] == -1){\n            return -1; // Indicates a disjoint node/subgraph not correctly rooted or parented\n        }\n    }\n\n    return current_total_score;\n}\n\n// Function to check for cycles efficiently during a proposed parent change.\n// Returns true if new_p is an ancestor of v (which means setting parent[v] = new_p forms a cycle).\nbool forms_cycle(int v, int new_p, const std::vector<int>& current_p, const ProblemData& pd) {\n    if (new_p == -1) return false; // Making v a root never forms a cycle with v itself.\n\n    // Traverse up from new_p using current parent pointers.\n    // A limit of H_limit + 2 is a safe upper bound for this traversal.\n    int curr = new_p;\n    for(int i = 0; i < pd.H_limit + 2 && curr != -1; ++i) { \n        if (curr == v) {\n            return true; // Found v, so v is an ancestor of new_p, forms a cycle.\n        }\n        curr = current_p[curr];\n    }\n    return false; // No cycle detected within the relevant path length.\n}\n\nvoid solve() {\n    ProblemData pd;\n    std::cin >> pd.N >> pd.M >> pd.H_limit;\n    pd.A.resize(pd.N);\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.A[i];\n    \n    // Precompute A_prefix_sum for biased node selection\n    pd.A_prefix_sum.resize(pd.N);\n    pd.A_prefix_sum[0] = pd.A[0];\n    for(int i = 1; i < pd.N; ++i) {\n        pd.A_prefix_sum[i] = pd.A_prefix_sum[i-1] + pd.A[i];\n    }\n\n    pd.adj.resize(pd.N);\n    for (int i = 0; i < pd.M; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        pd.adj[u].push_back(v);\n        pd.adj[v].push_back(u);\n    }\n    // Coordinates and specific edge data are not used by the SA algorithm.\n    for (int i = 0; i < pd.N; ++i) {\n        int x, y; // Placeholder variables\n        std::cin >> x >> y;\n    }\n\n    // Initial solution: all nodes are roots.\n    Solution current_sol(pd.N);\n    current_sol.score = eval_score(pd, current_sol.parent, current_sol.heights);\n\n    Solution best_sol = current_sol;\n\n    // Simulated Annealing parameters\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Slightly less than 2 seconds to be safe\n    \n    double start_temp = 500.0;           \n    double end_temp = 1.0;               \n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> node_dist_uniform(0, pd.N - 1); \n\n    const double PROB_BIAS_A = 0.5; // 50% chance to pick node based on A_v value\n\n    // Main Simulated Annealing loop\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration<double, std::milli>(current_time - start_time).count();\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            break; \n        }\n\n        double progress = elapsed_ms / TIME_LIMIT_MS;\n        double temp = start_temp * (1.0 - progress) + end_temp * progress; \n\n        // Choose a random vertex 'v' to try changing its parent, with bias\n        int v;\n        if (dist_0_1(rng) < PROB_BIAS_A) {\n            // Biased selection: pick node proportional to its A_v value\n            long long total_A_sum = pd.A_prefix_sum[pd.N - 1];\n            // total_A_sum will be at least N (1000) since A_v >= 1.\n            std::uniform_int_distribution<long long> dist_sum_A(0, total_A_sum - 1);\n            long long target_sum = dist_sum_A(rng);\n            // Use upper_bound to find the index v such that A_prefix_sum[v-1] <= target_sum < A_prefix_sum[v]\n            v = std::upper_bound(pd.A_prefix_sum.begin(), pd.A_prefix_sum.end(), target_sum) - pd.A_prefix_sum.begin();\n        } else {\n            // Uniform selection: pick any node with equal probability\n            v = node_dist_uniform(rng); \n        }\n\n        int original_p_v = current_sol.parent[v];\n        \n        std::vector<int> candidate_parents;\n        candidate_parents.push_back(-1); // Option to make v a root\n        for (int neighbor : pd.adj[v]) {\n            if (neighbor != v) { \n                candidate_parents.push_back(neighbor);\n            }\n        }\n        \n        if (candidate_parents.empty()) { \n            current_sol.parent[v] = original_p_v; \n            continue;\n        }\n\n        std::uniform_int_distribution<int> parent_dist(0, candidate_parents.size() - 1);\n        int new_p = candidate_parents[parent_dist(rng)];\n        \n        current_sol.parent[v] = new_p;\n\n        if (forms_cycle(v, new_p, current_sol.parent, pd)) {\n             current_sol.parent[v] = original_p_v; \n             continue;\n        }\n        \n        Solution next_sol = current_sol; // Create a temporary copy for evaluation\n        long long new_score = eval_score(pd, next_sol.parent, next_sol.heights);\n\n        if (new_score != -1) { // If the new state is valid\n            next_sol.score = new_score; \n\n            if (next_sol.score > best_sol.score) {\n                best_sol = next_sol; \n            }\n\n            if (next_sol.score > current_sol.score || \n                dist_0_1(rng) < std::exp((double)(next_sol.score - current_sol.score) / temp)) {\n                \n                current_sol = next_sol; // Accept the move\n            } else {\n                current_sol.parent[v] = original_p_v; // Revert\n            }\n        } else {\n            current_sol.parent[v] = original_p_v; // Revert\n        }\n    }\n\n    for (int i = 0; i < pd.N; ++i) {\n        std::cout << best_sol.parent[i] << (i == pd.N - 1 ? \"\" : \" \");\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}\n","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <limits>  // For std::numeric_limits\n\n// Structure to store an operation\nstruct Operation {\n    char direction;\n    int index;\n\n    Operation(char d, int i) : direction(d), index(i) {}\n};\n\n// Structure to encapsulate the best choice found in an iteration\nstruct BestChoice {\n    double cost_per_oni; // Primary metric: moves / num_oni_removed (minimize)\n    int num_oni_removed; // Secondary metric: maximize\n    int moves_count;     // Tertiary metric: minimize\n    std::pair<int, int> target_oni_pos; // The specific Oni this action was calculated for\n    char direction;\n    int index;\n\n    // Default constructor for initialization to \"worst possible\" values\n    BestChoice() : cost_per_oni(std::numeric_limits<double>::max()),\n                   num_oni_removed(0), // Maximize this, so start low\n                   moves_count(std::numeric_limits<int>::max()),\n                   target_oni_pos({-1, -1}), direction(' '), index(-1) {}\n\n    // Method to check if 'this' choice is strictly better than 'other'\n    bool is_strictly_better_than(const BestChoice& other) const {\n        // 1. Compare cost_per_oni (less is better)\n        if (cost_per_oni < other.cost_per_oni) return true;\n        if (cost_per_oni > other.cost_per_oni) return false;\n\n        // 2. cost_per_oni is equal, compare num_oni_removed (more is better)\n        if (num_oni_removed > other.num_oni_removed) return true;\n        if (num_oni_removed < other.num_oni_removed) return false;\n\n        // 3. num_oni_removed is equal, compare moves_count (less is better)\n        if (moves_count < other.moves_count) return true;\n\n        return false; // Not strictly better\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N;\n    std::cin >> N;\n\n    // Store initial Fukunokami positions for constant lookup, as they never move\n    std::set<std::pair<int, int>> fuku_positions_set;\n    // Store current Oni positions. This set will be modified as Oni are removed.\n    std::set<std::pair<int, int>> current_oni_positions_set;\n\n    for (int i = 0; i < N; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                current_oni_positions_set.insert({i, j});\n            } else if (row_str[j] == 'o') {\n                fuku_positions_set.insert({i, j});\n            }\n        }\n    }\n\n    std::vector<Operation> operations;\n\n    // Continue as long as there are Oni on the board\n    while (!current_oni_positions_set.empty()) {\n        BestChoice best_overall_choice;\n\n        // Iterate through all currently present Oni to find the best action.\n        // The iteration order of std::set provides a stable tie-breaking for target_oni_pos\n        for (const auto& oni_pos : current_oni_positions_set) {\n            int r = oni_pos.first;\n            int c = oni_pos.second;\n\n            // --- Check Upward path ---\n            bool up_clear = true;\n            int oni_in_up_path_count = 0;\n            // Iterate from row 0 up to and including 'r' in column 'c'\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    up_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_up_path_count++;\n                }\n            }\n\n            if (up_clear) {\n                int moves = 2 * (r + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_up_path_count;\n                // 'num_oni_removed' is guaranteed to be at least 1 (the target Oni itself)\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_up_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'U';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Downward path ---\n            bool down_clear = true;\n            int oni_in_down_path_count = 0;\n            // Iterate from row 'r' down to and including 'N-1' in column 'c'\n            for (int k_row = r; k_row < N; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    down_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_down_path_count++;\n                }\n            }\n\n            if (down_clear) {\n                int moves = 2 * (N - r);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_down_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_down_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'D';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Leftward path ---\n            bool left_clear = true;\n            int oni_in_left_path_count = 0;\n            // Iterate from column 0 up to and including 'c' in row 'r'\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    left_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_left_path_count++;\n                }\n            }\n\n            if (left_clear) {\n                int moves = 2 * (c + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_left_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_left_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'L';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Rightward path ---\n            bool right_clear = true;\n            int oni_in_right_path_count = 0;\n            // Iterate from column 'c' down to and including 'N-1' in row 'r'\n            for (int k_col = c; k_col < N; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    right_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_right_path_count++;\n                }\n            }\n\n            if (right_clear) {\n                int moves = 2 * (N - c);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_right_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_right_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'R';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n        } // End loop over current_oni_positions_set\n\n        // Apply the best found operations and update the set of Oni\n        int r = best_overall_choice.target_oni_pos.first;\n        int c = best_overall_choice.target_oni_pos.second;\n        char chosen_direction = best_overall_choice.direction;\n        int chosen_index = best_overall_choice.index;\n\n        // The problem guarantee ensures that a valid choice is always found.\n        // If it weren't, chosen_index would be -1, indicating an error or no more Oni.\n        // For robustness, could add: if (chosen_index == -1) break;\n\n        if (chosen_direction == 'U') {\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('U', chosen_index);\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('D', chosen_index);\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'D') {\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('D', chosen_index);\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('U', chosen_index);\n            for (int k_row = r; k_row < N; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'L') {\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('L', chosen_index);\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('R', chosen_index);\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        } else if (chosen_direction == 'R') {\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('R', chosen_index);\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('L', chosen_index);\n            for (int k_col = c; k_col < N; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        }\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        std::cout << op.direction << \" \" << op.index << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric> // For std::accumulate\n#include <cmath>   // For std::abs, std::pow, std::exp\n#include <random>  // For std::mt19937, std::uniform_int_distribution, std::uniform_real_distribution\n#include <chrono>  // For high_resolution_clock\n#include <map>     // For cycle detection\n#include <algorithm> // For std::min (though not strictly used, good practice)\n\n// Use a global random number generator for convenience and efficiency\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Function to calculate the error for a given assignment\n// N: Number of employees\n// L: Total number of weeks\n// T: Target cleaning counts for each employee\n// assignments: Vector of pairs (a_i, b_i) for each employee i\nlong long calculate_error(\n    int N, int L, \n    const std::vector<int>& T, \n    const std::vector<std::pair<int, int>>& assignments\n) {\n    std::vector<long long> actual_final_counts(N, 0); // Stores the final cleaning counts for each employee\n\n    int current_cleaner = 0; // The employee who cleans in the current week (starts with employee 0)\n    // counts_in_sim tracks cleaning counts *during this specific simulation run* for cycle detection\n    std::vector<int> counts_in_sim(N, 0); \n    \n    // For cycle detection:\n    // path_cleaners stores the sequence of employees who cleaned, week by week (0-indexed)\n    std::vector<int> path_cleaners; \n    // visited_states_map maps (cleaner_id, count_parity) -> week_idx (the first week_idx this state was observed)\n    std::map<std::pair<int, int>, int> visited_states_map; \n\n    for (int week_idx = 0; week_idx < L; ++week_idx) {\n        int cleaner_for_this_week = current_cleaner;\n        counts_in_sim[cleaner_for_this_week]++; // Increment count for the current cleaner\n        path_cleaners.push_back(cleaner_for_this_week); // Record this week's cleaner\n\n        // A state is defined by (employee who just finished cleaning, their total cleaning count parity)\n        std::pair<int, int> state_after_cleaning = {cleaner_for_this_week, counts_in_sim[cleaner_for_this_week] % 2};\n\n        // Check if this state has been visited before, indicating a cycle\n        if (visited_states_map.count(state_after_cleaning)) {\n            int cycle_start_idx = visited_states_map[state_after_cleaning]; // Index where the cycle began\n            int cycle_length = week_idx - cycle_start_idx + 1;             // Length of the detected cycle\n\n            // Step 1: Accumulate counts for the pre-cycle part (weeks 0 to cycle_start_idx-1)\n            for (int i = 0; i < cycle_start_idx; ++i) {\n                actual_final_counts[path_cleaners[i]]++;\n            }\n\n            // Step 2: Calculate cleaning counts within one full cycle period\n            std::vector<long long> cycle_counts_one_period(N, 0);\n            for (int i = cycle_start_idx; i <= week_idx; ++i) {\n                cycle_counts_one_period[path_cleaners[i]]++;\n            }\n\n            // Step 3: Distribute remaining weeks using the cycle counts\n            // Total weeks that need to be covered by the cycle from cycle_start_idx until L\n            long long remaining_weeks_to_fill_from_cycle_start = L - cycle_start_idx;\n            \n            if (cycle_length > 0) { // Safety check to prevent division by zero, though cycle_length should always be > 0\n                // Add full cycles\n                long long num_full_cycles = remaining_weeks_to_fill_from_cycle_start / cycle_length;\n                for (int i = 0; i < N; ++i) {\n                    actual_final_counts[i] += num_full_cycles * cycle_counts_one_period[i];\n                }\n                // Add remaining part of a partial cycle at the very end\n                long long remaining_in_partial_cycle = remaining_weeks_to_fill_from_cycle_start % cycle_length;\n                for (int i = 0; i < remaining_in_partial_cycle; ++i) {\n                    actual_final_counts[path_cleaners[cycle_start_idx + i]]++;\n                }\n            }\n            \n            // All L weeks have been accounted for, so we can exit the simulation\n            goto end_simulation; \n        }\n        \n        // If no cycle detected yet, record the current state and its week index\n        visited_states_map[state_after_cleaning] = week_idx;\n\n        // Determine the next cleaner based on current cleaner's count parity and assignments\n        if (counts_in_sim[cleaner_for_this_week] % 2 != 0) { // If total count is odd\n            current_cleaner = assignments[cleaner_for_this_week].first;\n        } else { // If total count is even\n            current_cleaner = assignments[cleaner_for_this_week].second;\n        }\n    }\n\n    // This block is reached if the loop completes without finding a cycle.\n    // This happens if L is small enough that no state repeats, or if L happens to be exactly the pre-cycle length.\n    // In this case, 'path_cleaners' contains the cleaners for all L weeks, and their counts\n    // haven't been added to 'actual_final_counts' yet.\n    for (int i = 0; i < L; ++i) {\n        actual_final_counts[path_cleaners[i]]++;\n    }\n\nend_simulation:; // Label for goto\n\n    // Calculate the total absolute error\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += std::abs(actual_final_counts[i] - T[i]);\n    }\n    return error;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_val, L_val; // Use different variable names to avoid potential shadowing\n    std::cin >> N_val >> L_val;\n\n    std::vector<int> T(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        std::cin >> T[i];\n    }\n\n    std::vector<std::pair<int, int>> best_assignments(N_val);\n    std::vector<std::pair<int, int>> current_assignments(N_val);\n\n    // Initial random assignments for a_i and b_i\n    std::uniform_int_distribution<int> dist_N(0, N_val - 1); // For picking employee IDs [0, N-1]\n    for (int i = 0; i < N_val; ++i) {\n        current_assignments[i] = {dist_N(rng), dist_N(rng)};\n    }\n\n    // Calculate initial state error\n    long long current_error = calculate_error(N_val, L_val, T, current_assignments);\n    long long best_error = current_error;\n    best_assignments = current_assignments; // Deep copy the initial best state\n\n    // Simulated Annealing parameters\n    double start_temp = 2000.0; // Initial temperature (can be tuned)\n    double end_temp = 0.01;     // Final temperature (can be tuned)\n    int iteration_limit = 1000000; // Maximum number of SA iterations (will be capped by time)\n    \n    auto start_time = std::chrono::high_resolution_clock::now();\n    long long time_limit_ms = 1900; // Allot 1.9 seconds for computation, leave 0.1s buffer\n\n    for (int iter = 0; iter < iteration_limit; ++iter) {\n        // Check elapsed time to ensure compliance with the time limit\n        auto current_time = std::chrono::high_resolution_clock::now();\n        long long elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break; // Exit SA loop if time limit approached\n        }\n\n        // Geometric cooling schedule for temperature\n        double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / iteration_limit);\n        \n        // Generate a neighbor state by modifying one a_i or b_i\n        int employee_to_change = dist_N(rng); // Randomly pick an employee\n        bool change_first_val = (rng() % 2 == 0); // Randomly decide to change a_i (true) or b_i (false)\n        \n        // Store the original value to allow reverting if the move is not accepted\n        int original_val_to_revert;\n        if (change_first_val) {\n            original_val_to_revert = current_assignments[employee_to_change].first;\n            current_assignments[employee_to_change].first = dist_N(rng); // Propose a new random value\n        } else {\n            original_val_to_revert = current_assignments[employee_to_change].second;\n            current_assignments[employee_to_change].second = dist_N(rng); // Propose a new random value\n        }\n\n        // Calculate the error for the new (modified) assignments\n        long long next_error = calculate_error(N_val, L_val, T, current_assignments);\n\n        if (next_error < current_error) {\n            // If the new solution is better, always accept it\n            current_error = next_error;\n            if (next_error < best_error) {\n                // If it's the best solution found so far, update best_assignments\n                best_error = next_error;\n                best_assignments = current_assignments; // Deep copy\n            }\n        } else {\n            // If the new solution is worse, accept it with a certain probability\n            double probability = std::exp(-(static_cast<double>(next_error - current_error)) / temp);\n            std::uniform_real_distribution<double> dist_real(0.0, 1.0); // For generating a random probability\n            if (dist_real(rng) < probability) {\n                current_error = next_error; // Accept the worse solution\n            } else {\n                // If the worse solution is not accepted, revert the change\n                if (change_first_val) {\n                    current_assignments[employee_to_change].first = original_val_to_revert;\n                } else {\n                    current_assignments[employee_to_change].second = original_val_to_revert;\n                }\n            }\n        }\n    }\n\n    // Output the best assignments found after the SA process\n    for (int i = 0; i < N_val; ++i) {\n        std::cout << best_assignments[i].first << \" \" << best_assignments[i].second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::sqrt, std::floor, std::ceil, std::max\n\n// Structure to hold city bounding box\nstruct Rect {\n    int lx, rx, ly, ry;\n};\n\n// Structure to hold city data\nstruct City {\n    int id;\n    int cx, cy; // Center coordinates, using integer division for consistency with sample\n    unsigned int z_order_val; // Z-order curve value for sorting\n    Rect bounds;\n};\n\n// Disjoint Set Union structure for Kruskal's algorithm\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) return i;\n        return parent[i] = find(parent[i]);\n    }\n    bool 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            return true;\n        }\n        return false;\n    }\n};\n\n// Edge structure for Kruskal's\nstruct Edge {\n    int u, v;\n    std::pair<int, long long> weight; // rank (0=queried, 1=estimated), estimated_dist_sq\n};\n\n// Helper for Z-order curve: bit interleaving (Morton code)\n// Optimized for 16-bit inputs (max value 65535) resulting in 32-bit output.\n// Coordinates up to 10000 fit into 14 bits.\n// For example, an input of 10000 will have its 14 bits interleaved into a 32-bit output.\nunsigned int morton_encode(unsigned int x, unsigned int y) {\n    x = (x | (x << 8)) & 0x00FF00FF;\n    x = (x | (x << 4)) & 0x0F0F0F0F;\n    x = (x | (x << 2)) & 0x33333333;\n    x = (x | (x << 1)) & 0x55555555;\n    y = (y | (y << 8)) & 0x00FF00FF;\n    y = (y | (y << 4)) & 0x0F0F0F0F;\n    y = (y | (y << 2)) & 0x33333333;\n    y = (y | (y << 1)) & 0x55555555;\n    return x | (y << 1);\n}\n\n// Functions to calculate min/max squared distance components along one axis\nlong long calc_min_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff;\n    if (r1_max < r2_min) { // Rect 1 is entirely before Rect 2 on this axis\n        diff = r2_min - r1_max;\n    } else if (r2_max < r1_min) { // Rect 2 is entirely before Rect 1 on this axis\n        diff = r1_min - r2_max;\n    } else { // Rectangles overlap on this axis\n        diff = 0;\n    }\n    return diff * diff;\n}\n\nlong long calc_max_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff1 = (long long)r1_max - r2_min;\n    long long diff2 = (long long)r2_max - r1_min;\n    return std::max(diff1 * diff1, diff2 * diff2);\n}\n\n// Function to calculate estimated squared distance using min/max bounds range midpoint\nlong long estimated_dist_mid_range_sq(int u_id, int v_id, const std::vector<City>& cities_data) {\n    const Rect& r_u = cities_data[u_id].bounds;\n    const Rect& r_v = cities_data[v_id].bounds;\n\n    long long min_dx_sq = calc_min_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long min_dy_sq = calc_min_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_min_sq = min_dx_sq + min_dy_sq;\n\n    long long max_dx_sq = calc_max_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long max_dy_sq = calc_max_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_max_sq = max_dx_sq + max_dy_sq;\n\n    // Use the midpoint of the possible squared distance range\n    return (d_min_sq + d_max_sq) / 2;\n}\n\n\n// Function to make a query to the judge\nstd::vector<std::pair<int, int>> make_query(const std::vector<int>& c_subset) {\n    std::cout << \"? \" << c_subset.size();\n    for (int city_id : c_subset) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl; // Flush!\n\n    std::vector<std::pair<int, int>> result;\n    result.reserve(c_subset.size() - 1);\n    for (size_t i = 0; i < c_subset.size() - 1; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        if (u > v) std::swap(u, v); // Ensure canonical form (u < v)\n        result.push_back({u, v});\n    }\n    return result;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL); // Untie cin and cout for faster I/O, though flushing is still needed for queries\n\n    int N, M, Q, L_actual, W;\n    std::cin >> N >> M >> Q >> L_actual >> 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_data(N);\n    for (int i = 0; i < N; ++i) {\n        cities_data[i].id = i;\n        std::cin >> cities_data[i].bounds.lx >> cities_data[i].bounds.rx >> cities_data[i].bounds.ly >> cities_data[i].bounds.ry;\n        \n        // Use center for Z-order calculation as well\n        cities_data[i].cx = (cities_data[i].bounds.lx + cities_data[i].bounds.rx) / 2;\n        cities_data[i].cy = (cities_data[i].bounds.ly + cities_data[i].bounds.ry) / 2;\n        cities_data[i].z_order_val = morton_encode(cities_data[i].cx, cities_data[i].cy);\n    }\n\n    // 1. Initial Grouping: Sort by Z-order curve value\n    std::vector<int> p(N); // p stores sorted city IDs\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return cities_data[i].z_order_val < cities_data[j].z_order_val;\n    });\n\n    std::vector<std::vector<int>> tentative_groups(M);\n    int current_city_idx_p = 0;\n    for (int k = 0; k < M; ++k) {\n        tentative_groups[k].reserve(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            tentative_groups[k].push_back(p[current_city_idx_p++]);\n        }\n    }\n\n    // 2. Query Phase\n    std::set<std::pair<int, int>> queried_edges;\n    int Q_rem = Q;\n\n    // Phase 1: Query small groups entirely\n    for (int k = 0; k < M; ++k) {\n        if (G[k] >= 2 && G[k] <= L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k]; // Use const ref\n            std::vector<std::pair<int, int>> res_edges = make_query(current_group);\n            for (auto edge : res_edges) {\n                queried_edges.insert(edge);\n            }\n            Q_rem--;\n        }\n    }\n\n    // Phase 2: Query large groups with adaptive step_size\n    long long num_chunks_to_query_if_step1 = 0; // Total count of (G_k - L_actual + 1) for large groups\n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual) { // This condition ensures G[k] >= L_actual + 1, so G[k] - L_actual >= 1\n            num_chunks_to_query_if_step1 += (G[k] - L_actual + 1);\n        }\n    }\n\n    int step_size = 1;\n    if (Q_rem > 0 && num_chunks_to_query_if_step1 > 0) {\n        // Calculate step_size to distribute Q_rem queries among the total chunks\n        step_size = static_cast<int>(std::ceil(static_cast<double>(num_chunks_to_query_if_step1) / Q_rem));\n        step_size = std::max(1, step_size); // Ensure step_size is at least 1\n    } else {\n        step_size = N + 1; // Effectively skip this phase if no queries left or no large groups to query\n    }\n    \n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k];\n            int last_queried_start = -1; // To track the starting index of the last query made\n            \n            for (int i = 0; i <= (int)current_group.size() - L_actual; i += step_size) {\n                if (Q_rem <= 0) break;\n                \n                std::vector<int> c_subset;\n                c_subset.reserve(L_actual);\n                for (int j = 0; j < L_actual; ++j) {\n                    c_subset.push_back(current_group[i+j]);\n                }\n                \n                std::vector<std::pair<int, int>> res_edges = make_query(c_subset);\n                for (auto edge : res_edges) {\n                    queried_edges.insert(edge);\n                }\n                Q_rem--;\n                last_queried_start = i;\n            }\n\n            // Handle cities at the end of the group that might not have been fully covered\n            // Query the last L_actual cities if the last possible window was not queried\n            // and we still have queries left.\n            if (Q_rem > 0) { // Check Q_rem again\n                int ideal_last_start_idx = (int)current_group.size() - L_actual;\n                if (ideal_last_start_idx >= 0 && last_queried_start != ideal_last_start_idx) { // Ensure ideal_last_start_idx is valid\n                    std::vector<int> c_subset_end;\n                    c_subset_end.reserve(L_actual);\n                    for(int j = ideal_last_start_idx; j < current_group.size(); ++j) {\n                        c_subset_end.push_back(current_group[j]);\n                    }\n                    if (c_subset_end.size() >= 2) { // Ensure minimum size for query\n                        std::vector<std::pair<int, int>> res_edges = make_query(c_subset_end);\n                        for (auto edge : res_edges) {\n                            queried_edges.insert(edge);\n                        }\n                        Q_rem--;\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Output Phase\n    std::cout << \"!\" << std::endl;\n\n    for (int k = 0; k < M; ++k) {\n        // Output cities in group k\n        for (int i = 0; i < G[k]; ++i) {\n            std::cout << tentative_groups[k][i] << (i == G[k] - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] == 1) { // A single city group needs no roads\n            continue;\n        }\n\n        // Prepare edges for MST\n        std::vector<Edge> edges_for_mst;\n        const std::vector<int>& current_group = tentative_groups[k];\n        \n        // Create all possible edges within the group\n        for (size_t i = 0; i < current_group.size(); ++i) {\n            for (size_t j = i + 1; j < current_group.size(); ++j) {\n                int u = current_group[i];\n                int v = current_group[j];\n                \n                // Ensure u < v for canonical form (matches queried_edges)\n                if (u > v) std::swap(u, v); \n                \n                int rank = 1; // 1 for estimated, 0 for queried\n                if (queried_edges.count({u, v})) {\n                    rank = 0;\n                }\n                \n                long long dist_sq = estimated_dist_mid_range_sq(u, v, cities_data); // Use new estimation\n                edges_for_mst.push_back({u, v, {rank, dist_sq}});\n            }\n        }\n\n        // Sort edges\n        std::sort(edges_for_mst.begin(), edges_for_mst.end(), [](const Edge& a, const Edge& b) {\n            if (a.weight.first != b.weight.first) {\n                return a.weight.first < b.weight.first;\n            }\n            // Tie-break with estimated squared distance\n            if (a.weight.second != b.weight.second) {\n                return a.weight.second < b.weight.second;\n            }\n            // Final tie-break with lexicographical order of cities\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Run Kruskal's\n        DSU dsu(N); // Initialize DSU for all N cities for simplicity\n        std::vector<std::pair<int, int>> mst_output_edges;\n        int edges_count = 0;\n        for (const auto& edge : edges_for_mst) {\n            if (edges_count == G[k] - 1) break; // Found enough edges\n            \n            if (dsu.unite(edge.u, edge.v)) {\n                mst_output_edges.push_back({edge.u, edge.v});\n                edges_count++;\n            }\n        }\n\n        // Output MST edges (lexicographically within group, as required by problem)\n        std::sort(mst_output_edges.begin(), mst_output_edges.end());\n        for (const auto& edge : mst_output_edges) {\n            std::cout << edge.first << \" \" << edge.second << std::endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int N_SIZE = 20;\n\n// Directions for movement and alter actions\n// Corresponding to U, D, L, R\nint DR[] = {-1, 1, 0, 0}; \nint DC[] = {0, 0, -1, 1}; \nchar DIR_CHARS[] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int r, c;\n    int cost;\n\n    // Custom comparator for priority queue (min-heap)\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Enum to categorize the type of action that led to a state\nenum ActionType {\n    MOVE,\n    MOVE_REMOVE_BLOCK,    // Move into a square that was blocked, removing the block first\n    SLIDE_WALL,           // Slide, stopping because of an N x N boundary wall\n    SLIDE_EXISTING_BLOCK  // Slide, stopping because of an existing block\n};\n\n// Information to reconstruct the path\nstruct ParentInfo {\n    int pr, pc; // previous row, previous column\n    ActionType type;\n    char dir_char; // direction character for the action (U, D, L, R)\n    int br, bc;   // block row, block column (relevant for SLIDE_EXISTING_BLOCK or MOVE_REMOVE_BLOCK)\n                  // For SLIDE_WALL, it's (-1,-1).\n};\n\n// Global board state, tracks currently existing blocks\nset<pair<int, int>> current_blocks;\n\n// Helper function to check if coordinates are within grid bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_SIZE && c >= 0 && c < N_SIZE;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M; // N will be 20, M will be 40 as per problem statement\n    cin >> N >> M;\n\n    vector<pair<int, int>> targets(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> targets[k].first >> targets[k].second;\n    }\n\n    vector<pair<char, char>> all_actions; // Stores the final sequence of actions to output\n\n    int current_r = targets[0].first;\n    int current_c = targets[0].second;\n\n    // Iterate through each target segment (from current_pos to next target)\n    for (int k = 0; k < M - 1; ++k) {\n        int start_r = current_r;\n        int start_c = current_c;\n        int target_r = targets[k+1].first;\n        int target_c = targets[k+1].second;\n\n        // Dijkstra's algorithm for shortest path in terms of turns\n        vector<vector<int>> dist(N, vector<int>(N, INF));\n        vector<vector<ParentInfo>> parent(N, vector<ParentInfo>(N)); \n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[start_r][start_c] = 0;\n        pq.push({start_r, start_c, 0});\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n            int d = current.cost;\n\n            // If we found a shorter path previously, skip this one\n            if (d > dist[r][c]) {\n                continue;\n            }\n            // If we reached the target, we found the shortest path for this segment\n            if (r == target_r && c == target_c) {\n                break; \n            }\n\n            // --- Explore possible Move actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                if (!is_valid(nr, nc)) continue; // Check bounds\n\n                int cost = 0;\n                ActionType type;\n                if (current_blocks.count({nr, nc})) {\n                    // Moving onto a square that currently has a block.\n                    // This costs 1 for Alter (to remove the block) + 1 for Move. Total 2 turns.\n                    cost = 2;\n                    type = MOVE_REMOVE_BLOCK;\n                } else {\n                    // Moving onto an empty square. Costs 1 for Move.\n                    cost = 1;\n                    type = MOVE;\n                }\n\n                if (d + cost < dist[nr][nc]) {\n                    dist[nr][nc] = d + cost;\n                    parent[nr][nc] = {r, c, type, dir_char, nr, nc}; // br, bc store coord of block removed for MOVE_REMOVE_BLOCK\n                    pq.push({nr, nc, d + cost});\n                }\n            }\n\n            // --- Explore possible Slide actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int dr = DR[i];\n                int dc = DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                int current_slide_r = r;\n                int current_slide_c = c;\n                \n                // This loop finds all possible valid stopping points for a slide in a given direction.\n                while (true) {\n                    // Tentatively advance one step to find the next square the slide *could* reach.\n                    int next_r = current_slide_r + dr;\n                    int next_c = current_slide_c + dc;\n\n                    // If the next square is out of bounds or blocked by an existing block,\n                    // we cannot slide *into* it. Thus, current_slide_r,c is a potential stopping point.\n                    if (!is_valid(next_r, next_c) || current_blocks.count({next_r, next_c})) {\n                        // We can only stop at current_slide_r,c if we've actually moved.\n                        // If current_slide_r,c is still (r,c), it means we can't even slide one square.\n                        if (current_slide_r == r && current_slide_c == c) {\n                             break; // Cannot slide even one square, no valid stops in this direction.\n                        }\n\n                        // current_slide_r,c is a valid stopping square.\n                        int stop_r = current_slide_r;\n                        int stop_c = current_slide_c;\n                        \n                        // The \"stopper\" is either the boundary or the existing block at (next_r, next_c)\n                        int stopper_block_r = next_r;\n                        int stopper_block_c = next_c;\n\n                        int slide_cost = 1; // All valid slides cost 1 turn\n                        ActionType type;\n\n                        if (!is_valid(stopper_block_r, stopper_block_c)) {\n                            type = SLIDE_WALL;\n                            stopper_block_r = -1; stopper_block_c = -1; // Sentinel\n                        } else { // It must be an existing block at (stopper_block_r, stopper_block_c)\n                            type = SLIDE_EXISTING_BLOCK;\n                        }\n\n                        if (d + slide_cost < dist[stop_r][stop_c]) {\n                            dist[stop_r][stop_c] = d + slide_cost;\n                            parent[stop_r][stop_c] = {r, c, type, dir_char, stopper_block_r, stopper_block_c};\n                            pq.push({stop_r, stop_c, d + slide_cost});\n                        }\n                        break; // This slide path ends here, either at boundary or existing block\n                    }\n\n                    // If next_r,c is valid and not blocked, we slide past current_slide_r,c.\n                    // So, current_slide_r,c itself cannot be a stopping point (because nothing stops us there).\n                    // Update current_slide_r,c to next_r,c and continue to find further stops.\n                    current_slide_r = next_r;\n                    current_slide_c = next_c;\n                }\n            }\n        }\n\n        // --- Path reconstruction and action recording ---\n        vector<tuple<int,int,ActionType,char,int,int>> path_segments_info;\n        int curr_r = target_r;\n        int curr_c = target_c;\n\n        // Traverse parent pointers backwards from target to start, storing segment info.\n        // This gives actions in reverse order of execution.\n        while (curr_r != start_r || curr_c != start_c) {\n            ParentInfo p = parent[curr_r][curr_c];\n            path_segments_info.emplace_back(p.pr, p.pc, p.type, p.dir_char, p.br, p.bc);\n            curr_r = p.pr;\n            curr_c = p.pc;\n        }\n        // Reverse to get actions in the correct execution order.\n        reverse(path_segments_info.begin(), path_segments_info.end()); \n\n        // Process each action segment in forward order and update global blocks and the action list\n        for (const auto& info : path_segments_info) {\n            int pr, pc, br, bc;\n            ActionType type;\n            char dir_char;\n            tie(pr, pc, type, dir_char, br, bc) = info;\n\n            if (type == MOVE) {\n                all_actions.emplace_back('M', dir_char);\n            } else if (type == MOVE_REMOVE_BLOCK) {\n                all_actions.emplace_back('A', dir_char); // First Alter to remove block at (br,bc)\n                current_blocks.erase({br, bc});           // Update global block state (remove it)\n                all_actions.emplace_back('M', dir_char); // Then Move\n            } else if (type == SLIDE_WALL || type == SLIDE_EXISTING_BLOCK) {\n                // No Alter action needed for these slide types, just the Slide itself.\n                // The block for SLIDE_EXISTING_BLOCK is already there and isn't toggled by us.\n                all_actions.emplace_back('S', dir_char);\n            }\n        }\n\n        // Update current player position for the next segment\n        current_r = target_r;\n        current_c = target_c;\n    }\n    \n    // Output all recorded actions\n    for (const auto& action : all_actions) {\n        cout << action.first << \" \" << action.second << endl;\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // for std::iota\n\n// Global random number generator (seeded once in main)\n// Used to seed per-run RNGs for multi-start.\nstd::mt19937_64 global_mt_rand(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Company data structure\nstruct Company {\n    int id;\n    int x, y, r; // desired location (cell x,y) and desired area\n};\n\n// Rectangle structure\nstruct Rect {\n    int x1, y1, x2, y2; // [x1, x2) x [y1, y2)\n    long long area() const {\n        return (long long)(x2 - x1) * (y2 - y1);\n    }\n    // Check if point (px, py) is contained (for 0.5 offset points, this means cell (px, py) is contained)\n    bool contains(int px, int py) const {\n        return x1 <= px && px < x2 && y1 <= py && py < y2;\n    }\n};\n\n// Node in the D&C tree\nstruct Node {\n    Rect rect; // The bounding box for this node\n    bool is_leaf;\n    int company_id; // Valid if is_leaf is true, stores original company index\n    bool is_vertical_cut; // True for vertical, false for horizontal\n    int cut_coord; // The coordinate of the cut\n    std::vector<int> company_indices; // Indices of companies that fall into this node's rectangle\n    int parent_idx; // Index to parent node\n    int left_child_idx; // Index to left/bottom child\n    int right_child_idx; // Index to right/top child\n\n    // Added fields for SA optimization: min/max coordinates of companies in children subtrees\n    int left_comp_min_x, left_comp_max_x;\n    int left_comp_min_y, left_comp_max_y;\n    int right_comp_min_x, right_comp_max_x;\n    int right_comp_min_y, right_comp_max_y;\n\n    Node(Rect r, bool leaf, int id, const std::vector<int>& indices)\n        : rect(r), is_leaf(leaf), company_id(id), is_vertical_cut(false), cut_coord(-1),\n          company_indices(indices), parent_idx(-1), left_child_idx(-1), right_child_idx(-1),\n          left_comp_min_x(10001), left_comp_max_x(-1), left_comp_min_y(10001), left_comp_max_y(-1),\n          right_comp_min_x(10001), right_comp_max_x(-1), right_comp_min_y(10001), right_comp_max_y(-1) {}\n};\n\nstd::vector<Company> companies_data_global; // Store company data globally\nint N_global; // Store N globally\n\n// These vectors will be local to a single run. They are declared globally to avoid reallocations\n// on the stack for large N, but conceptually managed per-run.\nstd::vector<Rect> current_final_ad_rects;\nstd::vector<Node> current_tree_nodes;\nstd::vector<int> current_internal_node_indices;\n\n// Calculate satisfaction for a single company\ndouble calculate_satisfaction(const Company& company, const Rect& ad_rect) {\n    if (!ad_rect.contains(company.x, company.y)) {\n        return 0.0;\n    }\n    long long s_i = ad_rect.area();\n    long long r_i = company.r;\n    if (s_i == 0) return 0.0; // Area must be positive as per problem statement\n    double ratio = (double)std::min(r_i, s_i) / std::max(r_i, s_i);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Helper function to collect company IDs in a subtree\nvoid get_companies_in_subtree(int node_idx, std::vector<int>& company_ids_in_subtree) {\n    const Node& node = current_tree_nodes[node_idx];\n    if (node.is_leaf) {\n        if (node.company_id != -1) {\n            company_ids_in_subtree.push_back(node.company_id);\n        }\n        return;\n    }\n    get_companies_in_subtree(node.left_child_idx, company_ids_in_subtree);\n    get_companies_in_subtree(node.right_child_idx, company_ids_in_subtree);\n}\n\n// Recursive function to build the D&C tree and determine initial rectangle placements\nvoid build_tree_and_solve(int node_idx, int x1, int y1, int x2, int y2, std::vector<int>&& indices, std::mt19937_64& rng) {\n    current_tree_nodes[node_idx].rect = {x1, y1, x2, y2};\n    current_tree_nodes[node_idx].company_indices = indices; // Store indices for SA bounds calculation later\n\n    if (indices.empty()) {\n        current_tree_nodes[node_idx].is_leaf = true; // Mark as leaf, no company\n        return;\n    }\n    if (indices.size() == 1) {\n        current_tree_nodes[node_idx].is_leaf = true;\n        current_tree_nodes[node_idx].company_id = indices[0];\n        current_final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n    \n    // This is an internal node\n    current_internal_node_indices.push_back(node_idx);\n\n    int best_v_cut_coord = -1;\n    long long min_v_area_diff = -1;\n    int best_v_split_point_idx = -1;\n\n    int best_h_cut_coord = -1;\n    long long min_h_area_diff = -1;\n    int best_h_split_point_idx = -1;\n\n    long long total_r_sum = 0;\n    for (int idx : indices) total_r_sum += companies_data_global[idx].r;\n\n    // Try Vertical Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data_global[i].x < companies_data_global[j].x;\n    });\n    long long current_left_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_left_r_sum += companies_data_global[indices[k]].r;\n        int max_x_left_group = companies_data_global[indices[k]].x;\n        int min_x_right_group = companies_data_global[indices[k+1]].x;\n        \n        // The cut coordinate `C` must satisfy: max_x_left_group < C <= min_x_right_group\n        // And also `x1 < C < x2`\n        int candidate_cut_coord = max_x_left_group + 1;\n        \n        if (candidate_cut_coord > min_x_right_group || candidate_cut_coord < x1 + 1 || candidate_cut_coord > x2 - 1) {\n             continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_left_r_sum - (total_r_sum - current_left_r_sum));\n        if (best_v_cut_coord == -1 || diff < min_v_area_diff) {\n            min_v_area_diff = diff;\n            best_v_cut_coord = candidate_cut_coord;\n            best_v_split_point_idx = k + 1;\n        }\n    }\n\n    // Try Horizontal Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data_global[i].y < companies_data_global[j].y;\n    });\n    long long current_bottom_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_bottom_r_sum += companies_data_global[indices[k]].r;\n        int max_y_bottom_group = companies_data_global[indices[k]].y;\n        int min_y_top_group = companies_data_global[indices[k+1]].y;\n        \n        int candidate_cut_coord = max_y_bottom_group + 1;\n\n        if (candidate_cut_coord > min_y_top_group || candidate_cut_coord < y1 + 1 || candidate_cut_coord > y2 - 1) {\n            continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_bottom_r_sum - (total_r_sum - current_bottom_r_sum));\n        if (best_h_cut_coord == -1 || diff < min_h_area_diff) {\n            min_h_area_diff = diff;\n            best_h_cut_coord = candidate_cut_coord;\n            best_h_split_point_idx = k + 1;\n        }\n    }\n    \n    // Choose the best cut among vertical and horizontal\n    int final_cut_coord = -1;\n    int final_split_point_idx = -1;\n    bool is_vertical_cut_chosen = false;\n\n    // Random choice if area differences are equal for v/h cuts\n    std::uniform_int_distribution<int> dist_01_int(0, 1);\n\n    if (best_v_cut_coord != -1 && best_h_cut_coord != -1) {\n        if (min_v_area_diff < min_h_area_diff) {\n            final_cut_coord = best_v_cut_coord;\n            final_split_point_idx = best_v_split_point_idx;\n            is_vertical_cut_chosen = true;\n        } else if (min_h_area_diff < min_v_area_diff) {\n            final_cut_coord = best_h_cut_coord;\n            final_split_point_idx = best_h_split_point_idx;\n            is_vertical_cut_chosen = false;\n        } else { // min_v_area_diff == min_h_area_diff: random choice\n            if (dist_01_int(rng) == 0) { // 50/50 chance\n                final_cut_coord = best_v_cut_coord;\n                final_split_point_idx = best_v_split_point_idx;\n                is_vertical_cut_chosen = true;\n            } else {\n                final_cut_coord = best_h_cut_coord;\n                final_split_point_idx = best_h_split_point_idx;\n                is_vertical_cut_chosen = false;\n            }\n        }\n    } else if (best_v_cut_coord != -1) {\n        final_cut_coord = best_v_cut_coord;\n        final_split_point_idx = best_v_split_point_idx;\n        is_vertical_cut_chosen = true;\n    } else if (best_h_cut_coord != -1) {\n        final_cut_coord = best_h_cut_coord;\n        final_split_point_idx = best_h_split_point_idx;\n        is_vertical_cut_chosen = false;\n    } else {\n        // Fallback: If no valid cut is found, assign the entire region to the first company.\n        // This should only happen for very small regions or degenerate point distributions\n        // where it's impossible to make a valid cut for multiple companies.\n        current_tree_nodes[node_idx].is_leaf = true; \n        current_tree_nodes[node_idx].company_id = indices[0];\n        current_final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    current_tree_nodes[node_idx].cut_coord = final_cut_coord;\n    current_tree_nodes[node_idx].is_vertical_cut = is_vertical_cut_chosen;\n\n    // Re-sort indices based on the chosen cut dimension for partitioning\n    if (is_vertical_cut_chosen) {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data_global[i].x < companies_data_global[j].x;\n        });\n    } else {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data_global[i].y < companies_data_global[j].y;\n        });\n    }\n\n    std::vector<int> left_indices(indices.begin(), indices.begin() + final_split_point_idx);\n    std::vector<int> right_indices(indices.begin() + final_split_point_idx, indices.end());\n\n    current_tree_nodes[node_idx].left_child_idx = current_tree_nodes.size();\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    current_tree_nodes.back().parent_idx = node_idx;\n\n    current_tree_nodes[node_idx].right_child_idx = current_tree_nodes.size();\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    current_tree_nodes.back().parent_idx = node_idx;\n\n    if (is_vertical_cut_chosen) {\n        build_tree_and_solve(current_tree_nodes[node_idx].left_child_idx, x1, y1, final_cut_coord, y2, std::move(left_indices), rng);\n        build_tree_and_solve(current_tree_nodes[node_idx].right_child_idx, final_cut_coord, y1, x2, y2, std::move(right_indices), rng);\n    } else { // Horizontal cut\n        build_tree_and_solve(current_tree_nodes[node_idx].left_child_idx, x1, y1, x2, final_cut_coord, std::move(left_indices), rng); // 'left' means bottom here\n        build_tree_and_solve(current_tree_nodes[node_idx].right_child_idx, x1, final_cut_coord, x2, y2, std::move(right_indices), rng); // 'right' means top here\n    }\n}\n\n// Function to calculate and store min/max company coordinates for children\nvoid calculate_child_company_bounds_recursive(int node_idx) {\n    Node& node = current_tree_nodes[node_idx];\n\n    if (node.is_leaf) {\n        return;\n    }\n\n    // Recursively call for children first (post-order traversal)\n    calculate_child_company_bounds_recursive(node.left_child_idx);\n    calculate_child_company_bounds_recursive(node.right_child_idx);\n\n    // Calculate bounds for left child's companies\n    int current_min_x_left = 10001, current_max_x_left = -1;\n    int current_min_y_left = 10001, current_max_y_left = -1;\n    Node& left_child_node = current_tree_nodes[node.left_child_idx];\n    if (left_child_node.is_leaf && left_child_node.company_id != -1) { // It's a leaf and contains a company\n        current_min_x_left = companies_data_global[left_child_node.company_id].x;\n        current_max_x_left = companies_data_global[left_child_node.company_id].x;\n        current_min_y_left = companies_data_global[left_child_node.company_id].y;\n        current_max_y_left = companies_data_global[left_child_node.company_id].y;\n    } else if (!left_child_node.company_indices.empty()){ // It's an internal node or a leaf that split an empty region\n        for (int company_idx : left_child_node.company_indices) {\n            current_min_x_left = std::min(current_min_x_left, companies_data_global[company_idx].x);\n            current_max_x_left = std::max(current_max_x_left, companies_data_global[company_idx].x);\n            current_min_y_left = std::min(current_min_y_left, companies_data_global[company_idx].y);\n            current_max_y_left = std::max(current_max_y_left, companies_data_global[company_idx].y);\n        }\n    }\n    node.left_comp_min_x = current_min_x_left;\n    node.left_comp_max_x = current_max_x_left;\n    node.left_comp_min_y = current_min_y_left;\n    node.left_comp_max_y = current_max_y_left;\n\n    // Calculate bounds for right child's companies\n    int current_min_x_right = 10001, current_max_x_right = -1;\n    int current_min_y_right = 10001, current_max_y_right = -1;\n    Node& right_child_node = current_tree_nodes[node.right_child_idx];\n    if (right_child_node.is_leaf && right_child_node.company_id != -1) {\n        current_min_x_right = companies_data_global[right_child_node.company_id].x;\n        current_max_x_right = companies_data_global[right_child_node.company_id].x;\n        current_min_y_right = companies_data_global[right_child_node.company_id].y;\n        current_max_y_right = companies_data_global[right_child_node.company_id].y;\n    } else if (!right_child_node.company_indices.empty()){\n        for (int company_idx : right_child_node.company_indices) {\n            current_min_x_right = std::min(current_min_x_right, companies_data_global[company_idx].x);\n            current_max_x_right = std::max(current_max_x_right, companies_data_global[company_idx].x);\n            current_min_y_right = std::min(current_min_y_right, companies_data_global[company_idx].y);\n            current_max_y_right = std::max(current_max_y_right, companies_data_global[company_idx].y);\n        }\n    }\n    node.right_comp_min_x = current_min_x_right;\n    node.right_comp_max_x = current_max_x_right;\n    node.right_comp_min_y = current_min_y_right;\n    node.right_comp_max_y = current_max_y_right;\n}\n\n// Function to update rectangles in a subtree after a cut coordinate changes\nvoid update_subtree_rects(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = current_tree_nodes[node_idx];\n    node.rect = {x1, y1, x2, y2};\n\n    if (node.is_leaf) {\n        if (node.company_id != -1) { \n            current_final_ad_rects[node.company_id] = {x1, y1, x2, y2};\n        }\n        return;\n    }\n\n    if (node.is_vertical_cut) {\n        update_subtree_rects(node.left_child_idx, x1, y1, node.cut_coord, y2);\n        update_subtree_rects(node.right_child_idx, node.cut_coord, y1, x2, y2);\n    } else { // Horizontal cut\n        update_subtree_rects(node.left_child_idx, x1, y1, x2, node.cut_coord);\n        update_subtree_rects(node.right_child_idx, x1, node.cut_coord, x2, y2);\n    }\n}\n\nvoid simulated_annealing(double time_limit_ms_per_run, std::mt19937_64& rng) {\n    auto start_time = std::chrono::steady_clock::now();\n    \n    // Calculate initial score once here\n    double current_score = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        current_score += calculate_satisfaction(companies_data_global[i], current_final_ad_rects[i]);\n    }\n\n    double best_score = current_score;\n    std::vector<Rect> best_ad_rects_for_this_run = current_final_ad_rects;\n\n    // SA parameters (tuned values)\n    double T_start = 0.02; // Adjusted (lower) based on analysis for shorter runs\n    double T_end = 1e-9;\n    \n    std::uniform_real_distribution<double> dist_01(0.0, 1.0);\n    \n    // Ensure internal_node_indices is not empty before creating distribution\n    if (current_internal_node_indices.empty()) {\n        return; \n    }\n    std::uniform_int_distribution<int> dist_internal_node_idx(0, current_internal_node_indices.size() - 1);\n\n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms >= time_limit_ms_per_run) {\n            break;\n        }\n\n        // Cooling schedule (exponential)\n        double T = T_start * std::pow(T_end / T_start, elapsed_ms / time_limit_ms_per_run);\n\n        // Pick a random internal node to modify its cut\n        int node_idx_to_modify = current_internal_node_indices[dist_internal_node_idx(rng)];\n        Node& node_to_modify = current_tree_nodes[node_idx_to_modify];\n        \n        // Parent's rect boundaries are stored in node_to_modify.rect\n        int parent_x1 = node_to_modify.rect.x1;\n        int parent_y1 = node_to_modify.rect.y1;\n        int parent_x2 = node_to_modify.rect.x2;\n        int parent_y2 = node_to_modify.rect.y2;\n        \n        int min_cut_coord_bound, max_cut_coord_bound;\n\n        if (node_to_modify.is_vertical_cut) {\n            // Use precomputed bounds\n            int max_x_in_left_subtree = node_to_modify.left_comp_max_x;\n            int min_x_in_right_subtree = node_to_modify.right_comp_min_x;\n            \n            min_cut_coord_bound = std::max(parent_x1 + 1, max_x_in_left_subtree + 1);\n            max_cut_coord_bound = std::min(parent_x2 - 1, min_x_in_right_subtree);\n\n        } else { // Horizontal cut\n            // Use precomputed bounds\n            int max_y_in_bottom_subtree = node_to_modify.left_comp_max_y; // Left child refers to bottom here\n            int min_y_in_top_subtree = node_to_modify.right_comp_min_y;   // Right child refers to top here\n            \n            min_cut_coord_bound = std::max(parent_y1 + 1, max_y_in_bottom_subtree + 1);\n            max_cut_coord_bound = std::min(parent_y2 - 1, min_y_in_top_subtree);\n        }\n\n        if (min_cut_coord_bound > max_cut_coord_bound) {\n            continue; // Cannot move this cut, its position is fixed by point constraints\n        }\n\n        // Store old cut_coord for backtracking\n        int original_cut_coord = node_to_modify.cut_coord;\n        \n        // Generate new cut_coord randomly within valid range\n        std::uniform_int_distribution<int> dist_cut(min_cut_coord_bound, max_cut_coord_bound);\n        node_to_modify.cut_coord = dist_cut(rng);\n        \n        if (original_cut_coord == node_to_modify.cut_coord) { // If random pick same as old, no change\n            continue;\n        }\n\n        // --- Incremental Score Update ---\n        std::vector<int> affected_company_ids;\n        get_companies_in_subtree(node_idx_to_modify, affected_company_ids);\n        \n        double old_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            old_affected_score_sum += calculate_satisfaction(companies_data_global[comp_id], current_final_ad_rects[comp_id]);\n        }\n        \n        // Update rectangles for the subtree\n        update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        \n        double new_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            new_affected_score_sum += calculate_satisfaction(companies_data_global[comp_id], current_final_ad_rects[comp_id]);\n        }\n\n        double new_total_score = current_score - old_affected_score_sum + new_affected_score_sum;\n\n        if (new_total_score > current_score || dist_01(rng) < std::exp((new_total_score - current_score) / T)) {\n            // Accept new state\n            current_score = new_total_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ad_rects_for_this_run = current_final_ad_rects;\n            }\n        } else {\n            // Revert to old state\n            node_to_modify.cut_coord = original_cut_coord;\n            // Revert the rectangles in the subtree to their previous state\n            update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n            // current_score remains unchanged\n        }\n    }\n    \n    current_final_ad_rects = best_ad_rects_for_this_run; // Save the best rectangles found in this run\n}\n\n// Function to perform a single D&C + SA run\n// Returns the best score found in this run\ndouble solve_single_run(double time_limit_ms_per_run, std::mt19937_64& rng) {\n    // Clear and resize global/shared state for this run\n    current_final_ad_rects.assign(N_global, Rect{}); // Reset all rects\n    current_tree_nodes.clear();\n    current_tree_nodes.reserve(2 * N_global); // Reserve memory to prevent frequent reallocations\n    current_internal_node_indices.clear();\n    \n    // Initial D&C\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{}); // Root node\n    std::vector<int> initial_company_indices(N_global);\n    std::iota(initial_company_indices.begin(), initial_company_indices.end(), 0);\n    \n    build_tree_and_solve(0, 0, 0, 10000, 10000, std::move(initial_company_indices), rng);\n    \n    // Precompute min/max company coordinates for children of each internal node\n    // Only if the root is not a leaf (i.e., N_global > 1)\n    if (!current_tree_nodes[0].is_leaf) { \n        calculate_child_company_bounds_recursive(0);\n    }\n    \n    // Simulated Annealing\n    simulated_annealing(time_limit_ms_per_run, rng);\n\n    // Calculate the final score for the best solution found in this run\n    double final_score = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        final_score += calculate_satisfaction(companies_data_global[i], current_final_ad_rects[i]);\n    }\n    return final_score;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N_global;\n\n    companies_data_global.resize(N_global);\n    for (int i = 0; i < N_global; ++i) {\n        companies_data_global[i].id = i;\n        std::cin >> companies_data_global[i].x >> companies_data_global[i].y >> companies_data_global[i].r;\n    }\n\n    double total_time_limit_ms = 4950.0; // Slightly less than 5 seconds\n    int num_runs = 10; // Increased number of independent SA runs\n    double time_per_run_ms = total_time_limit_ms / num_runs;\n\n    double overall_best_score = -1.0;\n    std::vector<Rect> overall_best_ad_rects(N_global);\n\n    for (int run = 0; run < num_runs; ++run) {\n        // Create a new RNG for each run, seeded from the global_mt_rand.\n        // This ensures different random walks for each run.\n        std::mt19937_64 run_rng(global_mt_rand()); \n        \n        // Call the single run solver\n        double current_run_score = solve_single_run(time_per_run_ms, run_rng);\n        \n        if (current_run_score > overall_best_score) {\n            overall_best_score = current_run_score;\n            overall_best_ad_rects = current_final_ad_rects; // Copy the best rects from this run\n        }\n    }\n    \n    // Output the overall best results\n    for (int i = 0; i < N_global; ++i) {\n        std::cout << overall_best_ad_rects[i].x1 << \" \" << overall_best_ad_rects[i].y1 << \" \"\n                  << overall_best_ad_rects[i].x2 << \" \" << overall_best_ad_rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <bitset>\n#include <random>\n#include <numeric>\n\n// Using standard namespace for convenience in competitive programming\nusing namespace std;\n\n// Constants\nconst int GRID_SIZE = 50;\nconst int MAX_TILES = GRID_SIZE * GRID_SIZE; // Max possible number of tiles (all 1x1)\n\n// Global variables to store input data\nint si, sj; // Start row, start column\nint tile_id_grid[GRID_SIZE][GRID_SIZE]; // tile_id_grid[i][j] stores the tile ID for square (i,j)\nint p_grid[GRID_SIZE][GRID_SIZE];       // p_grid[i][j] stores the score value for square (i,j)\n\n// Global variables for best path found so far\nlong long max_score_global = 0;\nstring best_path_string_global = \"\";\n\n// Random number generator. Using std::mt19937 for better randomness than rand().\nmt19937 rng;\n\n// Structure to represent a potential move\nstruct Move {\n    int r, c;           // Next square's row and column\n    char move_char;     // Character representing the move ('U', 'D', 'L', 'R')\n    int score_value;    // Score obtained by moving to (r, c)\n    int tile_id;        // Tile ID of the next square\n    long long total_priority; // Heuristic value for move selection (now just immediate score)\n};\n\n// Function to get all valid next moves from the current position (r, c)\n// A move is valid if it stays within grid boundaries and leads to an unvisited tile.\nvector<Move> get_valid_moves(int r, int c, const bitset<MAX_TILES>& visited_tiles) { // Corrected: added 'int' before 'c'\n    vector<Move> valid_moves;\n    // Possible movements: Up, Down, Left, Right\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1}; \n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + dr[k];\n        int nc = c + dc[k]; // 'c' is now correctly declared as an 'int' parameter.\n\n        // Check if the next position is within grid boundaries\n        if (nr >= 0 && nr < GRID_SIZE && nc >= 0 && nc < GRID_SIZE) {\n            int next_tile_id = tile_id_grid[nr][nc];\n            // Check if the tile has not been visited yet\n            if (!visited_tiles[next_tile_id]) {\n                // Heuristic: The priority for a move is simply the score of the square it leads to.\n                // This is a pure greedy approach for immediate rewards.\n                valid_moves.push_back({nr, nc, move_chars[k], p_grid[nr][nc], next_tile_id, (long long)p_grid[nr][nc]});\n            }\n        }\n    }\n    return valid_moves;\n}\n\n// Function to generate a single path using a randomized greedy approach.\n// It stops when no more valid moves are available or the time limit for this path generation is near.\npair<long long, string> generate_path(chrono::high_resolution_clock::time_point global_start_time, chrono::milliseconds total_time_limit) {\n    long long current_score = p_grid[si][sj]; // Start with score of initial square\n    string current_path_str = \"\";\n    bitset<MAX_TILES> visited_tiles; // Keep track of visited tiles\n    visited_tiles[tile_id_grid[si][sj]] = true; // Mark initial tile as visited\n    int curr_r = si;\n    int curr_c = sj;\n\n    // Use a local random number generator for path generation, seeded by the global one.\n    // This ensures different paths are generated across calls to generate_path.\n    mt19937 local_rng(rng()); \n\n    // Continue extending the path until no more moves or global time limit is approached\n    while (true) {\n        // Periodically check remaining time to avoid exceeding total_time_limit\n        // Stop if less than 10ms remaining to finish current path and update best.\n        // This small buffer helps ensure the program terminates gracefully within the limit.\n        if (chrono::high_resolution_clock::now() - global_start_time >= total_time_limit - chrono::milliseconds(10)) {\n            break; \n        }\n\n        vector<Move> moves = get_valid_moves(curr_r, curr_c, visited_tiles);\n        if (moves.empty()) {\n            break; // No more valid moves from current position\n        }\n\n        // Sort valid moves by their `total_priority` (immediate score) in descending order.\n        // This prioritizes moves that give higher immediate scores.\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.total_priority > b.total_priority;\n        });\n\n        // Heuristic: consider a \"beam\" of top N moves, and pick one randomly.\n        // This balances greedy exploitation (picking good moves) with exploration (trying slightly worse but potentially beneficial moves).\n        // `effective_beam_width` is set to 5, meaning we consider the top 5 highest-scoring moves.\n        const int BEAM_WIDTH = 5;\n        int effective_beam_width = min((int)moves.size(), BEAM_WIDTH); \n        \n        // Randomly pick an index within the `effective_beam_width`.\n        // This introduces randomness while still preferring high-scoring moves from the top choices.\n        uniform_int_distribution<int> dist(0, effective_beam_width - 1);\n        int choice_idx = dist(local_rng);\n        \n        const Move& chosen_move = moves[choice_idx];\n\n        // Update current state based on the chosen move\n        curr_r = chosen_move.r;\n        curr_c = chosen_move.c;\n        current_score += chosen_move.score_value;\n        current_path_str += chosen_move.move_char;\n        visited_tiles[chosen_move.tile_id] = true;\n    }\n    return {current_score, current_path_str};\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed the random number generator using the current time.\n    // This provides a different sequence of random numbers for each execution,\n    // which is crucial for iterated randomized algorithms.\n    rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Read input: starting position (si, sj)\n    cin >> si >> sj;\n\n    // Read tile IDs for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> tile_id_grid[i][j];\n        }\n    }\n\n    // Read score values for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> p_grid[i][j];\n        }\n    }\n\n    // Initialize global best score with the score of the starting square.\n    // The path string is initially empty as no moves have been made yet (start square is implicitly visited).\n    max_score_global = p_grid[si][sj];\n    best_path_string_global = \"\"; \n\n    // Record the start time of the entire program execution\n    auto global_start_time = chrono::high_resolution_clock::now();\n    // Set a total time limit slightly less than 2 seconds (e.g., 1950 ms) to ensure output completes.\n    const auto TOTAL_TIME_LIMIT = chrono::milliseconds(1950); \n\n    // Iteratively generate paths and keep the best one found within the time limit.\n    while (chrono::high_resolution_clock::now() - global_start_time < TOTAL_TIME_LIMIT) {\n        // Call generate_path with the global start time and total time limit.\n        // The path generation function itself will manage its internal time checking.\n        pair<long long, string> result = generate_path(global_start_time, TOTAL_TIME_LIMIT);\n        \n        // If the newly generated path has a higher score, update the global best.\n        if (result.first > max_score_global) {\n            max_score_global = result.first;\n            best_path_string_global = result.second;\n        }\n    }\n\n    // Output the sequence of moves for the highest scoring path found.\n    cout << best_path_string_global << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <algorithm> // For std::reverse\n\n// Constants\nconst int GRID_SIZE = 30;\nconst int NUM_VERTICES = GRID_SIZE * GRID_SIZE;\nconst int NUM_QUERIES = 1000; // Total number of queries\n\n// Parameters for learning and exploration\nconst double INITIAL_EDGE_ESTIMATE = 5000.0; // Average of possible edge lengths\n\n// C_ALPHA (for learning rate): alpha = 1.0 / (usage_count + C_ALPHA)\n// Higher C_ALPHA -> slower learning, more stable estimates against noise.\n// Decreased from 20.0 to 15.0 for slightly faster individual edge learning.\nconst double C_ALPHA = 15.0;                 \n\n// INITIAL_EXPLORATION_BONUS: Initial bonus for less-used edges in Dijkstra's.\n// This bonus will decay over time.\nconst double INITIAL_EXPLORATION_BONUS = 200.0; \n\n// Smoothing parameter: applies a small pull towards row/column average.\n// Increased from 0.005 to 0.01 for a stronger smoothing effect.\nconst double SMOOTHING_BETA = 0.01; \n\n// Clamping ranges for estimated edge lengths and effective weights\nconst double MIN_CLAMP_ESTIMATE = 900.0;   // Based on problem constraints (min ~1000)\nconst double MAX_CLAMP_ESTIMATE = 9100.0;  // Based on problem constraints (max ~9000)\nconst double MIN_CLAMP_EFFECTIVE_WEIGHT = 1.0; // To prevent negative effective effective weights in Dijkstra\n\n// Edge structures\n// h_len[i][j] is edge between (i,j) and (i,j+1)\n// v_len[i][j] is edge between (i,j) and (i+1,j)\n// These arrays store estimated lengths and usage counts for each individual edge.\ndouble estimated_h_len[GRID_SIZE][GRID_SIZE - 1];\ndouble estimated_v_len[GRID_SIZE - 1][GRID_SIZE];\n\nlong long usage_h_count[GRID_SIZE][GRID_SIZE - 1];\nlong long usage_v_count[GRID_SIZE - 1][GRID_SIZE];\n\n// Node to index mapping for Dijkstra's\nint node_to_idx(int r, int c) {\n    return r * GRID_SIZE + c;\n}\n\n// Index to node mapping\nstd::pair<int, int> idx_to_node(int idx) {\n    return {idx / GRID_SIZE, idx % GRID_SIZE};\n}\n\n// Function to clamp a double value within a specified range\ndouble clamp(double val, double min_val, double max_val) {\n    if (val < min_val) return min_val;\n    if (val > max_val) return max_val;\n    return val;\n}\n\n// Dijkstra's algorithm to find the shortest path based on current estimates\n// Takes current_exploration_bonus_val to apply time-decaying exploration.\nstd::string find_path(int start_r, int start_c, int end_r, int end_c, double& path_estimated_len, double current_exploration_bonus_val) {\n    int start_idx = node_to_idx(start_r, start_c);\n    int end_idx = node_to_idx(end_r, end_c);\n\n    std::vector<double> dist(NUM_VERTICES, 1e18); // Stores cumulative effective weights\n    std::vector<int> prev_node(NUM_VERTICES, -1);\n    std::vector<char> prev_dir(NUM_VERTICES, ' ');\n\n    std::priority_queue<std::pair<double, int>, std::vector<std::pair<double, int>>, std::greater<std::pair<double, int>>> pq;\n\n    dist[start_idx] = 0;\n    pq.push({0, start_idx});\n\n    while (!pq.empty()) {\n        double d = pq.top().first;\n        int u_idx = pq.top().second;\n        pq.pop();\n\n        if (d > dist[u_idx]) continue;\n        if (u_idx == end_idx) break;\n\n        int ur = idx_to_node(u_idx).first;\n        int uc = idx_to_node(u_idx).second;\n\n        // Explore neighbors (Up, Down, Left, Right)\n        // U: (ur-1, uc) from (ur, uc)\n        if (ur > 0) {\n            int v_idx = node_to_idx(ur - 1, uc);\n            // Edge is v_len[ur-1][uc]\n            double current_estimate = estimated_v_len[ur - 1][uc];\n            long long current_usage = usage_v_count[ur - 1][uc];\n            // Apply exploration bonus for this edge\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE); // Clamp effective weight\n            \n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'U';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // D: (ur+1, uc) from (ur, uc)\n        if (ur < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur + 1, uc);\n            // Edge is v_len[ur][uc]\n            double current_estimate = estimated_v_len[ur][uc];\n            long long current_usage = usage_v_count[ur][uc];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'D';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // L: (ur, uc-1) from (ur, uc)\n        if (uc > 0) {\n            int v_idx = node_to_idx(ur, uc - 1);\n            // Edge is h_len[ur][uc-1]\n            double current_estimate = estimated_h_len[ur][uc - 1];\n            long long current_usage = usage_h_count[ur][uc - 1];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'L';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // R: (ur, uc+1) from (ur, uc)\n        if (uc < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur, uc + 1);\n            // Edge is h_len[ur][uc]\n            double current_estimate = estimated_h_len[ur][uc];\n            long long current_usage = usage_h_count[ur][uc];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'R';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    int curr_idx = end_idx;\n    double actual_path_len_sum = 0.0; // Sum of actual estimated edge lengths (without exploration bonus)\n\n    // Reconstruct path and calculate sum of actual estimated edge lengths\n    while (curr_idx != start_idx && curr_idx != -1) {\n        if (prev_node[curr_idx] == -1) {\n             path_estimated_len = 1e18; \n             return \"\"; // Path not found or error\n        }\n        path_str += prev_dir[curr_idx];\n        \n        int prev_idx = prev_node[curr_idx];\n        int pr = idx_to_node(prev_idx).first;\n        int pc = idx_to_node(prev_idx).second;\n\n        // Add the *actual estimated length* of the edge\n        if (prev_dir[curr_idx] == 'U') { // Means we moved from (pr,pc) to (pr-1,pc), so edge is v_len[pr-1][pc]\n            actual_path_len_sum += estimated_v_len[pr-1][pc];\n        } else if (prev_dir[curr_idx] == 'D') { // Means we moved from (pr,pc) to (pr+1,pc), so edge is v_len[pr][pc]\n            actual_path_len_sum += estimated_v_len[pr][pc];\n        } else if (prev_dir[curr_idx] == 'L') { // Means we moved from (pr,pc) to (pr,pc-1), so edge is h_len[pr][pc-1]\n            actual_path_len_sum += estimated_h_len[pr][pc-1];\n        } else { // prev_dir[curr_idx] == 'R' // Means we moved from (pr,pc) to (pr,pc+1), so edge is h_len[pr][pc]\n            actual_path_len_sum += estimated_h_len[pr][pc];\n        }\n        curr_idx = prev_node[curr_idx];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    \n    path_estimated_len = actual_path_len_sum; // This is the total estimated length of the path without exploration bonus\n    return path_str;\n}\n\nvoid solve() {\n    // Initialize estimated edge lengths and usage counts\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            estimated_h_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_h_count[i][j] = 1; // Initialize usage count to 1\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            estimated_v_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_v_count[i][j] = 1; // Initialize usage count to 1\n        }\n    }\n\n    // Main query loop\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        int si, sj, ti, tj;\n        std::cin >> si >> sj >> ti >> tj;\n\n        // Calculate the current exploration bonus, decaying linearly.\n        // The divisor (NUM_QUERIES * 2.0) ensures that at k=NUM_QUERIES-1 (i.e. query 999),\n        // the bonus is approx. 1/2 of INITIAL_EXPLORATION_BONUS.\n        double current_exploration_bonus_val = INITIAL_EXPLORATION_BONUS * (1.0 - static_cast<double>(k) / (NUM_QUERIES * 2.0)); \n        current_exploration_bonus_val = std::max(0.0, current_exploration_bonus_val); // Ensure non-negative\n\n        double current_path_estimated_len; \n        std::string path = find_path(si, sj, ti, tj, current_path_estimated_len, current_exploration_bonus_val);\n        \n        std::cout << path << std::endl;\n        std::cout.flush();\n\n        int observed_path_len_int;\n        std::cin >> observed_path_len_int;\n        double observed_path_len = static_cast<double>(observed_path_len_int);\n\n        // Update edge length estimates\n        // Ensure current_path_estimated_len is not too small to avoid division by zero or extreme scaling.\n        if (current_path_estimated_len < 1.0) current_path_estimated_len = 1.0; \n        double scaling_factor = observed_path_len / current_path_estimated_len;\n        \n        int curr_r = si;\n        int curr_c = sj;\n\n        for (char dir : path) {\n            double* edge_len_ptr;\n            long long* usage_count_ptr;\n            int r_idx, c_idx; // Indices for the specific edge in the respective array\n\n            // Determine which edge was used and its current stats using pre-move coordinates\n            if (dir == 'U') {\n                r_idx = curr_r - 1; // Edge (curr_r-1, curr_c) to (curr_r, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r--; // Move to the new node\n            } else if (dir == 'D') {\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r+1, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r++; // Move to the new node\n            } else if (dir == 'L') {\n                r_idx = curr_r; // Edge (curr_r, curr_c-1) to (curr_r, curr_c)\n                c_idx = curr_c - 1;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c--; // Move to the new node\n            } else { // dir == 'R'\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r, curr_c+1)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c++; // Move to the new node\n            }\n\n            // Apply weighted average update\n            double alpha = 1.0 / (static_cast<double>(*usage_count_ptr) + C_ALPHA);\n            double new_estimate_value = (*edge_len_ptr) * scaling_factor;\n            *edge_len_ptr = clamp((1.0 - alpha) * (*edge_len_ptr) + alpha * new_estimate_value, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            \n            // Increment usage count for the updated edge\n            (*usage_count_ptr)++;\n        }\n\n        // --- Neighborhood Smoothing ---\n        // This attempts to leverage the implicit structure (M=1 or M=2) by pulling estimates\n        // towards the average of their respective row/column.\n        \n        // Horizontal edges smoothing\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            double row_sum = 0.0;\n            // No need for row_count, it's always GRID_SIZE-1\n            for (int j = 0; j < GRID_SIZE - 1; ++j) {\n                row_sum += estimated_h_len[i][j];\n            }\n            double row_average = row_sum / (GRID_SIZE - 1);\n            for (int j = 0; j < GRID_SIZE - 1; ++j) {\n                estimated_h_len[i][j] = clamp((1.0 - SMOOTHING_BETA) * estimated_h_len[i][j] + SMOOTHING_BETA * row_average, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            }\n        }\n\n        // Vertical edges smoothing\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            double col_sum = 0.0;\n            // No need for col_count, it's always GRID_SIZE-1\n            for (int i = 0; i < GRID_SIZE - 1; ++i) {\n                col_sum += estimated_v_len[i][j];\n            }\n            double col_average = col_sum / (GRID_SIZE - 1);\n            for (int i = 0; i < GRID_SIZE - 1; ++i) {\n                estimated_v_len[i][j] = clamp((1.0 - SMOOTHING_BETA) * estimated_v_len[i][j] + SMOOTHING_BETA * col_average, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            }\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set> // Temporarily for unique s_idx/pm_idx collection, will replace with boolean arrays\n#include <tuple> \n\n// Global constants\nconst int N_MATRIX = 20; // N is fixed to 20\nint M;\nstd::vector<std::string> S; // Input strings\n\n// Character to integer mapping for internal use (A=0, ..., H=7, .=8)\nstd::map<char, int> char_to_int_map;\nstd::vector<char> int_to_char_map;\n\n// Simulated Annealing parameters\nlong long MAX_ITERATIONS = 100000000; \ndouble START_TEMP = 2.0;\ndouble END_TEMP = 1e-9;\n\n// Random number generator\nstd::mt19937 mt;\n\n// Time measurement\nstd::chrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 2.95; // seconds\n\n// --- State Variables for SA ---\nstd::vector<std::string> current_grid;\nint num_dots; \nint num_matched_strings; \n\nstd::vector<int> num_actual_matches_for_string; \n\nstd::vector<int> unmatched_string_indices;\nstd::vector<int> s_idx_to_unmatched_list_pos; \n\n// SNAPSHOTS for revert: These will be copied once per SA iteration to guarantee correctness\nstd::vector<std::string> prev_grid;\nint prev_num_dots;\nint prev_num_matched_strings;\nstd::vector<int> prev_num_actual_matches_for_string;\nstd::vector<int> prev_num_mismatches_for_potential_match;\nstd::vector<bool> prev_is_potential_match_active;\nstd::vector<int> prev_unmatched_string_indices_vec; // Renamed to avoid conflict\nstd::vector<int> prev_s_idx_to_unmatched_list_pos_vec; // Renamed to avoid conflict\n\n\n// --- Precomputed data structures for efficient updates ---\nstruct PotentialMatchInfoBase {\n    int s_idx;\n    int sr, sc; \n    int dir;    \n};\n\nstd::vector<PotentialMatchInfoBase> all_potential_match_info_bases; \nstd::vector<std::pair<int, int>> cell_covers[N_MATRIX][N_MATRIX];\nstd::vector<int> num_mismatches_for_potential_match_global; // Renamed for clarity in context of snapshots\nstd::vector<bool> is_potential_match_active_global; // Renamed for clarity\nstd::vector<std::vector<int>> potential_matches_for_string;\n\n// For tracking affected elements in current iteration (optimization over std::set)\nstd::vector<bool> s_idx_is_affected_this_iter;\nstd::vector<int> affected_s_idx_list_this_iter;\nstd::vector<bool> pm_idx_is_affected_this_iter;\nstd::vector<int> affected_pm_idx_list_this_iter;\n\n\nint mod(int i, int n) {\n    return (i % n + n) % n;\n}\n\nvoid init_char_maps() {\n    char_to_int_map['A'] = 0; char_to_int_map['B'] = 1; char_to_int_map['C'] = 2; char_to_int_map['D'] = 3;\n    char_to_int_map['E'] = 4; char_to_int_map['F'] = 5; char_to_int_map['G'] = 6; char_to_int_map['H'] = 7;\n    char_to_int_map['.'] = 8;\n\n    int_to_char_map.resize(9);\n    int_to_char_map[0] = 'A'; int_to_char_map[1] = 'B'; int_to_char_map[2] = 'C'; int_to_char_map[3] = 'D';\n    int_to_char_map[4] = 'E'; int_to_char_map[5] = 'F'; int_to_char_map[6] = 'G'; int_to_char_map[7] = 'H';\n    int_to_char_map[8] = '.';\n}\n\ndouble calculate_objective(int c, int d) {\n    if (c < M) {\n        return (double)c / M;\n    } else {\n        return 1.0 + (double)(2.0 * N_MATRIX * N_MATRIX) / (2.0 * N_MATRIX * N_MATRIX - d);\n    }\n}\n\nvoid precompute_potential_matches() {\n    potential_matches_for_string.resize(M);\n    std::map<std::tuple<int, int, int, int>, int> potential_match_key_to_idx; \n    int pm_counter = 0; \n\n    for (int s_idx = 0; s_idx < M; ++s_idx) {\n        for (int sr = 0; sr < N_MATRIX; ++sr) {\n            for (int sc = 0; sc < N_MATRIX; ++sc) {\n                std::tuple<int, int, int, int> pm_key_h = {s_idx, sr, sc, 0}; \n                if (potential_match_key_to_idx.find(pm_key_h) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_h] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 0});\n                }\n                int pm_idx_h = potential_match_key_to_idx[pm_key_h];\n                potential_matches_for_string[s_idx].push_back(pm_idx_h); \n\n                std::tuple<int, int, int, int> pm_key_v = {s_idx, sr, sc, 1}; \n                if (potential_match_key_to_idx.find(pm_key_v) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_v] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 1});\n                }\n                int pm_idx_v = potential_match_key_to_idx[pm_key_v];\n                potential_matches_for_string[s_idx].push_back(pm_idx_v); \n            }\n        }\n    }\n\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        int k = S[pm_info_base.s_idx].length();\n        for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n            cell_covers[r][c].push_back({pm_idx, p_in_s});\n        }\n    }\n\n    num_mismatches_for_potential_match_global.resize(pm_counter);\n    is_potential_match_active_global.resize(pm_counter, false);\n    \n    s_idx_is_affected_this_iter.resize(M, false);\n    pm_idx_is_affected_this_iter.resize(pm_counter, false);\n}\n\nvoid initialize_state() {\n    current_grid.assign(N_MATRIX, std::string(N_MATRIX, '.')); \n    \n    std::uniform_int_distribution<int> dist_char_AH(0, 7); \n    for (int r = 0; r < N_MATRIX; ++r) {\n        for (int c = 0; c < N_MATRIX; ++c) {\n            current_grid[r][c] = int_to_char_map[dist_char_AH(mt)];\n        }\n    }\n    num_dots = 0; \n\n    num_matched_strings = 0;\n    num_actual_matches_for_string.assign(M, 0);\n\n    unmatched_string_indices.reserve(M); \n    s_idx_to_unmatched_list_pos.assign(M, -1); \n    for (int i = 0; i < M; ++i) {\n        unmatched_string_indices.push_back(i);\n        s_idx_to_unmatched_list_pos[i] = i;\n    }\n\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        const std::string& s = S[pm_info_base.s_idx];\n        int k = s.length();\n        int mismatches = 0;\n\n        for (int p = 0; p < k; ++p) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n            \n            if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                mismatches++;\n            }\n        }\n        num_mismatches_for_potential_match_global[pm_idx] = mismatches;\n\n        if (mismatches == 0) { \n            is_potential_match_active_global[pm_idx] = true;\n            if (num_actual_matches_for_string[pm_info_base.s_idx] == 0) { \n                num_matched_strings++;\n                int s_idx = pm_info_base.s_idx;\n                int pos = s_idx_to_unmatched_list_pos[s_idx];\n                if (pos != -1) { \n                    int last_s_idx_in_list = unmatched_string_indices.back();\n                    unmatched_string_indices[pos] = last_s_idx_in_list;\n                    s_idx_to_unmatched_list_pos[last_s_idx_in_list] = pos;\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[s_idx] = -1;\n                }\n            }\n            num_actual_matches_for_string[pm_info_base.s_idx]++;\n        }\n    }\n\n    // Initialize snapshot vectors to correct sizes\n    prev_grid.resize(N_MATRIX);\n    prev_num_actual_matches_for_string.resize(M);\n    prev_num_mismatches_for_potential_match.resize(all_potential_match_info_bases.size());\n    prev_is_potential_match_active.resize(all_potential_match_info_bases.size());\n    prev_unmatched_string_indices_vec.reserve(M);\n    prev_s_idx_to_unmatched_list_pos_vec.resize(M);\n}\n\nvoid solve() {\n    start_time = std::chrono::high_resolution_clock::now();\n    \n    init_char_maps();\n    precompute_potential_matches();\n    initialize_state();\n\n    std::uniform_int_distribution<int> dist_rc(0, N_MATRIX - 1);\n    std::uniform_int_distribution<int> dist_char_all(0, int_to_char_map.size() - 1); \n    std::uniform_int_distribution<int> dist_char_AH(0, 7); \n    std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    double best_score = calculate_objective(num_matched_strings, num_dots);\n    std::vector<std::string> best_grid = current_grid;\n\n    double p_aggressive_targeted_fix_attempt = 0.7; \n    double p_single_cell_targeted_fix_attempt = 0.3; \n\n    struct CellChangeInfo {\n        int r, c;\n        char old_char;\n        char new_char;\n    };\n    std::vector<CellChangeInfo> current_perturbation_cells; \n\n    for (long long iter = 0; iter < MAX_ITERATIONS; ++iter) {\n        double current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            std::chrono::high_resolution_clock::now() - start_time).count() / 1e9;\n        if (current_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = START_TEMP * std::pow(END_TEMP / START_TEMP, (double)iter / MAX_ITERATIONS);\n\n        current_perturbation_cells.clear();\n        bool is_perturbation_generated = false;\n\n        // --- Perturbation Logic ---\n        if (num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_aggressive_targeted_fix_attempt) {\n            int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            std::vector<int> candidates_pm_idx_for_s_with_mismatches;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match_global[pm_idx] > 0) { \n                    candidates_pm_idx_for_s_with_mismatches.push_back(pm_idx);\n                }\n            }\n\n            if (!candidates_pm_idx_for_s_with_mismatches.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s_with_mismatches[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s_with_mismatches.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                bool changes_made = false;\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    char required_char = s_to_fix[p_in_s];\n                    if (current_grid[r_p][c_p] != required_char) {\n                        current_perturbation_cells.push_back({r_p, c_p, current_grid[r_p][c_p], required_char});\n                        changes_made = true;\n                    }\n                }\n                if (changes_made) is_perturbation_generated = true;\n            }\n        }\n\n        if (!is_perturbation_generated && num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_single_cell_targeted_fix_attempt) {\n             int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            std::vector<int> candidates_pm_idx_for_s_with_mismatches;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match_global[pm_idx] > 0) {\n                    candidates_pm_idx_for_s_with_mismatches.push_back(pm_idx);\n                }\n            }\n            if (!candidates_pm_idx_for_s_with_mismatches.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s_with_mismatches[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s_with_mismatches.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                std::vector<std::pair<int, int>> mismatched_cells_coords; \n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    if (current_grid[r_p][c_p] != s_to_fix[p_in_s] || current_grid[r_p][c_p] == '.') {\n                        mismatched_cells_coords.push_back({r_p, c_p});\n                    }\n                }\n\n                if (!mismatched_cells_coords.empty()) {\n                    auto target_cell = mismatched_cells_coords[std::uniform_int_distribution<int>(0, mismatched_cells_coords.size() - 1)(mt)];\n                    int r_changed_candidate = target_cell.first;\n                    int c_changed_candidate = target_cell.second;\n                    char old_char = current_grid[r_changed_candidate][c_changed_candidate];\n                    \n                    int p_in_s_for_target = (pm_info_base.dir == 0) ? \n                                             mod(c_changed_candidate - pm_info_base.sc, N_MATRIX) : \n                                             mod(r_changed_candidate - pm_info_base.sr, N_MATRIX);\n\n                    char new_char = s_to_fix[p_in_s_for_target];\n                    if (new_char != old_char) { \n                        current_perturbation_cells.push_back({r_changed_candidate, c_changed_candidate, old_char, new_char});\n                        is_perturbation_generated = true;\n                    }\n                }\n            }\n        }\n\n        if (!is_perturbation_generated) {\n            int r_changed_candidate = dist_rc(mt);\n            int c_changed_candidate = dist_rc(mt);\n            char old_char = current_grid[r_changed_candidate][c_changed_candidate];\n            char new_char;\n            \n            if (num_matched_strings == M) {\n                if (dist_prob(mt) < 0.8) { \n                    new_char = '.';\n                } else {\n                    new_char = int_to_char_map[dist_char_all(mt)]; \n                }\n            } else {\n                new_char = int_to_char_map[dist_char_AH(mt)]; \n            }\n            if (new_char == old_char) continue; \n            current_perturbation_cells.push_back({r_changed_candidate, c_changed_candidate, old_char, new_char});\n            is_perturbation_generated = true;\n        }\n\n        if (!is_perturbation_generated || current_perturbation_cells.empty()) continue; \n\n\n        // --- TAKE FULL STATE SNAPSHOT ---\n        prev_grid = current_grid; // O(N^2)\n        prev_num_dots = num_dots;\n        prev_num_matched_strings = num_matched_strings;\n        prev_num_actual_matches_for_string = num_actual_matches_for_string; // O(M)\n        prev_num_mismatches_for_potential_match = num_mismatches_for_potential_match_global; // O(MAX_PM)\n        prev_is_potential_match_active = is_potential_match_active_global; // O(MAX_PM)\n        prev_unmatched_string_indices_vec = unmatched_string_indices; // O(M)\n        prev_s_idx_to_unmatched_list_pos_vec = s_idx_to_unmatched_list_pos; // O(M)\n        \n\n        // --- Apply proposed changes to current_grid and update all dependent state variables ---\n        // This is where current_grid and all derived states are directly modified.\n        // If rejected, everything is reverted from snapshots.\n\n        affected_s_idx_list_this_iter.clear();\n        for (int s_idx : affected_s_idx_list_this_iter) s_idx_is_affected_this_iter[s_idx] = false; // reset flags\n\n        affected_pm_idx_list_this_iter.clear();\n        for (int pm_idx : affected_pm_idx_list_this_iter) pm_idx_is_affected_this_iter[pm_idx] = false; // reset flags\n\n\n        for(const auto& cell_change : current_perturbation_cells) {\n            int r = cell_change.r;\n            int c = cell_change.c;\n            char old_char = current_grid[r][c]; // Use current_grid's char as it may have been changed by a prior cell in this multi-cell perturbation\n            char new_char = cell_change.new_char;\n\n            // Apply change to grid (temporarily)\n            current_grid[r][c] = new_char;\n\n            // Update num_dots\n            if (old_char == '.' && new_char != '.') { num_dots--; }\n            else if (old_char != '.' && new_char == '.') { num_dots++; }\n            \n            for (auto const& p : cell_covers[r][c]) {\n                int pm_idx = p.first;\n                int p_in_s = p.second; \n\n                if (!pm_idx_is_affected_this_iter[pm_idx]) {\n                    affected_pm_idx_list_this_iter.push_back(pm_idx);\n                    pm_idx_is_affected_this_iter[pm_idx] = true;\n                }\n\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n                int s_idx = pm_info_base.s_idx;\n                char required_char = S[s_idx][p_in_s];\n\n                if (!s_idx_is_affected_this_iter[s_idx]) {\n                    affected_s_idx_list_this_iter.push_back(s_idx);\n                    s_idx_is_affected_this_iter[s_idx] = true;\n                }\n            }\n        }\n\n        // Re-calculate all affected num_mismatches_for_potential_match_global and is_potential_match_active_global\n        // This is safe because current_grid reflects the *proposed* state.\n        // We use the temporary list of affected pm_idx to avoid recalculating everything.\n        for(int pm_idx : affected_pm_idx_list_this_iter) {\n            const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n            const std::string& s = S[pm_info_base.s_idx];\n            int k = s.length();\n            int mismatches = 0;\n\n            for (int p = 0; p < k; ++p) {\n                int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n                int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n                \n                if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                    mismatches++;\n                }\n            }\n            num_mismatches_for_potential_match_global[pm_idx] = mismatches;\n            is_potential_match_active_global[pm_idx] = (mismatches == 0);\n        }\n\n        // Re-calculate affected num_actual_matches_for_string and unmatched_string_indices\n        // Use a temporary list for unmatched_string_indices construction.\n        // This is complex, so for now, we'll iterate through all M strings.\n        // The previous simple O(M) copy for unmatched_string_indices and s_idx_to_unmatched_list_pos\n        // is actually done by the full snapshot/revert. This part is simplified.\n        \n        // Reset counts for affected strings\n        for(int s_idx : affected_s_idx_list_this_iter) {\n            num_actual_matches_for_string[s_idx] = 0;\n        }\n\n        // Recompute counts for affected strings based on new pm_active states\n        for(int pm_idx : affected_pm_idx_list_this_iter) {\n            if (is_potential_match_active_global[pm_idx]) {\n                num_actual_matches_for_string[all_potential_match_info_bases[pm_idx].s_idx]++;\n            }\n        }\n\n        // Recalculate global num_matched_strings and update unmatched_string_indices/s_idx_to_unmatched_list_pos\n        num_matched_strings = 0;\n        unmatched_string_indices.clear();\n        std::fill(s_idx_to_unmatched_list_pos.begin(), s_idx_to_unmatched_list_pos.end(), -1);\n\n        for(int s_idx = 0; s_idx < M; ++s_idx) {\n            if (num_actual_matches_for_string[s_idx] > 0) {\n                num_matched_strings++;\n            } else {\n                s_idx_to_unmatched_list_pos[s_idx] = unmatched_string_indices.size();\n                unmatched_string_indices.push_back(s_idx);\n            }\n        }\n\n\n        // --- Decision (Accept/Revert) ---\n        double current_obj_val = calculate_objective(prev_num_matched_strings, prev_num_dots);\n        double proposed_obj_val = calculate_objective(num_matched_strings, num_dots);\n\n        if (proposed_obj_val >= current_obj_val || dist_prob(mt) < std::exp((proposed_obj_val - current_obj_val) / T)) {\n            // Accept. All current_grid and derived state variables are already in the proposed state.\n        } else {\n            // Revert ALL state variables from snapshots\n            current_grid = prev_grid;\n            num_dots = prev_num_dots;\n            num_matched_strings = prev_num_matched_strings;\n            num_actual_matches_for_string = prev_num_actual_matches_for_string;\n            num_mismatches_for_potential_match_global = prev_num_mismatches_for_potential_match;\n            is_potential_match_active_global = prev_is_potential_match_active;\n            unmatched_string_indices = prev_unmatched_string_indices_vec;\n            s_idx_to_unmatched_list_pos = prev_s_idx_to_unmatched_list_pos_vec;\n        }\n        \n        double current_final_obj_val = calculate_objective(num_matched_strings, num_dots);\n        if (current_final_obj_val > best_score) {\n            best_score = current_final_obj_val;\n            best_grid = current_grid;\n        }\n    }\n\n    current_grid = best_grid; \n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N_input; \n    std::cin >> N_input >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> S[i];\n    }\n\n    solve();\n\n    for (int i = 0; i < N_MATRIX; ++i) {\n        std::cout << current_grid[i] << std::endl;\n    }\n\n    return 0;\n}\n","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm> // For std::reverse\n\n// No external libraries other than standard C++ ones are strictly necessary.\n\nusing namespace std;\n\n// Global variables to store map data and current state for convenience\nint N_global;\nint SI_global, SJ_global;\nvector<string> grid_global;\nvector<vector<int>> costs_global; // Stores char '5'-'9' as int\nvector<vector<bool>> is_road_global; // True if square is a road, false if obstacle\n// visible_left/right/up/down store the inclusive boundaries of the visible segment\n// For example, visible_left_global[r][c] is the minimum column index k such that (r,k) is road and on the path to (r,c)\nvector<vector<int>> visible_left_global, visible_right_global, visible_up_global, visible_down_global; \nint total_road_squares_global = 0; // Total count of road squares\nvector<vector<bool>> covered_status_global; // True if the square has been made visible\nint current_covered_count_global = 0; // Count of currently visible road squares\n\n// Structure for Dijkstra's priority queue state\nstruct State {\n    int r, c;\n    long long cost;\n    // For priority queue: min-heap based on cost\n    bool operator>(const State& other) const {\n        return cost > other.cost; // FIXED: Changed other.other.cost to other.cost\n    }\n};\n\n// Precompute visible ranges for each road square (O(N^3))\n// This populates visible_left/right/up/down_global arrays.\nvoid precompute_visibility() {\n    visible_left_global.assign(N_global, vector<int>(N_global));\n    visible_right_global.assign(N_global, vector<int>(N_global));\n    visible_up_global.assign(N_global, vector<int>(N_global));\n    visible_down_global.assign(N_global, vector<int>(N_global));\n\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            if (!is_road_global[i][j]) continue; // Only process road squares\n\n            // Horizontal visibility (left)\n            int left_bound = j;\n            while (left_bound > 0 && is_road_global[i][left_bound - 1]) {\n                left_bound--;\n            }\n            visible_left_global[i][j] = left_bound;\n\n            // Horizontal visibility (right)\n            int right_bound = j;\n            while (right_bound < N_global - 1 && is_road_global[i][right_bound + 1]) {\n                right_bound++;\n            }\n            visible_right_global[i][j] = right_bound;\n\n            // Vertical visibility (up)\n            int up_bound = i;\n            while (up_bound > 0 && is_road_global[up_bound - 1][j]) {\n                up_bound--;\n            }\n            visible_up_global[i][j] = up_bound;\n\n            // Vertical visibility (down)\n            int down_bound = i;\n            while (down_bound < N_global - 1 && is_road_global[down_bound + 1][j]) {\n                down_bound++;\n            }\n            visible_down_global[i][j] = down_bound;\n        }\n    }\n}\n\n// Update the global coverage status based on visiting (r, c) (O(N))\n// Returns the number of newly covered squares.\nint update_coverage_and_count_new(int r, int c) {\n    int newly_covered_count = 0;\n    // Horizontal line of sight\n    for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n        if (is_road_global[r][k] && !covered_status_global[r][k]) {\n            covered_status_global[r][k] = true;\n            newly_covered_count++;\n        }\n    }\n    // Vertical line of sight\n    for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n        if (is_road_global[k][c] && !covered_status_global[k][c]) {\n            covered_status_global[k][c] = true;\n            newly_covered_count++;\n        }\n    }\n    return newly_covered_count;\n}\n\n// Dijkstra from start_r, start_c to find the next best node to visit\n// The \"best\" node maximizes (new coverage gained) / (cost to reach it).\n// Returns {best_r, best_c} and updates path_cost_found with the cost to reach it.\npair<int, int> find_best_next_node(int start_r, int start_c, long long& path_cost_found) {\n    // dist[r][c] stores the minimum cost to reach (r,c) from (start_r, start_c)\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1)); \n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int best_r = -1, best_c = -1;\n    double max_score = -1.0; // Initialize with a very low score\n    long long min_cost_to_best_target = -1; // Stores cost of best found target\n    int max_coverage_gain_best = -1; // Stores coverage gain of best found target (for tie-breaking)\n\n    // Directions for moving (Up, Down, Left, Right)\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        // If a shorter path to (r,c) has already been found and processed, skip\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        // --- Start of refined coverage_gain_current_node calculation ---\n        int coverage_gain_current_node = 0;\n        bool current_cell_r_c_counted = false; // Flag to track if (r,c) itself has been counted\n\n        // Count newly visible squares horizontally\n        for (int k_col = visible_left_global[r][c]; k_col <= visible_right_global[r][c]; ++k_col) {\n            if (is_road_global[r][k_col] && !covered_status_global[r][k_col]) {\n                coverage_gain_current_node++;\n                if (k_col == c) { // FIXED: Condition for central cell in horizontal scan\n                    current_cell_r_c_counted = true; \n                }\n            }\n        }\n        // Count newly visible squares vertically\n        for (int k_row = visible_up_global[r][c]; k_row <= visible_down_global[r][c]; ++k_row) {\n            if (is_road_global[k_row][c] && !covered_status_global[k_row][c]) {\n                // FIXED: Condition for central cell in vertical scan\n                if (k_row == r && current_cell_r_c_counted) { \n                    // Skip, already counted (r,c) itself\n                } else {\n                    coverage_gain_current_node++;\n                }\n            }\n        }\n        // --- End of refined coverage_gain_current_node calculation ---\n        \n        // We only consider moves that yield new coverage AND require movement (cost > 0).\n        if (coverage_gain_current_node > 0 && cost > 0) { \n            double score = (double)coverage_gain_current_node / cost;\n\n            // Tie-breaking:\n            // 1. Higher score (coverage_gain / cost)\n            // 2. If scores are equal, prefer higher coverage_gain (more squares covered)\n            // 3. If scores and coverage_gain are both equal, prefer lower cost (shorter path)\n            if (score > max_score || \n                (score == max_score && coverage_gain_current_node > max_coverage_gain_best) ||\n                (score == max_score && coverage_gain_current_node == max_coverage_gain_best && cost < min_cost_to_best_target)) \n            {\n                max_score = score;\n                best_r = r;\n                best_c = c;\n                min_cost_to_best_target = cost;\n                max_coverage_gain_best = coverage_gain_current_node;\n            }\n        }\n\n        // Explore neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            // Check if neighbor is within bounds and is a road square\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc]; // Cost to move to (nr,nc)\n                // If a shorter path to (nr,nc) is found\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // If no suitable target was found (best_r remains -1), it means all reachable squares \n    // from start_r, start_c are already covered, or no path with coverage_gain > 0 and cost > 0 exists.\n    if (best_r == -1) { \n        path_cost_found = 0;\n        return {start_r, start_c}; // Return current position\n    }\n\n    path_cost_found = min_cost_to_best_target;\n    return {best_r, best_c};\n}\n\n// Reconstruct path segment using Dijkstra's prev array (O(N^2))\n// This function computes the shortest path between start and end and returns it as a string of moves.\nstring reconstruct_path_segment(int start_r, int start_c, int end_r, int end_c) {\n    if (start_r == end_r && start_c == end_c) return \"\"; // No movement needed\n\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1));\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1})); // To reconstruct path\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int dr[] = {-1, 1, 0, 0}; // Relative moves for U, D, L, R\n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (r == end_r && c == end_c) break; // Reached the end node, path found\n\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c}; // Store previous node for path reconstruction\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    // Reconstruct path string by backtracking from end_r, end_c to start_r, start_c\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    \n    // If no path was found (dist[end_r][end_c] is -1), return empty.\n    if (dist[end_r][end_c] == -1) {\n        return \"\"; \n    }\n\n    while (curr_r != start_r || curr_c != start_c) {\n        int pr = prev[curr_r][curr_c].first;\n        int pc = prev[curr_r][curr_c].second;\n        \n        // This check guards against errors where prev pointers might be invalid\n        if (pr == -1 || pc == -1) { \n            return \"\"; \n        }\n\n        // Determine the move character based on (pr,pc) to (curr_r,curr_c)\n        if (pr == curr_r - 1 && pc == curr_c) path_segment += 'D'; // Previous was up, current is down (move D)\n        else if (pr == curr_r + 1 && pc == curr_c) path_segment += 'U'; // Previous was down, current is up (move U)\n        else if (pr == curr_r && pc == curr_c - 1) path_segment += 'R'; // Previous was left, current is right (move R)\n        else if (pr == curr_r && pc == curr_c + 1) path_segment += 'L'; // Previous was right, current is left (move L)\n        curr_r = pr;\n        curr_c = pc;\n    }\n    reverse(path_segment.begin(), path_segment.end()); // Path was built backwards, reverse to get correct order\n    return path_segment;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); // Optimize C++ standard streams for faster I/O\n    cin.tie(NULL);\n\n    cin >> N_global >> SI_global >> SJ_global;\n\n    grid_global.resize(N_global);\n    costs_global.assign(N_global, vector<int>(N_global));\n    is_road_global.assign(N_global, vector<bool>(N_global, false));\n    covered_status_global.assign(N_global, vector<bool>(N_global, false));\n\n    for (int i = 0; i < N_global; ++i) {\n        cin >> grid_global[i];\n        for (int j = 0; j < N_global; ++j) {\n            if (grid_global[i][j] == '#') {\n                is_road_global[i][j] = false;\n            } else {\n                is_road_global[i][j] = true;\n                costs_global[i][j] = grid_global[i][j] - '0'; // Convert char digit to int\n                total_road_squares_global++; // Count total road squares\n            }\n        }\n    }\n\n    // Precompute visibility for all road squares\n    precompute_visibility();\n\n    // Initial coverage from the starting point (si,sj)\n    current_covered_count_global += update_coverage_and_count_new(SI_global, SJ_global);\n\n    // Handle the special case where all squares are covered from the starting point\n    // This avoids generating an empty path (t=0), which would result in WA.\n    if (current_covered_count_global == total_road_squares_global) {\n        string initial_move_path = \"\";\n        // Try to move Right-Left\n        if (SJ_global + 1 < N_global && is_road_global[SI_global][SJ_global + 1]) {\n            initial_move_path += 'R';\n            initial_move_path += 'L';\n        } \n        // If R-L isn't possible, try Down-Up\n        else if (SI_global + 1 < N_global && is_road_global[SI_global + 1][SJ_global]) {\n            initial_move_path += 'D';\n            initial_move_path += 'U';\n        } \n        cout << initial_move_path << endl;\n        return 0; // Exit\n    }\n\n    int current_r = SI_global;\n    int current_c = SJ_global;\n    string full_path = \"\";\n\n    // Main loop: find next best node until all squares are covered\n    while (current_covered_count_global < total_road_squares_global) {\n        long long path_cost_to_next_node = 0;\n        pair<int, int> next_target = find_best_next_node(current_r, current_c, path_cost_to_next_node);\n\n        if (next_target.first == current_r && next_target.second == current_c) {\n            // No new valid target with coverage gain and positive cost was found\n            break; \n        }\n\n        string segment_str = reconstruct_path_segment(current_r, current_c, next_target.first, next_target.second);\n        \n        int temp_r = current_r;\n        int temp_c = current_c;\n        string current_segment_moves = \"\";\n\n        // Iterate through each move in the segment to next_target\n        // Update coverage and check if all cells are covered along the way\n        for (char move_char : segment_str) {\n            current_segment_moves += move_char;\n            \n            // Determine new (temp_r, temp_c)\n            if (move_char == 'U') temp_r--;\n            else if (move_char == 'D') temp_r++;\n            else if (move_char == 'L') temp_c--;\n            else if (move_char == 'R') temp_c++;\n            \n            // Apply coverage and count newly covered squares\n            current_covered_count_global += update_coverage_and_count_new(temp_r, temp_c);\n\n            // If all squares are now covered, we can stop and return to SI,SJ\n            if (current_covered_count_global == total_road_squares_global) {\n                full_path += current_segment_moves; // Add the path segment taken so far\n                string final_return_segment = reconstruct_path_segment(temp_r, temp_c, SI_global, SJ_global);\n                full_path += final_return_segment;\n                cout << full_path << endl;\n                return 0; // Exit successfully\n            }\n        }\n        \n        // If the entire segment was traversed and still not 100% covered, append it and continue\n        full_path += segment_str; // Append the full segment\n        current_r = next_target.first; // Update current position to the end of the segment\n        current_c = next_target.second;\n    }\n\n    // This part is reached if the loop broke early (e.g., heuristic got stuck)\n    // or if the loop completed by covering all squares but the 100% check inside the loop\n    // didn't trigger an early exit (i.e., the last segment completed at exactly next_target).\n    // In any case, make sure to return to SI,SJ\n    string return_segment = reconstruct_path_segment(current_r, current_c, SI_global, SJ_global);\n    full_path += return_segment;\n\n    cout << full_path << endl; // Output the final path string\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <iomanip>\n#include <map>\n#include <cmath> // For std::round, std::clamp\n\n// Global constants and variables\nconst int MAX_SKILL_VAL = 100; // Upper bound for skills, based on problem generation info\nconst double INITIAL_S_GUESS = 20.0; // Initial guess for skill levels (from s_i,j generation range [20,60])\nconst double LEARNING_RATE_DENOM = 2.0; // Denominator for learning rate. Smaller value means faster learning.\n\nint N, M, K, R;\nstd::vector<std::vector<int>> D; // Task difficulties D[N][K]\nstd::vector<std::vector<int>> adj; // Adjacency list for dependencies: adj[u] lists tasks v that depend on u\nstd::vector<int> in_degree; // Number of prerequisites not yet completed for each task\n\nenum TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint total_tasks_completed = 0;\n\nstruct AssignedTask {\n    int task_id;\n    int start_day;\n};\n\nstd::vector<bool> member_is_free;\nstd::vector<AssignedTask> assigned_task_info; // assigned_task_info[member_idx]\nstd::vector<double> S_sum_D_task_difficulty; // Sum of D values for a task\n\n// Skill estimation\nstd::vector<std::vector<double>> S; // Estimated skill levels S[M][K]\nstd::vector<std::vector<double>> S_lower_bound; // Conservative lower bounds for skills\n\nint current_day = 0;\n\n// Set of ready tasks (in_degree is 0 and NOT_STARTED)\nstd::set<int> ready_tasks_set; // Stores task_id\n\n// Helper functions\ndouble calculate_w_internal(int member_idx, int task_idx) {\n    double w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += std::max(0.0, (double)D[task_idx][k] - S[member_idx][k]);\n    }\n    return w;\n}\n\nint calculate_t_estimated(int member_idx, int task_idx) {\n    double w = calculate_w_internal(member_idx, task_idx);\n    return std::max(1, (int)std::round(w)); // Round to nearest int, minimum 1\n}\n\n// Function to flush standard output\nvoid flush_stdout() {\n    std::cout << std::flush;\n}\n\n// Struct for candidate assignments to sort them\nstruct AssignmentCandidate {\n    int estimated_time;\n    int member_id;\n    int task_id;\n    // For tie-breaking\n    int out_degree; // Number of tasks unlocked by this task\n    double total_task_difficulty; // Sum of D values for the task\n\n    bool operator<(const AssignmentCandidate& other) const {\n        if (estimated_time != other.estimated_time) {\n            return estimated_time < other.estimated_time; // Prioritize shortest estimated time\n        }\n        // Tie-breaking for estimated_time\n        if (out_degree != other.out_degree) {\n            return out_degree > other.out_degree; // Prioritize tasks that unlock more tasks\n        }\n        if (total_task_difficulty != other.total_task_difficulty) {\n            return total_task_difficulty > other.total_task_difficulty; // Prioritize harder tasks\n        }\n        return task_id < other.task_id; // Stable sort by task_id\n    }\n};\n\nint main() {\n    // Faster I/O\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> K >> R;\n\n    D.resize(N, std::vector<int>(K));\n    S_sum_D_task_difficulty.resize(N);\n    for (int i = 0; i < N; ++i) {\n        double current_sum_D = 0;\n        for (int k = 0; k < K; ++k) {\n            std::cin >> D[i][k];\n            current_sum_D += D[i][k];\n        }\n        S_sum_D_task_difficulty[i] = current_sum_D;\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    task_status.resize(N, NOT_STARTED);\n    member_is_free.resize(M, true);\n    assigned_task_info.resize(M);\n\n    S.resize(M, std::vector<double>(K, INITIAL_S_GUESS));\n    S_lower_bound.resize(M, std::vector<double>(K, 0.0));\n\n    // Initialize ready_tasks_set: tasks with no dependencies or all dependencies met\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            ready_tasks_set.insert(i);\n        }\n    }\n\n    while (true) {\n        current_day++;\n\n        // Process daily input (completed tasks)\n        int n_completed;\n        std::cin >> n_completed;\n\n        if (n_completed == -1) {\n            break; // All tasks completed or max days reached, exit program\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_idx;\n            std::cin >> member_idx;\n            --member_idx; // 0-indexed\n\n            int completed_task_id = assigned_task_info[member_idx].task_id;\n            int start_day = assigned_task_info[member_idx].start_day;\n            int actual_t_ij = current_day - start_day + 1; // Actual days taken\n\n            // Update task status\n            task_status[completed_task_id] = COMPLETED;\n            total_tasks_completed++;\n\n            // Skill Estimation Update for member_idx\n            // Infer w_ij from actual_t_ij. If actual_t_ij == 1, assume w_ij=0 (most optimistic).\n            // Otherwise, assume w_ij = actual_t_ij, ignoring small random noise.\n            double observed_w = (actual_t_ij == 1) ? 0.0 : (double)actual_t_ij;\n            double current_predicted_w = calculate_w_internal(member_idx, completed_task_id);\n\n            // Strong evidence for S_lower_bound if task completed in 1 day\n            if (actual_t_ij == 1) { \n                for (int k = 0; k < K; ++k) {\n                    S_lower_bound[member_idx][k] = std::max(S_lower_bound[member_idx][k], (double)D[completed_task_id][k]);\n                }\n            } else { // actual_t_ij > 1, adjust S based on difference between predicted and observed w\n                double error = current_predicted_w - observed_w; // Positive if predicted was too high, negative if too low\n                int active_skills_count = 0; // Count skills where d_ik > S_jk currently\n                for (int k = 0; k < K; ++k) {\n                    if (D[completed_task_id][k] > S[member_idx][k]) {\n                        active_skills_count++;\n                    }\n                }\n\n                if (active_skills_count > 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (D[completed_task_id][k] > S[member_idx][k]) {\n                            // Adjust S[member_idx][k] to reduce the error.\n                            // If error > 0 (predicted w was too high), S[member_idx][k] needs to increase\n                            // If error < 0 (predicted w was too low), S[member_idx][k] needs to decrease\n                            S[member_idx][k] -= error / (active_skills_count * LEARNING_RATE_DENOM);\n                            S[member_idx][k] = std::clamp(S[member_idx][k], 0.0, (double)MAX_SKILL_VAL);\n                        }\n                    }\n                }\n            }\n\n            // Always apply lower bounds after any other adjustments to maintain consistency\n            for (int k = 0; k < K; ++k) {\n                S[member_idx][k] = std::max(S[member_idx][k], S_lower_bound[member_idx][k]);\n            }\n            \n            // Output skill predictions for visualization (round to nearest integer for output)\n            std::cout << \"#s \" << member_idx + 1;\n            for (int k = 0; k < K; ++k) {\n                std::cout << \" \" << static_cast<int>(std::round(S[member_idx][k]));\n            }\n            std::cout << std::endl;\n\n            // Free the member\n            member_is_free[member_idx] = true;\n\n            // Update in_degree for tasks dependent on the completed task\n            for (int dependent_task_id : adj[completed_task_id]) {\n                in_degree[dependent_task_id]--;\n                if (in_degree[dependent_task_id] == 0 && task_status[dependent_task_id] == NOT_STARTED) {\n                    ready_tasks_set.insert(dependent_task_id);\n                }\n            }\n        }\n\n        // Task Assignment Phase\n        std::vector<std::pair<int, int>> assignments_today;\n        std::vector<int> current_free_members;\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            if (member_is_free[m_idx]) {\n                current_free_members.push_back(m_idx);\n            }\n        }\n\n        // Prioritize a subset of ready tasks to consider for efficiency\n        std::vector<int> tasks_to_consider;\n        if (!ready_tasks_set.empty()) {\n            // Priority for selecting tasks to consider:\n            // High out_degree (unlocks more tasks), high average skill difficulty, then lower task_id\n            std::vector<std::pair<int, int>> sorted_ready_tasks; // (priority_score, task_id)\n            for(int tid : ready_tasks_set) {\n                // Heuristic score: combine out_degree (weighted) and average task difficulty\n                // Multiplying by 100 ensures out_degree has significant impact\n                int score = adj[tid].size() * 100 + static_cast<int>(S_sum_D_task_difficulty[tid] / K); \n                sorted_ready_tasks.push_back({score, tid});\n            }\n            std::sort(sorted_ready_tasks.rbegin(), sorted_ready_tasks.rend()); // Sort descending by score\n\n            // Limit the number of tasks considered to avoid O(M * N_ready * K) complexity\n            // Choose M * (some factor) or a fixed max (e.g., 200)\n            int num_to_consider = std::min((int)sorted_ready_tasks.size(), M * 15); \n            for (int i = 0; i < num_to_consider; ++i) {\n                tasks_to_consider.push_back(sorted_ready_tasks[i].second);\n            }\n        }\n\n        std::vector<AssignmentCandidate> candidates;\n        for (int m_idx : current_free_members) {\n            for (int t_idx : tasks_to_consider) {\n                if (task_status[t_idx] == NOT_STARTED) { // Double check task isn't assigned concurrently\n                    candidates.push_back({\n                        calculate_t_estimated(m_idx, t_idx),\n                        m_idx,\n                        t_idx,\n                        (int)adj[t_idx].size(),\n                        S_sum_D_task_difficulty[t_idx]\n                    });\n                }\n            }\n        }\n        std::sort(candidates.begin(), candidates.end());\n\n        // Greedily assign tasks based on sorted candidates\n        for (const auto& candidate : candidates) {\n            int m_idx = candidate.member_id;\n            int t_idx = candidate.task_id;\n\n            if (member_is_free[m_idx] && task_status[t_idx] == NOT_STARTED) {\n                assignments_today.push_back({m_idx + 1, t_idx + 1});\n                member_is_free[m_idx] = false;\n                task_status[t_idx] = IN_PROGRESS;\n                assigned_task_info[m_idx] = {t_idx, current_day}; // Store start day and task ID\n                ready_tasks_set.erase(t_idx); // Remove from ready set as it's now in progress\n            }\n            \n            // Break conditions: if all free members have been assigned OR all remaining tasks are assigned\n            if (assignments_today.size() == current_free_members.size() || \n                total_tasks_completed + assignments_today.size() == N) {\n                break; \n            }\n        }\n\n        // Output assignments for the day\n        std::cout << assignments_today.size();\n        for (const auto& p : assignments_today) {\n            std::cout << \" \" << p.first << \" \" << p.second;\n        }\n        std::cout << std::endl;\n        flush_stdout(); // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc006":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_set>\n#include <tuple> // For std::tie\n#include <limits> // For std::numeric_limits\n\n// --- Structs ---\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id; // 1-indexed original ID\n    Point p; // pickup\n    Point d; // delivery\n};\n\nenum NodeType {\n    PICKUP_TYPE = 0,\n    DELIVERY_TYPE = 1\n};\n\nstruct RouteNode {\n    int order_id;\n    NodeType type;\n    Point coord;\n};\n\n// --- Global Constants ---\nconst Point OFFICE = {400, 400};\nconst int NUM_TOTAL_ORDERS = 1000;\nconst int NUM_DELIVERIES_QUOTA = 50;\n\n// --- Random Number Generator ---\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\nlong long manhattan_dist(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\n// Calculate total distance for a route represented by a sequence of RouteNodes\nlong long calculate_total_route_distance(const std::vector<RouteNode>& route_nodes) {\n    long long total_dist = 0;\n    if (route_nodes.empty()) {\n        return manhattan_dist(OFFICE, OFFICE);\n    }\n\n    total_dist += manhattan_dist(OFFICE, route_nodes[0].coord);\n    for (size_t i = 0; i < route_nodes.size() - 1; ++i) {\n        total_dist += manhattan_dist(route_nodes[i].coord, route_nodes[i+1].coord);\n    }\n    total_dist += manhattan_dist(route_nodes.back().coord, OFFICE);\n    return total_dist;\n}\n\n// Generates an initial route using a greedy Nearest Neighbor heuristic.\nstd::vector<RouteNode> generate_nearest_neighbor_route(const std::vector<int>& selected_order_ids, \n                                                       const std::map<int, Order>& all_orders_map) {\n    std::vector<RouteNode> route;\n    std::unordered_set<int> unpicked_order_ids(selected_order_ids.begin(), selected_order_ids.end());\n    std::unordered_set<int> un_delivered_order_ids;\n\n    Point current_pos = OFFICE;\n\n    while (!unpicked_order_ids.empty() || !un_delivered_order_ids.empty()) {\n        std::vector<std::pair<long long, RouteNode>> candidates; \n\n        for (int order_id : unpicked_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.p), {order_id, PICKUP_TYPE, order.p}});\n        }\n\n        for (int order_id : un_delivered_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.d), {order_id, DELIVERY_TYPE, order.d}});\n        }\n\n        if (candidates.empty()) break;\n\n        long long min_dist = candidates[0].first;\n        for (size_t i = 1; i < candidates.size(); ++i) {\n            if (candidates[i].first < min_dist) {\n                min_dist = candidates[i].first;\n            }\n        }\n\n        std::vector<RouteNode> best_candidates_nodes;\n        for (const auto& cand : candidates) {\n            if (cand.first == min_dist) {\n                best_candidates_nodes.push_back(cand.second);\n            }\n        }\n        \n        std::uniform_int_distribution<int> dist_cand_idx(0, best_candidates_nodes.size() - 1);\n        RouteNode chosen_node = best_candidates_nodes[dist_cand_idx(rng)];\n\n        route.push_back(chosen_node);\n        current_pos = chosen_node.coord;\n\n        if (chosen_node.type == PICKUP_TYPE) {\n            unpicked_order_ids.erase(chosen_node.order_id);\n            un_delivered_order_ids.insert(chosen_node.order_id);\n        } else { // DELIVERY_TYPE\n            un_delivered_order_ids.erase(chosen_node.order_id);\n        }\n    }\n    return route;\n}\n\n// Calculates delta cost for removing a node at `idx` from `current_route`.\nlong long calculate_removal_delta(const std::vector<RouteNode>& current_route, int idx) {\n    if (current_route.empty()) return 0; \n    if (current_route.size() == 1) { \n        return -(manhattan_dist(OFFICE, current_route[0].coord) + manhattan_dist(current_route[0].coord, OFFICE));\n    }\n\n    Point p_before = (idx == 0) ? OFFICE : current_route[idx - 1].coord;\n    Point p_node = current_route[idx].coord;\n    Point p_after = (idx == current_route.size() - 1) ? OFFICE : current_route[idx + 1].coord;\n    \n    long long dist_removed_segment = manhattan_dist(p_before, p_node) + manhattan_dist(p_node, p_after);\n    long long dist_merged_segment = manhattan_dist(p_before, p_after);\n    return dist_merged_segment - dist_removed_segment;\n}\n\n// Calculates delta cost for inserting a node at `insert_idx` into `current_route`.\nlong long calculate_insertion_delta(const std::vector<RouteNode>& current_route, int insert_idx, const RouteNode& node_to_insert) {\n    if (current_route.empty()) { \n        return manhattan_dist(OFFICE, node_to_insert.coord) + manhattan_dist(node_to_insert.coord, OFFICE);\n    }\n    \n    Point p_before = (insert_idx == 0) ? OFFICE : current_route[insert_idx - 1].coord;\n    Point p_after = (insert_idx == current_route.size()) ? OFFICE : current_route[insert_idx].coord;\n    \n    long long dist_new_segment = manhattan_dist(p_before, node_to_insert.coord) + manhattan_dist(node_to_insert.coord, p_after);\n    long long dist_old_at_insert_point = manhattan_dist(p_before, p_after);\n    return dist_new_segment - dist_old_at_insert_point;\n}\n\n\n// Applies a node relocation local search operator (1-opt equivalent).\n// Returns the new route and the new total distance.\nstd::pair<std::vector<RouteNode>, long long> apply_1opt_relocation(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist) {\n\n    if (current_route.empty()) return {current_route, current_total_dist};\n\n    std::uniform_int_distribution<int> dist_move_idx(0, current_route.size() - 1);\n    int move_idx = dist_move_idx(rng);\n    RouteNode node_to_move = current_route[move_idx];\n\n    long long delta_from_removal = calculate_removal_delta(current_route, move_idx);\n\n    // Create a temporary route with the node removed (copying to new vector)\n    std::vector<RouteNode> new_route_temp;\n    new_route_temp.reserve(current_route.size() - 1);\n    for (size_t i = 0; i < current_route.size(); ++i) {\n        if (i == (size_t)move_idx) continue;\n        new_route_temp.push_back(current_route[i]);\n    }\n    \n    int min_insert_idx = 0;\n    int max_insert_idx = new_route_temp.size(); \n\n    if (node_to_move.type == PICKUP_TYPE) {\n        int Di_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == DELIVERY_TYPE) {\n                Di_pos = i;\n                break;\n            }\n        }\n        if (Di_pos != -1) { \n            max_insert_idx = Di_pos;\n        }\n    } else { // DELIVERY_TYPE\n        int Pi_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == PICKUP_TYPE) {\n                Pi_pos = i;\n                break;\n            }\n        }\n        if (Pi_pos != -1) { \n            min_insert_idx = Pi_pos + 1;\n        }\n    }\n    \n    if (min_insert_idx > max_insert_idx) { \n         min_insert_idx = 0; \n         max_insert_idx = new_route_temp.size();\n    }\n    if (new_route_temp.empty()) { \n        min_insert_idx = 0;\n        max_insert_idx = 0;\n    }\n\n    std::uniform_int_distribution<int> dist_insert_pos(min_insert_idx, max_insert_idx);\n    int insert_pos = dist_insert_pos(rng); \n    \n    long long delta_from_insertion = calculate_insertion_delta(new_route_temp, insert_pos, node_to_move);\n\n    new_route_temp.insert(new_route_temp.begin() + insert_pos, node_to_move);\n\n    long long new_total_dist = current_total_dist + delta_from_removal + delta_from_insertion;\n\n    return {new_route_temp, new_total_dist};\n}\n\n// Applies a 2-opt operation to the route with O(1) distance calculation and precedence validation.\n// Returns the new route and the new total distance, or original route if invalid.\nstd::pair<std::vector<RouteNode>, long long> apply_2opt_swap(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist,\n    const std::vector<int>& selected_order_ids) {\n\n    if (current_route.size() < 2) return {current_route, current_total_dist}; \n\n    std::uniform_int_distribution<int> dist_idx(0, current_route.size() - 1);\n    int i = dist_idx(rng); // first break point (node i)\n    int j = dist_idx(rng); // second break point (node j)\n\n    // Ensure i and j are distinct and i < j for consistent segment reversal logic\n    if (i == j) return {current_route, current_total_dist}; \n    if (i > j) std::swap(i, j);\n\n    // Points for distance calculation, considering boundary (OFFICE)\n    Point p_i_minus_1 = (i == 0) ? OFFICE : current_route[i - 1].coord;\n    Point p_i         = current_route[i].coord;\n    Point p_j         = current_route[j].coord;\n    Point p_j_plus_1  = (j == current_route.size() - 1) ? OFFICE : current_route[j + 1].coord;\n\n    // Calculate incremental distance change\n    long long delta_dist = -manhattan_dist(p_i_minus_1, p_i) \n                           -manhattan_dist(p_j, p_j_plus_1)  \n                           +manhattan_dist(p_i_minus_1, p_j) \n                           +manhattan_dist(p_i, p_j_plus_1); \n    \n    std::vector<RouteNode> new_route_candidate = current_route;\n    \n    // Reverse the segment [i, j]\n    std::reverse(new_route_candidate.begin() + i, new_route_candidate.begin() + j + 1);\n\n    // Validate precedence constraints after the swap\n    // Use vectors for quick mapping of order_id to index\n    std::vector<int> p_pos_map(NUM_TOTAL_ORDERS + 1, -1);\n    std::vector<int> d_pos_map(NUM_TOTAL_ORDERS + 1, -1);\n    \n    for (size_t k = 0; k < new_route_candidate.size(); ++k) {\n        if (new_route_candidate[k].type == PICKUP_TYPE) {\n            p_pos_map[new_route_candidate[k].order_id] = k;\n        } else {\n            d_pos_map[new_route_candidate[k].order_id] = k;\n        }\n    }\n\n    for (int order_id : selected_order_ids) {\n        if (p_pos_map[order_id] != -1 && d_pos_map[order_id] != -1) { // Should always be true for selected orders\n            if (p_pos_map[order_id] > d_pos_map[order_id]) {\n                return {current_route, current_total_dist}; // Invalid move\n            }\n        }\n    }\n\n    long long new_total_dist = current_total_dist + delta_dist;\n    return {new_route_candidate, new_total_dist};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // --- Input Reading ---\n    std::vector<Order> all_orders_orig(NUM_TOTAL_ORDERS); \n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        all_orders_orig[i].id = i + 1; // 1-indexed\n        std::cin >> all_orders_orig[i].p.x >> all_orders_orig[i].p.y >> all_orders_orig[i].d.x >> all_orders_orig[i].d.y;\n    }\n\n    // --- Initial Selection (Greedy based on standalone cost) ---\n    std::vector<std::pair<long long, int>> order_costs(NUM_TOTAL_ORDERS); \n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        long long cost = manhattan_dist(OFFICE, all_orders_orig[i].p) +\n                         manhattan_dist(all_orders_orig[i].p, all_orders_orig[i].d) +\n                         manhattan_dist(all_orders_orig[i].d, OFFICE);\n        order_costs[i] = {cost, all_orders_orig[i].id};\n    }\n    std::sort(order_costs.begin(), order_costs.end());\n\n    std::vector<int> current_selected_order_ids_vec;\n    std::map<int, Order> current_selected_orders_map; \n    std::vector<int> unselected_order_ids_vec;\n\n    for (int i = 0; i < NUM_DELIVERIES_QUOTA; ++i) {\n        int order_id = order_costs[i].second;\n        current_selected_order_ids_vec.push_back(order_id);\n        current_selected_orders_map[order_id] = all_orders_orig[order_id - 1]; \n    }\n    for (int i = NUM_DELIVERIES_QUOTA; i < NUM_TOTAL_ORDERS; ++i) {\n        unselected_order_ids_vec.push_back(order_costs[i].second);\n    }\n\n    // --- Initial Route Generation ---\n    std::vector<RouteNode> current_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n    long long current_total_dist = calculate_total_route_distance(current_route_nodes);\n\n    // --- Best Solution Tracking ---\n    long long best_total_dist = current_total_dist;\n    std::vector<RouteNode> best_route_nodes = current_route_nodes;\n    std::vector<int> best_selected_order_ids = current_selected_order_ids_vec;\n\n    // --- Simulated Annealing Parameters ---\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SEC = 1.95; \n    const double T_START = 5000.0;     \n    const double T_END = 1.0;          \n    const double PROB_ORDER_SWAP = 0.08; // Adjusted from 0.05\n    const double PROB_2OPT_ROUTE_MOVE = 0.12; // Adjusted from 0.45, previously 0.15\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_selected_idx(0, NUM_DELIVERIES_QUOTA - 1);\n    \n    // --- Simulated Annealing Loop ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_sec = std::chrono::duration<double>(current_time - start_time).count();\n\n        if (elapsed_sec >= TIME_LIMIT_SEC) {\n            break;\n        }\n\n        double progress = elapsed_sec / TIME_LIMIT_SEC;\n        double current_T = T_START * std::pow(T_END / T_START, progress);\n\n        long long new_total_dist;\n        std::vector<RouteNode> new_route_nodes_candidate; \n\n        bool orders_swapped_this_iter = false; \n        int out_vec_idx = -1; \n        int in_vec_idx = -1;\n        \n        double op_choice = dist_0_1(rng);\n\n        if (op_choice < PROB_ORDER_SWAP && !unselected_order_ids_vec.empty()) {\n            orders_swapped_this_iter = true;\n            out_vec_idx = dist_selected_idx(rng);\n            int order_out_id = current_selected_order_ids_vec[out_vec_idx];\n\n            std::uniform_int_distribution<int> dist_unselected_idx(0, unselected_order_ids_vec.size() - 1);\n            in_vec_idx = dist_unselected_idx(rng);\n            int order_in_id = unselected_order_ids_vec[in_vec_idx];\n\n            // 1. Create a temporary route by removing order_out_id's nodes\n            std::vector<RouteNode> temp_route_after_removal;\n            temp_route_after_removal.reserve(current_route_nodes.size() - 2);\n            for(const auto& node : current_route_nodes) {\n                if(node.order_id != order_out_id) {\n                    temp_route_after_removal.push_back(node);\n                }\n            }\n            long long dist_after_removal = calculate_total_route_distance(temp_route_after_removal);\n\n            // 2. Insert order_in_id's nodes (P_in, D_in) greedily\n            const Order& order_in = all_orders_orig[order_in_id - 1];\n            RouteNode p_in_node = {order_in_id, PICKUP_TYPE, order_in.p};\n            RouteNode d_in_node = {order_in_id, DELIVERY_TYPE, order_in.d};\n\n            // Find best insertion for P_in\n            std::vector<RouteNode> route_working_copy = temp_route_after_removal;\n            long long dist_working_copy = dist_after_removal;\n            int best_p_in_insert_pos = 0;\n            long long min_p_in_delta = std::numeric_limits<long long>::max(); \n\n            for (int i = 0; i <= route_working_copy.size(); ++i) {\n                long long current_delta = calculate_insertion_delta(route_working_copy, i, p_in_node);\n                if (current_delta < min_p_in_delta) {\n                    min_p_in_delta = current_delta;\n                    best_p_in_insert_pos = i;\n                }\n            }\n            route_working_copy.insert(route_working_copy.begin() + best_p_in_insert_pos, p_in_node);\n            dist_working_copy += min_p_in_delta;\n            \n            int p_in_actual_pos = best_p_in_insert_pos; \n\n            // Find best insertion for D_in (after P_in's actual position)\n            int best_d_in_insert_pos = p_in_actual_pos + 1; \n            long long min_d_in_delta = std::numeric_limits<long long>::max(); \n\n            for (int i = p_in_actual_pos + 1; i <= route_working_copy.size(); ++i) {\n                 long long current_delta = calculate_insertion_delta(route_working_copy, i, d_in_node);\n                if (current_delta < min_d_in_delta) {\n                    min_d_in_delta = current_delta;\n                    best_d_in_insert_pos = i;\n                }\n            }\n            \n            new_route_nodes_candidate = route_working_copy; \n            new_route_nodes_candidate.insert(new_route_nodes_candidate.begin() + best_d_in_insert_pos, d_in_node);\n            new_total_dist = dist_working_copy + min_d_in_delta;\n            \n            // --- Temporarily Apply the swap to selected order list for acceptance check ---\n            current_selected_order_ids_vec[out_vec_idx] = order_in_id;\n            unselected_order_ids_vec[in_vec_idx] = order_out_id;\n            current_selected_orders_map.erase(order_out_id);\n            current_selected_orders_map[order_in_id] = all_orders_orig[order_in_id - 1];\n\n        } else if (op_choice < PROB_ORDER_SWAP + PROB_2OPT_ROUTE_MOVE) { // 2-opt move\n             std::tie(new_route_nodes_candidate, new_total_dist) = apply_2opt_swap(current_route_nodes, current_total_dist, current_selected_order_ids_vec);\n        }\n        else { // 1-opt (node relocation)\n            std::tie(new_route_nodes_candidate, new_total_dist) = apply_1opt_relocation(current_route_nodes, current_total_dist);\n        }\n\n        // --- Acceptance Criteria ---\n        if (new_total_dist < current_total_dist) {\n            current_total_dist = new_total_dist;\n            current_route_nodes = new_route_nodes_candidate; \n        } else {\n            double prob_acceptance = std::exp((double)(current_total_dist - new_total_dist) / current_T);\n            if (dist_0_1(rng) < prob_acceptance) {\n                current_total_dist = new_total_dist;\n                current_route_nodes = new_route_nodes_candidate; \n            } else {\n                // Reject: if orders were swapped, revert them\n                if (orders_swapped_this_iter) {\n                    int order_in_id_to_revert = current_selected_order_ids_vec[out_vec_idx]; \n                    int order_out_id_to_revert = unselected_order_ids_vec[in_vec_idx];     \n\n                    current_selected_order_ids_vec[out_vec_idx] = order_out_id_to_revert;\n                    unselected_order_ids_vec[in_vec_idx] = order_in_id_to_revert;\n                    \n                    current_selected_orders_map.erase(order_in_id_to_revert);\n                    current_selected_orders_map[order_out_id_to_revert] = all_orders_orig[order_out_id_to_revert - 1];\n                }\n            }\n        }\n\n        // --- Update Best Solution ---\n        if (current_total_dist < best_total_dist) {\n            best_total_dist = current_total_dist;\n            best_route_nodes = current_route_nodes;\n            best_selected_order_ids = current_selected_order_ids_vec; \n        }\n    }\n\n    // --- Output ---\n    std::cout << NUM_DELIVERIES_QUOTA;\n    for (int id : best_selected_order_ids) {\n        std::cout << \" \" << id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_route_nodes.size() + 2; \n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (const auto& node : best_route_nodes) {\n        std::cout << \" \" << node.coord.x << \" \" << node.coord.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric> \n#include <iomanip>\n#include <algorithm>\n\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    long long d; // Precomputed rounded Euclidean distance\n};\n\n// Global constants for problem size\nconst int N_NODES = 400;\nconst int M_EDGES = 1995;\n\n// Function to calculate rounded Euclidean distance\nlong long calculate_d(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    // dx*dx + dy*dy can be up to 800^2 + 800^2 = 1,280,000. Fits in long long.\n    // sqrt of 1,280,000 is approx 1131.\n    return std::round(std::sqrt(static_cast<double>(dx * dx + dy * dy)));\n}\n\n// Heuristic parameters for tuning\n// TAU_MIN: Initial strictness for cost ratio l_i / d_i\n// Decreased from 1.3 to 1.2 to be more selective early on.\nconst double TAU_MIN = 1.2; \n// TAU_MAX: Final leniency for cost ratio l_i / d_i when close to connecting all nodes\n// Kept at 3.0 to ensure connectivity at the very end.\nconst double TAU_MAX = 3.0; \n\n// BASE_REDUNDANCY_FACTOR: M_EDGES / (N_NODES - 1) is the factual average redundancy.\n// For N=400, M=1995, this is 1995 / 399 = 5.0.\nconst double BASE_REDUNDANCY_FACTOR = static_cast<double>(M_EDGES) / (N_NODES - 1.0);\n\n// EFFECTIVE_REDUNDANCY_DENOMINATOR: A tuning parameter. Lowering this makes\n// `potential_useful_remaining` larger, delaying the urgency trigger.\n// Decreased from 6.0 to 5.5 to be less aggressive with urgency (more cost-sensitive).\nconst double EFFECTIVE_REDUNDANCY_DENOMINATOR = 5.5; \n\n// URGENCY_SAFETY_MARGIN: A small buffer for the urgency condition.\n// Kept at 0.0 to ensure strict urgency when it does trigger.\nconst double URGENCY_SAFETY_MARGIN = 0.0; \n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    std::vector<Point> vertices(N_NODES);\n    for (int i = 0; i < N_NODES; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<EdgeInfo> edges(M_EDGES);\n    for (int i = 0; i < M_EDGES; ++i) {\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].d = calculate_d(vertices[edges[i].u], vertices[edges[i].v]);\n    }\n\n    atcoder::dsu dsu(N_NODES);\n    int edges_taken_count = 0;\n\n    for (int i = 0; i < M_EDGES; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        long long d_val = edges[i].d;\n\n        long long l_val;\n        std::cin >> l_val;\n\n        int decision = 0; // Default: reject\n\n        if (!dsu.same(u, v)) {\n            int needed_to_connect = dsu.groups().size() - 1; \n            int remaining_candidates = M_EDGES - (i + 1);\n            double cost_ratio = static_cast<double>(l_val) / d_val;\n\n            double potential_useful_remaining = 0.0;\n            // Guard against division by zero. EFFECTIVE_REDUNDANCY_DENOMINATOR is constant > 0.\n            if (EFFECTIVE_REDUNDANCY_DENOMINATOR > 0) { \n                 potential_useful_remaining = static_cast<double>(remaining_candidates) / EFFECTIVE_REDUNDANCY_DENOMINATOR;\n            }\n            \n            // --- Urgency Check ---\n            // If the number of merges needed is greater than or equal to the (pessimistic)\n            // estimate of useful edges remaining, then we must take this edge.\n            if (needed_to_connect >= potential_useful_remaining - URGENCY_SAFETY_MARGIN) {\n                decision = 1;\n            } else {\n                // --- Adaptive Threshold Check ---\n                // progress_ratio_taken is (edges_taken_count / (N_NODES - 1.0)), which is also\n                // equivalent to ((N_NODES - dsu.groups().size()) / (N_NODES - 1.0)),\n                // measuring how much of the MST has been completed.\n                double progress_ratio_taken = static_cast<double>(edges_taken_count) / (N_NODES - 1.0);\n                // current_tau interpolates between TAU_MIN (at start) and TAU_MAX (at completion).\n                double current_tau = TAU_MIN + (TAU_MAX - TAU_MIN) * progress_ratio_taken;\n\n                if (cost_ratio <= current_tau) {\n                    decision = 1;\n                }\n            }\n        }\n\n        if (decision == 1) {\n            dsu.merge(u, v);\n            edges_taken_count++;\n        }\n\n        std::cout << decision << std::endl;\n    }\n\n    return 0;\n}\n","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <set>\n#include <algorithm>\n#include <tuple> // For std::tie\n#include <map>   // For BFS path reconstruction\n\nusing namespace std;\n\n// Global constants\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: U, D, L, R\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    // Overload operators for use in sets/maps and comparisons\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    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// Game state variables\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type; // Not used for movement prediction in this solution\nvector<Point> human_pos;\n\n// Board state: 0=passable, 1=impassable (wall)\nvector<vector<int>> board(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n\n// Global BFS data structures (re-used each time BFS is called)\nvector<vector<int>> dist_bfs;\nvector<vector<Point>> parent_bfs;\n\n// Function to check if a point is within grid boundaries\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// BFS to find shortest path distance from start to target_dest_for_human.\n// Also stores parent pointers to reconstruct the first step of the path.\n// `start`: The starting point for BFS (human's current position).\n// `target_dest_for_human`: The specific cell the human wants to move to.\n// `current_blocked_this_turn`: Set of cells that will become walls this turn by other humans.\n// `current_moved_to_this_turn_targets`: Set of cells that other humans are planning to move to this turn.\n// `all_human_current_pos`: Current positions of all humans (to avoid pathfinding through other humans' current spots).\n// `self_idx`: Index of the human for whom BFS is being run (to allow passing through its own start cell).\nint bfs(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n        const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    dist_bfs.assign(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    parent_bfs.assign(GRID_SIZE, vector<Point>(GRID_SIZE, {-1, -1}));\n    queue<Point> q;\n\n    q.push(start);\n    dist_bfs[start.r][start.c] = 0;\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        if (curr == target_dest_for_human) {\n            return dist_bfs[curr.r][curr.c]; // Target reached\n        }\n\n        // Explore 4 cardinal neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.r + DR[i];\n            int nc = curr.c + DC[i];\n            Point next = {nr, nc};\n\n            // Basic checks: within bounds, not visited yet\n            if (!is_valid(nr, nc) || dist_bfs[nr][nc] != -1) continue;\n\n            // Check if 'next' cell is impassable due to existing walls or planned blocks\n            if (board[nr][nc] == 1) continue; // Existing permanent wall\n            if (current_blocked_this_turn.count(next)) continue; // Blocked by another human this turn\n\n            // Check if 'next' cell is a target for another human's move this turn\n            if (current_moved_to_this_turn_targets.count(next)) continue;\n            \n            // Check if 'next' cell is currently occupied by another human (who isn't moving out of it)\n            bool is_other_human_current_pos = false;\n            for(int h_idx_other = 0; h_idx_other < M; ++h_idx_other) {\n                if (h_idx_other == self_idx) continue; // Current human can pass through its own start\n                if (all_human_current_pos[h_idx_other] == next) {\n                    is_other_human_current_pos = true;\n                    break;\n                }\n            }\n            if (is_other_human_current_pos) continue; // Impassable if another human is currently there\n\n            // If all checks pass, 'next' is a valid step\n            dist_bfs[nr][nc] = dist_bfs[curr.r][curr.c] + 1;\n            parent_bfs[nr][nc] = curr;\n            q.push(next);\n        }\n    }\n    return -1; // Target not reachable\n}\n\n// Reconstructs the character for the first move from 'start' to 'target_dest_for_human' based on BFS path.\nchar get_move_char(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n                   const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    if (bfs(start, target_dest_for_human, current_blocked_this_turn, current_moved_to_this_turn_targets, all_human_current_pos, self_idx) == -1) {\n        return '.'; // No path found\n    }\n\n    // Path reconstruction: find the first step from 'start' towards 'target_dest_for_human'\n    Point curr = target_dest_for_human;\n    // Walk back from target until we find the child of 'start'\n    while (parent_bfs[curr.r][curr.c] != start) {\n        curr = parent_bfs[curr.r][curr.c];\n        if (curr.r == -1 || curr.c == -1) return '.'; // Safety break for invalid parent\n    }\n\n    // 'curr' is now the first step from 'start'\n    for (int i = 0; i < 4; ++i) {\n        if (start.r + DR[i] == curr.r && start.c + DC[i] == curr.c) {\n            return MOVE_CHARS[i]; // Return corresponding move character\n        }\n    }\n    return '.'; // Should not be reached if BFS found a path\n}\n\n// Structure to represent a rectangle (inclusive coordinates, 0-indexed)\nstruct Rect {\n    int r1, c1, r2, c2;\n    int area() const { \n        if (r1 < 0 || c1 < 0 || r2 >= GRID_SIZE || c2 >= GRID_SIZE || r1 > r2 || c1 > c2) return 0; // Handle invalid rectangles\n        return (r2 - r1 + 1) * (c2 - c1 + 1); \n    }\n    // Check if a point is inside the rectangle\n    bool contains(Point p) const {\n        return p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2;\n    }\n};\n\nRect target_rect = {0, 0, 0, 0}; // The main region humans will try to enclose\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read initial pet information\n    cin >> N;\n    pet_pos.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i];\n        pet_pos[i].r--; // Convert to 0-indexed\n        pet_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // Read initial human information\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].r >> human_pos[i].c;\n        human_pos[i].r--; // Convert to 0-indexed\n        human_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // --- Initialization Phase: Find the best target rectangle ---\n    long long max_heuristic_score = -2e18; // Initialize with a very small number\n    Rect best_initial_rect = {-1, -1, -1, -1}; // Initialize with an invalid rectangle\n\n    // Brute force search for the best pet-free rectangle\n    for (int r1 = 0; r1 < GRID_SIZE; ++r1) {\n        for (int c1 = 0; c1 < GRID_SIZE; ++c1) {\n            for (int r2 = r1; r2 < GRID_SIZE; ++r2) {\n                for (int c2 = c1; c2 < GRID_SIZE; ++c2) {\n                    Rect current_rect = {r1, c1, r2, c2};\n                    bool is_pet_free = true;\n                    // Check if any pet is inside the current rectangle\n                    for (int i = 0; i < N; ++i) {\n                        if (current_rect.contains(pet_pos[i])) {\n                            is_pet_free = false;\n                            break;\n                        }\n                    }\n\n                    if (is_pet_free) {\n                        long long current_area = current_rect.area();\n                        if (current_area == 0) continue; // Skip 0-area rectangles\n                        \n                        // 1. Calculate sum of Manhattan distances from humans to perimeter of current_rect itself\n                        long long dist_sum_to_human_perimeter = 0;\n                        vector<Point> perimeter_of_rect_itself;\n                        for (int c = c1; c <= c2; ++c) {\n                            perimeter_of_rect_itself.push_back({r1, c});\n                            if (r1 != r2) perimeter_of_rect_itself.push_back({r2, c});\n                        }\n                        for (int r = r1 + 1; r < r2; ++r) { // Start from r1+1 to avoid double-counting corners with top/bottom rows\n                            perimeter_of_rect_itself.push_back({r, c1});\n                            if (c1 != c2) perimeter_of_rect_itself.push_back({r, c2});\n                        }\n                        \n                        if (!perimeter_of_rect_itself.empty()) {\n                            for (int i = 0; i < M; ++i) {\n                                int min_dist = 100000; \n                                for (const auto& p_cell : perimeter_of_rect_itself) {\n                                    min_dist = min(min_dist, abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c));\n                                }\n                                dist_sum_to_human_perimeter += min_dist;\n                            }\n                        } else { \n                            dist_sum_to_human_perimeter = 100000 * M; // High penalty for unapproachable/empty perimeter\n                        }\n\n                        // 2. Calculate initial \"vulnerability\" (number of unblockable wall cells around it)\n                        int vulnerability_score = 0;\n                        // Find potential wall cells (adjacent to current_rect, outside it)\n                        for (int r_outer = 0; r_outer < GRID_SIZE; ++r_outer) {\n                            for (int c_outer = 0; c_outer < GRID_SIZE; ++c_outer) {\n                                Point p_outer = {r_outer, c_outer};\n                                if (current_rect.contains(p_outer)) continue; // Can't block inside target rect\n                                bool adjacent_to_rect_internal = false;\n                                for (int d = 0; d < 4; ++d) {\n                                    Point neighbor_internal = {r_outer + DR[d], c_outer + DC[d]};\n                                    if (current_rect.contains(neighbor_internal)) {\n                                        adjacent_to_rect_internal = true;\n                                        break;\n                                    }\n                                }\n                                if (adjacent_to_rect_internal) { // p_outer is a candidate wall cell\n                                    // Check if this wall cell is initially unblockable due to pets\n                                    bool is_unblockable_by_pet_influence = false;\n                                    for (int p_idx = 0; p_idx < N; ++p_idx) {\n                                        Point pet = pet_pos[p_idx];\n                                        if (pet == p_outer) { // Pet is on the wall cell itself\n                                            is_unblockable_by_pet_influence = true;\n                                            break;\n                                        }\n                                        for (int d_pet = 0; d_pet < 4; ++d_pet) {\n                                            Point pet_neighbor = {pet.r + DR[d_pet], pet.c + DC[d_pet]};\n                                            if (pet_neighbor == p_outer) { // Wall cell is adjacent to a pet\n                                                is_unblockable_by_pet_influence = true;\n                                                break;\n                                            }\n                                        }\n                                        if (is_unblockable_by_pet_influence) break;\n                                    }\n                                    if (is_unblockable_by_pet_influence) {\n                                        vulnerability_score++;\n                                    }\n                                }\n                            }\n                        }\n                        \n                        // Heuristic score: Area - W1 * Sum_of_Distances - W2 * Vulnerability_Score\n                        // W1 = 1 to value proximity to humans\n                        // W2 = 10 to strongly penalize walls that are hard to build initially due to pets\n                        long long current_heuristic_score = current_area - dist_sum_to_human_perimeter * 1 - (long long)vulnerability_score * 10; \n\n                        if (current_heuristic_score > max_heuristic_score) {\n                            max_heuristic_score = current_heuristic_score;\n                            best_initial_rect = current_rect;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback: If no good pet-free rectangle found or area is too small.\n    // Use an arbitrary threshold of 25 cells for \"too small\" for M=5 humans.\n    if (best_initial_rect.area() == 0 || best_initial_rect.area() < (long long)M * 5) { \n        target_rect = {5, 5, 24, 24}; // Default to 20x20 central square (0-indexed)\n        // Ensure this fallback is also pet-free, if not, then the entire score will be zero anyway.\n        // It's assumed inputs guarantee at least some viable region.\n    } else {\n        target_rect = best_initial_rect;\n    }\n\n    // Generate the set of actual target wall cells that humans will block\n    // These are cells adjacent to target_rect, but outside target_rect.\n    set<Point> wall_target_cells_set;\n    for (int r_cell = 0; r_cell < GRID_SIZE; ++r_cell) {\n        for (int c_cell = 0; c_cell < GRID_SIZE; ++c_cell) {\n            Point p = {r_cell, c_cell};\n            if (target_rect.contains(p)) continue; // Cannot block inside the target rect\n            bool is_adjacent_to_target_rect_internal = false;\n            for (int d = 0; d < 4; ++d) {\n                Point neighbor = {r_cell + DR[d], c_cell + DC[d]};\n                if (target_rect.contains(neighbor)) {\n                    is_adjacent_to_target_rect_internal = true;\n                    break;\n                }\n            }\n            if (is_adjacent_to_target_rect_internal) {\n                wall_target_cells_set.insert(p);\n            }\n        }\n    }\n    // Convert to vector for easier iteration with indices.\n    vector<Point> target_wall_goals_vector(wall_target_cells_set.begin(), wall_target_cells_set.end());\n    \n    // `human_target_wall_goals[i]` stores the specific wall cell that human 'i' is trying to block.\n    vector<Point> human_target_wall_goals(M, {-1,-1}); \n\n    // --- Main Loop: 300 turns of human actions and pet movements ---\n    for (int turn = 0; turn < MAX_TURNS; ++turn) {\n        // 1. Determine `can_block_grid`: which cells are valid to block this turn.\n        // Initialize to true, then mark invalid ones.\n        vector<vector<bool>> can_block_grid(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n        // Pets make cells unblockable\n        for (int i = 0; i < N; ++i) {\n            Point p = pet_pos[i];\n            // Cell containing pet is unblockable\n            if(is_valid(p.r, p.c)) can_block_grid[p.r][p.c] = false; \n            // Cells adjacent to a pet are unblockable\n            for (int d = 0; d < 4; ++d) { \n                int nr = p.r + DR[d];\n                int nc = p.c + DC[d];\n                if (is_valid(nr, nc)) {\n                    can_block_grid[nr][nc] = false;\n                }\n            }\n        }\n        // Humans make cells unblockable (their own position)\n        for (int i = 0; i < M; ++i) {\n            Point h = human_pos[i];\n            if(is_valid(h.r, h.c)) can_block_grid[h.r][h.c] = false; \n        }\n\n        // 2. Human Action Planning\n        vector<char> actions_output(M, '.'); // Stores the final action character for each human\n        vector<Point> next_human_pos_candidates(M); // Stores each human's position AFTER actions\n        for(int i=0; i<M; ++i) next_human_pos_candidates[i] = human_pos[i]; // Default: stay put\n\n        set<Point> current_blocked_this_turn;       // Cells chosen to be blocked by humans THIS turn\n        set<Point> current_moved_to_this_turn_targets; // Cells chosen to be moved into by humans THIS turn\n\n        // 2.1. Update each human's block goal\n        // Humans greedily pick the best available wall target cell based on a score.\n        for (int i = 0; i < M; ++i) {\n            // Re-assign goal if current goal is completed, invalid, or already blocked\n            if (human_target_wall_goals[i].r == -1 || \n                !is_valid(human_target_wall_goals[i].r, human_target_wall_goals[i].c) ||\n                board[human_target_wall_goals[i].r][human_target_wall_goals[i].c] == 1) { \n                \n                Point best_goal = {-1,-1};\n                long long max_current_cell_score_for_human = -2e18; // Initialize with a very small number\n\n                // Temporarily track goals assigned to other humans (within this turn's assignment phase)\n                set<Point> temp_assigned_goals;\n                for(int j=0; j<M; ++j) {\n                    if (j != i && human_target_wall_goals[j].r != -1) {\n                        temp_assigned_goals.insert(human_target_wall_goals[j]);\n                    }\n                }\n\n                for (const auto& p_cell : target_wall_goals_vector) { // Iterate over actual wall target cells\n                    // Check if the wall target cell is currently:\n                    //   1. Passable (not already a permanent wall)\n                    //   2. Blockable (no pets nearby, not occupied by human/pet)\n                    //   3. Not already being blocked by another human this turn (from current_blocked_this_turn)\n                    //   4. Not already assigned as a goal to another human (for current goal assignment phase)\n                    if (board[p_cell.r][p_cell.c] == 0 && can_block_grid[p_cell.r][p_cell.c] && \n                        !current_blocked_this_turn.count(p_cell) && !temp_assigned_goals.count(p_cell)) {\n                        \n                        long long current_cell_score = 0;\n                        int dist_to_human = abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c); \n                        \n                        // Penalty for distance from human (lower dist is better, so subtract dist)\n                        current_cell_score -= (long long)dist_to_human * 1; \n\n                        // Bonus for blocking cells that are near pets (higher danger is better to block)\n                        int pet_danger_score = 0;\n                        for (int p_idx = 0; p_idx < N; ++p_idx) {\n                            Point pet = pet_pos[p_idx];\n                            if (target_rect.contains(pet)) continue; // Only consider pets outside target_rect\n                            \n                            int pet_dist = abs(pet.r - p_cell.r) + abs(pet.c - p_cell.c);\n                            if (pet_dist == 1) { // Manhattan dist 1 means adjacent\n                                pet_danger_score += 100; // Significant bonus for blocking a cell directly adjacent to a pet\n                            } else if (pet_dist == 2) { // Manhattan dist 2\n                                pet_danger_score += 10; // Moderate bonus\n                            } else if (pet_dist == 3) {\n                                pet_danger_score += 1; // Small bonus\n                            }\n                        }\n                        current_cell_score += pet_danger_score;\n\n                        if (current_cell_score > max_current_cell_score_for_human) {\n                            max_current_cell_score_for_human = current_cell_score;\n                            best_goal = p_cell;\n                        }\n                    }\n                }\n                human_target_wall_goals[i] = best_goal; // Assign the new best goal\n            }\n        }\n        \n        // 2.2. Phase 1: Determine BLOCK actions\n        // Humans who are adjacent to their block goal perform the block action.\n        for (int i = 0; i < M; ++i) {\n            if (human_target_wall_goals[i].r != -1) {\n                Point goal_to_block = human_target_wall_goals[i]; // This is the cell to make impassable\n                for (int d = 0; d < 4; ++d) { // Check if human is adjacent to this goal_to_block\n                    if (human_pos[i].r + DR[d] == goal_to_block.r && human_pos[i].c + DC[d] == goal_to_block.c) { \n                        // Human is adjacent to goal_to_block. Can they block it?\n                        if (board[goal_to_block.r][goal_to_block.c] == 0 && can_block_grid[goal_to_block.r][goal_to_block.c] && !current_blocked_this_turn.count(goal_to_block)) {\n                            actions_output[i] = BLOCK_CHARS[d]; // Set block action\n                            current_blocked_this_turn.insert(goal_to_block); // Mark as blocked for this turn\n                            board[goal_to_block.r][goal_to_block.c] = 1; // Temporarily update board for pathfinding in Phase 2\n                            human_target_wall_goals[i] = {-1,-1}; // Goal achieved, reset\n                        }\n                        break; // A human can only perform one action (block or move)\n                    }\n                }\n            }\n        }\n        \n        // 2.3. Phase 2: Determine MOVE actions for humans who did not block.\n        // Use a priority queue to resolve conflicts for moving to the same cell.\n        struct MoveCandidate {\n            int human_idx;\n            Point next_pos; // The cell human will move TO\n            char move_char;\n            int priority; // Higher priority (e.g., closer to goal) is better\n            bool operator<(const MoveCandidate& other) const {\n                return priority < other.priority; // Min-priority queue for default, so this makes it max-priority.\n            }\n        };\n        priority_queue<MoveCandidate> move_queue;\n\n        for (int i = 0; i < M; ++i) {\n            if (actions_output[i] == '.') { // Only if human didn't block in Phase 1\n                Point wall_cell_to_block = human_target_wall_goals[i];\n                if (wall_cell_to_block.r != -1) { // If there's still a wall target to move towards\n                    // Find the best position for the human to *stand* in order to block 'wall_cell_to_block'.\n                    // This means finding a cell adjacent to 'wall_cell_to_block' that is pathable for the human.\n                    Point target_human_stand_pos = {-1,-1};\n                    int min_dist_to_stand_pos = 100000;\n\n                    for(int d=0; d<4; ++d) {\n                        Point candidate_stand_pos = {wall_cell_to_block.r + DR[d], wall_cell_to_block.c + DC[d]};\n                        \n                        // Preliminary checks for a valid 'stand_pos' (more thorough check in BFS)\n                        if (is_valid(candidate_stand_pos.r, candidate_stand_pos.c) &&\n                            board[candidate_stand_pos.r][candidate_stand_pos.c] == 0 && // Not existing wall\n                            !current_blocked_this_turn.count(candidate_stand_pos)) { // Not blocked this turn\n                            \n                            int dist = abs(human_pos[i].r - candidate_stand_pos.r) + abs(human_pos[i].c - candidate_stand_pos.c); // Manhattan distance\n                            if (dist < min_dist_to_stand_pos) {\n                                min_dist_to_stand_pos = dist;\n                                target_human_stand_pos = candidate_stand_pos;\n                            }\n                        }\n                    }\n\n                    if (target_human_stand_pos.r != -1 && target_human_stand_pos != human_pos[i]) { // Found a valid stand position, and it's not current position\n                        // Use BFS to get the first move character towards target_human_stand_pos\n                        char move_c = get_move_char(human_pos[i], target_human_stand_pos, \n                                                    current_blocked_this_turn, current_moved_to_this_turn_targets, \n                                                    human_pos, i); \n                        if (move_c != '.') { // If a path was found\n                            Point first_step = human_pos[i]; // Will be updated\n                            for (int d_idx = 0; d_idx < 4; ++d_idx) {\n                                if (MOVE_CHARS[d_idx] == move_c) {\n                                    first_step = {human_pos[i].r + DR[d_idx], human_pos[i].c + DC[d_idx]};\n                                    break;\n                                }\n                            }\n                            // Priority is based on negative distance to target_human_stand_pos. Smaller distance means higher priority\n                            move_queue.push({i, first_step, move_c, -min_dist_to_stand_pos}); \n                        }\n                    }\n                }\n            }\n        }\n\n        // Process the move_queue to resolve conflicts (multiple humans wanting to move to the same cell)\n        while (!move_queue.empty()) {\n            MoveCandidate mc = move_queue.top();\n            move_queue.pop();\n\n            if (actions_output[mc.human_idx] == '.') { // If human hasn't been assigned an action yet\n                // Check if the target cell for this move is free (not blocked or targeted by another human)\n                if (!current_blocked_this_turn.count(mc.next_pos) && !current_moved_to_this_turn_targets.count(mc.next_pos)) {\n                    actions_output[mc.human_idx] = mc.move_char; // Assign the move action\n                    next_human_pos_candidates[mc.human_idx] = mc.next_pos; // Update planned position\n                    current_moved_to_this_turn_targets.insert(mc.next_pos); // Mark as targeted\n                }\n                // Else: Conflict occurred, the human stays put (action remains '.')\n            }\n        }\n\n        // 3. Output actions for all humans\n        for (int i = 0; i < M; ++i) {\n            cout << actions_output[i];\n        }\n        cout << endl; // Newline after all actions\n        fflush(stdout); // Crucial for interactive problems\n\n        // 4. Update game state (board and human_pos) based on actions\n        for (int i = 0; i < M; ++i) {\n            // If the action was a block, update the board state permanently\n            // Check if it's not a '.' and not one of the move characters ('U', 'D', 'L', 'R')\n            if (actions_output[i] != '.' && string(MOVE_CHARS).find(actions_output[i]) == string::npos) {\n                Point blocked_cell = human_pos[i]; // Default value\n                char block_char = actions_output[i];\n                for(int d=0; d<4; ++d) {\n                    if (BLOCK_CHARS[d] == block_char) {\n                        blocked_cell = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                        break;\n                    }\n                }\n                if (is_valid(blocked_cell.r, blocked_cell.c)) { // Sanity check for blocked_cell\n                    board[blocked_cell.r][blocked_cell.c] = 1; // Mark cell as impassable\n                }\n            }\n            human_pos[i] = next_human_pos_candidates[i]; // Update human positions\n        }\n\n        // 5. Read pet movements and update pet positions\n        string pet_moves_str;\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves_str;\n            if (pet_moves_str == \".\") continue; // Pet did not move\n            \n            for (char move_char : pet_moves_str) {\n                for (int d = 0; d < 4; ++d) {\n                    if (MOVE_CHARS[d] == move_char) {\n                        pet_pos[i].r += DR[d];\n                        pet_pos[i].c += DC[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int H = 20;\nconst int W = 20;\nconst int MAX_PATH_LENGTH = 200;\n\n// Global variables for problem input\nint start_r, start_c, target_r, target_c;\ndouble p_forget_val;\nbool has_wall_right[H][W - 1]; // wall between (r,c) and (r,c+1)\nbool has_wall_down[H - 1][W];  // wall between (r,c) and (r+1,c)\n\n// Directions for movement\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar move_chars[] = {'U', 'D', 'L', 'R'};\n\n// Helper function to calculate next position, staying if wall or boundary\npair<int, int> get_next_pos(int r, int c, char move_char) {\n    int nr = r, nc = c; // Default to staying\n    if (move_char == 'U') {\n        if (r > 0 && !has_wall_down[r - 1][c]) {\n            nr = r - 1;\n        }\n    } else if (move_char == 'D') {\n        if (r < H - 1 && !has_wall_down[r][c]) {\n            nr = r + 1;\n        }\n    } else if (move_char == 'L') {\n        if (c > 0 && !has_wall_right[r][c - 1]) {\n            nc = c - 1;\n        }\n    } else if (move_char == 'R') {\n        if (c < W - 1 && !has_wall_right[r][c]) {\n            nc = c + 1;\n        }\n    }\n    return {nr, nc};\n}\n\n// DP states (declared globally to avoid reallocations and for performance)\nvector<vector<double>> current_dp_state(H, vector<double>(W));\nvector<vector<double>> next_dp_state(H, vector<double>(W));\n\n// Evaluates a given path string\ndouble evaluate(const string& path) {\n    // Reset initial state for a new path evaluation\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_dp_state[i][j] = 0.0;\n        }\n    }\n    current_dp_state[start_r][start_c] = 1.0;\n\n    double total_expected_score = 0.0;\n\n    for (int k = 0; k < path.length(); ++k) {\n        // Clear next_dp_state for this turn's calculations\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                next_dp_state[i][j] = 0.0;\n            }\n        }\n\n        double prob_reach_this_turn = 0.0;\n        char move_char = path[k];\n\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                // Use a small epsilon for double comparison\n                if (current_dp_state[r][c] < 1e-18) continue; \n\n                // Option 1: Forgets char (prob p_forget_val), stays at (r,c)\n                next_dp_state[r][c] += current_dp_state[r][c] * p_forget_val;\n\n                // Option 2: Remembers char (prob 1-p_forget_val), moves according to move_char\n                pair<int, int> next_pos = get_next_pos(r, c, move_char);\n                int nr = next_pos.first;\n                int nc = next_pos.second;\n\n                if (nr == target_r && nc == target_c) {\n                    // Reached target at turn k+1\n                    prob_reach_this_turn += current_dp_state[r][c] * (1.0 - p_forget_val);\n                } else {\n                    // Did not reach target\n                    next_dp_state[nr][nc] += current_dp_state[r][c] * (1.0 - p_forget_val);\n                }\n            }\n        }\n\n        total_expected_score += prob_reach_this_turn * (401.0 - (k + 1));\n        current_dp_state.swap(next_dp_state); // Efficiently update current_dp_state\n    }\n    return total_expected_score;\n}\n\n// BFS to find the shortest path\nstring get_bfs_path() {\n    vector<vector<int>> dist(H, vector<int>(W, -1));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> move_to_parent(H, vector<char>(W, ' '));\n    queue<pair<int, int>> q;\n\n    q.push({start_r, start_c});\n    dist[start_r][start_c] = 0;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        if (r == target_r && c == target_c) break; // Found target\n\n        for (int i = 0; i < 4; ++i) { // For each direction (U, D, L, R)\n            int potential_nr = r + dr[i];\n            int potential_nc = c + dc[i];\n            char move_char = move_chars[i];\n\n            bool can_move = true;\n            if (move_char == 'U') {\n                if (r == 0 || has_wall_down[r - 1][c]) can_move = false;\n            } else if (move_char == 'D') {\n                if (r == H - 1 || has_wall_down[r][c]) can_move = false;\n            } else if (move_char == 'L') {\n                if (c == 0 || has_wall_right[r][c - 1]) can_move = false;\n            } else if (move_char == 'R') {\n                if (c == W - 1 || has_wall_right[r][c]) can_move = false;\n            }\n\n            if (!can_move) continue;\n            \n            // If can_move, the next valid position is (potential_nr, potential_nc)\n            if (dist[potential_nr][potential_nc] == -1) { // If not visited\n                dist[potential_nr][potential_nc] = dist[r][c] + 1;\n                parent[potential_nr][potential_nc] = {r, c};\n                move_to_parent[potential_nr][potential_nc] = move_char;\n                q.push({potential_nr, potential_nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path_str = \"\";\n    int curr_r = target_r;\n    int curr_c = target_c;\n    \n    // Problem guarantees start and target are different and reachable.\n    while (curr_r != start_r || curr_c != start_c) {\n        path_str += move_to_parent[curr_r][curr_c];\n        pair<int, int> p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read input\n    cin >> start_r >> start_c >> target_r >> target_c >> p_forget_val;\n\n    for (int i = 0; i < H; ++i) {\n        string row_h;\n        cin >> row_h;\n        for (int j = 0; j < W - 1; ++j) {\n            has_wall_right[i][j] = (row_h[j] == '1');\n        }\n    }\n    for (int i = 0; i < H - 1; ++i) {\n        string row_v;\n        cin >> row_v;\n        for (int j = 0; j < W; ++j) {\n            has_wall_down[i][j] = (row_v[j] == '1');\n        }\n    }\n\n    // Timer setup\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0; // Use 1.95 seconds to be safe\n\n    // Initial path (BFS shortest path)\n    string best_path_str = get_bfs_path();\n    double best_score = evaluate(best_path_str);\n    string current_path_str = best_path_str;\n    double current_score = best_score;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    // SA parameters: T_start is back to a robust value that worked.\n    double T_start = 2000.0; \n    double T_end = 1.0;     \n\n    // Cache BFS path length for mutation probability calculation\n    int bfs_path_length = best_path_str.length();\n\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) break;\n\n        double T = T_start * pow(T_end / T_start, elapsed_ms / TIME_LIMIT_MS);\n        \n        string new_path_str = current_path_str;\n        \n        // Adaptive Operation Selection Probabilities\n        double current_len = new_path_str.length();\n        \n        // Base weights for different operations\n        double change_char_weight = 2.0;\n        double insert_char_weight = 1.0;\n        double delete_char_weight = 1.0;\n        double duplicate_segment_weight = 1.0;\n\n        // Scale p_forget_val from [0.1, 0.5] to [0, 1]\n        double p_scaled = (p_forget_val - 0.1) / (0.5 - 0.1); \n\n        // Adjust weights based on p_forget_val (slightly adjusted)\n        // Higher p_forget_val -> more need for redundancy (insert/duplicate)\n        duplicate_segment_weight += p_scaled * 2.5; // Adjusted from 2.2\n        insert_char_weight += p_scaled * 1.5;      // Adjusted from 1.2\n        delete_char_weight -= p_scaled * 0.7;      // Adjusted from 0.9\n\n        // Estimate an \"optimal\" path length\n        // Multiplier for p_forget_val, encouraging longer paths for higher p (retained from last successful change)\n        double estimated_optimal_len = min((double)MAX_PATH_LENGTH, (double)bfs_path_length * (1.0 + p_forget_val * 4.0)); \n        \n        // Adjust weights based on current path length relative to estimated optimal (retained)\n        double len_diff_normalized = (current_len - estimated_optimal_len) / (MAX_PATH_LENGTH - bfs_path_length + 1e-9);\n        len_diff_normalized = max(-1.0, min(1.0, len_diff_normalized)); \n\n        insert_char_weight -= len_diff_normalized * 1.5; \n        duplicate_segment_weight -= len_diff_normalized * 1.5;\n        delete_char_weight += len_diff_normalized * 2.0; \n        \n        // Floor weights to ensure they are at least a small positive value\n        change_char_weight = max(0.01, change_char_weight);\n        insert_char_weight = max(0.01, insert_char_weight);\n        delete_char_weight = max(0.01, delete_char_weight);\n        duplicate_segment_weight = max(0.01, duplicate_segment_weight);\n        \n        // Calculate total weight and normalize to probabilities\n        double total_weight = change_char_weight + insert_char_weight + delete_char_weight + duplicate_segment_weight;\n        double p_change = change_char_weight / total_weight;\n        double p_insert = insert_char_weight / total_weight;\n        double p_delete = delete_char_weight / total_weight;\n        double p_duplicate = duplicate_segment_weight / total_weight;\n\n        // Cumulative probabilities for random choice\n        double cum_p_change = p_change;\n        double cum_p_insert = cum_p_change + p_insert;\n        double cum_p_delete = cum_p_insert + p_delete;\n        \n        double op_choice_rand = prob_dist(rng);\n\n        if (op_choice_rand < cum_p_change) { \n            // --- Operation 1: Change character ---\n            if (new_path_str.empty()) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            char original_char = new_path_str[idx];\n            \n            char new_char;\n            do {\n                uniform_int_distribution<int> char_dist(0, 3);\n                new_char = move_chars[char_dist(rng)];\n            } while (new_char == original_char); \n            \n            new_path_str[idx] = new_char;\n        } else if (op_choice_rand < cum_p_insert) {\n            // --- Operation 2: Insert character ---\n            if (new_path_str.length() >= MAX_PATH_LENGTH) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length()); \n            int idx = idx_dist(rng);\n            uniform_int_distribution<int> char_dist(0, 3);\n            char char_to_insert = move_chars[char_dist(rng)];\n            \n            new_path_str.insert(idx, 1, char_to_insert);\n        } else if (op_choice_rand < cum_p_delete) { \n            // --- Operation 3: Delete character ---\n            if (new_path_str.empty() || new_path_str.length() == 1) continue; \n\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            \n            new_path_str.erase(idx, 1);\n        } else {\n            // --- Operation 4: Duplicate/Repeat Segment (Refined) ---\n            if (new_path_str.length() < 2) continue; \n\n            uniform_int_distribution<int> seg_start_idx_dist(0, (int)new_path_str.length() - 2); \n            int seg_start_idx = seg_start_idx_dist(rng);\n            \n            int max_possible_seg_len_from_start = new_path_str.length() - seg_start_idx;\n            uniform_int_distribution<int> seg_len_dist(2, min(max_possible_seg_len_from_start, 20)); \n            int seg_len = seg_len_dist(rng);\n            \n            string segment = new_path_str.substr(seg_start_idx, seg_len);\n\n            if (new_path_str.length() + segment.length() > MAX_PATH_LENGTH) {\n                segment = segment.substr(0, MAX_PATH_LENGTH - new_path_str.length());\n                if (segment.length() < 2) continue; \n            }\n            if (segment.empty()) continue; \n\n            uniform_int_distribution<int> insert_idx_dist(0, (int)new_path_str.length()); \n            int insert_idx = insert_idx_dist(rng);\n            \n            new_path_str.insert(insert_idx, segment);\n        }\n\n        // Evaluate new path\n        double new_score = evaluate(new_path_str);\n\n        // SA acceptance criterion\n        if (new_score > current_score || prob_dist(rng) < exp((new_score - current_score) / T)) {\n            current_score = new_score;\n            current_path_str = new_path_str;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path_str = current_path_str;\n            }\n        }\n    }\n\n    cout << best_path_str << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple> // For std::tuple\n\n// Define grid dimensions\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0=Left, 1=Up, 2=Right, 3=Down\n// di, dj: changes in row and column for each direction\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0}; // Corrected curly braces\n\n// initial_to[tile_type][entry_direction] -> exit_direction\n// Provided by problem statement\nconst int initial_to[8][4] = {\n    {1, 0, -1, -1}, // Type 0: L-U curve (0-1)\n    {-1, 2, 1, -1}, // Type 1: U-R curve (1-2)\n    {-1, -1, 3, 2}, // Type 2: R-D curve (2-3)\n    {3, -1, -1, 0}, // Type 3: D-L curve (3-0)\n    {1, 0, 3, 2},   // Type 4: L-U and R-D (0-1, 2-3)\n    {3, 2, 1, 0},   // Type 5: U-R and D-L (1-2, 3-0)\n    {2, -1, 0, -1}, // Type 6: horizontal straight (0-2)\n    {-1, 3, -1, 1}  // Type 7: vertical straight (1-3)\n};\n\n// Stores the initial tile types read from input\nstd::vector<std::vector<int>> initial_tiles(H, std::vector<int>(W));\n// Stores the current rotation for each tile (0-3)\nstd::vector<std::vector<int>> current_rotations(H, std::vector<int>(W));\n\n// Precompute effective_to table for faster lookup\n// effective_to[initial_tile_type][rotation_count][entry_direction] -> exit_direction\nint effective_to[8][4][4];\n\nvoid precompute_effective_to() {\n    for (int t_initial = 0; t_initial < 8; ++t_initial) {\n        for (int r_rot = 0; r_rot < 4; ++r_rot) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // 1. Convert absolute entry direction to tile's original orientation\n                int d_base = (d_entry - r_rot + 4) % 4;\n                \n                // 2. Find exit direction in tile's original orientation\n                int exit_base = initial_to[t_initial][d_base];\n                \n                // 3. If broken, mark as -1\n                if (exit_base == -1) {\n                    effective_to[t_initial][r_rot][d_entry] = -1;\n                } else {\n                    // 4. Convert exit direction back to absolute orientation\n                    effective_to[t_initial][r_rot][d_entry] = (exit_base + r_rot) % 4;\n                }\n            }\n        }\n    }\n}\n\n// Function to calculate the exit direction for a given tile and entry\ninline int get_exit_dir(int r, int c, int d_entry) {\n    return effective_to[initial_tiles[r][c]][current_rotations[r][c]][d_entry];\n}\n\nstruct VisitedState {\n    int id;  // Unique ID for the current calculate_score() call or active path\n    int len; // Path length when this state was first visited in current active path\n};\n// Use static to initialize once to {0,0} for all entries\nstatic VisitedState visited_tracking[H][W][4];\nstatic int current_search_id = 0; // Incremented for each calculate_score() call\n\n// Global/static vector to avoid repeated allocations in calculate_score\nstatic std::vector<std::tuple<int, int, int>> nodes_in_current_path_segment_global;\n\nlong long calculate_score() {\n    std::vector<long long> loop_lengths;\n    current_search_id++; // New unique ID for this score calculation\n\n    // `active_path_id` is used to mark nodes *currently in the path exploration*.\n    // `current_search_id` is used to mark nodes that have been *fully processed*\n    // (either part of a completed cycle or a path that dead-ended/merged into an already processed segment).\n    int active_path_id = current_search_id + 1; // Unique ID for current path traversal\n\n    for (int r = 0; r < H; ++r) {\n        for (int c = 0; c < W; ++c) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // Skip if this state has already been part of a fully processed path/cycle\n                if (visited_tracking[r][c][d_entry].id == current_search_id) {\n                    continue; \n                }\n\n                int curr_r = r;\n                int curr_c = c;\n                int curr_d_entry = d_entry;\n                long long path_len = 0;\n                \n                nodes_in_current_path_segment_global.clear(); // Clear for current path exploration\n\n                while (true) {\n                    // Check if current node is out of bounds\n                    if (curr_r < 0 || curr_r >= H || curr_c < 0 || curr_c >= W) {\n                        break; // Out of bounds, path broken\n                    }\n                    \n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == active_path_id) {\n                        // Cycle detected! Current node was visited in this active path.\n                        // The length of the loop is the current path length minus the length\n                        // when this node was first visited in this active path.\n                        long long cycle_start_len = visited_tracking[curr_r][curr_c][curr_d_entry].len;\n                        loop_lengths.push_back(path_len - cycle_start_len);\n                        break;\n                    }\n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == current_search_id) {\n                        // Merged into an already processed path/cycle. This means this path segment\n                        // doesn't form a new distinct loop starting from `(r,c,d_entry)`.\n                        break;\n                    }\n\n                    // Mark current node as 'in active path' and record its length\n                    visited_tracking[curr_r][curr_c][curr_d_entry] = {active_path_id, (int)path_len};\n                    nodes_in_current_path_segment_global.emplace_back(curr_r, curr_c, curr_d_entry); // Store nodes for later global marking\n\n                    int d_exit = get_exit_dir(curr_r, curr_c, curr_d_entry);\n                    if (d_exit == -1) {\n                        break; // Broken line\n                    }\n\n                    int next_r = curr_r + di[d_exit];\n                    int next_c = curr_c + dj[d_exit];\n                    // The train enters the next tile from the opposite direction it exited.\n                    int next_d_entry = (d_exit + 2) % 4; \n                    path_len++;\n\n                    curr_r = next_r;\n                    curr_c = next_c;\n                    curr_d_entry = next_d_entry;\n                }\n\n                // After path ends (break from loop), mark all nodes visited in `nodes_in_current_path_segment_global`\n                // as 'processed for current_search_id'. This ensures they are not re-evaluated as starting points\n                // for new paths within the same `calculate_score` call.\n                for (const auto& node : nodes_in_current_path_segment_global) {\n                    visited_tracking[std::get<0>(node)][std::get<1>(node)][std::get<2>(node)].id = current_search_id;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) {\n        return 0; // Score is 0 if less than two loop lines\n    }\n\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend()); // Sort descending\n    return loop_lengths[0] * loop_lengths[1]; // Product of two longest loops\n}\n\n// Random number generator\nstd::mt19937 mt;\n\nvoid solve() {\n    auto start_time = std::chrono::high_resolution_clock::now();\n\n    // Read initial tile types\n    for (int i = 0; i < H; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < W; ++j) {\n            initial_tiles[i][j] = row_str[j] - '0';\n        }\n    }\n\n    precompute_effective_to();\n\n    // Initialize random number generator using current time\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\n    mt.seed(seed);\n\n    // Initial solution: assign random rotations to all tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_rotations[i][j] = mt() % 4;\n        }\n    }\n\n    std::vector<std::vector<int>> best_rotations = current_rotations;\n    long long current_score = calculate_score();\n    long long best_score = current_score;\n\n    // Simulated Annealing parameters\n    // T_START adjusted. Reverted to single-tile changes.\n    // This value is chosen to allow sufficient exploration at the start.\n    double T_START = 5000.0; \n    double TIME_LIMIT_MS = 1900.0; // Run for 1.9 seconds out of 2.0s total\n\n    // Store the changed tile and its old rotation for easy reversion\n    int r_idx_changed, c_idx_changed, old_rot_changed;\n\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) { \n            break; // Time limit exceeded, terminate SA\n        }\n\n        // Linear cooling schedule: temperature decreases over time\n        double T = T_START * (1.0 - elapsed_ms / TIME_LIMIT_MS);\n        if (T < 0.1) T = 0.1; // Prevent T from becoming too small, avoiding `exp()` issues or division by zero\n\n        // Generate neighbor state: change only ONE random tile\n        r_idx_changed = mt() % H;\n        c_idx_changed = mt() % W;\n        old_rot_changed = current_rotations[r_idx_changed][c_idx_changed];\n        int new_rot = (old_rot_changed + (mt() % 3) + 1) % 4; // Ensures new_rot is different from old_rot\n        \n        current_rotations[r_idx_changed][c_idx_changed] = new_rot;\n\n        long long neighbor_score = calculate_score();\n        \n        long long delta_score = neighbor_score - current_score;\n\n        // Acceptance criteria based on Metropolis-Hastings:\n        // Always accept if score improves (delta_score > 0).\n        // Otherwise, accept with probability exp(delta_score / T).\n        if (delta_score > 0 || std::uniform_real_distribution<double>(0.0, 1.0)(mt) < std::exp(delta_score / T)) {\n            current_score = neighbor_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations; // Update overall best solution\n            }\n        } else {\n            // Revert to old rotation if new state is not accepted\n            current_rotations[r_idx_changed][c_idx_changed] = old_rot_changed;\n        }\n    }\n\n    // Output the rotations corresponding to the best score found\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            std::cout << best_rotations[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\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 <random>\n#include <chrono>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <limits> // For numeric_limits\n\nusing namespace std;\n\n// --- Constants and Global Variables ---\nconst long long TIME_LIMIT_MS = 2800; // 2.8 seconds for computation\nconst double T_START = 1000.0;       // Initial temperature for more exploration\nconst double T_END = 50.0;           // Significantly increased final temperature for longer exploration\n\nint N;               // Board size\nint MAX_S_VALUE;     // Maximum possible S value (N*N - 1)\nlong long MAX_MOVES; // Maximum allowed operations (T = 2 * N^3)\n\n// Energy function weights\nlong double W_S_CRITICAL; // Huge weight for (MAX_S_VALUE - S) when S < MAX_S_VALUE\nlong double W_K = 1.0;    // Weight for K\n\n// Directions for empty square movement\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_char[] = {'U', 'D', 'L', 'R'};\nint opposite_dir[] = {1, 0, 3, 2}; // e.g., opposite of U(0) is D(1)\n\n// Global random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- DSU Structure for Score Calculation ---\nstruct DSU {\n    vector<int> parent;\n    vector<int> comp_size;\n    vector<int> num_edges;\n    vector<bool> has_cycle;\n    int num_cells;\n\n    DSU(int n_squared) : num_cells(n_squared) {\n        parent.resize(num_cells);\n        iota(parent.begin(), parent.end(), 0); // Initialize parent[i] = i\n        comp_size.assign(num_cells, 1);        // Each cell starts as a component of size 1\n        num_edges.assign(num_cells, 0);        // Each component starts with 0 edges\n        has_cycle.assign(num_cells, false);    // No cycles initially\n    }\n\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\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            // Union by size/rank: attach smaller tree to larger tree\n            if (comp_size[root_i] < comp_size[root_j])\n                swap(root_i, root_j);\n            parent[root_j] = root_i;\n            comp_size[root_i] += comp_size[root_j];\n            num_edges[root_i] += num_edges[root_j]; // Add edges from merged component\n            num_edges[root_i]++;                     // Add the new edge\n            has_cycle[root_i] = has_cycle[root_i] || has_cycle[root_j]; // Propagate cycle info\n        } else {\n            num_edges[root_i]++;         // Edge added within the same component\n            has_cycle[root_i] = true;    // This implies a cycle\n        }\n    }\n};\n\n// --- BoardState Structure ---\nstruct BoardState {\n    vector<vector<int>> board;\n    int empty_r, empty_c;\n    string moves;\n    int last_move_idx; // Index of the last move (0:U, 1:D, 2:L, 3:R), -1 if no previous move\n\n    BoardState(int n_val) : board(n_val, vector<int>(n_val)), empty_r(-1), empty_c(-1), last_move_idx(-1) {}\n\n    // Calculate the score S for the current board configuration\n    // S is the number of vertices in the largest tree component (connected and acyclic)\n    int calculate_S() const {\n        DSU dsu(N * N);\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // The empty cell is not part of the graph formed by tiles\n                if (r == empty_r && c == empty_c) continue;\n\n                int current_tile = board[r][c];\n                int current_idx = r * N + c;\n\n                // Check downward connection with (r+1, c)\n                if (r + 1 < N) {\n                    if (!(r + 1 == empty_r && c == empty_c)) { \n                        int neighbor_tile = board[r+1][c];\n                        int neighbor_idx = (r+1) * N + c;\n                        if ((current_tile & 8) && (neighbor_tile & 2)) { // Down line on current, Up line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n                // Check rightward connection with (r, c+1)\n                if (c + 1 < N) {\n                    if (!(r == empty_r && c + 1 == empty_c)) {\n                        int neighbor_tile = board[r][c+1];\n                        int neighbor_idx = r * N + (c+1);\n                        if ((current_tile & 4) && (neighbor_tile & 1)) { // Right line on current, Left line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n            }\n        }\n\n        int max_S = 0;\n        for (int i = 0; i < N * N; ++i) {\n            if (i == empty_r * N + empty_c) continue; // Skip empty square\n\n            if (dsu.parent[i] == i) { // If 'i' is the root of a component\n                if (!dsu.has_cycle[i]) {\n                    max_S = max(max_S, dsu.comp_size[i]);\n                }\n            }\n        }\n        return max_S;\n    }\n};\n\n// Function to calculate energy for SA\nlong double calculate_energy(int current_S, int current_K) {\n    if (current_S == MAX_S_VALUE) {\n        return (long double)current_K * W_K;\n    } else {\n        return (long double)(MAX_S_VALUE - current_S) * W_S_CRITICAL + (long double)current_K * W_K;\n    }\n}\n\n\n// --- Main Function ---\nint main() {\n    ios_base::sync_with_stdio(false); // Faster I/O\n    cin.tie(NULL);\n\n    cin >> N >> MAX_MOVES;\n\n    MAX_S_VALUE = N * N - 1; // Total number of tiles, excluding the empty one\n    W_S_CRITICAL = (long double)MAX_MOVES + 1.0; \n\n    BoardState current_state(N);\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            current_state.board[i][j] = stoi(string(1, row_str[j]), nullptr, 16);\n            if (current_state.board[i][j] == 0) { // Found the empty square\n                current_state.empty_r = i;\n                current_state.empty_c = j;\n            }\n        }\n    }\n\n    // Initialize best state with the initial state\n    BoardState best_state = current_state;\n    int current_S = current_state.calculate_S();\n    int current_K = 0; // Number of operations starts at 0\n\n    int best_S = current_S;\n    int best_K = current_K;\n\n    auto start_time = chrono::steady_clock::now();\n    long long iter_count = 0;\n\n    uniform_real_distribution<long double> dist_prob(0.0, 1.0); // For acceptance probability\n\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() < TIME_LIMIT_MS) {\n        iter_count++;\n\n        long double progress = (long double)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() / TIME_LIMIT_MS;\n        long double temp = T_START * pow(T_END / T_START, progress);\n        \n        if (temp < 1e-12) temp = 1e-12; // Safety net for extremely low temperatures\n\n        // Calculate energy for the current state\n        long double current_energy = calculate_energy(current_S, current_K);\n\n        // Determine possible moves\n        vector<int> possible_moves_indices;\n        for (int i = 0; i < 4; ++i) {\n            int next_empty_r = current_state.empty_r + dr[i];\n            int next_empty_c = current_state.empty_c + dc[i];\n\n            if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                if (current_state.last_move_idx == -1 || i != opposite_dir[current_state.last_move_idx]) {\n                    possible_moves_indices.push_back(i);\n                }\n            }\n        }\n        \n        if (possible_moves_indices.empty()) { // Fallback: if no non-reverting moves are available\n            for (int i = 0; i < 4; ++i) {\n                int next_empty_r = current_state.empty_r + dr[i];\n                int next_empty_c = current_state.empty_c + dc[i];\n                if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                     possible_moves_indices.push_back(i);\n                }\n            }\n            if (possible_moves_indices.empty()) { \n                 continue; // Should not happen for N >= 2\n            }\n        }\n\n        uniform_int_distribution<int> dist_valid_dir(0, possible_moves_indices.size() - 1);\n        int move_idx = possible_moves_indices[dist_valid_dir(rng)];\n\n        int prev_empty_r = current_state.empty_r;\n        int prev_empty_c = current_state.empty_c;\n        int moved_tile_r = prev_empty_r + dr[move_idx];\n        int moved_tile_c = prev_empty_c + dc[move_idx];\n        \n        BoardState next_state = current_state; // Copy\n        \n        next_state.board[prev_empty_r][prev_empty_c] = next_state.board[moved_tile_r][moved_tile_c];\n        next_state.board[moved_tile_r][moved_tile_c] = 0;\n        next_state.empty_r = moved_tile_r;\n        next_state.empty_c = moved_tile_c;\n        next_state.moves += dir_char[move_idx];\n        next_state.last_move_idx = move_idx;\n\n        int next_K = next_state.moves.length();\n        if (next_K > MAX_MOVES) {\n            continue; \n        }\n\n        int next_S = next_state.calculate_S();\n        long double next_energy = calculate_energy(next_S, next_K);\n\n        long double delta_E = next_energy - current_energy;\n\n        if (delta_E < 0 || dist_prob(rng) < exp(-delta_E / temp)) {\n            current_state = next_state;\n            current_S = next_S;\n            current_K = next_K;\n            \n            // Update the best solution found so far based on problem scoring rules\n            if (current_S > best_S) {\n                best_S = current_S;\n                best_K = current_K;\n                best_state = current_state;\n            } else if (current_S == best_S && current_K < best_K) { \n                best_K = current_K;\n                best_state = current_state;\n            }\n        }\n    }\n\n    // Output debug information to stderr\n    cerr << \"Iterations: \" << iter_count << endl;\n    cerr << \"Best S: \" << best_S << \" / \" << MAX_S_VALUE << endl;\n    cerr << \"Best K: \" << best_K << \" / \" << MAX_MOVES << endl;\n    \n    // Calculate final score for the best found state based on problem formula\n    long long final_score;\n    if (best_S == MAX_S_VALUE) {\n        final_score = round(500000.0 * (2.0 - (long double)best_K / MAX_MOVES));\n    } else {\n        final_score = round(500000.0 * ((long double)best_S / MAX_S_VALUE));\n    }\n    cerr << \"Final Score: \" << final_score << endl;\n\n    cout << best_state.moves << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // For std::gcd\n#include <algorithm> // For std::min, std::max\n#include <unordered_map>\n#include <bitset>    // For std::bitset\n#include <cassert>   // For debugging assertions\n#include <set>       // For tracking used strawberry pairs\n\n// Using long long for coordinates and intermediate calculations for lines\n// Max value for Ax + By + C can be large but fits in long long.\n\nusing namespace std;\n\n// --- Constants and Type Definitions ---\nconst int K_MAX_CUTS_CONST = 100; // K is fixed at 100\nconst long long MAX_INITIAL_LINE_COORD = 100000LL; // Range for line points (10x cake radius)\nconst long long MAX_PERTURB_MAG = 50000LL; // Max perturbation magnitude (5x cake radius)\n\n// --- Random Number Generator ---\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<long long> dist_line_coord(-MAX_INITIAL_LINE_COORD, MAX_INITIAL_LINE_COORD); \nuniform_int_distribution<int> dist_k_idx(0, K_MAX_CUTS_CONST - 1); \nuniform_int_distribution<int> dist_coord_choice(0, 3); // 0=px, 1=py, 2=qx, 3=qy\nuniform_real_distribution<double> dist_01(0.0, 1.0); // For SA acceptance probability\nuniform_int_distribution<int> dist_strawberry_idx; // Will be initialized with N_strawberries\n\n// --- Global variables ---\nint N_strawberries;\nint K_max_cuts; \nvector<int> a_attendees(11); // a_d for d=1 to 10. a_attendees[0] unused.\nlong long total_attendees_demand = 0; // Sum of a_d\n\nstruct Strawberry {\n    long long x, y;\n};\nvector<Strawberry> strawberries;\n\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C; // Line equation Ax + By + C = 0\n\n    Line(long long p1x, long long p1y, long long p2x, long long p2y) :\n        px(p1x), py(p1y), qx(p2x), qy(p2y) {\n        // Points (p1x, p1y) and (p2x, p2y) are guaranteed to be distinct by the caller.\n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n        \n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero, points were identical or other issue.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        \n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n    Line() : px(0), py(0), qx(1), qy(0), A(0), B(-1), C(0) {} // Default horizontal line y=0\n\n    void perturb(double decrease_factor) { // decrease_factor goes from 1.0 to 0.0 over time\n        long long perturb_magnitude = (long long)(MAX_PERTURB_MAG * decrease_factor) + 1; \n        \n        long long old_px = px, old_py = py, old_qx = qx, old_qy = qy; \n        \n        long long *coord_ptr;\n        switch (dist_coord_choice(rng)) {\n            case 0: coord_ptr = &px; break;\n            case 1: coord_ptr = &py; break;\n            case 2: coord_ptr = &qx; break;\n            default: coord_ptr = &qy; break;\n        }\n        long long new_coord_val = *coord_ptr + uniform_int_distribution<long long>(-perturb_magnitude, perturb_magnitude)(rng);\n        *coord_ptr = max(-MAX_INITIAL_LINE_COORD, min(MAX_INITIAL_LINE_COORD, new_coord_val));\n\n        if (px == qx && py == qy) { // If perturbation makes points identical, revert to original.\n            px = old_px; py = old_py; qx = old_qx; qy = old_qy;\n        }\n        \n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n\n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero after perturbation.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n};\n\n// Using std::bitset for piece signatures. Faster hashing and comparison than std::vector<char>.\n// A 'true' bit represents a positive side, 'false' a negative side.\nusing PieceSignature = std::bitset<K_MAX_CUTS_CONST>;\n\n// Custom hash for std::bitset (using std::hash for bitset)\nstruct BitsetHash {\n    std::size_t operator()(const PieceSignature& b) const {\n        return std::hash<std::bitset<K_MAX_CUTS_CONST>>{}(b);\n    }\n};\n\n// State variables for Simulated Annealing\nvector<PieceSignature> strawberry_line_sides_current_bits; \nvector<short> num_lines_passing_through_strawberry_current; \nunordered_map<PieceSignature, int, BitsetHash> piece_strawberry_counts_current; \nvector<long long> b_d_current(11, 0); \nlong long current_score = 0; \nvector<Line> current_lines; \n\n// Function to calculate the score based on a given b_d vector.\nlong long calculate_score(const vector<long long>& b_d_vec) {\n    long long actual_distributed = 0;\n    for (int d = 1; d <= 10; ++d) {\n        actual_distributed += min(a_attendees[d], (int)b_d_vec[d]);\n    }\n    if (total_attendees_demand == 0) return 0; // Should not happen given problem constraints (N > 0).\n    return round(1e6 * (double)actual_distributed / total_attendees_demand);\n}\n\n// Function to generate a purely random line\nLine generate_random_line() {\n    long long p1x, p1y, p2x, p2y;\n    do {\n        p1x = dist_line_coord(rng);\n        p1y = dist_line_coord(rng);\n        p2x = dist_line_coord(rng);\n        p2y = dist_line_coord(rng);\n    } while (p1x == p2x && p1y == p2y); \n    return Line(p1x, p1y, p2x, p2y);\n}\n\n// Function to generate a line passing through two specific strawberries\nLine generate_line_through_strawberries(int idx1, int idx2) {\n    return Line(strawberries[idx1].x, strawberries[idx1].y, strawberries[idx2].x, strawberries[idx2].y);\n}\n\n\n// Performs a full evaluation of the given set of lines.\nvoid full_evaluate(const vector<Line>& lines) {\n    strawberry_line_sides_current_bits.assign(N_strawberries, PieceSignature());\n    num_lines_passing_through_strawberry_current.assign(N_strawberries, 0); \n    piece_strawberry_counts_current.clear();\n    fill(b_d_current.begin(), b_d_current.end(), 0);\n\n    for (int j = 0; j < N_strawberries; ++j) {\n        for (int i = 0; i < K_max_cuts; ++i) {\n            long long val = lines[i].A * strawberries[j].x + lines[i].B * strawberries[j].y + lines[i].C;\n            if (val == 0) {\n                num_lines_passing_through_strawberry_current[j]++;\n                strawberry_line_sides_current_bits[j].set(i, true); // Arbitrary: set to true if on line\n            } else {\n                strawberry_line_sides_current_bits[j].set(i, val > 0); // true for >0, false for <0\n            }\n        }\n        if (num_lines_passing_through_strawberry_current[j] == 0) { \n            piece_strawberry_counts_current[strawberry_line_sides_current_bits[j]]++;\n        }\n    }\n\n    for (const auto& pair : piece_strawberry_counts_current) {\n        if (pair.second > 0 && pair.second <= 10) { \n            b_d_current[pair.second]++;\n        }\n    }\n    current_score = calculate_score(b_d_current);\n}\n\nvoid solve() {\n    cin >> N_strawberries >> K_max_cuts;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a_attendees[d];\n        total_attendees_demand += a_attendees[d];\n    }\n    strawberries.resize(N_strawberries);\n    dist_strawberry_idx = uniform_int_distribution<int>(0, N_strawberries - 1); // Initialize distribution for strawberry indices\n    num_lines_passing_through_strawberry_current.resize(N_strawberries); \n    for (int i = 0; i < N_strawberries; ++i) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n\n    current_lines.resize(K_max_cuts);\n    \n    // --- Smarter Initial Line Generation ---\n    // Generate K/2 lines connecting two random strawberries, K - K/2 purely random.\n    int num_strategic_lines = K_max_cuts / 2;\n    set<pair<int, int>> used_strawberry_pairs; // To avoid duplicate lines or lines through same strawberry pair\n    \n    for (int i = 0; i < num_strategic_lines; ++i) {\n        int idx1, idx2;\n        int attempts = 0;\n        do { // Ensure unique, distinct strawberry pair\n            idx1 = dist_strawberry_idx(rng);\n            idx2 = dist_strawberry_idx(rng);\n            if (idx1 > idx2) swap(idx1, idx2);\n            attempts++;\n            if (attempts > 1000 && N_strawberries < 200) { // If N_strawberries is small, can run out of unique pairs.\n                // Fallback to random if too hard to find unique pair\n                current_lines[i] = generate_random_line(); \n                idx1 = -1; idx2 = -1; // Mark as non-strawberry line\n                break;\n            }\n        } while (idx1 == idx2 || used_strawberry_pairs.count({idx1, idx2}));\n        \n        if (idx1 != -1) { // If a valid strawberry pair was found\n            current_lines[i] = generate_line_through_strawberries(idx1, idx2);\n            used_strawberry_pairs.insert({idx1, idx2});\n        }\n    }\n\n    for (int i = num_strategic_lines; i < K_max_cuts; ++i) {\n        current_lines[i] = generate_random_line();\n    }\n    // --- End Smarter Initial Line Generation ---\n    \n    full_evaluate(current_lines);\n\n    vector<Line> best_lines = current_lines;\n    long long best_score = current_score;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.95; \n\n    double T_start = 1e7; \n    double T_end = 1e-1;   \n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double temp_ratio = elapsed_time / TIME_LIMIT; \n        double T = T_start * pow(T_end / T_start, temp_ratio); \n\n        int line_idx_to_perturb = dist_k_idx(rng);\n        Line original_line_at_idx = current_lines[line_idx_to_perturb];\n        Line candidate_line = original_line_at_idx;\n\n        // --- Perturbation Strategy: Local adjustment OR Full replacement ---\n        if (dist_01(rng) < 0.05) { // 5% chance to completely replace the line\n            candidate_line = generate_random_line();\n        } else { // 95% chance for local adjustment\n            candidate_line.perturb(1.0 - temp_ratio); \n        }\n        // --- End Perturbation Strategy ---\n\n        vector<long long> temp_b_d = b_d_current;\n        unordered_map<PieceSignature, int, BitsetHash> temp_piece_strawberry_counts = piece_strawberry_counts_current;\n        \n        vector<bool> next_line_side_values_at_idx_bit(N_strawberries);\n        vector<short> next_num_lines_passing_through_commit(N_strawberries);\n\n\n        for (int j = 0; j < N_strawberries; ++j) {\n            long long val_original_line_k = original_line_at_idx.A * strawberries[j].x + original_line_at_idx.B * strawberries[j].y + original_line_at_idx.C;\n            long long val_candidate_line_k = candidate_line.A * strawberries[j].x + candidate_line.B * strawberries[j].y + candidate_line.C;\n\n            bool was_on_original_line_k = (val_original_line_k == 0);\n            bool is_on_candidate_line_k = (val_candidate_line_k == 0);\n\n            short temp_num_lines_passing_for_j = num_lines_passing_through_strawberry_current[j];\n            if (was_on_original_line_k && !is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j--;\n            } else if (!was_on_original_line_k && is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j++;\n            }\n            next_num_lines_passing_through_commit[j] = temp_num_lines_passing_for_j; \n\n            bool was_lost_j = (num_lines_passing_through_strawberry_current[j] > 0);\n            bool is_lost_j_candidate = (temp_num_lines_passing_for_j > 0);\n\n            bool new_side_k_value_for_key = (val_candidate_line_k > 0);\n            if (is_on_candidate_line_k) { \n                 new_side_k_value_for_key = true; \n            }\n            next_line_side_values_at_idx_bit[j] = new_side_k_value_for_key; \n            \n            // --- Update temp_b_d and temp_piece_strawberry_counts ---\n            \n            // Step 1: Remove strawberry j from its previous piece (if it was in one).\n            if (!was_lost_j) {\n                PieceSignature old_piece_key = strawberry_line_sides_current_bits[j];\n                int count_in_old_piece = temp_piece_strawberry_counts[old_piece_key]; \n                \n                temp_piece_strawberry_counts[old_piece_key]--;\n                if (count_in_old_piece >= 1 && count_in_old_piece <= 10) {\n                    temp_b_d[count_in_old_piece]--; \n                }\n                if (count_in_old_piece - 1 >= 1 && count_in_old_piece - 1 <= 10) { \n                    temp_b_d[count_in_old_piece - 1]++; \n                }\n            }\n\n            // Step 2: Add strawberry j to its new piece (if it will be in one).\n            if (!is_lost_j_candidate) {\n                PieceSignature new_piece_key = strawberry_line_sides_current_bits[j]; \n                new_piece_key.set(line_idx_to_perturb, new_side_k_value_for_key); \n                \n                int count_in_new_piece_before_add = temp_piece_strawberry_counts[new_piece_key];\n                temp_piece_strawberry_counts[new_piece_key]++;\n                \n                if (count_in_new_piece_before_add >= 1 && count_in_new_piece_before_add <= 10) {\n                    temp_b_d[count_in_new_piece_before_add]--;\n                }\n                if (count_in_new_piece_before_add + 1 >= 1 && count_in_new_piece_before_add + 1 <= 10) {\n                    temp_b_d[count_in_new_piece_before_add + 1]++;\n                }\n            }\n        } // End of strawberry loop\n        \n        long long new_score = calculate_score(temp_b_d);\n\n        if (new_score > current_score || dist_01(rng) < exp((double)(new_score - current_score) / T)) {\n            // Accept the change\n            current_lines[line_idx_to_perturb] = candidate_line;\n            b_d_current = temp_b_d;\n            piece_strawberry_counts_current = temp_piece_strawberry_counts;\n            current_score = new_score;\n\n            // Commit changes to global strawberry state variables.\n            for (int j = 0; j < N_strawberries; ++j) {\n                num_lines_passing_through_strawberry_current[j] = next_num_lines_passing_through_commit[j];\n                strawberry_line_sides_current_bits[j].set(line_idx_to_perturb, next_line_side_values_at_idx_bit[j]);\n            }\n\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_lines = current_lines;\n            }\n        }\n    }\n\n    cout << K_max_cuts << endl;\n    for (const auto& line : best_lines) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << endl;\n    }\n}\n\n// Main function to run the solution.\nint main() {\n    ios_base::sync_with_stdio(false); \n    cin.tie(NULL); \n    solve();\n    return 0;\n}\n","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set> \n#include <chrono>\n\n// To manage execution time\nstd::chrono::high_resolution_clock::time_point start_time;\ndouble time_limit_ms = 4900.0; // 4.9 seconds to be safe\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        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\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\nstruct RectangleOp {\n    Point p1, p2, p3, p4; // p1 is the new dot, p2, p3, p4 are existing dots\n};\n\nint N_global;\nint center_x_coord; \nint center_y_coord; \nstd::vector<std::vector<bool>> has_dot;\n\n// For condition 3: tracking drawn segments\n// horizontal_drawn[y][x]: segment (x,y)-(x+1,y)\nstd::vector<std::vector<bool>> horizontal_drawn;\n// vertical_drawn[x][y]: segment (x,y)-(x,y+1)\nstd::vector<std::vector<bool>> vertical_drawn; \n// diag_up_drawn[x][y]: segment (x,y)-(x+1,y+1) (slope +1)\nstd::vector<std::vector<bool>> diag_up_drawn;\n// diag_down_drawn[x][y]: segment (x,y+1)-(x+1,y) (slope -1)\nstd::vector<std::vector<bool>> diag_down_drawn;\n\n// Weights precomputation\nstd::vector<std::vector<double>> point_weights;\n\nbool is_in_bounds(Point p) {\n    return p.x >= 0 && p.x < N_global && p.y >= 0 && p.y < N_global;\n}\n\nvoid precompute_weights() {\n    point_weights.resize(N_global, std::vector<double>(N_global));\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            point_weights[i][j] = (double)((long long)(i - center_x_coord) * (i - center_x_coord) + \n                                           (long long)(j - center_y_coord) * (j - center_y_coord) + 1);\n        }\n    }\n}\n\ndouble get_weight(Point p) {\n    if (!is_in_bounds(p)) return -1.0; \n    return point_weights[p.x][p.y];\n}\n\nbool is_allowed_dot(Point p, Point p2, Point p3, Point p4) {\n    return p == p2 || p == p3 || p == p4;\n}\n\nbool check_perimeter_dots(Point p1_new, Point p2, Point p3, Point p4) {\n    auto check_segment = [&](Point start, Point end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        int steps = std::max(std::abs(dx), std::abs(dy));\n\n        if (steps == 0) return true; \n\n        for (int i = 1; i < steps; ++i) { // Exclude endpoints, only check intermediate points\n            Point p = {start.x + dx * i / steps, start.y + dy * i / steps};\n            \n            if (has_dot[p.x][p.y] && !is_allowed_dot(p, p2, p3, p4)) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    if (!check_segment(p1_new, p2)) return false;\n    if (!check_segment(p2, p3)) return false;\n    if (!check_segment(p3, p4)) return false;\n    if (!check_segment(p4, p1_new)) return false;\n    return true;\n}\n\nbool check_shared_segments(Point p1_new, Point p2, Point p3, Point p4, bool dry_run) {\n    auto process_segment = [&](Point start, Point end, bool dry_run_local) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0 && dy == 0) return true; // Not a segment of positive length\n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                if (dry_run_local) {\n                    if (vertical_drawn[x][y]) return false;\n                } else {\n                    vertical_drawn[x][y] = true;\n                }\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                if (dry_run_local) {\n                    if (horizontal_drawn[y][x]) return false;\n                } else {\n                    horizontal_drawn[y][x] = true;\n                }\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                if (dry_run_local) {\n                    if (diag_up_drawn[min_x + i][min_y + i]) return false;\n                } else {\n                    diag_up_drawn[min_x + i][min_y + i] = true;\n                }\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end); \n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                int x_curr = current_start.x + i;\n                int y_curr = current_start.y - i - 1; \n\n                if (dry_run_local) {\n                    if (diag_down_drawn[x_curr][y_curr]) return false;\n                } else {\n                    diag_down_drawn[x_curr][y_curr] = true;\n                }\n            }\n        }\n        return true;\n    };\n\n    if (!process_segment(p1_new, p2, dry_run)) return false;\n    if (!process_segment(p2, p3, dry_run)) return false;\n    if (!process_segment(p3, p4, dry_run)) return false;\n    if (!process_segment(p4, p1_new, dry_run)) return false;\n\n    return true; \n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    start_time = std::chrono::high_resolution_clock::now();\n\n    int M;\n    std::cin >> N_global >> M;\n\n    center_x_coord = (N_global - 1) / 2; \n    center_y_coord = (N_global - 1) / 2; \n\n    has_dot.resize(N_global, std::vector<bool>(N_global, false));\n    horizontal_drawn.resize(N_global, std::vector<bool>(N_global - 1, false));\n    vertical_drawn.resize(N_global, std::vector<bool>(N_global - 1, false)); \n    diag_up_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n    diag_down_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n\n    std::vector<Point> current_dots_list;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        std::cin >> x >> y;\n        current_dots_list.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    precompute_weights();\n\n    std::vector<RectangleOp> operations;\n    \n    // Loop until no more operations can be found or time runs out.\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n\n        double best_P1_weight = -1.0;\n        RectangleOp best_op;\n        bool found_op = false;\n\n        // Iterate over pairs of existing dots p_adj1 and p_adj2.\n        // Iterate current_dots_list in reverse to prioritize newer (typically outer) dots,\n        // which might help form new rectangles further from the center.\n        for (auto it1 = current_dots_list.rbegin(); it1 != current_dots_list.rend(); ++it1) {\n            Point p_adj1 = *it1; \n            for (auto it2 = current_dots_list.rbegin(); it2 != current_dots_list.rend(); ++it2) {\n                if (p_adj1 == *it2) continue; // p_adj1 and p_adj2 must be distinct\n                Point p_adj2 = *it2; \n\n                // --- Try Axis-aligned rectangle ---\n                // For vertices (P1, P2, P3, P4) in order: P1+P3 = P2+P4\n                // We pick P2=p_adj1, P4=p_adj2. Then P1 and P3 are derived.\n                // For axis-aligned, P1=(P2.x, P4.y) and P3=(P4.x, P2.y)\n                Point p1_new_aa = {p_adj1.x, p_adj2.y};\n                Point p_opp_aa = {p_adj2.x, p_adj1.y}; // This is P3\n\n                // Check for degenerate rectangle (zero width or height)\n                if (p_adj1.x == p_adj2.x || p_adj1.y == p_adj2.y) continue; \n\n                if (is_in_bounds(p1_new_aa) && !has_dot[p1_new_aa.x][p1_new_aa.y] && // p1_new must be empty\n                    is_in_bounds(p_opp_aa) && has_dot[p_opp_aa.x][p_opp_aa.y] &&    // p_opp must have a dot\n                    p1_new_aa != p_adj1 && p1_new_aa != p_opp_aa && p1_new_aa != p_adj2) // All 4 points distinct\n                {\n                    if (check_perimeter_dots(p1_new_aa, p_adj1, p_opp_aa, p_adj2) &&\n                        check_shared_segments(p1_new_aa, p_adj1, p_opp_aa, p_adj2, true)) { // dry_run = true\n                        double current_weight = get_weight(p1_new_aa);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_aa, p_adj1, p_opp_aa, p_adj2};\n                            found_op = true;\n                        }\n                    }\n                }\n\n                // --- Try 45-degree inclined rectangle ---\n                // Transform to (U,V) coordinates where U = x+y, V = x-y\n                // A 45-degree rectangle in (x,y) becomes axis-aligned in (U,V)\n                // Let (U2,V2) be from p_adj1, (U4,V4) from p_adj2.\n                // Then (U1,V1) = (U2,V4) and (U3,V3) = (U4,V2) (or vice versa for P1, P3)\n                int u_adj1 = p_adj1.x + p_adj1.y;\n                int v_adj1 = p_adj1.x - p_adj1.y;\n                int u_adj2 = p_adj2.x + p_adj2.y;\n                int v_adj2 = p_adj2.x - p_adj2.y;\n\n                // Check for degenerate rectangle in (U,V) space (zero width or height)\n                if (u_adj1 == u_adj2 || v_adj1 == v_adj2) continue;\n                \n                int u1_new = u_adj1; // U-coord for P1\n                int v1_new = v_adj2; // V-coord for P1\n                int u3_opp = u_adj2; // U-coord for P3\n                int v3_opp = v_adj1; // V-coord for P3\n\n                // Check parity for integer coordinates after inverse transform: x = (U+V)/2, y = (U-V)/2\n                // (U+V) and (U-V) must both be even, implies U and V must have the same parity.\n                if (((u1_new + v1_new) % 2 != 0) || ((u1_new - v1_new) % 2 != 0) ||\n                    ((u3_opp + v3_opp) % 2 != 0) || ((u3_opp - v3_opp) % 2 != 0)) {\n                    continue; // Points would not be on integer grid\n                }\n\n                Point p1_new_45 = {(u1_new + v1_new) / 2, (u1_new - v1_new) / 2};\n                Point p_opp_45 = {(u3_opp + v3_opp) / 2, (u3_opp - v3_opp) / 2};\n\n                if (is_in_bounds(p1_new_45) && !has_dot[p1_new_45.x][p1_new_45.y] &&\n                    is_in_bounds(p_opp_45) && has_dot[p_opp_45.x][p_opp_45.y] &&\n                    p1_new_45 != p_adj1 && p1_new_45 != p_opp_45 && p1_new_45 != p_adj2) {\n                    if (check_perimeter_dots(p1_new_45, p_adj1, p_opp_45, p_adj2) &&\n                        check_shared_segments(p1_new_45, p_adj1, p_opp_45, p_adj2, true)) { \n                        double current_weight = get_weight(p1_new_45);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_45, p_adj1, p_opp_45, p_adj2};\n                            found_op = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found_op) {\n            break; // No more valid operations found in this entire scan.\n        }\n\n        // Perform the single best operation found in this iteration\n        operations.push_back(best_op);\n        has_dot[best_op.p1.x][best_op.p1.y] = true;\n        current_dots_list.push_back(best_op.p1); // Add new dot to list for future iterations\n        check_shared_segments(best_op.p1, best_op.p2, best_op.p3, best_op.p4, false); // dry_run = false to mark segments\n    }\n\n    std::cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        std::cout << op.p1.x << \" \" << op.p1.y << \" \"\n                  << op.p2.x << \" \" << op.p2.y << \" \"\n                  << op.p3.x << \" \" << op.p3.y << \" \"\n                  << op.p4.x << \" \" << op.p4.y << \"\\n\";\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#include <queue> // For BFS in component calculation\n\n// Using std namespace for convenience in competitive programming context\nusing namespace std;\n\n// Constants for board size\nconst int N = 10; \n\n// Global board state\nvector<vector<int>> board(N, vector<int>(N, 0)); // 0: empty, 1,2,3: flavors\n\n// Stores the flavors of candies in the order they are received (f_1 to f_100)\nvector<int> flavors_data(100);\n\n// For the tie-breaker heuristic:\n// Maps original flavor index (1,2,3) to its assigned region index (0,1,2)\nmap<int, int> flavor_to_region_idx;\n// Maps assigned region index (0,1,2) back to its original flavor index (1,2,3)\nvector<int> region_idx_to_flavor(3); \n// Stores start and end rows for each assigned region (0,1,2)\nvector<int> region_rows_start(3); \nvector<int> region_rows_end(3);   \n\n// Directions for BFS and neighbor checks (4-way adjacency)\nconst int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\nconst int dc[] = {0, 0, -1, 1};\n\n\n// Function to find the (r, c) coordinates of the p-th empty cell\npair<int, int> get_coords_from_p_idx(int p_idx) {\n    int count = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) {\n                count++;\n                if (count == p_idx) {\n                    return {r, c};\n                }\n            }\n        }\n    }\n    return {-1, -1}; // Should not happen in a valid problem scenario\n}\n\n// Function to apply a tilt operation to a given board\nvoid apply_tilt(vector<vector<int>>& current_board, char dir) {\n    if (dir == 'F') { // Forward (up, towards row 0)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = 0; r < N; ++r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = 0; r < N; ++r) {\n                if (r < candies_in_col.size()) {\n                    current_board[r][c] = candies_in_col[r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'B') { // Backward (down, towards row N-1)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = N - 1; r >= 0; --r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = N - 1; r >= 0; --r) {\n                if ((N - 1 - r) < candies_in_col.size()) { // Fill from bottom up\n                    current_board[r][c] = candies_in_col[N - 1 - r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'L') { // Left (towards col 0)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = 0; c < N; ++c) {\n                if (c < candies_in_row.size()) {\n                    current_board[r][c] = candies_in_row[c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'R') { // Right (towards col N-1)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = N - 1; c >= 0; --c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = N - 1; c >= 0; --c) {\n                if ((N - 1 - c) < candies_in_row.size()) { // Fill from right to left\n                    current_board[r][c] = candies_in_row[N - 1 - c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    }\n}\n\n// Helper function to calculate the sum of n_i^2 for a given board state\nlong long calculate_sum_n_sq(const vector<vector<int>>& current_board) {\n    long long total_n_sq = 0;\n    \n    for (int flavor_to_check = 1; flavor_to_check <= 3; ++flavor_to_check) {\n        vector<vector<bool>> visited_for_flavor(N, vector<bool>(N, false));\n        \n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] == flavor_to_check && !visited_for_flavor[r][c]) {\n                    int current_component_size = 0;\n                    queue<pair<int, int>> q; \n                    q.push({r, c});\n                    visited_for_flavor[r][c] = true;\n                    \n                    while(!q.empty()){\n                        pair<int, int> curr = q.front();\n                        q.pop();\n                        current_component_size++;\n\n                        for (int i = 0; i < 4; ++i) {\n                            int nr = curr.first + dr[i];\n                            int nc = curr.second + dc[i];\n\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                                current_board[nr][nc] == flavor_to_check && !visited_for_flavor[nr][nc]) {\n                                visited_for_flavor[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                    total_n_sq += (long long)current_component_size * current_component_size;\n                }\n            }\n        }\n    }\n    return total_n_sq;\n}\n\n// Function to get the target flavor for a given cell (r, c) based on region partitioning\n// This function is for the tie-breaker heuristic\nint get_target_flavor_for_pos(int r, int c) {\n    int assigned_region_idx;\n    if (r >= region_rows_start[0] && r <= region_rows_end[0]) {\n        assigned_region_idx = 0;\n    } else if (r >= region_rows_start[1] && r <= region_rows_end[1]) {\n        assigned_region_idx = 1;\n    } else { // r must be in region 2\n        assigned_region_idx = 2;\n    }\n    return region_idx_to_flavor[assigned_region_idx];\n}\n\n// Function to calculate the score for the tie-breaker.\n// Rewards candies in correct regions (+1.0), penalizes those in wrong regions (-1.0),\n// and adds a bonus for same-flavor neighbors.\ndouble calculate_regional_match_score(const vector<vector<int>>& current_board) {\n    double match_score = 0.0;\n    const double neighbor_bonus_weight = 0.01; // Small bonus for each same-flavor neighbor\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (current_board[r][c] != 0) { // If there's a candy in this cell\n                int candy_flavor = current_board[r][c];\n                int target_flavor = get_target_flavor_for_pos(r, c); \n                \n                if (candy_flavor == target_flavor) {\n                    match_score += 1.0; \n                } else {\n                    match_score -= 1.0; // Penalty for being in the wrong region\n                }\n\n                // Add bonus for same-flavor neighbors (4-direction)\n                int same_flavor_neighbors = 0;\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                        current_board[nr][nc] == candy_flavor) {\n                        same_flavor_neighbors++;\n                    }\n                }\n                match_score += same_flavor_neighbors * neighbor_bonus_weight;\n            }\n        }\n    }\n    return match_score;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read all candy flavors (f_1 to f_100)\n    vector<int> d_counts(4, 0); // d_counts[0] unused, d_counts[1,2,3] for flavors 1,2,3\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors_data[i];\n        d_counts[flavors_data[i]]++;\n    }\n\n    // Determine region assignment based on flavor counts (for tie-breaker)\n    vector<pair<int, int>> flavor_data_sorted; \n    flavor_data_sorted.push_back({d_counts[1], 1});\n    flavor_data_sorted.push_back({d_counts[2], 2});\n    flavor_data_sorted.push_back({d_counts[3], 3});\n\n    sort(flavor_data_sorted.rbegin(), flavor_data_sorted.rend()); \n\n    for (int i = 0; i < 3; ++i) {\n        flavor_to_region_idx[flavor_data_sorted[i].second] = i;\n        region_idx_to_flavor[i] = flavor_data_sorted[i].second;\n    }\n\n    vector<int> row_counts(3);\n    int assigned_total_rows = 0;\n    for (int i = 0; i < 2; ++i) { \n        row_counts[i] = round(flavor_data_sorted[i].first * static_cast<double>(N) / 100.0);\n        row_counts[i] = max(1, row_counts[i]); \n        assigned_total_rows += row_counts[i];\n    }\n    row_counts[2] = max(1, N - assigned_total_rows); \n\n    int current_sum_row_counts = row_counts[0] + row_counts[1] + row_counts[2];\n    int diff = current_sum_row_counts - N;\n    if (diff > 0) { \n        for (int i = 0; i < 3 && diff > 0; ++i) {\n            if (row_counts[i] > 1) { \n                int decrement_val = min(diff, row_counts[i] - 1);\n                row_counts[i] -= decrement_val;\n                diff -= decrement_val;\n            }\n        }\n    }\n\n    int current_row_idx = 0;\n    for (int i = 0; i < 3; ++i) {\n        region_rows_start[i] = current_row_idx;\n        region_rows_end[i] = current_row_idx + row_counts[i] - 1;\n        current_row_idx += row_counts[i];\n    }\n    \n    // Main loop: process each candy one by one\n    char directions[] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p_t;\n        cin >> p_t; // Read the index of the empty cell for the current candy\n\n        // Find coordinates for the new candy\n        pair<int, int> new_candy_coords = get_coords_from_p_idx(p_t);\n        int r_new = new_candy_coords.first;\n        int c_new = new_candy_coords.second;\n\n        // Place the new candy on the board\n        board[r_new][c_new] = flavors_data[t];\n\n        long long best_tilt_score_n_sq = -1; // Initialize with a small number, scores are non-negative\n        double best_tie_breaker_score = -1e18; // Initialize tie-breaker score with a very small number (can be negative)\n        char best_dir = ' ';\n\n        // Evaluate each of the four possible tilt directions\n        for (char dir : directions) {\n            vector<vector<int>> temp_board = board; // Create a copy of the board for simulation\n            apply_tilt(temp_board, dir); // Simulate the tilt\n\n            // Primary metric: sum of n_i^2\n            long long current_tilt_score_n_sq = calculate_sum_n_sq(temp_board);\n            \n            // Secondary metric (for tie-breaking): regional match score with neighbor bonus\n            double current_tie_breaker_score = calculate_regional_match_score(temp_board);\n\n            // Update best direction if current tilt yields a higher primary score,\n            // or if primary scores are equal and secondary score is higher.\n            if (current_tilt_score_n_sq > best_tilt_score_n_sq) {\n                best_tilt_score_n_sq = current_tilt_score_n_sq;\n                best_tie_breaker_score = current_tie_breaker_score;\n                best_dir = dir;\n            } else if (current_tilt_score_n_sq == best_tilt_score_n_sq) {\n                if (current_tie_breaker_score > best_tie_breaker_score) {\n                    best_tie_breaker_score = current_tie_breaker_score;\n                    best_dir = dir;\n                }\n            }\n        }\n\n        // Apply the chosen best tilt to the actual board\n        apply_tilt(board, best_dir);\n\n        // Output the chosen direction and flush stdout\n        cout << best_dir << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <map>\n#include <iomanip>\n#include <cmath> // For std::round, std::abs, std::pow\n\n// Adjacency matrix representation\nusing AdjMatrix = std::vector<std::vector<bool>>;\n\n// Function to convert adjacency matrix to string representation\nstd::string graph_to_string(const AdjMatrix& adj, int N) {\n    std::string s = \"\";\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Function to convert string representation to adjacency matrix\nAdjMatrix string_to_graph(const std::string& s, int N) {\n    AdjMatrix adj(N, std::vector<bool>(N, false));\n    int k_str = 0; // Index for the string s\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[k_str] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            k_str++;\n        }\n    }\n    return adj;\n}\n\n// Computes WL refinement color histogram (fingerprint) of a graph\nstd::map<int, int> compute_wl_fingerprint(const AdjMatrix& adj, int N, int wl_iters) {\n    std::vector<int> colors(N);\n    // Initial colors based on degrees\n    for (int i = 0; i < N; ++i) {\n        int degree = 0;\n        for (int j = 0; j < N; ++j) {\n            if (adj[i][j]) {\n                degree++;\n            }\n        }\n        colors[i] = degree;\n    }\n\n    // If wl_iters is 0, just return the degree distribution as fingerprint\n    if (wl_iters == 0) {\n        std::map<int, int> histogram;\n        for (int c : colors) {\n            histogram[c]++;\n        }\n        return histogram;\n    }\n\n    // For WL iterations > 0\n    // Use a unique color_map for each iteration to avoid global state issues.\n    // Or, more efficiently, reset/clear the map for each graph's WL computation.\n    // However, the current structure means 'color_map' is local to compute_wl_fingerprint,\n    // so it's fresh for each graph processed. The 'next_color_idx' ensures unique IDs within one graph's WL processing.\n    std::map<std::vector<int>, int> color_map; // Maps unique (current_color, sorted_neighbor_colors) to a new integer color\n    int next_color_idx = 0; // Counter for assigning new unique colors for this iteration\n\n    for (int iter = 0; iter < wl_iters; ++iter) {\n        // Clear color_map and reset next_color_idx for each iteration for distinctness\n        // No, this is incorrect. The colors are global for all N vertices within ONE graph.\n        // It's 'colors' (the vector) that holds the current iteration's state.\n        // `color_map` is used to map combinations of old_color+neighbor_colors to NEW_color.\n        // This mapping has to be consistent within one iteration for all vertices.\n        // The implementation already correctly uses a single color_map and next_color_idx for a full WL computation for one graph.\n        std::vector<int> new_colors(N);\n        for (int i = 0; i < N; ++i) {\n            std::vector<int> neighbor_colors;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    neighbor_colors.push_back(colors[j]);\n                }\n            }\n            std::sort(neighbor_colors.begin(), neighbor_colors.end());\n\n            // Construct key for color_map: current color + sorted list of neighbor colors\n            std::vector<int> current_key = {colors[i]};\n            current_key.insert(current_key.end(), neighbor_colors.begin(), neighbor_colors.end());\n            \n            // Assign a new unique color if this key hasn't been seen before\n            if (color_map.find(current_key) == color_map.end()) {\n                color_map[current_key] = next_color_idx++;\n            }\n            new_colors[i] = color_map[current_key];\n        }\n        colors = new_colors; // Update colors for the next iteration\n    }\n\n    // Compute histogram of final colors\n    std::map<int, int> histogram;\n    for (int c : colors) {\n        histogram[c]++;\n    }\n    return histogram;\n}\n\n// Calculates squared Euclidean distance between two color histograms\ndouble histogram_distance(const std::map<int, int>& h1, const std::map<int, int>& h2) {\n    double dist_sq = 0;\n    \n    // Collect all unique colors present in either histogram\n    std::vector<int> all_colors_keys;\n    for(const auto& pair : h1) all_colors_keys.push_back(pair.first);\n    for(const auto& pair : h2) all_colors_keys.push_back(pair.first);\n    std::sort(all_colors_keys.begin(), all_colors_keys.end());\n    all_colors_keys.erase(std::unique(all_colors_keys.begin(), all_colors_keys.end()), all_colors_keys.end());\n\n    for (int color : all_colors_keys) {\n        int count1 = h1.count(color) ? h1.at(color) : 0;\n        int count2 = h2.count(color) ? h2.at(color) : 0;\n        dist_sq += (double)(count1 - count2) * (count1 - count2);\n    }\n    return dist_sq;\n}\n\n// Global variables for problem parameters and generated graphs\nint M_param;\ndouble EPSILON_param;\nint N_chosen;\nstd::vector<AdjMatrix> G_graphs;\nstd::vector<std::map<int, int>> G_fingerprints; // Precomputed fingerprints for G_graphs\nstd::vector<int> G_edge_counts; // Precomputed edge counts for G_graphs\nint WL_ITERS_chosen; // Number of WL iterations to use\nint E_total_possible; // Total possible edges for N_chosen vertices\n\n// Function to precompute N and all M graphs G_k\nvoid precompute_graphs() {\n    // Determine N based on M and epsilon. Refined heuristic choice.\n    // Aims for a smaller N to minimize score penalty, while still providing enough capacity.\n    N_chosen = std::min(100, std::max(4, (int)(M_param * 0.3 + 10 + EPSILON_param * 20))); // Adjusted factors\n\n    // Determine WL_ITERS based on epsilon. Heuristic choice.\n    // Fewer iterations for higher epsilon to prevent noise from propagating too much.\n    // wl_iters can be 0, meaning only initial degree distribution is used.\n    WL_ITERS_chosen = std::max(0, 3 - (int)(EPSILON_param * 5));\n\n    E_total_possible = N_chosen * (N_chosen - 1) / 2; // Total possible edges\n    \n    G_graphs.resize(M_param);\n    G_fingerprints.resize(M_param);\n    G_edge_counts.resize(M_param);\n\n    // List all possible edges to facilitate random selection\n    std::vector<std::pair<int, int>> all_possible_edges;\n    for (int i = 0; i < N_chosen; ++i) {\n        for (int j = i + 1; j < N_chosen; ++j) {\n            all_possible_edges.push_back({i, j});\n        }\n    }\n\n    for (int k = 0; k < M_param; ++k) {\n        AdjMatrix current_G(N_chosen, std::vector<bool>(N_chosen, false));\n        \n        // Target number of edges for G_k.\n        // Distributed from 0 to E_total across M graphs.\n        int target_edges_count = std::round((double)k / (M_param - 1) * E_total_possible);\n        if (M_param == 1) target_edges_count = 0; // Special case for M=1 to avoid division by zero\n        \n        // Generate edges using a pseudo-random approach.\n        // A fixed seed 'k' ensures G_k is deterministic and distinct for each k.\n        std::mt19937 rng(k); \n        std::vector<std::pair<int, int>> shuffled_edges = all_possible_edges;\n        std::shuffle(shuffled_edges.begin(), shuffled_edges.end(), rng);\n\n        // Add the target number of edges\n        int actual_edges = 0;\n        for (int i = 0; i < target_edges_count; ++i) {\n            auto edge = shuffled_edges[i];\n            current_G[edge.first][edge.second] = true;\n            current_G[edge.second][edge.first] = true;\n            actual_edges++;\n        }\n        G_graphs[k] = current_G;\n        G_edge_counts[k] = actual_edges; // Store precomputed edge count\n        \n        // Precompute fingerprint for efficiency\n        G_fingerprints[k] = compute_wl_fingerprint(current_G, N_chosen, WL_ITERS_chosen);\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read M and epsilon\n    std::cin >> M_param >> EPSILON_param;\n\n    // Perform precomputation (determine N, generate G_k graphs and their fingerprints)\n    precompute_graphs();\n\n    // Output N and the M generated graphs\n    std::cout << N_chosen << std::endl;\n    for (int k = 0; k < M_param; ++k) {\n        std::cout << graph_to_string(G_graphs[k], N_chosen) << std::endl;\n    }\n    std::cout << std::flush; // Crucial for interactive problems\n\n    // Calculate normalization factor for WL distance. Max possible squared difference in a histogram of N vertices.\n    // If N is very small (e.g., N=4), 2.0 * N_chosen * N_chosen could be too large relative to max actual diff.\n    // For N_chosen vertices, the sum of counts in a histogram is N_chosen.\n    // Max diff for any single bucket is N_chosen. Max sum of squared diffs is 2*N_chosen^2.\n    // This value seems okay for normalization.\n    double wl_norm_factor = 2.0 * N_chosen * N_chosen;\n    if (N_chosen <= 1) wl_norm_factor = 1.0; // Defensive check, N_chosen >= 4\n\n    // Calculate weight alpha for combining distances.\n    // Alpha scales from 0 (pure WL) to 1 (pure edge count diff) as epsilon goes from 0 to 0.4.\n    // Using a square root power ensures edge_diff becomes relevant more quickly for intermediate epsilon.\n    double alpha_weight_base = EPSILON_param / 0.4;\n    double alpha_weight = std::pow(alpha_weight_base, 0.5); // Using sqrt to adjust weighting curve\n    \n    // Clamp alpha_weight to [0, 1] for robustness against floating point errors or edge cases.\n    alpha_weight = std::max(0.0, std::min(1.0, alpha_weight));\n\n    // For very small epsilon, ensure alpha_weight is 0 to prioritize WL.\n    if (EPSILON_param < 0.001) alpha_weight = 0.0;\n    // For very large epsilon, ensure alpha_weight is 1 to prioritize edge count.\n    if (EPSILON_param > 0.399) alpha_weight = 1.0;\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str; // Read the received graph H_k\n        \n        // Compute fingerprint for H_k\n        AdjMatrix H_adj = string_to_graph(H_str, N_chosen);\n        std::map<int, int> H_fingerprint = compute_wl_fingerprint(H_adj, N_chosen, WL_ITERS_chosen);\n        \n        // Count edges in H_k\n        int H_edge_count = 0;\n        for (char c : H_str) {\n            if (c == '1') {\n                H_edge_count++;\n            }\n        }\n\n        double min_total_dist = -1.0;\n        int best_t = -1;\n\n        // Compare H_k's fingerprint and edge count with all precomputed G_t\n        for (int t = 0; t < M_param; ++t) {\n            // WL distance\n            double wl_dist = histogram_distance(H_fingerprint, G_fingerprints[t]);\n            double normalized_wl_dist = wl_dist / wl_norm_factor;\n\n            // Edge count difference distance\n            double edge_diff = std::abs((double)H_edge_count - G_edge_counts[t]);\n            double normalized_edge_diff = edge_diff / (double)E_total_possible;\n            if (E_total_possible == 0) normalized_edge_diff = 0.0; // Should not happen with N_chosen>=4, but for safety.\n\n            // Combined distance\n            double current_total_dist = (1.0 - alpha_weight) * normalized_wl_dist + alpha_weight * normalized_edge_diff;\n            \n            if (best_t == -1 || current_total_dist < min_total_dist) {\n                min_total_dist = current_total_dist;\n                best_t = t;\n            }\n        }\n        std::cout << best_t << std::endl; // Output the prediction\n        std::cout << std::flush; // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <limits>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <map>\n#include <iomanip> // For setprecision\n#include <random>\n\nusing namespace std;\n\n// Using long long for distances to avoid overflow for sums\nconst long long INF = numeric_limits<long long>::max() / 2; // A sufficiently large value that avoids overflow when added to\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Node {\n    long long dist;\n    int u;\n    bool operator>(const Node& other) const {\n        return dist > other.dist;\n    }\n};\n\nstruct EdgeInfo {\n    int u, v, w, id;\n    long double val; // combined importance score: extra_dist * edge_betweenness\n};\n\nvector<vector<pair<int, int>>> adj; // adj[u] = list of {v, edge_id}\nvector<Edge> edges_data;\nint N_global, M_global, D_global, K_global;\n\n// Dijkstra's algorithm to find shortest paths from a source s\n// Optionally excludes a specific edge for extra_dist calculation\n// Returns a vector of distances from s to all other vertices.\nvector<long long> dijkstra(int s, const vector<vector<pair<int, int>>>& current_adj, int excluded_edge_id = -1) {\n    vector<long long> dist(N_global, INF);\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n    dist[s] = 0;\n    pq.push({0, s});\n\n    while (!pq.empty()) {\n        long long d = pq.top().dist;\n        int u = pq.top().u;\n        pq.pop();\n\n        if (d > dist[u]) continue; // Already found a shorter path\n\n        for (auto& edge_pair : current_adj[u]) {\n            int v = edge_pair.first;\n            int edge_id = edge_pair.second;\n\n            if (edge_id == excluded_edge_id) continue;\n\n            long long weight = edges_data[edge_id].w;\n            if (dist[u] != INF && dist[u] + weight < dist[v]) { // dist[u] != INF check to prevent overflow\n                dist[v] = dist[u] + weight;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Brandes' algorithm for Edge Betweenness Centrality\n// Returns a vector where element i is the betweenness centrality of edge_data[i]\nvector<long double> calculate_edge_betweenness() {\n    vector<long double> edge_betweenness(M_global, 0.0);\n\n    for (int s = 0; s < N_global; ++s) {\n        vector<long long> dist(N_global, INF);\n        vector<long long> num_shortest_paths(N_global, 0); // Count of shortest paths from s to v\n        vector<vector<int>> predecessors(N_global); // For each v, a list of vertices u that precede v on shortest paths from s\n        vector<int> stack; // To process vertices in decreasing order of distance\n\n        priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n        dist[s] = 0;\n        num_shortest_paths[s] = 1;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            long long d = pq.top().dist;\n            int u = pq.top().u;\n            pq.pop();\n\n            if (d > dist[u]) continue; \n            \n            stack.push_back(u); // Add to stack for processing in reverse order of distance\n\n            for (auto& edge_pair : adj[u]) {\n                int v = edge_pair.first;\n                int edge_id = edge_pair.second;\n                long long weight = edges_data[edge_id].w;\n\n                if (dist[u] != INF) { // Only consider paths from reachable u\n                    if (dist[u] + weight < dist[v]) {\n                        dist[v] = dist[u] + weight;\n                        num_shortest_paths[v] = num_shortest_paths[u];\n                        predecessors[v].clear();\n                        predecessors[v].push_back(u);\n                        pq.push({dist[v], v});\n                    } else if (dist[u] + weight == dist[v]) {\n                        num_shortest_paths[v] += num_shortest_paths[u];\n                        predecessors[v].push_back(u);\n                    }\n                }\n            }\n        }\n\n        vector<long double> delta(N_global, 0.0); // Dependency of s on v\n        while (!stack.empty()) {\n            int v = stack.back();\n            stack.pop_back();\n\n            for (int u_pred : predecessors[v]) {\n                // Fraction of shortest paths from s to v that pass through u_pred\n                // num_shortest_paths[v] must be > 0 here, because v is reachable from s\n                long double path_fraction = (long double)num_shortest_paths[u_pred] / num_shortest_paths[v];\n                long double contribution = path_fraction * (1.0 + delta[v]);\n                \n                // Find edge_id for (u_pred, v)\n                int found_edge_id = -1;\n                for(const auto& edge_pair : adj[u_pred]) {\n                    if (edge_pair.first == v) {\n                        found_edge_id = edge_pair.second;\n                        break; \n                    }\n                }\n                \n                if (found_edge_id != -1) { // Should always be found for edges on shortest paths\n                    edge_betweenness[found_edge_id] += contribution;\n                }\n                delta[u_pred] += contribution;\n            }\n        }\n    }\n    return edge_betweenness;\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    cin >> N_global >> M_global >> D_global >> K_global;\n\n    adj.resize(N_global);\n    edges_data.resize(M_global);\n\n    for (int i = 0; i < M_global; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v; // 0-indexed\n        edges_data[i] = {u, v, w, i};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i}); // Add edge for both directions\n    }\n\n    // Skip coordinates input as they are not used in this solution\n    for (int i = 0; i < N_global; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge betweenness centrality for each edge\n    vector<long double> edge_betweenness = calculate_edge_betweenness();\n\n    // 2. Precompute extra_dist for each edge (d'(u,v) - w when edge (u,v) is removed)\n    vector<long long> extra_dist(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        int u = edges_data[i].u;\n        int v = edges_data[i].v;\n        int w = edges_data[i].w;\n        vector<long long> dist_from_u_without_edge = dijkstra(u, adj, i);\n        // If u and v become disconnected, consider the path effectively infinite (10^9 from problem)\n        // Ensure extra_dist is non-negative\n        extra_dist[i] = (dist_from_u_without_edge[v] == INF) ? (1000000000LL - w) : (dist_from_u_without_edge[v] - w);\n        if (extra_dist[i] < 0) extra_dist[i] = 0; \n    }\n    \n    // 3. Combine scores: val[e_idx] = extra_dist[e_idx] * edge_betweenness[e_idx]\n    vector<EdgeInfo> edge_infos(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        edge_infos[i] = {edges_data[i].u, edges_data[i].v, edges_data[i].w, i, (long double)extra_dist[i] * edge_betweenness[i]};\n    }\n    \n    // 4. Initial assignment (r[M]): Sort edges by combined importance (val) and assign round-robin\n    sort(edge_infos.begin(), edge_infos.end(), [](const EdgeInfo& a, const EdgeInfo& b) {\n        return a.val > b.val;\n    });\n\n    vector<int> r(M_global); // repair day for each edge (1-indexed)\n    vector<int> day_load(D_global + 1, 0); // Number of edges assigned to each day\n    vector<long double> current_sum_val(D_global + 1, 0.0); // Sum of val for edges assigned to each day\n\n    for (int i = 0; i < M_global; ++i) {\n        int edge_id = edge_infos[i].id;\n        int day = (i % D_global) + 1; // Round-robin assignment based on sorted importance\n        r[edge_id] = day;\n        day_load[day]++;\n        current_sum_val[day] += edge_infos[i].val;\n    }\n    \n    // Calculate initial estimated frustration score (sum of average vals per day)\n    long double current_total_approx_score = 0.0;\n    for (int k = 1; k <= D_global; ++k) {\n        if (day_load[k] > 0) {\n            current_total_approx_score += current_sum_val[k] / day_load[k];\n        }\n    }\n\n    vector<int> best_r = r;\n    long double best_total_approx_score = current_total_approx_score;\n\n    // Simulated Annealing parameters\n    double time_limit_sec = 5.9; // Allocate 5.9 seconds for SA\n    long double T_start = 1e12; // Starting temperature\n    long double T_end = 1e-4;   // Ending temperature\n    \n    // Random number generation setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_edge(0, M_global - 1);\n    uniform_int_distribution<int> dist_day(1, D_global);\n    uniform_real_distribution<long double> dist_01(0.0, 1.0);\n\n    // SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time_sec = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time_sec > time_limit_sec) {\n            break;\n        }\n\n        // Linear cooling schedule\n        long double current_T = T_start * (1.0 - elapsed_time_sec / time_limit_sec);\n        if (current_T < T_end) current_T = T_end;\n\n        int edge_idx = dist_edge(rng); // Randomly pick an edge to move\n        int day_from = r[edge_idx];\n        int day_to = dist_day(rng); // Randomly pick a target day\n\n        // Check feasibility and efficiency constraints\n        if (day_from == day_to || day_load[day_to] >= K_global) {\n            continue; // Cannot move to same day or to an already full day\n        }\n\n        long double val_e = edge_infos[edge_idx].val; // Importance value of the edge being moved\n\n        // Calculate old average frustration for affected days\n        long double old_f_from = current_sum_val[day_from] / day_load[day_from];\n        long double old_f_to = (day_load[day_to] > 0) ? (current_sum_val[day_to] / day_load[day_to]) : 0.0; // If day_to is empty, old frustration is 0\n\n        // Calculate new average frustration if move is accepted\n        long double new_f_from = (day_load[day_from] > 1) ? ((current_sum_val[day_from] - val_e) / (day_load[day_from] - 1.0)) : 0.0; // If day_from becomes empty, new frustration is 0\n        long double new_f_to = (current_sum_val[day_to] + val_e) / (day_load[day_to] + 1.0);\n        \n        long double delta_score = (new_f_from - old_f_from) + (new_f_to - old_f_to);\n\n        // Acceptance criteria for Simulated Annealing\n        if (delta_score < 0 || dist_01(rng) < exp(-delta_score / current_T)) {\n            // Accept the move\n            r[edge_idx] = day_to;\n            day_load[day_from]--;\n            day_load[day_to]++;\n            current_sum_val[day_from] -= val_e;\n            current_sum_val[day_to] += val_e;\n            current_total_approx_score += delta_score;\n\n            // Update best solution found so far\n            if (current_total_approx_score < best_total_approx_score) {\n                best_total_approx_score = current_total_approx_score;\n                best_r = r;\n            }\n        }\n    }\n\n    // Output the best assignment found\n    for (int i = 0; i < M_global; ++i) {\n        cout << best_r[i] << (i == M_global - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}\n","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <queue>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\n// Global D for convenience\nint D;\n\n// Struct for 3D point\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& 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 Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\n// Represents a polycube shape as a vector of relative points\nusing Shape = vector<Point>;\n\n// Function to apply a rotation to a point relative to its origin (0,0,0)\nPoint rotate_point(const Point& p, int rot_idx) {\n    // This defines the 24 unique rotations\n    // Each case maps (x,y,z) to a permutation of (+/-x, +/-y, +/-z)\n    switch (rot_idx) {\n        case 0: return {p.x, p.y, p.z};\n        case 1: return {p.x, p.z, -p.y};\n        case 2: return {p.x, -p.y, -p.z};\n        case 3: return {p.x, -p.z, p.y};\n        \n        case 4: return {-p.x, -p.y, p.z};\n        case 5: return {-p.x, -p.z, -p.y};\n        case 6: return {-p.x, p.y, -p.z};\n        case 7: return {-p.x, p.z, p.y};\n\n        case 8: return {p.y, p.x, -p.z};\n        case 9: return {p.y, p.z, p.x};\n        case 10: return {p.y, -p.x, p.z};\n        case 11: return {p.y, -p.z, -p.x};\n\n        case 12: return {-p.y, p.x, p.z};\n        case 13: return {-p.y, p.z, -p.x};\n        case 14: return {-p.y, -p.x, -p.z};\n        case 15: return {-p.y, -p.z, p.x};\n        \n        case 16: return {p.z, p.x, p.y};\n        case 17: return {p.z, p.y, -p.x};\n        case 18: return {p.z, -p.x, -p.y};\n        case 19: return {p.z, -p.y, p.x};\n        \n        case 20: return {-p.z, p.x, p.y};\n        case 21: return {-p.z, p.y, -p.x};\n        case 22: return {-p.z, -p.x, -p.y};\n        case 23: return {-p.z, -p.y, p.x};\n    }\n    return p; // Should not be reached\n}\n\n// Function to canonicalize a shape (vector of relative points)\nShape get_canonical_form(const Shape& shape) {\n    if (shape.empty()) return {};\n\n    Shape canonical_shape = shape;\n    sort(canonical_shape.begin(), canonical_shape.end()); // Initial sort\n\n    for (int rot_idx = 0; rot_idx < 24; ++rot_idx) {\n        Shape rotated_shape_temp;\n        for (const auto& p : shape) {\n            rotated_shape_temp.push_back(rotate_point(p, rot_idx));\n        }\n\n        // Translate to (0,0,0) origin\n        int min_x = D, min_y = D, min_z = D;\n        for (const auto& p : rotated_shape_temp) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated_shape_temp) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n\n        sort(rotated_shape_temp.begin(), rotated_shape_temp.end());\n        if (rotated_shape_temp < canonical_shape) {\n            canonical_shape = rotated_shape_temp;\n        }\n    }\n    return canonical_shape;\n}\n\n// BFS to find a connected component and return its absolute points.\n// Also modifies `grid_to_search` by setting visited cells to 0.\n// Returns a pair: {vector of absolute points, relative shape}\npair<vector<Point>, Shape> find_and_extract_component(vector<vector<vector<int>>>& grid_to_search, int start_x, int start_y, int start_z) {\n    vector<Point> absolute_points;\n    Shape relative_shape;\n\n    if (start_x < 0 || start_x >= D || start_y < 0 || start_y >= D || start_z < 0 || start_z >= D || grid_to_search[start_x][start_y][start_z] == 0) {\n        return {absolute_points, relative_shape};\n    }\n\n    queue<Point> q;\n    q.push({start_x, start_y, start_z});\n    grid_to_search[start_x][start_y][start_z] = 0; // Mark as visited and remove from current grid\n    absolute_points.push_back({start_x, start_y, start_z});\n\n    int dx[] = {0, 0, 0, 0, 1, -1};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {1, -1, 0, 0, 0, 0};\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            int nz = curr.z + dz[i];\n\n            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D && grid_to_search[nx][ny][nz] == 1) {\n                grid_to_search[nx][ny][nz] = 0; // Mark as visited\n                q.push({nx, ny, nz});\n                absolute_points.push_back({nx, ny, nz});\n            }\n        }\n    }\n    \n    // Translate the component points to be relative to their bounding box min corner\n    if (absolute_points.empty()) return {absolute_points, relative_shape};\n\n    int min_x = D, min_y = D, min_z = D;\n    for (const auto& p : absolute_points) {\n        min_x = min(min_x, p.x);\n        min_y = min(min_y, p.y);\n        min_z = min(min_z, p.z);\n    }\n    \n    for (const auto& p : absolute_points) {\n        relative_shape.push_back({p.x - min_x, p.y - min_y, p.z - min_z});\n    }\n    sort(relative_shape.begin(), relative_shape.end());\n    \n    return {absolute_points, relative_shape};\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D;\n\n    vector<string> f1_str(D), r1_str(D), f2_str(D), r2_str(D);\n    for (int i = 0; i < D; ++i) cin >> f1_str[i];\n    for (int i = 0; i < D; ++i) cin >> r1_str[i];\n    for (int i = 0; i < D; ++i) cin >> f2_str[i];\n    for (int i = 0; i < D; ++i) cin >> r2_str[i];\n\n    // U_i_grid_initial[x][y][z] == 1 if (x,y,z) can be occupied based on silhouettes\n    // These grids are the \"ground truth\" and are not modified during component extraction.\n    vector<vector<vector<int>>> U1_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U2_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (f1_str[z][x] == '1' && r1_str[z][y] == '1') U1_grid_initial[x][y][z] = 1;\n                if (f2_str[z][x] == '1' && r2_str[z][y] == '1') U2_grid_initial[x][y][z] = 1;\n            }\n        }\n    }\n\n    // b_raw grids store temporary IDs for blocks discovered for each object independently.\n    // They are populated to fully cover U_grid_initial for their respective objects.\n    vector<vector<vector<int>>> b1_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Stores (canonical_shape, volume) for each temporary block in b1_raw and b2_raw\n    // 1-indexed, so push a dummy element at index 0.\n    vector<tuple<Shape, int>> b1_temp_blocks_info; \n    b1_temp_blocks_info.emplace_back(Shape{}, 0); \n    vector<tuple<Shape, int>> b2_temp_blocks_info; \n    b2_temp_blocks_info.emplace_back(Shape{}, 0); \n    \n    int current_temp_id_b1 = 1;\n    int current_temp_id_b2 = 1;\n\n    // Phase 1: Fill b1_raw completely based on U1_grid_initial\n    // Use a mutable copy for BFS, as it modifies the grid by setting visited cells to 0.\n    vector<vector<vector<int>>> U1_grid_mutable = U1_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U1_grid_mutable[x][y][z] == 1) { \n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U1_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n\n                    if (!absolute_points.empty()) { \n                        int temp_id = current_temp_id_b1++;\n                        for (const auto& p_abs : absolute_points) {\n                            b1_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b1_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Fill b2_raw completely based on U2_grid_initial\n    // Similar to Phase 1, but for object 2.\n    vector<vector<vector<int>>> U2_grid_mutable = U2_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U2_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U2_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int temp_id = current_temp_id_b2++;\n                        for (const auto& p_abs : absolute_points) {\n                            b2_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b2_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n\n    // Phase 3: Consolidate temporary blocks into final block set and IDs\n    vector<int> map_b1_to_final_id(current_temp_id_b1, 0); // Maps b1_raw temp_id to final_id\n    vector<int> map_b2_to_final_id(current_temp_id_b2, 0); // Maps b2_raw temp_id to final_id\n    \n    int current_final_id = 1; // Start final block IDs from 1\n    \n    // These vectors store info about the *final* set of unique blocks.\n    // They are not directly used for output, but for score calculation logic.\n    // Kept for clarity and potential future optimizations.\n    vector<Shape> final_block_shapes;\n    vector<int> final_block_volumes;\n    vector<bool> final_block_used_in_1;\n    vector<bool> final_block_used_in_2;\n\n    // Dummy entries for 1-indexed final_ids\n    final_block_shapes.push_back({});\n    final_block_volumes.push_back(0);\n    final_block_used_in_1.push_back(false);\n    final_block_used_in_2.push_back(false);\n\n    // Group temporary blocks by their canonical shape\n    map<Shape, vector<int>> temp_ids_b1_by_shape; // canonical_shape -> list of b1_raw temp_id\n    map<Shape, vector<int>> temp_ids_b2_by_shape; // canonical_shape -> list of b2_raw temp_id\n\n    for (int i = 1; i < b1_temp_blocks_info.size(); ++i) {\n        temp_ids_b1_by_shape[get<0>(b1_temp_blocks_info[i])].push_back(i);\n    }\n    for (int i = 1; i < b2_temp_blocks_info.size(); ++i) {\n        temp_ids_b2_by_shape[get<0>(b2_temp_blocks_info[i])].push_back(i);\n    }\n\n    set<Shape> processed_shapes; // To avoid processing same shape twice (from b1 and b2 loops)\n\n    // First, process shapes that appear in b1_raw. Try to match them with b2_raw blocks.\n    for (auto const& [shape, b1_raw_ids_for_shape] : temp_ids_b1_by_shape) {\n        processed_shapes.insert(shape); // Mark this shape as processed\n        \n        auto it_b2 = temp_ids_b2_by_shape.find(shape);\n        vector<int> b2_raw_ids_for_shape;\n        if (it_b2 != temp_ids_b2_by_shape.end()) {\n            b2_raw_ids_for_shape = it_b2->second;\n        }\n\n        // Match as many b1 blocks with b2 blocks of the same shape as possible\n        int num_to_match = min(b1_raw_ids_for_shape.size(), b2_raw_ids_for_shape.size());\n        for (int i = 0; i < num_to_match; ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n            \n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]])); // Volume is same for same shape\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(true);\n        }\n\n        // Remaining b1_raw blocks (only used in Object 1)\n        for (int i = num_to_match; i < b1_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(false);\n        }\n\n        // Remaining b2_raw blocks (only used in Object 2), for this shape\n        for (int i = num_to_match; i < b2_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n\n    // Process shapes that were only present in b2_raw (not in b1_raw)\n    for (auto const& [shape, b2_raw_ids_for_shape] : temp_ids_b2_by_shape) {\n        if (processed_shapes.count(shape)) continue; // Already handled if present in b1_raw\n        \n        for (int b2_id : b2_raw_ids_for_shape) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_id] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_id]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n    \n    // Phase 4: Populate final b1 and b2 grids with assigned final IDs\n    vector<vector<vector<int>>> b1_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (b1_raw[x][y][z] != 0) {\n                    b1_final_output[x][y][z] = map_b1_to_final_id[b1_raw[x][y][z]];\n                }\n                if (b2_raw[x][y][z] != 0) {\n                    b2_final_output[x][y][z] = map_b2_to_final_id[b2_raw[x][y][z]];\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << current_final_id - 1 << endl; // Total number of unique final blocks\n\n    // Output b1_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b1_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    // Output b2_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b2_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\nconst long long INF_LL = 4e18; // Sufficiently large infinity for long long\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\nstruct Edge {\n    int id; // original edge index (0 to M-1)\n    int u, v;\n    long long w;\n};\n\nstruct EdgeInfo { // For adjacency list\n    int to_node;\n    long long weight;\n    int original_edge_idx;\n};\n\n// For Dijkstra\nstruct State {\n    long long cost;\n    int u;\n\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\nint N, M, K;\nvector<Point> nodes;\nvector<Edge> edges_data;\nvector<Point> residents;\nvector<vector<EdgeInfo>> adj; // adjacency list for graph\n\n// Precomputed distances\nvector<vector<long long>> dist_res_node_sq; // dist_res_node_sq[k][i] = squared Euclidean distance from resident k to node i\nvector<long long> dist_from_1; // Shortest path cost from node 1 to node i\nvector<int> parent_on_spt_node; // parent_on_spt_node[i] = parent node in SPT from node 1\nvector<int> parent_on_spt_edge_idx; // parent_on_spt_edge_idx[i] = original edge index of (parent[i], i)\n\n// Global random generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to calculate squared Euclidean distance\nlong long distSq(Point p1, 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\n// Calculate rounded Euclidean distance\nint round_dist_val(long long dist_sq) {\n    return static_cast<int>(round(sqrt((long double)dist_sq))); // Cast to long double for sqrt for precision\n}\n\n// Dijkstra from node 1\nvoid run_dijkstra() {\n    dist_from_1.assign(N + 1, INF_LL);\n    parent_on_spt_node.assign(N + 1, -1);\n    parent_on_spt_edge_idx.assign(N + 1, -1);\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist_from_1[1] = 0;\n    pq.push({0, 1});\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        long long d = current.cost;\n        int u = current.u;\n\n        if (d > dist_from_1[u]) continue;\n\n        for (auto& edge_info : adj[u]) {\n            int v = edge_info.to_node;\n            long long weight = edge_info.weight;\n            int edge_idx = edge_info.original_edge_idx;\n\n            if (dist_from_1[u] + weight < dist_from_1[v]) {\n                dist_from_1[v] = dist_from_1[u] + weight;\n                parent_on_spt_node[v] = u;\n                parent_on_spt_edge_idx[v] = edge_idx;\n                pq.push({dist_from_1[v], v});\n            }\n        }\n    }\n}\n\n// Recalculates edge cost for a given set of active stations\nlong long calculate_edge_cost_from_active_stations(const set<int>& active_stations, vector<int>& B_output_temp) {\n    set<int> edges_on_idx_set;\n    long long current_edge_cost = 0;\n\n    for (int u : active_stations) {\n        if (dist_from_1[u] == INF_LL) { \n            return INF_LL; // Should not happen if `active_stations` are already filtered or cost is set to INF_LL\n        }\n        if (u == 1) continue; \n        \n        int curr = u;\n        while (curr != 1 && parent_on_spt_node[curr] != -1) {\n            int edge_idx = parent_on_spt_edge_idx[curr];\n            if (edges_on_idx_set.find(edge_idx) == edges_on_idx_set.end()) {\n                edges_on_idx_set.insert(edge_idx);\n                current_edge_cost += edges_data[edge_idx].w;\n            }\n            curr = parent_on_spt_node[curr];\n        }\n    }\n    \n    // Populate B_output_temp\n    B_output_temp.assign(M, 0);\n    for (int j = 0; j < M; ++j) {\n        if (edges_on_idx_set.count(j)) {\n            B_output_temp[j] = 1;\n        }\n    }\n\n    return current_edge_cost;\n}\n\n\nvoid solve() {\n    // Precomputation (read input, run Dijkstra, calculate resident-node distances)\n    nodes.resize(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        cin >> nodes[i].x >> nodes[i].y;\n        nodes[i].id = i;\n    }\n\n    adj.resize(N + 1);\n    edges_data.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges_data[j].u >> edges_data[j].v >> edges_data[j].w;\n        edges_data[j].id = j;\n        adj[edges_data[j].u].push_back({edges_data[j].v, edges_data[j].w, j});\n        adj[edges_data[j].v].push_back({edges_data[j].u, edges_data[j].w, j});\n    }\n\n    residents.resize(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n\n    run_dijkstra();\n\n    dist_res_node_sq.resize(K, vector<long long>(N + 1));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            dist_res_node_sq[k][i] = distSq(residents[k], nodes[i]);\n        }\n    }\n    \n    // Initial solution (Greedy approach)\n    vector<int> P_current(N + 1, 0);\n    \n    // For each resident, assign it to its closest reachable station (within 5000 radius).\n    // Then combine P values for stations.\n    for (int k = 0; k < K; ++k) {\n        int best_station_for_k = -1;\n        long long min_dist_sq_for_k = (long long)5001 * 5001; // Max guaranteed distance is 5000\n        for (int i = 1; i <= N; ++i) {\n            if (dist_from_1[i] == INF_LL) continue; // Station must be reachable from 1\n            if (dist_res_node_sq[k][i] <= (long long)5000 * 5000) {\n                if (dist_res_node_sq[k][i] < min_dist_sq_for_k) {\n                    min_dist_sq_for_k = dist_res_node_sq[k][i];\n                    best_station_for_k = i;\n                }\n            }\n        }\n        if (best_station_for_k != -1) {\n            P_current[best_station_for_k] = max(P_current[best_station_for_k], round_dist_val(min_dist_sq_for_k));\n        } else {\n             // This indicates a problem as per problem statement guarantee. Should not happen.\n        }\n    }\n    // Cap all P values at 5000\n    for(int i=1; i<=N; ++i) {\n        P_current[i] = min(P_current[i], 5000);\n    }\n    \n    vector<int> B_best(M);\n    long long best_S = INF_LL;\n    vector<int> P_best = P_current;\n\n    // State variables for SA (to allow incremental updates)\n    long long current_P_cost_SA = 0;\n    set<int> active_stations_SA;\n    vector<int> num_covering_stations_for_resident(K, 0);\n    int num_residents_fully_covered = 0;\n\n    // Initialize SA state variables from P_current\n    for (int i = 1; i <= N; ++i) {\n        if (P_current[i] > 0 && dist_from_1[i] == INF_LL) { // If an initially active station is unreachable\n            current_P_cost_SA = INF_LL; // Mark initial state as invalid\n            break;\n        }\n        current_P_cost_SA += (long long)P_current[i] * P_current[i];\n        if (P_current[i] > 0) {\n            active_stations_SA.insert(i);\n        }\n    }\n    if (current_P_cost_SA != INF_LL) { // If initial P cost is valid (all active stations reachable)\n        for (int k = 0; k < K; ++k) {\n            for (int i = 1; i <= N; ++i) {\n                if (P_current[i] > 0) {\n                    if (dist_res_node_sq[k][i] <= (long long)P_current[i] * P_current[i]) {\n                        num_covering_stations_for_resident[k]++;\n                    }\n                }\n            }\n            if (num_covering_stations_for_resident[k] > 0) {\n                num_residents_fully_covered++;\n            }\n        }\n    }\n    \n    long long current_edge_cost_SA = 0;\n    if (current_P_cost_SA != INF_LL && num_residents_fully_covered == K) {\n        vector<int> temp_B(M); // Placeholder for calculate_edge_cost_from_active_stations\n        current_edge_cost_SA = calculate_edge_cost_from_active_stations(active_stations_SA, temp_B);\n        best_S = current_P_cost_SA + current_edge_cost_SA;\n        P_best = P_current;\n    }\n\n\n    // Simulated Annealing\n    chrono::high_resolution_clock::time_point start_time = chrono::high_resolution_clock::now();\n    long double current_temp;\n    if (best_S == INF_LL) { \n        current_temp = 1e9; \n    } else {\n        current_temp = (long double)best_S / 100.0; // Dynamic initial temperature\n    }\n    long double end_temp = 1.0;\n    long double time_limit = 1.95; // seconds\n    \n    // Parameters for SA moves\n    const int P_ADJUST_RANGE = 500; \n    \n    long long iter_count = 0;\n    while (true) {\n        chrono::high_resolution_clock::time_point current_time = chrono::high_resolution_clock::now();\n        long double elapsed_time = chrono::duration_cast<chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        if (elapsed_time > time_limit) {\n            break;\n        }\n        \n        current_temp = end_temp + (current_temp - end_temp) * (1.0 - elapsed_time / time_limit);\n        \n        vector<int> P_next = P_current; // P_next is a copy for perturbation\n        long long next_P_cost = current_P_cost_SA;\n        set<int> next_active_stations = active_stations_SA;\n        vector<int> next_num_covering_stations = num_covering_stations_for_resident;\n        int next_num_residents_fully_covered = num_residents_fully_covered;\n\n        int target_node = rng() % N + 1;\n        int old_P_val = P_current[target_node]; // Use P_current for old P value\n\n        if (dist_from_1[target_node] == INF_LL) { // Don't bother with unreachable nodes\n            continue;\n        }\n\n        int move_type = rng() % 100;\n\n        if (move_type < 60) { // Type 0: Adjust P_i for a random station i (60% chance)\n            int rand_delta = (rng() % (2 * P_ADJUST_RANGE + 1)) - P_ADJUST_RANGE;\n            int new_P_val = old_P_val + rand_delta;\n            new_P_val = max(0, min(5000, new_P_val));\n            P_next[target_node] = new_P_val;\n\n            // Update incremental costs\n            next_P_cost -= (long long)old_P_val * old_P_val;\n            next_P_cost += (long long)new_P_val * new_P_val;\n\n            if (old_P_val == 0 && new_P_val > 0) { // Station became active\n                next_active_stations.insert(target_node);\n            } else if (old_P_val > 0 && new_P_val == 0) { // Station became inactive\n                next_active_stations.erase(target_node);\n            }\n\n            // Update coverage counts incrementally for O(K) complexity\n            for (int k = 0; k < K; ++k) {\n                bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                if (old_covered_by_target && !new_covered_by_target) {\n                    next_num_covering_stations[k]--;\n                    if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                } else if (!old_covered_by_target && new_covered_by_target) {\n                    next_num_covering_stations[k]++;\n                    if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                }\n            }\n\n        } else { // Type 1: Try to turn off a station and re-assign coverage (40% chance)\n            \n            // If target_node is currently OFF, try turning it ON (random P)\n            if (old_P_val == 0) { \n                int new_P_val = rng() % 5001; // Random P between 0 and 5000\n                P_next[target_node] = new_P_val;\n\n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_P_cost += (long long)new_P_val * new_P_val;\n\n                if (new_P_val > 0) {\n                    next_active_stations.insert(target_node);\n                }\n\n                // Update coverage counts incrementally\n                for (int k = 0; k < K; ++k) {\n                    bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                    bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                    if (old_covered_by_target && !new_covered_by_target) {\n                        next_num_covering_stations[k]--;\n                        if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                    } else if (!old_covered_by_target && new_covered_by_target) {\n                        next_num_covering_stations[k]++;\n                        if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                    }\n                }\n\n            } else { // If target_node is currently ON, try turning it OFF and re-assign\n                // Temporarily remove target_node's coverage from next_num_covering_stations\n                // This makes it easy to find truly uncovered residents for re-assignment\n                for(int k=0; k<K; ++k){\n                    if(dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val){\n                        next_num_covering_stations[k]--;\n                        if(next_num_covering_stations[k] == 0){\n                            next_num_residents_fully_covered--;\n                        }\n                    }\n                }\n\n                P_next[target_node] = 0; \n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_active_stations.erase(target_node);\n\n                // For each resident that became uncovered, find the best station to cover it\n                for(int k=0; k<K; ++k){\n                    if(next_num_covering_stations[k] == 0){ // This resident is now uncovered\n                        int best_alt_station = -1;\n                        long long min_dist_sq = INF_LL; \n                        for(int i=1; i<=N; ++i){ \n                            if(dist_from_1[i] == INF_LL) continue; // Only consider reachable stations\n                            if(dist_res_node_sq[k][i] < min_dist_sq){\n                                min_dist_sq = dist_res_node_sq[k][i];\n                                best_alt_station = i;\n                            }\n                        }\n                        if(best_alt_station != -1){\n                            int old_alt_P = P_next[best_alt_station]; // Use P_next (which might already be updated)\n                            long long required_P_sq = min_dist_sq;\n                            int required_P = round_dist_val(required_P_sq);\n                            int new_alt_P = max(old_alt_P, min(5000, required_P));\n                            \n                            // Apply change to P_next and update costs incrementally\n                            P_next[best_alt_station] = new_alt_P;\n                            next_P_cost -= (long long)old_alt_P * old_alt_P;\n                            next_P_cost += (long long)new_alt_P * new_alt_P;\n                            if (old_alt_P == 0 && new_alt_P > 0) {\n                                next_active_stations.insert(best_alt_station);\n                            }\n                            // Update coverage for this resident 'k' by best_alt_station\n                            // (Only for k, not all residents affected by best_alt_station's P change)\n                            if (dist_res_node_sq[k][best_alt_station] <= (long long)new_alt_P * new_alt_P) {\n                                next_num_covering_stations[k]++;\n                                if(next_num_covering_stations[k] == 1) { // It just became covered again\n                                    next_num_residents_fully_covered++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        long long S_current_val = current_P_cost_SA + current_edge_cost_SA;\n        long long S_next = INF_LL;\n\n        if (next_num_residents_fully_covered == K) {\n            vector<int> B_temp(M);\n            long long next_edge_cost = calculate_edge_cost_from_active_stations(next_active_stations, B_temp);\n            S_next = next_P_cost + next_edge_cost;\n        }\n\n        if (S_next < best_S) {\n            P_current = P_next;\n            current_P_cost_SA = next_P_cost;\n            active_stations_SA = next_active_stations;\n            num_covering_stations_for_resident = next_num_covering_stations;\n            num_residents_fully_covered = next_num_residents_fully_covered;\n            current_edge_cost_SA = S_next - current_P_cost_SA; // derive edge cost from S_next and P_cost\n            best_S = S_next;\n            P_best = P_next;\n        } else if (S_next != INF_LL) {\n            long double prob = exp((S_current_val - S_next) / current_temp);\n            if (uniform_real_distribution<long double>(0.0, 1.0)(rng) < prob) {\n                P_current = P_next;\n                current_P_cost_SA = next_P_cost;\n                active_stations_SA = next_active_stations;\n                num_covering_stations_for_resident = next_num_covering_stations;\n                num_residents_fully_covered = next_num_residents_fully_covered;\n                current_edge_cost_SA = S_next - current_P_cost_SA;\n            }\n        }\n        \n        iter_count++;\n    }\n\n    // Final calculation for output\n    vector<int> B_final(M);\n    calculate_edge_cost_from_active_stations(active_stations_SA, B_final); \n\n    // Output\n    for (int i = 1; i <= N; ++i) {\n        cout << P_best[i] << (i == N ? \"\" : \" \");\n    }\n    cout << endl;\n    for (int j = 0; j < M; ++j) {\n        cout << B_final[j] << (j == M - 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 >> K;\n    solve();\n\n    return 0;\n}\n","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <tuple>   // For std::tuple\n\n// N is fixed to 30 for all inputs.\n// The problem defines N as the number of tiers.\n// Tiers are 0-indexed from 0 to N-1.\n// Ball coordinates are (x,y) where 0 <= x <= N-1 and 0 <= y <= x.\nconst int N = 30;\n\n// Global data structures for the pyramid state and operations.\n// The pyramid itself, storing the ball numbers.\nstd::vector<std::vector<int>> pyramid(N);\n\n// To quickly find the coordinates of a ball given its number.\n// `current_pos_of_value[ball_number]` stores `{x, y}`.\nstd::vector<std::pair<int, int>> current_pos_of_value(N * (N + 1) / 2);\n\n// Stores the sequence of swap operations.\n// Each operation is a tuple `{x1, y1, x2, y2}`.\nstd::vector<std::tuple<int, int, int, int>> operations;\n\n/**\n * @brief Performs a swap between two balls at given coordinates and records the operation.\n *\n * This function updates the `pyramid` and `current_pos_of_value` data structures\n * to reflect the swap, and adds the operation to the `operations` list.\n * The coordinates (r1, c1) and (r2, c2) must refer to adjacent balls.\n *\n * @param r1 Row coordinate of the first ball.\n * @param c1 Column coordinate of the first ball.\n * @param r2 Row coordinate of the second ball.\n * @param c2 Column coordinate of the second ball.\n */\nvoid perform_swap(int r1, int c1, int r2, int c2) {\n    int val1 = pyramid[r1][c1];\n    int val2 = pyramid[r2][c2];\n\n    // Swap values in the pyramid grid\n    pyramid[r1][c1] = val2;\n    pyramid[r2][c2] = val1;\n\n    // Update the mapping from value to its current position\n    current_pos_of_value[val1] = {r2, c2};\n    current_pos_of_value[val2] = {r1, c1};\n\n    // Record the swap operation\n    operations.emplace_back(r1, c1, r2, c2);\n}\n\n/**\n * @brief Sifts down an element at (r, c) to satisfy the min-pyramid property.\n *\n * This function repeatedly compares the ball at (r, c) with its two children\n * ((r+1, c) and (r+1, c+1)). If the parent ball is larger than either child,\n * it swaps the parent with the smallest child. This process continues until\n * the parent ball is smaller than or equal to both its children, or it reaches\n * the bottom tier.\n * This is an iterative implementation of the sift-down (or heapify-down) process.\n *\n * @param r Row coordinate of the ball to sift down.\n * @param c Column coordinate of the ball to sift down.\n */\nvoid sift_down(int r, int c) {\n    while (true) {\n        int parent_val = pyramid[r][c];\n        int min_val = parent_val; // Initialize min_val with parent's value\n        int target_r = r;         // Initialize target_r and target_c to parent's position\n        int target_c = c;\n\n        // Check left child: (r+1, c)\n        // Ensure that (r,c) is not in the last tier (N-1)\n        if (r + 1 < N) {\n            int child1_val = pyramid[r+1][c];\n            if (child1_val < min_val) {\n                min_val = child1_val;\n                target_r = r + 1;\n                target_c = c;\n            }\n        }\n\n        // Check right child: (r+1, c+1)\n        // Ensure (r,c) is not in the last tier AND (r+1, c+1) is a valid coordinate.\n        // For a tier x, valid column indices are from 0 to x.\n        // So for tier r+1, column c+1 must satisfy c+1 <= r+1.\n        if (r + 1 < N && c + 1 <= r + 1) {\n            int child2_val = pyramid[r+1][c+1];\n            // Crucially, compare against `min_val` (which might be child1_val already),\n            // not directly `parent_val`, to find the smallest among parent and both children.\n            if (child2_val < min_val) {\n                min_val = child2_val;\n                target_r = r + 1;\n                target_c = c + 1;\n            }\n        }\n\n        // If no child was smaller than the parent (or if it's a leaf node),\n        // the element is in its correct position relative to its children.\n        if (target_r == r && target_c == c) {\n            break; // Sifting process complete for this element\n        } else {\n            // Swap the current ball with the smallest child\n            perform_swap(r, c, target_r, target_c);\n\n            // Continue sifting down from the new position of the swapped element\n            r = target_r;\n            c = target_c;\n        }\n    }\n}\n\n\nint main() {\n    // Optimize C++ standard streams for competitive programming.\n    // This unties cin from cout and disables synchronization with C stdio,\n    // speeding up input/output operations.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read the initial state of the pyramid from standard input.\n    // Each row 'i' has 'i+1' balls.\n    for (int i = 0; i < N; ++i) {\n        pyramid[i].resize(i + 1); // Allocate space for balls in tier 'i'\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> pyramid[i][j];\n            // Store the initial position of each ball number.\n            current_pos_of_value[pyramid[i][j]] = {i, j};\n        }\n    }\n\n    // Apply the bottom-up heapify algorithm to satisfy the min-pyramid property.\n    // We iterate from the second-to-last tier (N-2) up to the top tier (0).\n    // For each ball in these tiers, we call sift_down to ensure it's smaller\n    // than its children. Since we process tiers bottom-up, when we sift down\n    // an element, its children's sub-pyramids are already correctly heapified.\n    for (int r = N - 2; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            sift_down(r, c);\n        }\n    }\n\n    // Output the total number of operations performed.\n    std::cout << operations.size() << std::endl;\n    // Output each swap operation in the specified format.\n    for (const auto& op : operations) {\n        std::cout << std::get<0>(op) << \" \"\n                  << std::get<1>(op) << \" \"\n                  << std::get<2>(op) << \" \"\n                  << std::get<3>(op) << std::endl;\n    }\n\n    return 0;\n}\n","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::abs\n\n// Global constants\nconst int D = 9;\nconst int DR[] = {-1, 1, 0, 0}; // delta row for neighbors (up, down, left, right)\nconst int DC[] = {0, 0, -1, 1}; // delta col for neighbors\n\n// Grid cell states\nconst int EMPTY = -1;\nconst int OBSTACLE = -2;\nconst int ENTRANCE_CELL = -3; // Renamed to avoid conflict with function entrance_r/c\nconst int UNVISITED = -1; // For BFS distance arrays\n\n// Global variables for the warehouse state\nint grid[D][D]; // Stores container ID (0 to M-1), or EMPTY/OBSTACLE/ENTRANCE_CELL\nbool is_obstacle[D][D];\nint static_dist[D][D]; // BFS distance from entrance on an empty grid\nstd::vector<std::pair<int, int>> static_ranked_squares; // Sorted by static_dist\nstd::map<std::pair<int, int>, int> square_to_static_rank; // Maps (r,c) to its rank in static_ranked_squares\n\nstd::pair<int, int> container_pos[D * D]; // Maps container ID to its (r,c) location\nint M; // Total number of containers\n\n// Coordinates of the entrance\nint entrance_r, entrance_c;\n\n// BFS utility function\n// Returns a vector of reachable empty squares (for placement phase)\n// Also populates reachable_container_ids_ptr if provided (for transport-out phase)\nstd::vector<std::pair<int, int>> bfs_reachable_info(\n    int (&current_grid)[D][D],\n    int (&current_dist)[D][D], // Output: distances from entrance\n    const bool* extracted_containers_mask_ptr, // Pointer to mask for extracted containers (nullptr for placement)\n    std::set<int>* reachable_container_ids_ptr // Output: reachable container IDs (nullptr for placement)\n) {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            current_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    current_dist[entrance_r][entrance_c] = 0;\n\n    std::vector<std::pair<int, int>> reachable_empty_squares_candidates;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue; // Out of bounds\n            if (is_obstacle[nr][nc]) continue; // Obstacle\n\n            if (current_dist[nr][nc] == UNVISITED) { // Not visited yet\n                if (current_grid[nr][nc] == EMPTY) {\n                    current_dist[nr][nc] = current_dist[r][c] + 1;\n                    q.push({nr, nc});\n                    reachable_empty_squares_candidates.push_back({nr, nc});\n                } else if (current_grid[nr][nc] == ENTRANCE_CELL) { \n                    // Entrance is traversable and starting point, already visited at dist 0.\n                    // No need to push again or add to reachable_empty_squares_candidates.\n                } else if (current_grid[nr][nc] >= 0) { // Contains a container\n                    int container_id = current_grid[nr][nc];\n                    if (extracted_containers_mask_ptr && extracted_containers_mask_ptr[container_id]) { \n                        // Container already extracted, treat as empty and traversable\n                        current_dist[nr][nc] = current_dist[r][c] + 1;\n                        q.push({nr, nc});\n                        reachable_empty_squares_candidates.push_back({nr, nc}); // Add as an available \"empty\" path square\n                    } else { \n                        // Container still present, cannot traverse, but is reachable for extraction\n                        if (reachable_container_ids_ptr) {\n                            reachable_container_ids_ptr->insert(container_id);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return reachable_empty_squares_candidates;\n}\n\n// Precomputes static distances from the entrance on an empty grid\nvoid precompute_static_distances() {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            static_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    static_dist[entrance_r][entrance_c] = 0;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (is_obstacle[nr][nc]) continue;\n\n            if (static_dist[nr][nc] == UNVISITED) {\n                static_dist[nr][nc] = static_dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Collect all valid container squares and sort them by static distance\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (!is_obstacle[i][j] && (i != entrance_r || j != entrance_c)) {\n                static_ranked_squares.push_back({i, j});\n            }\n        }\n    }\n\n    // Sort by static_dist, then row, then column for consistent ranking\n    std::sort(static_ranked_squares.begin(), static_ranked_squares.end(), [](const auto& a, const auto& b) {\n        if (static_dist[a.first][a.second] != static_dist[b.first][b.second]) {\n            return static_dist[a.first][a.second] < static_dist[b.first][b.second];\n        }\n        if (a.first != b.first) {\n            return a.first < b.first;\n        }\n        return a.second < b.second;\n    });\n\n    for (int i = 0; i < static_ranked_squares.size(); ++i) {\n        square_to_static_rank[static_ranked_squares[i]] = i;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_obstacles;\n    std::cin >> D >> N_obstacles; // D is fixed at 9, but read for generality\n\n    entrance_r = 0;\n    entrance_c = (D - 1) / 2;\n\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            grid[i][j] = EMPTY;\n            is_obstacle[i][j] = false;\n        }\n    }\n    grid[entrance_r][entrance_c] = ENTRANCE_CELL;\n\n    for (int k = 0; k < N_obstacles; ++k) {\n        int r_obs, c_obs;\n        std::cin >> r_obs >> c_obs;\n        is_obstacle[r_obs][c_obs] = true;\n        grid[r_obs][c_obs] = OBSTACLE;\n    }\n\n    M = D * D - 1 - N_obstacles; // Total number of containers\n\n    precompute_static_distances();\n\n    // Placement Phase\n    int current_dist[D][D]; // Temporary array for BFS distances in current state\n    bool dummy_extracted_mask[D*D] = {false}; // Placeholder, not used in placement phase BFS\n\n    for (int d = 0; d < M; ++d) {\n        int t_d; // Container ID\n        std::cin >> t_d;\n\n        std::vector<std::pair<int, int>> reachable_empty_squares =\n            bfs_reachable_info(grid, current_dist, dummy_extracted_mask, nullptr); // Nullptr for transport-out specific parameters\n\n        int best_score_diff = M + 1; // Max possible diff is M-1, so M+1 is a safe initial high value\n        std::pair<int, int> best_pos = {-1, -1};\n\n        for (const auto& p : reachable_empty_squares) {\n            int r = p.first;\n            int c = p.second;\n            int static_rank = square_to_static_rank[p];\n            int score_diff = std::abs(t_d - static_rank);\n\n            if (score_diff < best_score_diff) {\n                best_score_diff = score_diff;\n                best_pos = p;\n            } else if (score_diff == best_score_diff) {\n                // Tie-breaking rules for placement:\n                // 1. Prefer smaller current_dist (currently closer to entrance)\n                if (current_dist[r][c] < current_dist[best_pos.first][best_pos.second]) {\n                    best_pos = p;\n                }\n                // 2. If current_dist is also tied, prefer smaller static_dist (inherently closer)\n                else if (current_dist[r][c] == current_dist[best_pos.first][best_pos.second]) {\n                    if (static_dist[r][c] < static_dist[best_pos.first][best_pos.second]) {\n                        best_pos = p;\n                    }\n                    // 3. If static_dist is also tied, prefer smaller row, then smaller column (lexicographical)\n                    else if (static_dist[r][c] == static_dist[best_pos.first][best_pos.second]) {\n                        if (r < best_pos.first) {\n                            best_pos = p;\n                        } else if (r == best_pos.first) {\n                            if (c < best_pos.second) {\n                                best_pos = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        grid[best_pos.first][best_pos.second] = t_d;\n        container_pos[t_d] = best_pos;\n\n        std::cout << best_pos.first << \" \" << best_pos.second << std::endl;\n    }\n\n    // Transport-Out Phase\n    std::vector<int> b_sequence(M);\n    bool extracted_containers_mask[D*D]; // Tracks which containers have been extracted\n    for(int i = 0; i < D*D; ++i) extracted_containers_mask[i] = false;\n\n    for (int k = 0; k < M; ++k) {\n        std::set<int> reachable_containers;\n        // BFS to find all reachable containers given current grid state and extracted_containers_mask\n        bfs_reachable_info(grid, current_dist, extracted_containers_mask, &reachable_containers);\n\n        int min_reachable_id = -1;\n        if (!reachable_containers.empty()) {\n            min_reachable_id = *reachable_containers.begin(); // std::set keeps elements sorted, so begin() is the smallest\n        } else {\n            // This case should ideally not be reached if the problem guarantees connectivity\n            // and we always place containers in reachable spots.\n            // As a fallback, this would mean searching for the smallest unextracted ID,\n            // but this indicates a problem with logic or problem constraints.\n            // For now, assume a container is always reachable.\n            for (int id = 0; id < M; ++id) {\n                if (!extracted_containers_mask[id]) {\n                    min_reachable_id = id;\n                    break;\n                }\n            }\n        }\n\n        b_sequence[k] = min_reachable_id;\n        extracted_containers_mask[min_reachable_id] = true; // Mark container as extracted\n    }\n\n    for (int k = 0; k < M; ++k) {\n        std::pair<int, int> pos = container_pos[b_sequence[k]];\n        std::cout << pos.first << \" \" << pos.second << std::endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>   // For tracking affected pairs in adjacency check\n#include <tuple> // For std::tie\n\nusing namespace std;\n\n// Fixed grid size and number of wards\nconst int N = 50;\nconst int M = 100;\n\n// Original map from input\nint c[N][N];\n// Created map (modified during SA)\nint d[N][N];\n\n// Required adjacencies: adj_req[u][v] is true if u and v must be adjacent\nbool adj_req[M + 1][M + 1];\n\n// Current adjacencies in 'd' map: adj_count[u][v] stores number of edges between color u and color v\nint adj_count[M + 1][M + 1];\n\n// Number of cells for each color in 'd' map\nint num_cells[M + 1];\n\n// Stores coordinates of cells for each color\nvector<pair<int, int>> ward_cells[M + 1];\n// Stores the index of a cell (r,c) within ward_cells[d[r][c]].\n// This allows O(1) removal from ward_cells by swapping with the last element.\nint cell_idx_in_ward_cells[N][N];\n\n// Directions for neighbors (up, down, left, right)\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\n\n// Check if coordinates (r, c_val) are within the grid bounds\ninline bool is_valid_coord(int r, int c_val) {\n    return r >= 0 && r < N && c_val >= 0 && c_val < N;\n}\n\n// Check if a color 'k' is connected in the 'd' map.\n// If (excluded_r, excluded_c) is specified, that cell is temporarily ignored for connectivity.\nbool check_color_connectivity(int k, int excluded_r = -1, int excluded_c = -1) {\n    int current_num_k_cells = num_cells[k];\n    if (excluded_r != -1 && d[excluded_r][excluded_c] == k) {\n        current_num_k_cells--; // If the excluded cell has color k, reduce the count\n    }\n\n    if (current_num_k_cells == 0) return true; // Empty ward is trivially connected\n\n    // Find a starting point for BFS for color k\n    int start_r = -1, start_c = -1;\n    // Iterate through ward_cells to find a valid starting point that is not the excluded cell\n    for (auto p : ward_cells[k]) {\n        if (p.first == excluded_r && p.second == excluded_c) continue;\n        start_r = p.first;\n        start_c = p.second;\n        break;\n    }\n\n    if (start_r == -1) { // No cells of color k left after exclusion, but current_num_k_cells > 0. This shouldn't happen if num_cells is accurate.\n        return current_num_k_cells == 0;\n    }\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_count = 0;\n\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    reachable_count++;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == k && !visited[nr][nc]) {\n                if (nr == excluded_r && nc == excluded_c) continue; // Skip the excluded cell\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_count++;\n            }\n        }\n    }\n    return reachable_count == current_num_k_cells;\n}\n\n// Check if color 0 is connected (to the outside) in the 'd' map\nbool check_zero_connectivity() {\n    int current_zero_count = num_cells[0];\n    if (current_zero_count == 0) return true; // No 0s, trivially connected\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_zeros = 0;\n\n    // Add all boundary cells that are color 0 to the queue\n    for (int r = 0; r < N; ++r) {\n        if (d[r][0] == 0 && !visited[r][0]) {\n            q.push({r, 0});\n            visited[r][0] = true;\n            reachable_zeros++;\n        }\n        if (d[r][N - 1] == 0 && !visited[r][N - 1]) {\n            q.push({r, N - 1});\n            visited[r][N - 1] = true;\n            reachable_zeros++;\n        }\n    }\n    for (int c_val = 1; c_val < N - 1; ++c_val) { // Avoid double counting corners\n        if (d[0][c_val] == 0 && !visited[0][c_val]) {\n            q.push({0, c_val});\n            visited[0][c_val] = true;\n            reachable_zeros++;\n        }\n        if (d[N - 1][c_val] == 0 && !visited[N - 1][c_val]) {\n            q.push({N - 1, c_val});\n            visited[N - 1][c_val] = true;\n            reachable_zeros++;\n        }\n    }\n\n    // If no boundary '0' cells, but there are other '0' cells, they are disconnected.\n    if (current_zero_count > 0 && reachable_zeros == 0) return false;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == 0 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_zeros++;\n            }\n        }\n    }\n    return reachable_zeros == current_zero_count;\n}\n\nvoid solve() {\n    // Read input\n    int n_val, m_val;\n    cin >> n_val >> m_val; // N, M are fixed, but read them\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> c[i][j];\n        }\n    }\n\n    // Initialize d with c, and calculate initial state metrics\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            d[i][j] = c[i][j];\n            num_cells[d[i][j]]++;\n            // Add to ward_cells and record its index for O(1) removal later\n            cell_idx_in_ward_cells[i][j] = ward_cells[d[i][j]].size();\n            ward_cells[d[i][j]].push_back({i, j});\n        }\n    }\n\n    // Precompute required adjacencies (adj_req) from original map 'c'\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = c[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_req[curr_color][0] = adj_req[0][curr_color] = true;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = c[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_req[curr_color][neighbor_color] = adj_req[neighbor_color][curr_color] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initialize current adjacencies (adj_count) from 'd' (which is initially 'c')\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = d[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_count[min(curr_color, 0)][max(curr_color, 0)]++;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = d[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_count[min(curr_color, neighbor_color)][max(curr_color, neighbor_color)]++;\n                    }\n                }\n            }\n        }\n    }\n\n    // Each edge between two non-zero colors (u,v) where u,v > 0 is counted twice.\n    // So, divide by 2 for pairs (u,v) where u,v > 0.\n    // Pairs involving 0 (boundary adjacencies) are only counted once (when processing the non-zero cell).\n    // So for u=0 or v=0, we should not divide.\n    for (int u = 1; u <= M; ++u) { // Iterate only non-zero colors for u\n        for (int v = u; v <= M; ++v) { // Iterate only non-zero colors for v, ensuring u <= v\n            adj_count[u][v] /= 2;\n        }\n    }\n\n    // Store best map and score. Score is number of non-zero cells (maximize this).\n    vector<vector<int>> best_d(N, vector<int>(N));\n    int current_score = N * N - num_cells[0];\n    int best_score = current_score;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            best_d[i][j] = d[i][j];\n        }\n    }\n\n    // --- Simulated Annealing parameters ---\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95; // seconds (slightly less than 2s to allow for output)\n    double T_start = 2000.0;        // Initial temperature\n    double T_end = 1.0;             // Final temperature\n    long long iter_count = 0;       // Iteration counter\n\n    // Distributions for random selection\n    uniform_int_distribution<int> dist_rc(0, N - 1); // For random row/col\n    uniform_int_distribution<int> dist_color_m(1, M); // For random ward color (1 to M)\n    uniform_real_distribution<double> dist_real(0.0, 1.0); // For acceptance probability\n\n    // Main SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        iter_count++;\n        // Calculate current temperature\n        double T = T_start * pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int r = dist_rc(rng);       // Random row\n        int c_val = dist_rc(rng);   // Random column\n        int old_color = d[r][c_val]; // Current color of the cell\n        int new_color;              // Proposed new color\n\n        // Strategy to pick new_color:\n        // Prioritize reducing 0s, then explore other moves\n        if (old_color == 0) {\n            // Try to fill this 0 cell with a neighboring ward's color\n            vector<int> non_zero_neighbors;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] != 0) {\n                    non_zero_neighbors.push_back(d[nr][nc]);\n                }\n            }\n\n            if (!non_zero_neighbors.empty()) {\n                // Pick a random non-zero neighbor's color\n                uniform_int_distribution<int> dist_neighbor_idx(0, non_zero_neighbors.size() - 1);\n                new_color = non_zero_neighbors[dist_neighbor_idx(rng)];\n            } else {\n                // If no non-zero neighbors, pick a random ward color (less effective, might create isolated components)\n                new_color = dist_color_m(rng);\n            }\n        } else { // Current cell is a ward color (1 to M)\n            // Option 1: Change to 0 (might fix forbidden adjacencies, but increases 0s)\n            // Option 2: Change to another non-zero color (assimilation/swap with neighbor)\n            if (dist_real(rng) < 0.5) { // 50% chance to try changing to 0\n                new_color = 0;\n            } else { // 50% chance to try changing to a neighbor's color\n                vector<int> neighbor_colors;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc)) {\n                        neighbor_colors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!neighbor_colors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, neighbor_colors.size() - 1);\n                    new_color = neighbor_colors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); // Random if no neighbors, fallback\n                }\n            }\n        }\n\n        if (new_color == old_color) continue; // No effective change, skip\n\n        // --- Prepare for tentative move and checks ---\n        // Store original state to revert if move is invalid/rejected\n        int original_d_rc_val = d[r][c_val];\n\n        vector<tuple<int, int, int>> temp_adj_count_deltas; // {u, v, delta}\n        set<pair<int, int>> affected_adj_pairs; // Track unique (u,v) pairs affected\n\n        // Update adj_count based on (r,c_val) -> (new_color)\n        // This is done before changing d[r][c_val] to correctly reflect adjacencies with neighbors.\n        // Neighbors of (r,c_val) are still in their original colors.\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c_val + DC[i];\n            if (is_valid_coord(nr, nc)) {\n                int neighbor_color = d[nr][nc]; // Neighbor's current color\n\n                // Remove old_color's adjacency with neighbor_color\n                if (old_color != neighbor_color) {\n                    int u = min(old_color, neighbor_color);\n                    int v = max(old_color, neighbor_color);\n                    adj_count[u][v]--;\n                    temp_adj_count_deltas.emplace_back(u, v, 1); // For reverting: add 1\n                    affected_adj_pairs.insert({u, v});\n                }\n                // Add new_color's adjacency with neighbor_color\n                if (new_color != neighbor_color) {\n                    int u = min(new_color, neighbor_color);\n                    int v = max(new_color, neighbor_color);\n                    adj_count[u][v]++;\n                    temp_adj_count_deltas.emplace_back(u, v, -1); // For reverting: subtract 1\n                    affected_adj_pairs.insert({u, v});\n                }\n            }\n        }\n        // Handle boundary adjacencies with color 0\n        if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n            if (old_color != 0) {\n                int u = min(old_color, 0);\n                int v = max(old_color, 0);\n                adj_count[u][v]--;\n                temp_adj_count_deltas.emplace_back(u, v, 1);\n                affected_adj_pairs.insert({u, v});\n            }\n            if (new_color != 0) {\n                int u = min(new_color, 0);\n                int v = max(new_color, 0);\n                adj_count[u][v]++;\n                temp_adj_count_deltas.emplace_back(u, v, -1);\n                affected_adj_pairs.insert({u, v});\n            }\n        }\n\n        // Tentatively apply d[r][c_val] = new_color;\n        d[r][c_val] = new_color;\n\n        // --- Perform validity checks ---\n        bool move_is_valid = true;\n\n        // 1. Local Adjacency Check: No required adjacencies broken, no forbidden ones created\n        for (auto p : affected_adj_pairs) {\n            int u = p.first;\n            int v = p.second;\n            bool current_adj_exists = (adj_count[u][v] > 0);\n            if (current_adj_exists != adj_req[u][v]) {\n                move_is_valid = false;\n                break;\n            }\n        }\n        if (!move_is_valid) {\n            // Revert d[r][c_val] and adj_count immediately\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue; // Skip to next iteration\n        }\n\n        // 2. Connectivity check for old_color (if it's not 0 and shrinking)\n        // A move can cause an old_color to split only if num_cells[old_color] > 1.\n        // If it becomes 0 after this change (num_cells[old_color] == 1 initially), it's trivially connected.\n        // The adjacency check ensures that if the only cell of old_color is removed, its required adjacencies\n        // are not broken.\n        if (old_color != 0 && num_cells[old_color] > 1) {\n            // Heuristic: If (r,c_val) had 0 or 1 neighbor of old_color, connectivity is likely fine.\n            // Only perform BFS if (r,c_val) was connected to multiple old_color cells\n            int old_color_neighbors_count = 0;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == old_color) {\n                    old_color_neighbors_count++;\n                }\n            }\n            // If it had multiple connections, removal might split the component\n            if (old_color_neighbors_count >= 2) {\n                if (!check_color_connectivity(old_color, r, c_val)) {\n                    move_is_valid = false;\n                }\n            }\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 3. Connectivity check for new_color (if it's not 0 and expanding/connecting)\n        // If num_cells[new_color] was 0, and now it becomes 1 (i.e. this is the first cell), it's connected.\n        // If num_cells[new_color] > 0, the new cell must connect to existing new_color cells.\n        if (new_color != 0) {\n            if (num_cells[new_color] > 0) { // new_color already exists, so (r,c_val) must connect to it\n                bool connected_to_new_color_region = false;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc) && d[nr][nc] == new_color) {\n                        connected_to_new_color_region = true;\n                        break;\n                    }\n                }\n                if (!connected_to_new_color_region) {\n                    // If no new_color neighbors, it forms an isolated component, which is invalid\n                    move_is_valid = false;\n                }\n            }\n            // If num_cells[new_color] was 0 (now becomes 1), it is trivially connected. No need to check.\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // 4. Connectivity check for color 0 (expensive but crucial)\n        if (!check_zero_connectivity()) {\n            move_is_valid = false;\n        }\n        if (!move_is_valid) {\n            d[r][c_val] = original_d_rc_val;\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n            continue;\n        }\n\n        // --- Move is valid, now decide on acceptance ---\n        // Update num_cells first\n        num_cells[old_color]--;\n        num_cells[new_color]++;\n\n        int new_score = N * N - num_cells[0]; // Score is number of non-zero cells\n\n        // Simulated Annealing acceptance logic\n        if (new_score > current_score || dist_real(rng) < exp((new_score - current_score) / T)) {\n            // Accept the move: update ward_cells permanently (O(1) with indexed swap)\n            // Remove (r,c_val) from old_color's ward_cells\n            int old_idx = cell_idx_in_ward_cells[r][c_val];\n            pair<int, int> last_cell_of_old_color = ward_cells[old_color].back();\n            ward_cells[old_color][old_idx] = last_cell_of_old_color;\n            cell_idx_in_ward_cells[last_cell_of_old_color.first][last_cell_of_old_color.second] = old_idx;\n            ward_cells[old_color].pop_back();\n\n            // Add (r,c_val) to new_color's ward_cells\n            cell_idx_in_ward_cells[r][c_val] = ward_cells[new_color].size();\n            ward_cells[new_color].push_back({r, c_val});\n\n            current_score = new_score;\n\n            if (new_score > best_score) {\n                best_score = new_score;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        best_d[i][j] = d[i][j];\n                    }\n                }\n            }\n        } else {\n            // Reject the move: revert changes to d, adj_count, num_cells\n            num_cells[old_color]++;\n            num_cells[new_color]--;\n            d[r][c_val] = original_d_rc_val; // Revert d[r][c_val]\n            for (const auto& delta : temp_adj_count_deltas) {\n                int u_d, v_d, val_d;\n                tie(u_d, v_d, val_d) = delta;\n                adj_count[u_d][v_d] += val_d;\n            }\n        }\n    } // End of SA loop\n\n    // Output the best map found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_d[i][j] << (j == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n#include <map>\n\n// DSU structure\nstruct DSU {\n    std::vector<int> parent;\n    std::vector<int> sz; // Stores size of component for root\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    // Returns true if i and j were in different sets and are now united.\n    // comp_estimated_weight must be provided to update the new root's estimated weight.\n    bool unite(int i, int j, std::vector<double>& comp_estimated_weight) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            // Union by size\n            if (sz[root_i] < sz[root_j]) std::swap(root_i, root_j);\n            \n            // Weighted average for the new component's estimated weight\n            // This averages the estimated weights of all items in the two combined components.\n            double new_weight = (comp_estimated_weight[root_i] * sz[root_i] + comp_estimated_weight[root_j] * sz[root_j]) / (sz[root_i] + sz[root_j]);\n\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            comp_estimated_weight[root_i] = new_weight;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global random number generator\nstd::mt19937 mt;\n\n// Function to perform a query\nstd::string query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int item_idx : L) {\n        std::cout << \" \" << item_idx;\n    }\n    for (int item_idx : R) {\n        std::cout << \" \" << item_idx;\n    }\n    std::cout << std::endl; // Flush output\n    \n    std::string result;\n    std::cin >> result;\n    return result;\n}\n\n// Function to calculate variance for the partitioning\ndouble calculate_variance(int D, const std::vector<double>& group_sums) {\n    if (D == 0) return 0.0;\n    double sum_t = 0.0;\n    for (double t : group_sums) {\n        sum_t += t;\n    }\n    double mean_t = sum_t / D;\n    double variance = 0.0;\n    for (double t : group_sums) {\n        variance += (t - mean_t) * (t - mean_t);\n    }\n    return variance / D;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Use current time as seed for random number generator\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N, D, Q;\n    std::cin >> N >> D >> Q;\n\n    DSU dsu(N);\n    std::vector<double> comp_estimated_weight(N);\n    for (int i = 0; i < N; ++i) {\n        comp_estimated_weight[i] = 1.0; // Initial estimated weight for each component root\n    }\n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TOTAL_TIME_LIMIT = 1.9; // seconds\n\n    // Query parameters\n    const double initial_learning_rate = 0.05;\n    const double final_learning_rate = 0.001;\n    const int max_group_query_size = 5;\n\n    for (int q_idx = 0; q_idx < Q; ++q_idx) {\n        double current_learning_rate = initial_learning_rate - (initial_learning_rate - final_learning_rate) * q_idx / Q;\n\n        std::vector<int> active_roots;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.parent[i] == i) { // Check if 'i' is a root\n                active_roots.push_back(i);\n            }\n        }\n\n        std::vector<int> L_items, R_items;\n        int root_L_comp = -1, root_R_comp = -1; // Roots of components chosen for L and R\n\n        bool picked_from_distinct_roots = false;\n        if (active_roots.size() >= 2) {\n            std::shuffle(active_roots.begin(), active_roots.end(), mt);\n            root_L_comp = active_roots[0];\n            root_R_comp = active_roots[1];\n            picked_from_distinct_roots = true;\n        } else { // All items are already in one DSU component, or N < 2\n            // If all items are merged, we can still query, but roots will be the same.\n            // This primarily happens if all items are estimated as equal, so further comparisons may not yield much new info.\n            int item1 = mt() % N;\n            int item2 = mt() % N;\n            while (item1 == item2) {\n                item2 = mt() % N;\n            }\n            L_items.push_back(item1);\n            R_items.push_back(item2);\n            root_L_comp = dsu.find(item1);\n            root_R_comp = dsu.find(item2);\n        }\n\n        if (picked_from_distinct_roots) {\n            std::vector<int> items_in_root1_comp;\n            std::vector<int> items_in_root2_comp;\n            for (int i = 0; i < N; ++i) {\n                if (dsu.find(i) == root_L_comp) items_in_root1_comp.push_back(i);\n                if (dsu.find(i) == root_R_comp) items_in_root2_comp.push_back(i);\n            }\n            \n            int L_size = 1 + mt() % max_group_query_size;\n            int R_size = 1 + mt() % max_group_query_size;\n\n            L_size = std::min((int)items_in_root1_comp.size(), L_size);\n            R_size = std::min((int)items_in_root2_comp.size(), R_size);\n\n            if (L_size == 0 && !items_in_root1_comp.empty()) L_size = 1;\n            if (R_size == 0 && !items_in_root2_comp.empty()) R_size = 1;\n\n            if (items_in_root1_comp.empty() || items_in_root2_comp.empty()) { // Fallback, should rarely happen\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else {\n                std::shuffle(items_in_root1_comp.begin(), items_in_root1_comp.end(), mt);\n                std::shuffle(items_in_root2_comp.begin(), items_in_root2_comp.end(), mt);\n\n                for (int k = 0; k < L_size; ++k) L_items.push_back(items_in_root1_comp[k]);\n                for (int k = 0; k < R_size; ++k) R_items.push_back(items_in_root2_comp[k]);\n            }\n        }\n\n        // Safety check: ensure L and R are non-empty before query\n        if (L_items.empty() || R_items.empty()) {\n            if (N > 1) { \n                 L_items.clear(); R_items.clear();\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else { \n                continue; // Cannot query with N=1\n            }\n        }\n        // Ensure root_L_comp and root_R_comp are updated to their latest roots\n        root_L_comp = dsu.find(L_items[0]);\n        root_R_comp = dsu.find(R_items[0]);\n\n        // If roots are the same, it means we compare items already believed to be equal.\n        // Such queries might not provide new information if our model is perfect,\n        // but could help refine. For now, we only update if roots are distinct for inequalities.\n        // For equality, 1-1 comparison of items from same root yields no change.\n        // Group comparison of items from same root yields no change.\n\n        std::string result = query(L_items, R_items);\n\n        // Calculate current estimated sums based on component representatives\n        double sum_L_est = 0.0;\n        for (int item_idx : L_items) sum_L_est += comp_estimated_weight[dsu.find(item_idx)];\n        double sum_R_est = 0.0;\n        for (int item_idx : R_items) sum_R_est += comp_estimated_weight[dsu.find(item_idx)];\n\n        if (result == \"=\") {\n            if (root_L_comp != root_R_comp) { // Only adjust if they are distinct components\n                if (L_items.size() == 1 && R_items.size() == 1) {\n                    // Direct merge for 1-vs-1 equality\n                    dsu.unite(L_items[0], R_items[0], comp_estimated_weight);\n                } else { // Group equality for distinct components (e.g., A+B = C+D)\n                    // Softly adjust component weights to make their estimated sums equal\n                    // Target sum per side is the average of current estimated sums\n                    double target_sum_per_side = (sum_L_est + sum_R_est) / 2.0;\n                    \n                    double target_w_L = target_sum_per_side / L_items.size();\n                    double target_w_R = target_sum_per_side / R_items.size();\n\n                    comp_estimated_weight[root_L_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_L_comp] + current_learning_rate * target_w_L;\n                    comp_estimated_weight[root_R_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_R_comp] + current_learning_rate * target_w_R;\n                }\n            }\n        } else { // Inequality: L is lighter (<) or heavier (>) than R\n            if (root_L_comp != root_R_comp) { // Only adjust if distinct components\n                if (result == \"<\") { // Actual L < Actual R\n                    comp_estimated_weight[root_L_comp] *= (1.0 - current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 + current_learning_rate);\n                } else { // Actual L > Actual R (result == \">\")\n                    comp_estimated_weight[root_L_comp] *= (1.0 + current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 - current_learning_rate);\n                }\n            }\n        }\n\n        // Ensure weights are positive. Minimum actual weight is 1.0, but allowing estimates slightly lower might help explore.\n        comp_estimated_weight[root_L_comp] = std::max(0.1, comp_estimated_weight[root_L_comp]);\n        comp_estimated_weight[root_R_comp] = std::max(0.1, comp_estimated_weight[root_R_comp]);\n    }\n\n    // Phase 2: Partitioning using Simulated Annealing\n    std::vector<double> final_weights(N);\n    for (int i = 0; i < N; ++i) {\n        final_weights[i] = comp_estimated_weight[dsu.find(i)];\n    }\n\n    std::vector<int> item_to_group(N);\n    std::vector<int> item_indices(N);\n    std::iota(item_indices.begin(), item_indices.end(), 0);\n\n    // Initial greedy assignment: sort items by estimated weight descending\n    std::sort(item_indices.begin(), item_indices.end(), [&](int a, int b) {\n        return final_weights[a] > final_weights[b];\n    });\n\n    std::vector<double> group_sums(D, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int item_idx = item_indices[i];\n        int min_group = 0;\n        for (int d = 1; d < D; ++d) {\n            if (group_sums[d] < group_sums[min_group]) {\n                min_group = d;\n            }\n        }\n        item_to_group[item_idx] = min_group;\n        group_sums[min_group] += final_weights[item_idx];\n    }\n    \n    // Simulated Annealing parameters\n    // Estimate initial variance for T_start scaling\n    double initial_variance = calculate_variance(D, group_sums);\n    // T_start should be large enough to allow many uphill moves, scaled by initial variance magnitude.\n    double T_start = initial_variance * 10.0; \n    if (T_start < 1.0) T_start = 1.0; // Ensure a reasonable minimum T_start to prevent division by zero or too-small steps\n    double T_end = 0.01;      // Ending temperature, low enough to allow fine convergence\n\n    auto current_time = std::chrono::high_resolution_clock::now();\n    double elapsed_time_at_sa_start = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n    \n    // Time available for SA. Ensure at least a small amount of time.\n    double sa_duration_limit = std::max(0.05, TOTAL_TIME_LIMIT - elapsed_time_at_sa_start); \n\n    double current_variance = initial_variance;\n\n    while (true) {\n        current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time_total = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        \n        if (elapsed_time_total > TOTAL_TIME_LIMIT) break;\n\n        // Progress through the SA phase (0 to 1)\n        double progress = (elapsed_time_total - elapsed_time_at_sa_start) / sa_duration_limit;\n        if (progress < 0) progress = 0; // Should not happen with correct logic\n        if (progress > 1) progress = 1; // Cap progress at 1 for calculation stability\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        int item_to_move_idx = mt() % N;\n        int current_group = item_to_group[item_to_move_idx];\n        int new_group = mt() % D;\n        \n        if (new_group == current_group) {\n            continue; \n        }\n\n        // Temporarily adjust group sums to calculate next_variance\n        double old_group_sum_current = group_sums[current_group];\n        double old_group_sum_new = group_sums[new_group];\n        \n        group_sums[current_group] -= final_weights[item_to_move_idx];\n        group_sums[new_group] += final_weights[item_to_move_idx];\n        \n        double next_variance = calculate_variance(D, group_sums);\n\n        if (next_variance < current_variance) {\n            current_variance = next_variance;\n            item_to_group[item_to_move_idx] = new_group;\n        } else {\n            // Accept worse solution with probability\n            double prob = std::exp((current_variance - next_variance) / T);\n            if (std::uniform_real_distribution<double>(0.0, 1.0)(mt) < prob) {\n                current_variance = next_variance;\n                item_to_group[item_to_move_idx] = new_group;\n            } else {\n                // Revert changes if not accepted\n                group_sums[current_group] = old_group_sum_current;\n                group_sums[new_group] = old_group_sum_new;\n            }\n        }\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        std::cout << item_to_group[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <algorithm> // For std::min_element, std::min, std::max\n#include <limits>    // For std::numeric_limits\n\n// Fixed constants for N and M as per problem statement\nconst int N_BOXES = 200;\nconst int M_STACKS = 10;\nconst int SENTINEL_MIN_VAL = N_BOXES + 1; // Used for min_val_in_stack for empty stacks\n\n// Structure to hold the state of a box\nstruct BoxInfo {\n    int stack_idx;  // 0-indexed stack number (0 to M_STACKS-1)\n    int height_idx; // 0-indexed height from bottom (0 to stack.size()-1)\n};\n\n// Helper function to calculate min_val for a stack\nint calculate_min_in_stack(const std::deque<int>& stack) {\n    if (stack.empty()) {\n        return SENTINEL_MIN_VAL;\n    }\n    // std::min_element returns an iterator to the smallest element\n    return *std::min_element(stack.begin(), stack.end());\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n_input, m_input; // Read N and M, though they are fixed\n    std::cin >> n_input >> m_input;\n\n    // stacks[i] is a deque representing stack i, from bottom to top\n    std::vector<std::deque<int>> stacks(M_STACKS);\n    // box_location[v] stores BoxInfo for box v (1-indexed box_id)\n    std::vector<BoxInfo> box_location(N_BOXES + 1);\n    // min_val_in_stack[i] stores the minimum box ID currently in stack i\n    std::vector<int> min_val_in_stack(M_STACKS);\n\n    // Initialize stacks and box_location from input\n    for (int i = 0; i < M_STACKS; ++i) {\n        for (int j = 0; j < N_BOXES / M_STACKS; ++j) {\n            int box_id;\n            std::cin >> box_id;\n            stacks[i].push_back(box_id);\n            box_location[box_id] = {i, j};\n        }\n    }\n\n    // Initialize min_val_in_stack for all stacks\n    for (int i = 0; i < M_STACKS; ++i) {\n        min_val_in_stack[i] = calculate_min_in_stack(stacks[i]);\n    }\n\n    std::vector<std::pair<int, int>> operations;\n    // long long total_energy_expended = 0; // For debugging/local testing, not required for output\n\n    // Weights for scoring function (heuristic for destination stack selection)\n    const int W1_TOP_BOX = 100;        // Weight for stack.back()\n    const int W2_MIN_BOX = 10;         // Weight for min_val_in_stack[d]\n    const int W3_STACK_SIZE = 10;      // Weight for stack.size() (negative contribution)\n    const int K_LOOKAHEAD = 15;        // Number of future boxes to check for burial penalty\n    const int W4_BADNESS = 1000;       // Weight for burying a soon-needed box\n    const long long EMPTY_STACK_SCORE = 2000000; // A score higher than any possible non-empty stack score, type long long to be safe\n\n    // Iterate for each box from 1 to N_BOXES in ascending order\n    for (int v = 1; v <= N_BOXES; ++v) {\n        int current_stack_idx = box_location[v].stack_idx;\n        int current_height_idx = box_location[v].height_idx;\n\n        // If box v is already carried out, skip (this check is mostly for robustness/debugging)\n        if (current_stack_idx == -1) {\n            continue;\n        }\n\n        // Store min_val of current_stack_idx before any modifications\n        int old_min_val_src_stack = min_val_in_stack[current_stack_idx];\n\n        // Check if box v is at the top of its stack\n        // Using `(int)stacks[current_stack_idx].size() - 1` to ensure correct comparison with int `current_height_idx`\n        if (current_height_idx == (int)stacks[current_stack_idx].size() - 1) {\n            // Box v is at the top, can be carried out\n            operations.push_back({v, 0}); // Operation 2: (v, 0)\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out (stack_idx = -1 means carried out)\n\n            // Update min_val_in_stack for the source stack\n            if (v == old_min_val_src_stack) { // If v was the minimum, recalculate\n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        } else {\n            // Box v is not at the top, need to move boxes above it\n\n            // Identify the bottom-most box of the block to be moved\n            // These are boxes from current_height_idx + 1 up to the top\n            int block_bottom_box_id = stacks[current_stack_idx][current_height_idx + 1];\n            // Calculate number of boxes to move (k in problem statement)\n            // int num_boxes_to_move = stacks[current_stack_idx].size() - (current_height_idx + 1);\n            // total_energy_expended += (long long)num_boxes_to_move + 1; // Add cost (k+1)\n\n            // Choose destination stack for Operation 1 based on heuristic scoring\n            int dest_stack_idx = -1;\n            // Use long long for score to avoid overflow with potentially large penalties\n            long long best_score = std::numeric_limits<long long>::min(); \n\n            for (int d = 0; d < M_STACKS; ++d) {\n                if (d == current_stack_idx) continue; // Cannot move to the same stack\n\n                long long current_score;\n                if (stacks[d].empty()) {\n                    current_score = EMPTY_STACK_SCORE;\n                } else {\n                    current_score = (long long)stacks[d].back() * W1_TOP_BOX + \n                                    (long long)min_val_in_stack[d] * W2_MIN_BOX - \n                                    (long long)stacks[d].size() * W3_STACK_SIZE;\n\n                    long long badness_penalty = 0;\n                    for (int future_v = v + 1; future_v <= std::min(N_BOXES, v + K_LOOKAHEAD); ++future_v) {\n                        // Check if future_v is in stack 'd' and would be buried deeper by this move\n                        // This means future_v is in stack 'd' AND its current height is below the current top of 'd'\n                        // (which is where the new block would start)\n                        if (box_location[future_v].stack_idx == d && box_location[future_v].height_idx < (int)stacks[d].size()) {\n                            // Higher penalty for boxes needed sooner (smaller future_v)\n                            badness_penalty += (N_BOXES - future_v + 1); \n                        }\n                    }\n                    current_score -= badness_penalty * W4_BADNESS;\n                }\n\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    dest_stack_idx = d;\n                }\n            }\n            \n            // At this point, dest_stack_idx must have been selected as M_STACKS >= 2.\n\n            // Perform Operation 1: move block_bottom_box_id and boxes above it to dest_stack_idx\n            // Output stack_idx as 1-indexed, so dest_stack_idx + 1\n            operations.push_back({block_bottom_box_id, dest_stack_idx + 1});\n\n            // Temporarily store boxes that will be moved\n            std::vector<int> boxes_to_move;\n            // Iterate from the box above v up to the current top of the stack\n            for (size_t i = current_height_idx + 1; i < stacks[current_stack_idx].size(); ++i) {\n                boxes_to_move.push_back(stacks[current_stack_idx][i]);\n            }\n            \n            // Resize the original stack to remove the moved boxes\n            stacks[current_stack_idx].resize(current_height_idx + 1);\n\n            // Add the moved boxes to the destination stack and update their locations\n            for (int box_id : boxes_to_move) {\n                // Update height_idx for the box_id in the new stack\n                box_location[box_id] = {dest_stack_idx, (int)stacks[dest_stack_idx].size()};\n                stacks[dest_stack_idx].push_back(box_id);\n            }\n            \n            // Update min_val_in_stack for the destination stack\n            // If dest_stack_idx was empty, its min_val_in_stack was SENTINEL_MIN_VAL,\n            // so any box_id will be smaller and correctly set the new minimum.\n            for (int box_id : boxes_to_move) {\n                min_val_in_stack[dest_stack_idx] = std::min(min_val_in_stack[dest_stack_idx], box_id);\n            }\n\n            // After moving, box v is now at the top of its original stack.\n            // Update v's height_idx to reflect its new top position\n            box_location[v].height_idx = (int)stacks[current_stack_idx].size() - 1;\n\n            // Perform Operation 2: carry out box v\n            operations.push_back({v, 0});\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n\n            // Update min_val_in_stack for the source stack after v is removed\n            // If v was the minimum, recalculate. Otherwise, min_val is unchanged because only boxes above v were removed.\n            if (v == old_min_val_src_stack) { \n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        }\n    }\n\n    // Output the sequence of operations\n    for (const auto& op : operations) {\n        std::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 <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip> // For setprecision\n#include <functional> // For std::function\n#include <queue> // For BFS\n#include <set> // For unique affected cells\n\nusing namespace std;\n\nint N;\nvector<string> H_walls; // h[i][j] wall between (i,j) and (i+1,j)\nvector<string> V_walls; // v[i][j] wall between (i,j) and (i,j+1)\nvector<vector<int>> D_values; // d[i][j] dirt susceptibility\n\n// Directions: D, R, U, L\nint DR[] = {1, 0, -1, 0};\nint DC[] = {0, 1, 0, -1};\nchar DIR_CHARS[] = {'D', 'R', 'U', 'L'};\nchar REV_DIR_CHARS[] = {'U', 'L', 'D', 'R'};\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};\n\n// Get next position after moving in a given direction\nPos get_next_pos(Pos current, int dir_idx) {\n    return {current.r + DR[dir_idx], current.c + DC[dir_idx]};\n}\n\n// Check if move is valid (within bounds and no wall)\nbool is_valid_move(Pos current, int dir_idx) {\n    int nr = current.r + DR[dir_idx];\n    int nc = current.c + DC[dir_idx];\n\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n        return false; // Out of bounds\n    }\n\n    // Check for walls. Note that H_walls[r][c] is wall between (r,c) and (r+1,c)\n    // and V_walls[r][c] is wall between (r,c) and (r,c+1).\n    if (dir_idx == 0) { // Down: from (r,c) to (r+1,c)\n        return H_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 1) { // Right: from (r,c) to (r,c+1)\n        return V_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 2) { // Up: from (r,c) to (r-1,c)\n        // Moving from (current.r, current.c) to (nr,nc) means checking wall H_walls[nr][nc]\n        return H_walls[nr][nc] == '0'; \n    } else if (dir_idx == 3) { // Left: from (r,c) to (r,c-1)\n        // Moving from (current.r, current.c) to (nr,nc) means checking wall V_walls[nr][nc]\n        return V_walls[nr][nc] == '0';\n    }\n    return false;\n}\n\n// Helper function to calculate the contribution of a single cell to the total S_sum_terms\ndouble calculate_cell_contribution(int current_path_length, const vector<int>& cell_visits, int d_value) {\n    if (cell_visits.empty()) {\n        return 0.0; \n    }\n\n    double sum_term_for_cell = 0.0;\n    int N_ij = cell_visits.size();\n\n    for (int k = 0; k < N_ij - 1; ++k) {\n        long long T = cell_visits[k+1] - cell_visits[k];\n        sum_term_for_cell += (double)T * (T - 1) / 2.0;\n    }\n    // For the last interval that wraps around\n    // T_last connects the last visit `cell_visits[N_ij-1]` to the first visit `cell_visits[0]` across the cycle boundary `current_path_length`.\n    long long T_last = current_path_length - cell_visits[N_ij-1] + cell_visits[0];\n    sum_term_for_cell += (double)T_last * (T_last - 1) / 2.0;\n\n    return d_value * sum_term_for_cell;\n}\n\n// Perform BFS to find shortest path from start_pos to end_pos, returning path as string of moves\n// And store visited cells in 'path_coords' for easy updates\nstruct BFS_Parent {\n    Pos p;\n    int dir_idx; // Direction from p to current node\n};\n\nstring find_shortest_path_and_visited_cells(Pos start_pos, Pos end_pos, vector<Pos>& path_coords) {\n    vector<vector<BFS_Parent>> parent_map(N, vector<BFS_Parent>(N, {{-1, -1}, -1}));\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<Pos> q;\n\n    q.push(start_pos);\n    dist[start_pos.r][start_pos.c] = 0;\n\n    bool found = false;\n    while (!q.empty()) {\n        Pos current = q.front();\n        q.pop();\n\n        if (current == end_pos) {\n            found = true;\n            break;\n        }\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            if (is_valid_move(current, dir_idx) && dist[next.r][next.c] == -1) {\n                dist[next.r][next.c] = dist[current.r][current.c] + 1;\n                parent_map[next.r][next.c] = {current, dir_idx}; // Store parent and direction\n                q.push(next);\n            }\n        }\n    }\n\n    if (!found) {\n        return \"\"; // No path found\n    }\n\n    string path_moves = \"\";\n    Pos current = end_pos;\n    path_coords.clear(); \n    \n    while (!(current == start_pos)) {\n        path_coords.push_back(current); \n        BFS_Parent p_info = parent_map[current.r][current.c];\n        path_moves += DIR_CHARS[p_info.dir_idx];\n        current = p_info.p;\n    }\n    path_coords.push_back(start_pos); // Add start_pos to path_coords as well for full trace\n\n    reverse(path_moves.begin(), path_moves.end()); \n    reverse(path_coords.begin(), path_coords.end()); \n    return path_moves;\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    H_walls.resize(N - 1);\n    V_walls.resize(N);\n    D_values.resize(N, vector<int>(N));\n\n    for (int i = 0; i < N - 1; ++i) cin >> H_walls[i];\n    for (int i = 0; i < N; ++i) cin >> V_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D_values[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    string current_path_moves_str;\n    \n    // Initial DFS path generation\n    vector<bool> dfs_visited_cells(N * N, false);\n    \n    function<void(Pos)> build_dfs_path = \n        [&](Pos current) {\n        int current_idx = current.r * N + current.c;\n        dfs_visited_cells[current_idx] = true;\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            int next_idx = next.r * N + next.c;\n\n            if (next.r < 0 || next.r >= N || next.c < 0 || next.c >= N) continue; \n            if (!is_valid_move(current, dir_idx)) continue; \n            if (dfs_visited_cells[next_idx]) continue; \n\n            current_path_moves_str += DIR_CHARS[dir_idx];\n            build_dfs_path(next);\n            current_path_moves_str += REV_DIR_CHARS[dir_idx];\n        }\n    };\n    \n    build_dfs_path({0,0});\n    string initial_dfs_path_moves = current_path_moves_str; \n    int current_L = current_path_moves_str.length();\n\n    // Build initial visits list from the DFS path\n    vector<vector<int>> current_visits(N * N);\n    Pos temp_pos = {0,0};\n    \n    // (0,0) is cleaned initially at time t=0.\n    current_visits[0].push_back(0); \n    for (int t = 0; t < current_L; ++t) {\n        char move_char = current_path_moves_str[t];\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        temp_pos = get_next_pos(temp_pos, dir_idx);\n        current_visits[temp_pos.r * N + temp_pos.c].push_back(t + 1); \n    }\n\n    // Calculate initial total sum of terms for average dirtiness numerator\n    double current_S_sum_terms = 0.0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int sq_idx = i * N + j;\n            if (current_visits[sq_idx].empty()) { \n                current_S_sum_terms = 1e18; \n                break;\n            }\n            current_S_sum_terms += calculate_cell_contribution(current_L, current_visits[sq_idx], D_values[i][j]);\n        }\n        if (current_S_sum_terms >= 1e18) break;\n    }\n    double current_score = current_S_sum_terms / current_L;\n    \n    double best_score = current_score;\n    string best_path_moves = current_path_moves_str; \n\n    mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double T_start = 2000.0; // Increased T_start\n    double T_end = 0.01;     // Decreased T_end\n    long long max_iterations_for_temp = 1000000; \n\n    vector<Pos> all_cells;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            all_cells.push_back({i, j});\n        }\n    }\n\n    int iter_count = 0;\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1950) {\n        iter_count++;\n        double T = T_start + (T_end - T_start) * ((double)iter_count / max_iterations_for_temp);\n        if (T < T_end) T = T_end; \n\n        // --- Dynamic Weighted random choice for target cell ---\n        vector<double> cell_weights(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int sq_idx = i * N + j;\n                double avg_interval = (double)current_L / max(1, (int)current_visits[sq_idx].size());\n                cell_weights[sq_idx] = D_values[i][j] * avg_interval;\n                // Add a small constant to prevent zero weights, if D_values can be zero\n                // (problem statement says 1 <= D_values <= 1000, so no zero D_values)\n                if (cell_weights[sq_idx] < 1e-9) cell_weights[sq_idx] = 1e-9; // Ensure positive weight\n            }\n        }\n        discrete_distribution<int> cell_dist_discrete(cell_weights.begin(), cell_weights.end());\n        int chosen_cell_idx = cell_dist_discrete(rng);\n        Pos target_pos = all_cells[chosen_cell_idx];\n\n        // --- Find path from (0,0) to target_pos and back to (0,0) ---\n        Pos zero_zero_pos = {0,0};\n        vector<Pos> path_coords_1;\n        string path_moves_1 = find_shortest_path_and_visited_cells(zero_zero_pos, target_pos, path_coords_1);\n        if (path_moves_1.empty()) continue; \n\n        vector<Pos> path_coords_2;\n        string path_moves_2 = find_shortest_path_and_visited_cells(target_pos, zero_zero_pos, path_coords_2);\n        if (path_moves_2.empty()) continue; \n\n        string added_moves = path_moves_1 + path_moves_2;\n        int temp_L = current_L + added_moves.length();\n        \n        if (temp_L > 100000) continue; \n\n        // Collect all unique cells affected by this added loop\n        set<int> affected_set;\n        for (const auto& p : path_coords_1) {\n            affected_set.insert(p.r * N + p.c);\n        }\n        for (const auto& p : path_coords_2) {\n            affected_set.insert(p.r * N + p.c);\n        }\n        vector<int> affected_cell_indices(affected_set.begin(), affected_set.end());\n\n        // Create temporary visits lists for affected cells by copying from current_visits\n        vector<vector<int>> temp_visits_for_affected(N * N); \n        for(int idx : affected_cell_indices) {\n            temp_visits_for_affected[idx] = current_visits[idx];\n        }\n\n        // Add new visit times for all cells in the loop\n        Pos current_loop_pos = zero_zero_pos; \n        int current_time_offset = current_L;\n        for (char move_char : added_moves) {\n            current_time_offset++;\n            int dir_idx = -1;\n            if (move_char == 'D') dir_idx = 0;\n            else if (move_char == 'R') dir_idx = 1;\n            else if (move_char == 'U') dir_idx = 2;\n            else if (move_char == 'L') dir_idx = 3;\n            current_loop_pos = get_next_pos(current_loop_pos, dir_idx);\n            \n            int cell_idx = current_loop_pos.r * N + current_loop_pos.c;\n            auto it = lower_bound(temp_visits_for_affected[cell_idx].begin(), temp_visits_for_affected[cell_idx].end(), current_time_offset);\n            temp_visits_for_affected[cell_idx].insert(it, current_time_offset);\n        }\n\n        double temp_total_S_sum_terms = 0.0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int sq_idx = i * N + j;\n                const vector<int>* visits_ptr;\n                \n                if (temp_visits_for_affected[sq_idx].empty()) { \n                    visits_ptr = &current_visits[sq_idx]; \n                } else {\n                    visits_ptr = &temp_visits_for_affected[sq_idx]; \n                }\n\n                temp_total_S_sum_terms += calculate_cell_contribution(temp_L, *visits_ptr, D_values[i][j]);\n            }\n        }\n        double temp_score = temp_total_S_sum_terms / temp_L;\n        \n        double delta_score = temp_score - current_score;\n\n        if (delta_score < 0 || (T > 0 && dist_real(rng) < exp(-delta_score / T))) {\n            current_path_moves_str += added_moves; \n            current_L = temp_L;\n            for(int idx : affected_cell_indices) {\n                current_visits[idx] = temp_visits_for_affected[idx];\n            }\n            current_S_sum_terms = temp_total_S_sum_terms; \n            current_score = temp_score;\n\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_path_moves = current_path_moves_str;\n            }\n        }\n    }\n\n    // Final check for the best_path_moves: ensure it truly ends at (0,0)\n    Pos final_pos_check = {0,0};\n    for (char move_char : best_path_moves) {\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        final_pos_check = get_next_pos(final_pos_check, dir_idx);\n    }\n\n    if (!(final_pos_check == Pos{0,0})) {\n        cerr << \"WARNING: best_path_moves does not end at (0,0). Falling back to initial DFS path.\" << endl;\n        cout << initial_dfs_path_moves << endl;\n    } else {\n        cout << best_path_moves << endl;\n    }\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm> \n#include <tuple>     \n#include <cmath>     \n\n// Aho-Corasick Node definition\nstruct ACNode {\n    std::array<int, 26> go_direct; // Stores ONLY direct transitions from this node\n    int fail;                      // Failure link\n    std::vector<int> pattern_indices; // Indices of patterns ending at this node (or via failure links)\n    int depth;                     // Length of string represented by this node\n\n    ACNode() : fail(0), depth(0) {\n        go_direct.fill(0); // Initialize all direct transitions to 0\n    }\n};\n\nstd::vector<ACNode> ac_trie;         // The Aho-Corasick automaton trie\nstd::vector<char> global_found_tks; // Tracks which of the M patterns have been found\nint M_val;                          // Stores the total number of patterns (M)\n\n// Get the next state in the Aho-Corasick automaton (dynamic traversal using fail links)\n// This is the more robust, but potentially slower, way\nint get_next_ac_state_dynamic(int current_node, char ch) {\n    int c_idx = ch - 'A';\n    // Repeatedly follow failure links until a direct transition is found or root is reached\n    while (current_node != 0 && ac_trie[current_node].go_direct[c_idx] == 0) {\n        current_node = ac_trie[current_node].fail;\n    }\n    // If a direct transition from current_node (or its fail-link ancestor) exists, take it.\n    // If not (e.g., current_node is 0 and no direct transition), stay at root (0).\n    if (ac_trie[current_node].go_direct[c_idx] != 0) {\n        return ac_trie[current_node].go_direct[c_idx];\n    }\n    return 0; // Return root if no match\n}\n\n// Builds the Aho-Corasick automaton from the given patterns\nvoid build_ac(const std::vector<std::string>& patterns) {\n    ac_trie.clear();\n    ac_trie.emplace_back(); // Root node (node 0)\n    M_val = patterns.size();\n    global_found_tks.assign(M_val, 0); // Initialize all patterns as not found (0 for false)\n\n    // 1. Build Trie structure: Insert all patterns into the trie\n    for (int p_idx = 0; p_idx < M_val; ++p_idx) {\n        int curr = 0; // Start from the root\n        for (char ch : patterns[p_idx]) {\n            int c_idx = ch - 'A';\n            if (ac_trie[curr].go_direct[c_idx] == 0) { // If direct transition doesn't exist, create a new node\n                ac_trie[curr].go_direct[c_idx] = ac_trie.size(); // Assign new node ID\n                ac_trie.emplace_back();                   // Add new node to the trie\n                ac_trie.back().depth = ac_trie[curr].depth + 1; // Set its depth\n            }\n            curr = ac_trie[curr].go_direct[c_idx]; // Move to the next node\n        }\n        ac_trie[curr].pattern_indices.push_back(p_idx); // Mark this node as an end point for pattern p_idx\n    }\n\n    // 2. Build Failure Links and propagate output patterns using BFS\n    std::queue<int> q;\n    // For all direct children of the root, their failure link points to the root (0)\n    for (int i = 0; i < 26; ++i) {\n        if (ac_trie[0].go_direct[i] != 0) {\n            ac_trie[ac_trie[0].go_direct[i]].fail = 0; // Set fail link\n            q.push(ac_trie[0].go_direct[i]);           // Add to BFS queue\n        }\n    }\n\n    while (!q.empty()) {\n        int u = q.front(); // Current node\n        q.pop();\n\n        // Propagate pattern_indices from the failure link:\n        // Any patterns found via `u`'s failure link are also considered found when at `u`\n        int f = ac_trie[u].fail;\n        for (int p_idx : ac_trie[f].pattern_indices) {\n            ac_trie[u].pattern_indices.push_back(p_idx);\n        }\n        \n        // For each character in the alphabet\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            if (ac_trie[u].go_direct[c_idx] != 0) { // If a direct child `v` exists for char `c_idx`\n                int v = ac_trie[u].go_direct[c_idx];\n                // The fail link of `v` is found by dynamically traversing from `u`'s fail link\n                ac_trie[v].fail = get_next_ac_state_dynamic(ac_trie[u].fail, 'A' + c_idx);\n                q.push(v); // Add `v` to the BFS queue\n            }\n            // Note: No `else` branch to precompute shortcuts here.\n            // `get_next_ac_state_dynamic` handles traversal dynamically.\n        }\n    }\n}\n\n// Checks for newly found patterns at the given node and updates the global_found_tks array.\nvoid check_and_update_patterns(int node_id) {\n    for (int p_idx : ac_trie[node_id].pattern_indices) {\n        if (!global_found_tks[p_idx]) { // If this pattern hasn't been marked as found yet\n            global_found_tks[p_idx] = 1; // Mark it as found (1 for true)\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_grid, M_patterns;\n    std::cin >> N_grid >> M_patterns;\n\n    int s_i, s_j; // Initial finger position\n    std::cin >> s_i >> s_j;\n\n    std::vector<std::string> A_grid(N_grid);\n    std::vector<std::vector<std::pair<int, int>>> char_to_coords(26);\n    for (int i = 0; i < N_grid; ++i) {\n        std::cin >> A_grid[i];\n        for (int j = 0; j < N_grid; ++j) {\n            char_to_coords[A_grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    std::vector<std::string> t_patterns(M_patterns);\n    for (int k = 0; k < M_patterns; ++k) {\n        std::cin >> t_patterns[k];\n    }\n\n    build_ac(t_patterns); // Build the Aho-Corasick automaton\n\n    std::pair<int, int> current_pos = {s_i, s_j}; // Current finger position\n    int current_ac_node = 0; // Current state in the Aho-Corasick automaton (starts at root)\n    std::vector<std::pair<int, int>> operations; // List to store the sequence of operations\n\n    check_and_update_patterns(0); // Check for patterns found by empty string (usually none)\n\n    // Main greedy loop\n    while (true) {\n        int found_count = 0;\n        for (char b : global_found_tks) {\n            if (b) found_count++;\n        }\n\n        if (found_count == M_patterns) {\n            break; \n        }\n        if (operations.size() >= 5000) {\n            break; \n        }\n\n        int best_nr = -1, best_nc = -1; \n        char best_char_to_append = ' '; \n\n        // Metric for choosing the best next operation (maximize new patterns, then depth, then minimize cost)\n        std::tuple<int, int, int> best_metric = {-1, -1, 1}; \n\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            char c = 'A' + c_idx;\n            for (auto [nr, nc] : char_to_coords[c_idx]) { \n                int current_move_cost = std::abs(nr - current_pos.first) + std::abs(nc - current_pos.second) + 1;\n                // Use the dynamic state traversal\n                int next_node = get_next_ac_state_dynamic(current_ac_node, c); \n\n                int temp_new_tks_count = 0;\n                for (int p_idx : ac_trie[next_node].pattern_indices) {\n                    if (!global_found_tks[p_idx]) { \n                        temp_new_tks_count++;\n                    }\n                }\n                \n                std::tuple<int, int, int> current_metric = {temp_new_tks_count, ac_trie[next_node].depth, -current_move_cost};\n\n                if (current_metric > best_metric) { \n                    best_metric = current_metric;\n                    best_nr = nr;\n                    best_nc = nc;\n                    best_char_to_append = c;\n                }\n            }\n        }\n\n        if (best_nr == -1) { // Should not happen if patterns are not all found and ops < 5000\n            break;\n        }\n\n        operations.push_back({best_nr, best_nc});\n        current_pos = {best_nr, best_nc}; \n        current_ac_node = get_next_ac_state_dynamic(current_ac_node, best_char_to_append); \n        check_and_update_patterns(current_ac_node); \n    }\n\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <map>\n#include <set>\n#include <chrono>\n\n// Global variables for problem parameters\nint N, M;\ndouble EPS;\nstd::vector<std::vector<std::pair<int, int>>> poly_shapes; // M polyomino shapes, relative coordinates\n\n// Time limit management\nauto start_time = std::chrono::high_resolution_clock::now();\nlong long TIME_LIMIT_MS = 2800; // 2.8 seconds for safety, total time limit is 3.0 sec\n\nbool check_time() {\n    auto current_time = std::chrono::high_resolution_clock::now();\n    auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n    return elapsed_ms < TIME_LIMIT_MS;\n}\n\n// Coordinate struct\nstruct Coord {\n    int r, c;\n    bool operator<(const Coord& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Polyomino bounds (max_r, max_c) relative to (0,0)\nstd::vector<Coord> poly_bounds; // Store max_r, max_c for each poly shape\n\n// Helper to flush output\nvoid flush_output() {\n    std::cout << std::flush;\n}\n\n// Query 1 (drill)\nint query_1(int r, int c) {\n    std::cout << \"q 1 \" << r << \" \" << c << std::endl;\n    flush_output();\n    int v_val;\n    std::cin >> v_val;\n    return v_val;\n}\n\n// Query k (divine)\nint query_k(const std::vector<Coord>& coords) {\n    // This function assumes coords.size() >= 2 as per problem statement\n    std::cout << \"q \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int approx_v_sum;\n    std::cin >> approx_v_sum;\n    return approx_v_sum;\n}\n\n// Answer (guess)\nbool answer(const std::vector<Coord>& coords) {\n    std::cout << \"a \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int response;\n    std::cin >> response;\n    return response == 1;\n}\n\n// Cumulative distribution function for normal distribution\n// M_SQRT2 is from <cmath>, represents sqrt(2)\ndouble normalCDF(double x, double mean, double stddev) {\n    if (stddev < 1e-9) { // Handle very small standard deviation (effectively 0)\n        return x >= mean ? 1.0 : 0.0;\n    }\n    return 0.5 * (1.0 + std::erf((x - mean) / (stddev * M_SQRT2)));\n}\n\n// Particle structure\nstruct Particle {\n    std::vector<Coord> oil_field_positions; // (min_r, min_c) for each of M fields\n    std::vector<std::vector<int>> v_grid; // N x N grid for this particle's configuration\n    double weight;\n\n    Particle() : v_grid(N, std::vector<int>(N, 0)), weight(1.0) {}\n\n    void calculate_v_grid() {\n        for (int i = 0; i < N; ++i) {\n            std::fill(v_grid[i].begin(), v_grid[i].end(), 0);\n        }\n\n        for (int k = 0; k < M; ++k) {\n            const Coord& pos = oil_field_positions[k];\n            // Only process if the position is valid (not a dummy -1,-1)\n            if (pos.r == -1 && pos.c == -1) continue; \n\n            for (const auto& rel_coord : poly_shapes[k]) {\n                int r = pos.r + rel_coord.first;\n                int c = pos.c + rel_coord.second;\n                // Coordinates are guaranteed to be within N x N due to placement generation\n                v_grid[r][c]++;\n            }\n        }\n    }\n\n    int get_v_S_sum(const std::vector<Coord>& query_coords) const {\n        int sum = 0;\n        for (const auto& p : query_coords) {\n            sum += v_grid[p.r][p.c];\n        }\n        return sum;\n    }\n};\n\n// Global random number generator\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> EPS;\n\n    poly_shapes.resize(M);\n    poly_bounds.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d_k;\n        std::cin >> d_k;\n        poly_shapes[k].resize(d_k);\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d_k; ++i) {\n            std::cin >> poly_shapes[k][i].first >> poly_shapes[k][i].second;\n            max_r = std::max(max_r, poly_shapes[k][i].first);\n            max_c = std::max(max_c, poly_shapes[k][i].second);\n        }\n        poly_bounds[k] = {max_r, max_c};\n    }\n\n    // Precompute all possible top-left placements for each polyomino\n    std::vector<std::vector<Coord>> possible_poly_placements(M);\n    for (int k = 0; k < M; ++k) {\n        for (int r = 0; r <= N - 1 - poly_bounds[k].r; ++r) {\n            for (int c = 0; c <= N - 1 - poly_bounds[k].c; ++c) { \n                possible_poly_placements[k].push_back({r, c});\n            }\n        }\n    }\n\n    int NUM_PARTICLES = 5000; \n    if (N > 15) NUM_PARTICLES = 15000; // Increased\n    if (N <= 12) NUM_PARTICLES = 4000; // Increased\n    if (M >= 10 && N > 15) NUM_PARTICLES = 25000; // Increased significantly\n    else if (M >= 10 && N <= 15) NUM_PARTICLES = 10000; // New tier for many polyominos on smaller N\n\n\n    std::vector<Particle> particles(NUM_PARTICLES);\n\n    // Initialize particles: random positions, calculate v_grid, set uniform weights\n    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n        particles[p_idx].oil_field_positions.resize(M); \n        bool particle_valid = true;\n        for (int k = 0; k < M; ++k) {\n            if (possible_poly_placements[k].empty()) {\n                std::cout << \"#c WARNING: No possible placements for polyomino \" << k << \". Particle will be invalid.\\n\";\n                particle_valid = false;\n                particles[p_idx].oil_field_positions[k] = {-1, -1}; \n            } else {\n                std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n            }\n        }\n        \n        if (particle_valid) {\n            particles[p_idx].calculate_v_grid();\n            particles[p_idx].weight = 1.0 / NUM_PARTICLES; \n        } else {\n            particles[p_idx].weight = 0.0; // Invalid particles get 0 weight and will be filtered out by resampling\n        }\n    }\n\n    int ops_count = 0;\n    int MAX_OPS = 2 * N * N;\n\n    // Keep track of drilled squares and their true values\n    std::map<Coord, int> drilled_actual_v;\n\n    // ---- Initial broad queries (q N*N) ----\n    // Cheap queries for the whole grid to quickly refine the total oil count.\n    int initial_broad_queries_count = std::min(30, MAX_OPS / 10); // Increased for more initial passes\n    if (N < 15) initial_broad_queries_count = std::min(20, MAX_OPS/10); \n\n    for (int iter = 0; iter < initial_broad_queries_count; ++iter) {\n        if (!check_time() || ops_count >= MAX_OPS - 2) break; \n\n        std::vector<Coord> all_squares;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                all_squares.push_back({r, c});\n            }\n        }\n\n        int observed_sum = query_k(all_squares); \n        ops_count++;\n\n        double total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            if (particles[p_idx].weight == 0.0) continue; \n            int particle_v_sum = particles[p_idx].get_v_S_sum(all_squares);\n            \n            double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)N * N * EPS;\n            double sigma_sq = (double)N * N * EPS * (1.0 - EPS);\n            double stddev = std::sqrt(sigma_sq);\n\n            double likelihood;\n            if (observed_sum == 0) {\n                likelihood = normalCDF(0.5, mu, stddev);\n            } else {\n                likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n            }\n            if (likelihood < 1e-10) likelihood = 1e-10; \n\n            particles[p_idx].weight *= likelihood;\n            total_weight += particles[p_idx].weight;\n        }\n\n        // Resampling\n        if (total_weight > 1e-10) { \n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx]; \n                new_particles[i].weight = 1.0 / NUM_PARTICLES; \n            }\n            particles = new_particles;\n        } else {\n            std::cout << \"#c All particle weights zero, re-initializing!\\n\";\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                bool particle_valid_reinit = true;\n                for (int k = 0; k < M; ++k) {\n                    if (possible_poly_placements[k].empty()) {\n                        particle_valid_reinit = false;\n                        particles[p_idx].oil_field_positions[k] = {-1, -1};\n                    } else {\n                        std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                        particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                    }\n                }\n                if (particle_valid_reinit) {\n                    particles[p_idx].calculate_v_grid();\n                    particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n                } else {\n                    particles[p_idx].weight = 0.0;\n                }\n            }\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) total_weight += particles[p_idx].weight;\n            if (total_weight > 1e-10) { \n                 std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else {\n                std::cout << \"#c Still no particles after re-applying drilled data. Filter effectively failed.\\n\";\n                break; \n            }\n        }\n    }\n\n\n    // ---- Main particle filter loop with targeted queries ----\n    int drill_budget; \n    int k_query_budget; \n    \n    // Adjust budget based on EPS\n    if (EPS > 0.1) { // High error, prioritize drills (more budget for drills)\n        drill_budget = N*N / 8; // Increased\n        k_query_budget = N*N / 12; // Increased, but less than drill\n    } else { // Low error, more k-queries (more budget for k-queries)\n        drill_budget = N*N / 10; // Increased\n        k_query_budget = N*N / 8; // Increased\n    }\n    \n    int drills_done = 0;\n    int k_queries_done = 0;\n\n    int loop_iterations = 0;\n    const int MAX_MAIN_LOOP_ITERS = MAX_OPS - initial_broad_queries_count - 2; \n    \n    std::vector<std::vector<bool>> queried_mask(N, std::vector<bool>(N, false));\n\n    while (ops_count < MAX_OPS - 2 && loop_iterations < MAX_MAIN_LOOP_ITERS && check_time()) {\n        loop_iterations++;\n        \n        std::vector<std::vector<double>> P_has_oil(N, std::vector<double>(N, 0.0));\n        std::vector<std::vector<double>> E_v(N, std::vector<double>(N, 0.0));\n        double current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight < 1e-10) { \n            std::cout << \"#c Current total weight too small in main loop, breaking.\\n\";\n            break;\n        }\n\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            if (particles[p_idx].weight == 0.0) continue; \n            double normalized_weight = particles[p_idx].weight / current_total_weight;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (particles[p_idx].v_grid[r][c] > 0) {\n                        P_has_oil[r][c] += normalized_weight;\n                    }\n                    E_v[r][c] += normalized_weight * particles[p_idx].v_grid[r][c];\n                }\n            }\n        }\n        \n        bool queried_this_iter = false;\n\n        if (drills_done < drill_budget) {\n            double max_uncertainty = -1.0;\n            Coord best_drill_coord_uncertainty = {-1, -1};\n            double max_E_v = -1.0;\n            Coord best_drill_coord_Ev = {-1, -1};\n\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { \n                        double uncertainty = P_has_oil[r][c] * (1.0 - P_has_oil[r][c]); \n                        if (uncertainty > max_uncertainty) {\n                            max_uncertainty = uncertainty;\n                            best_drill_coord_uncertainty = current_coord;\n                        }\n                        if (E_v[r][c] > max_E_v) {\n                            max_E_v = E_v[r][c];\n                            best_drill_coord_Ev = current_coord;\n                        }\n                    }\n                }\n            }\n            \n            if (best_drill_coord_uncertainty.r != -1 && max_uncertainty > 0.05) { \n                 int actual_v = query_1(best_drill_coord_uncertainty.r, best_drill_coord_uncertainty.c);\n                 drilled_actual_v[best_drill_coord_uncertainty] = actual_v;\n                 ops_count++;\n                 drills_done++;\n                 queried_this_iter = true;\n                 for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                     if (particles[p_idx].v_grid[best_drill_coord_uncertainty.r][best_drill_coord_uncertainty.c] != actual_v) {\n                         particles[p_idx].weight = 0;\n                     }\n                 }\n            } else if (best_drill_coord_Ev.r != -1 && max_E_v > 0.2) { \n                int actual_v = query_1(best_drill_coord_Ev.r, best_drill_coord_Ev.c);\n                drilled_actual_v[best_drill_coord_Ev] = actual_v;\n                ops_count++;\n                drills_done++;\n                queried_this_iter = true;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[best_drill_coord_Ev.r][best_drill_coord_Ev.c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n        }\n        \n        if (!queried_this_iter && k_queries_done < k_query_budget) {\n            std::vector<std::pair<double, Coord>> uncertainty_list;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && !queried_mask[r][c]) {\n                        uncertainty_list.push_back({P_has_oil[r][c] * (1.0 - P_has_oil[r][c]) + E_v[r][c] / M, current_coord});\n                    }\n                }\n            }\n            std::sort(uncertainty_list.rbegin(), uncertainty_list.rend()); \n\n            if (uncertainty_list.size() >= 2) { \n                int k_val = std::min((int)uncertainty_list.size(), (int)(N * N / (10 + 50 * EPS))); \n                if (k_val < 2) k_val = 2; \n\n                std::vector<Coord> query_coords;\n                for (int i = 0; i < k_val; ++i) {\n                    query_coords.push_back(uncertainty_list[i].second);\n                    queried_mask[uncertainty_list[i].second.r][uncertainty_list[i].second.c] = true; \n                }\n                \n                int observed_sum = query_k(query_coords);\n                ops_count++;\n                k_queries_done++;\n                queried_this_iter = true;\n\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].weight == 0.0) continue; \n                    int particle_v_sum = particles[p_idx].get_v_S_sum(query_coords);\n                    double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)query_coords.size() * EPS;\n                    double sigma_sq = (double)query_coords.size() * EPS * (1.0 - EPS);\n                    double stddev = std::sqrt(sigma_sq);\n\n                    double likelihood;\n                    if (observed_sum == 0) {\n                        likelihood = normalCDF(0.5, mu, stddev);\n                    } else {\n                        likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n                    }\n                    if (likelihood < 1e-10) likelihood = 1e-10;\n\n                    particles[p_idx].weight *= likelihood;\n                }\n            } \n        }\n\n        current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight > 1e-10) {\n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / current_total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx];\n                new_particles[i].weight = 1.0 / NUM_PARTICLES;\n            }\n            particles = new_particles;\n        } else {\n            std::cout << \"#c All particle weights zero in main loop, re-initializing!\\n\";\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                bool particle_valid_reinit = true;\n                for (int k = 0; k < M; ++k) {\n                    if (possible_poly_placements[k].empty()) {\n                        particle_valid_reinit = false;\n                        particles[p_idx].oil_field_positions[k] = {-1, -1};\n                    } else {\n                        std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                        particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                    }\n                }\n                if (particle_valid_reinit) {\n                    particles[p_idx].calculate_v_grid();\n                    particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n                } else {\n                    particles[p_idx].weight = 0.0;\n                }\n            }\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            current_total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) current_total_weight += particles[p_idx].weight;\n            if (current_total_weight > 1e-10) { \n                std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / current_total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else { \n                break;\n            }\n        }\n\n        if (loop_iterations % (N) == 0) { \n            for (int r = 0; r < N; ++r) std::fill(queried_mask[r].begin(), queried_mask[r].end(), false);\n        }\n    }\n\n\n    // Final guess attempt\n    std::set<Coord> potential_oil_squares_set;\n    for(const auto& entry : drilled_actual_v) { \n        if (entry.second > 0) {\n            potential_oil_squares_set.insert(entry.first);\n        }\n    }\n\n    double final_total_weight = 0.0;\n    for(const auto& p : particles) final_total_weight += p.weight;\n    \n    if (final_total_weight > 1e-10) { \n        double p_threshold = 0.15; // Default for very high error\n        if (EPS < 0.15) p_threshold = 0.2;\n        if (EPS < 0.10) p_threshold = 0.3; \n        if (EPS < 0.05) p_threshold = 0.4;\n        if (EPS < 0.02) p_threshold = 0.5; \n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                Coord current_coord = {r, c};\n                if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { \n                    double P_val = 0.0;\n                    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                        if (particles[p_idx].weight == 0.0) continue; \n                        if (particles[p_idx].v_grid[r][c] > 0) {\n                            P_val += particles[p_idx].weight;\n                        }\n                    }\n                    P_val /= final_total_weight;\n                    if (P_val > p_threshold) { \n                        potential_oil_squares_set.insert(current_coord);\n                    }\n                }\n            }\n        }\n    } else { \n        std::cout << \"#c Particle filter collapsed before final guess. Relying on drilled data only.\\n\";\n    }\n\n\n    std::vector<Coord> final_oil_squares_vec(potential_oil_squares_set.begin(), potential_oil_squares_set.end());\n    std::sort(final_oil_squares_vec.begin(), final_oil_squares_vec.end()); \n\n    if (answer(final_oil_squares_vec)) {\n        return 0; \n    }\n    ops_count++;\n\n    std::cout << \"#c Initial guess incorrect. Falling back to drilling all remaining squares.\\n\";\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            Coord current_coord = {r, c};\n            if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && ops_count < MAX_OPS -1) { \n                int actual_v = query_1(r, c);\n                drilled_actual_v[current_coord] = actual_v;\n                ops_count++;\n            }\n        }\n    }\n\n    std::vector<Coord> final_fallback_squares;\n    for (const auto& entry : drilled_actual_v) {\n        if (entry.second > 0) {\n            final_fallback_squares.push_back(entry.first);\n        }\n    }\n    std::sort(final_fallback_squares.begin(), final_fallback_squares.end()); \n\n    if (!answer(final_fallback_squares)) {\n        std::cout << \"#c Fallback guess incorrect. This should not happen!\\n\";\n    }\n\n    return 0;\n}\n","ahc031":"long long calculate_delta_cost(int d, const Rect& old_r, const Rect& new_r, int k_id,\n                                 const bool H_prev_day[W+1][W], const bool V_prev_day[W][W+1],\n                                 GridManager& gm, long long current_total_cost) {\n    // 1. Calculate delta area cost:\n    long long delta_area_cost = 0;\n    // Remove old_r's contribution\n    if (old_r.area() < a_global[d][k_id]) delta_area_cost -= 100LL * (a_global[d][k_id] - old_r.area());\n    // Add new_r's contribution\n    if (new_r.area() < a_global[d][k_id]) delta_area_cost += 100LL * (a_global[d][k_id] - new_r.area());\n\n    // 2. Calculate delta partition cost:\n    long long delta_partition_cost = 0;\n    \n    // Temporarily revert the placed_rects entry for k_id to old_r\n    // (since gm.place(new_r, k_id) was already called for validation)\n    // We need the state *before* gm.place(new_r, k_id) to figure out diffs.\n    // The safest way is to manage `H_curr` and `V_curr` arrays incrementally.\n    \n    // Instead of directly calculating delta, calculate new total cost based on `gm.placed_rects`\n    // (which now includes new_r) and then subtract `current_total_cost`.\n    // This implies `calculate_day_cost` is called directly, but its performance needs to be improved\n    // beyond `O(W^2)`.\n\n    // Optimized `calculate_day_cost` for incremental SA updates:\n    // Store `H_current_sum` and `V_current_sum` (total active partitions)\n    // When `is_occupied[r][c]` changes, it affects 4 segments.\n    // For each affected segment `s = (i,j)-(i',j')`:\n    //  `old_H_curr_s = is_segment_a_border_before_change(s)`\n    //  `new_H_curr_s = is_segment_a_border_after_change(s)`\n    //  If `(old_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    //  If `(new_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    // This is the $O(Area)$ bottleneck.\n    // To implement `is_segment_a_border`, you need `is_occupied` state.\n\n    // A simpler way:\n    // Copy `is_occupied` state to a temporary `is_occupied_temp`\n    // Then `gm.remove(k_id, from_is_occupied_temp)`\n    // Compute `old_local_partition_status` using `is_occupied_temp` within `old_r`'s perimeter + 1 cell buffer.\n    // `gm.place(new_r, to_is_occupied_temp)`\n    // Compute `new_local_partition_status` using `is_occupied_temp` within `new_r`'s perimeter + 1 cell buffer.\n    // Then calculate the `delta_partition_cost` within these local affected regions.\n\n    // For simplicity of implementation (and hoping that AvgArea is small enough on average)\n    // just call the full `calculate_day_cost` after updating `gm.placed_rects`.\n    // With `SA_ITERATIONS` around 1000 per day, total $5 \\times 10^7$ iterations for `calculate_day_cost`.\n    // AvgArea $20000 \\approx 0.02 W^2$.\n    // If average $W^2$ operations is $2 \\times 10^4$, then $5 \\times 10^7 \\times 2 \\times 10^4 = 10^{12}$. Still too much.\n    // This is why `calculate_day_cost` *must* be O(Perimeter) in SA.\n    \n    // Let's go with the O(Perimeter) approach for SA iterations.\n    // Need to precompute `H_curr` and `V_curr` from `is_occupied` once per day.\n    // Then when a rectangle `R_k` changes, we update only the segments around its perimeter.\n    // This implies `H_curr_global[W+1][W]` and `V_curr_global[W][W+1]` must be updated incrementally.\n    \n    // `current_H_states[W+1][W]` and `current_V_states[W][W+1]` (booleans)\n    // `current_H_count`, `current_V_count` (total partition lengths)\n    // On a move:\n    //  `old_r_perimeter_segs = get_perimeter_segments(old_r)`\n    //  `new_r_perimeter_segs = get_perimeter_segments(new_r)`\n    //  For `s` in `old_r_perimeter_segs` and `new_r_perimeter_segs` (union):\n    //    `was_border = is_segment_a_border(s, is_occupied_before_change)`\n    //    `is_border = is_segment_a_border(s, is_occupied_after_change)`\n    //    If `was_border != is_border`:\n    //      if `was_border != global_H_prev[s]`: `delta_cost--`\n    //      if `is_border != global_H_prev[s]`: `delta_cost++`\n    // This `is_segment_a_border` checks `is_occupied` for neighbors of `s`, which means `O(1)` per segment.\n    // Total `O(Perimeter)` for partition cost delta. Area update is $O(Area)$.\n    // So the move is $O(Area + Perimeter)$, which becomes $O(Area)$ in worst case.\n    // Let's assume avg Area is small enough on average for $N=50$ given $W=1000$.\n    // If $W^2/N = 20000$, $Area \\sim 20000$. This is the largest factor.\n    // $50 \\times 1000 \\times 20000 = 10^9$. Maybe SA_ITERATIONS must be smaller, say 1000.\n    // $50 \\times 1000 \\times 20000 = 10^9$. This would be close to 1 second.\n    // $SA\\_ITERATIONS=1000$ per day. Total $50000$ iterations.\n    // Each is $O(Area)$, `20000`. So $50000 \\times 20000 = 10^9$. This will be slow for 3s.\n    // The input generation suggests `a_d,k` sum is around $W^2-E$. Smallest $E$ is $W^2 \\times 0.0025 = 2500$.\n    // So average desired area is typically $W^2/N \\approx 20000$.\n    // Maybe `Area` updates are sparse?\n}\n\nFinal decision: I will implement `calculate_day_cost` with `O(W^2)` per call, and reduce `SA_ITERATIONS` to a very small number (e.g., 50 per day). This makes total operations $D \\times SA\\_ITERATIONS \\times W^2 = 50 \\times 50 \\times 10^6 = 2.5 \\times 10^9$. This might barely pass, or be too slow. A hybrid: `O(Area)` based delta computation during SA, and full `O(W^2)` only once at the end of each day for `global_H_prev` update.\n","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>     // Potentially for std::accumulate, though not strictly used with the new scoring approach\n#include <algorithm>   // For std::sort, std::min, std::max\n#include <limits>      // For std::numeric_limits\n#include <chrono>      // For high_resolution_clock and duration for time limiting\n#include <random>      // For mt19937, uniform_int_distribution, and discrete_distribution\n\n// Define MOD constant\nconst int MOD = 998244353;\n\n// Structure to store an performed operation\nstruct Operation {\n    int m, p, q;\n};\n\n// Helper struct to store an option with its gain\nstruct Option {\n    long long gain;\n    int m, p, q;\n\n    // For sorting: higher gain comes first\n    bool operator<(const Option& other) const {\n        return gain > other.gain; // Sort in descending order of gain\n    }\n};\n\n// Function to calculate the total score for a given board state\n// This function sums up all b_i,j % MOD values\nlong long calculate_board_score(const std::vector<std::vector<int>>& board, int N) {\n    long long total_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            total_score += board[i][j]; // Values in board are already modulo MOD\n        }\n    }\n    return total_score;\n}\n\n\nint main() {\n    // Optimize C++ standard streams for faster input/output.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N, M, K;\n    std::cin >> N >> M >> K;\n\n    // Read initial board values.\n    std::vector<std::vector<int>> initial_board(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_board[i][j]; // a_i,j are guaranteed to be < MOD\n        }\n    }\n\n    // Read all stamp configurations `s_m,i,j`.\n    std::vector<std::vector<std::vector<int>>> s(M, std::vector<std::vector<int>>(3, std::vector<int>(3)));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> s[m][i][j]; // s_m,i,j are guaranteed to be < MOD\n            }\n        }\n    }\n\n    // Initialize random number generator using current time for varied seeds across runs.\n    std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Best overall score found and the sequence of operations that produced it.\n    long long max_overall_score = calculate_board_score(initial_board, N);\n    std::vector<Operation> best_overall_operations;\n\n    // Set a time limit for the iterative process (e.g., 1.98 seconds out of 2.0s total).\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 1.98; // Adjusted time limit\n\n    // Loop for multiple attempts (Iterated Randomly Perturbed Greedy).\n    // The loop continues as long as there is time remaining.\n    while (true) {\n        auto current_chrono_time = std::chrono::high_resolution_clock::now();\n        double elapsed_seconds = std::chrono::duration<double>(current_chrono_time - start_time).count();\n        if (elapsed_seconds >= TIME_LIMIT_SECONDS) {\n            break; // Stop if time limit is reached.\n        }\n\n        // Start a new greedy run with a fresh copy of the initial board.\n        std::vector<std::vector<int>> current_board = initial_board;\n        std::vector<Operation> current_operations;\n        long long current_run_score = calculate_board_score(current_board, N); // Keep track of score incrementally\n\n        // Perform up to K operations for this specific run.\n        for (int k_idx = 0; k_idx < K; ++k_idx) {\n            std::vector<Option> possible_options; // List to store all potential operations and their gains.\n\n            // Evaluate all M * (N-2)^2 possible operations.\n            for (int m_idx = 0; m_idx < M; ++m_idx) {\n                for (int p_idx = 0; p_idx <= N - 3; ++p_idx) {\n                    for (int q_idx = 0; q_idx <= N - 3; ++q_idx) {\n                        long long current_gain = 0; // Accumulated gain for the current stamp application.\n\n                        // Calculate the score change if this stamp is applied.\n                        for (int i_s = 0; i_s < 3; ++i_s) {\n                            for (int j_s = 0; j_s < 3; ++j_s) {\n                                int r = p_idx + i_s; // Row on the board\n                                int c = q_idx + j_s; // Column on the board\n\n                                int old_val_mod = current_board[r][c];\n                                // Calculate new value modulo MOD. Use long long for addition to prevent overflow.\n                                int new_val_mod = (int)(((long long)old_val_mod + s[m_idx][i_s][j_s]) % MOD);\n                                \n                                current_gain += (new_val_mod - old_val_mod);\n                            }\n                        }\n                        \n                        // Only consider operations that provide a strict positive gain.\n                        if (current_gain > 0) {\n                             possible_options.push_back({current_gain, m_idx, p_idx, q_idx});\n                        }\n                    }\n                }\n            }\n            \n            // If no operation can increase the score, this run stops early.\n            if (possible_options.empty()) {\n                break;\n            }\n\n            // Sort options by gain in descending order. This is essential for picking top X.\n            std::sort(possible_options.begin(), possible_options.end());\n\n            // Define how many top options to consider for weighted random selection.\n            // Adaptive TOP_X: Start with a higher number of options to explore,\n            // gradually reduce it towards the end to exploit better options.\n            const int MAX_TOP_X = 100; // Adjusted from 50 to 100\n            const int MIN_TOP_X = 10;  // Adjusted from 15 to 10\n            \n            // Calculate current_TOP_X based on k_idx (operations performed so far)\n            // Linear decay from MAX_TOP_X to MIN_TOP_X over K operations\n            int current_TOP_X = MAX_TOP_X - (MAX_TOP_X - MIN_TOP_X) * k_idx / K;\n            current_TOP_X = std::max(MIN_TOP_X, current_TOP_X); // Ensure it doesn't go below MIN_TOP_X\n\n            int actual_top_x_count = std::min((int)possible_options.size(), current_TOP_X);\n\n            // Prepare weights for discrete distribution (gains of top options)\n            std::vector<long long> weights;\n            weights.reserve(actual_top_x_count); // Pre-allocate memory for efficiency\n            for (int i = 0; i < actual_top_x_count; ++i) {\n                weights.push_back(possible_options[i].gain);\n            }\n\n            // Create a discrete distribution based on weights\n            // std::discrete_distribution requires positive weights. Since we only added options with gain > 0,\n            // and `gain` can be up to 9 * (MOD-1) which is positive, this is safe.\n            std::discrete_distribution<int> dist(weights.begin(), weights.end());\n            \n            // Randomly pick an index from the top options based on weights\n            int chosen_idx_in_top_x = dist(rng);\n            Option chosen_option = possible_options[chosen_idx_in_top_x];\n\n            // Apply the chosen operation to update the board state for this run.\n            for (int i_s = 0; i_s < 3; ++i_s) {\n                for (int j_s = 0; j_s < 3; ++j_s) {\n                    int r = chosen_option.p + i_s;\n                    int c = chosen_option.q + j_s;\n                    current_board[r][c] = (int)(((long long)current_board[r][c] + s[chosen_option.m][i_s][j_s]) % MOD);\n                }\n            }\n            // Update the score for the current run incrementally.\n            current_run_score += chosen_option.gain;\n            // Record the operation performed.\n            current_operations.push_back({chosen_option.m, chosen_option.p, chosen_option.q});\n        } // End of k_idx loop for one greedy run\n\n        // After completing one full greedy run (or breaking early), check if it's the best so far.\n        if (current_run_score > max_overall_score) {\n            max_overall_score = current_run_score;\n            best_overall_operations = current_operations;\n        }\n    } // End of time-limited loop for multiple runs\n\n    // Output the number of operations in the best sequence found.\n    std::cout << best_overall_operations.size() << std::endl;\n    // Output each operation's details (stamp index, top-left row, top-left column).\n    for (const auto& op : best_overall_operations) {\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 <set>\n#include <algorithm>\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 { // For map keys (container_locations still uses map)\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint DR[] = {-1, 1, 0, 0}; // U, D, L, R\nint DC[] = {0, 0, -1, 1};\n\n// Correct way to get char from dr,dc\nchar get_dir_char(int dr, int dc) {\n    if (dr == -1 && dc == 0) return 'U';\n    if (dr == 1 && dc == 0) return 'D';\n    if (dr == 0 && dc == -1) return 'L';\n    if (dr == 0 && dc == 1) return 'R';\n    return '.'; // Should not happen for a valid move\n}\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int holding_container_id; // -1 if not holding\n    bool is_large;\n    bool is_bombed;\n};\n\nstruct State {\n    vector<vector<int>> board; // container ID, -1 if empty\n    vector<Crane> cranes;\n    vector<int> incoming_idx; // next container index for each receiving gate (row)\n    vector<int> next_dispatch_val; // next container ID expected at each dispatch gate (row)\n    vector<vector<int>> A; // initial incoming container sequence\n    map<int, Pos> container_locations; // Map container_id to its (r,c) position or {-1,-1} if in crane's hand\n};\n\n// BFS to find the next step (dr, dc) and path cost\n// Returns {dr, dc} for the next step. {0,0} if no path or already at target.\n// path_cost_out will be set to the cost of the path, or -1 if no path.\nPos get_next_step(const State& current_state, int crane_id, Pos start_pos, Pos target_pos,\n                  bool is_holding_container, bool is_large_crane,\n                  const vector<Pos>& other_crane_current_pos_snapshot, // Snapshot of all crane positions before planning\n                  const vector<Pos>& target_next_crane_pos_planned, // Planned next positions for higher priority cranes (j < crane_id)\n                  int& path_cost_out) {\n\n    if (start_pos == target_pos) {\n        path_cost_out = 0;\n        return {0,0};\n    }\n\n    // Optimized BFS: use 2D array for distance and parent tracking\n    vector<vector<int>> dist_grid(N, vector<int>(N, -1)); // -1 means unvisited\n    vector<vector<Pos>> parent_grid(N, vector<Pos>(N, {-1,-1})); // Stores parent position to reconstruct path\n    queue<Pos> q;\n\n    q.push(start_pos);\n    dist_grid[start_pos.r][start_pos.c] = 0;\n\n    Pos next_step_dir = {0,0};\n    path_cost_out = -1; // Default to no path found\n\n    Pos found_target_pos = {-1,-1}; // To store the actual target_pos if found\n\n    while (!q.empty()) {\n        Pos u = q.front();\n        q.pop();\n\n        if (u == target_pos) {\n            found_target_pos = u;\n            break; // Path found\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos v = {u.r + DR[i], u.c + DC[i]};\n\n            if (v.r < 0 || v.r >= N || v.c < 0 || v.c >= N) continue; // Out of bounds\n\n            // If already visited, skip (or if new path isn't shorter)\n            if (dist_grid[v.r][v.c] != -1) continue;\n\n            // Check for container on destination square (for small cranes holding cargo)\n            // Small crane carrying container cannot move to occupied square.\n            // Large crane carrying container CAN move to occupied square, so this check is skipped for large cranes.\n            if (!is_large_crane && is_holding_container && current_state.board[v.r][v.c] != -1) {\n                continue; \n            }\n\n            bool collision = false;\n            for (int j = 0; j < N; ++j) {\n                if (j == crane_id || current_state.cranes[j].is_bombed) continue; // Skip self or bombed cranes\n\n                Pos other_curr_j = other_crane_current_pos_snapshot[j]; \n                \n                if (j < crane_id) { // Higher priority crane, its next position is already planned\n                    Pos other_next_j_planned = target_next_crane_pos_planned[j];\n                    \n                    if (v == other_next_j_planned) { // Target collision\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == other_next_j_planned) { // Swap collision\n                        collision = true; break;\n                    }\n                } else { // Lower priority crane, it hasn't planned its move yet. Consider its current position as blocked.\n                    if (v == other_curr_j) { // Target collision\n                        collision = true; break;\n                    }\n                }\n            }\n            if (collision) continue;\n\n            dist_grid[v.r][v.c] = dist_grid[u.r][u.c] + 1;\n            parent_grid[v.r][v.c] = u; // Store parent for path reconstruction\n            q.push(v);\n        }\n    }\n\n    if (found_target_pos.r != -1) { // Path found\n        path_cost_out = dist_grid[found_target_pos.r][found_target_pos.c];\n        \n        // Reconstruct the first step\n        Pos curr = found_target_pos;\n        while (parent_grid[curr.r][curr.c] != start_pos) {\n            curr = parent_grid[curr.r][curr.c];\n        }\n        next_step_dir = {curr.r - start_pos.r, curr.c - start_pos.c};\n    }\n    return next_step_dir;\n}\n\n// Helper for a crane (k) holding container C to find a suitable empty release position.\n// Returns a valid empty position or {-1,-1} if none found.\nPos find_best_release_pos(const State& state, int crane_id, int C, Pos crane_curr_pos) {\n    int C_target_row = C / N;\n    bool is_large_crane = state.cranes[crane_id].is_large;\n    bool is_next_dispatch = (C == state.next_dispatch_val[C_target_row]);\n\n    vector<Pos> candidates;\n\n    // 1. Direct dispatch (if next_dispatch_val)\n    if (is_next_dispatch) candidates.push_back({C_target_row, N-1});\n    \n    // 2. Primary staging for its target row\n    candidates.push_back({C_target_row, N-2});\n\n    // 3. Mid-column for cross-row transfers (its target row)\n    candidates.push_back({C_target_row, N/2});\n    \n    // 4. If small crane and holding cross-row cargo, its own row's mid-column for drop-off\n    if (!is_large_crane && crane_curr_pos.r != C_target_row) {\n        candidates.push_back({crane_curr_pos.r, N/2});\n    }\n\n    // 5. General in-row storage for target row (e.g. column 1)\n    candidates.push_back({C_target_row, 1});\n\n    // 6. Generic trash for large crane\n    if (is_large_crane) {\n        candidates.push_back({0, N-3}); // Example: (0,2) for N=5\n    }\n    \n    // Filter and find the first empty, valid position\n    for (Pos p : candidates) {\n        if (p.r >= 0 && p.r < N && p.c >= 0 && p.c < N && state.board[p.r][p.c] == -1) {\n            return p;\n        }\n    }\n    return {-1,-1}; // No suitable empty spot found\n}\n\n\nvoid solve() {\n    State current_state;\n    current_state.board.assign(N, vector<int>(N, -1));\n    current_state.A.assign(N, vector<int>(N));\n    current_state.incoming_idx.assign(N, 0);\n    \n    // Initialize next_dispatch_val correctly\n    current_state.next_dispatch_val.resize(N);\n    for(int i = 0; i < N; ++i) {\n        current_state.next_dispatch_val[i] = N * i;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> current_state.A[i][j];\n        }\n    }\n\n    current_state.cranes.resize(N);\n    for (int i = 0; i < N; ++i) {\n        current_state.cranes[i].id = i;\n        current_state.cranes[i].pos = {i, 0};\n        current_state.cranes[i].holding_container_id = -1;\n        current_state.cranes[i].is_large = (i == 0);\n        current_state.cranes[i].is_bombed = false;\n    }\n\n    int turns = 0;\n    int dispatched_count = 0;\n\n    vector<string> all_crane_actions(N, \"\");\n\n    while (dispatched_count < N*N && turns < MAX_TURNS) {\n        turns++;\n        \n        // 0. Store current crane positions for BFS collision detection\n        vector<Pos> other_crane_current_pos_snapshot(N);\n        for(int i=0; i<N; ++i) other_crane_current_pos_snapshot[i] = current_state.cranes[i].pos;\n\n        // Initialize planned positions and holding status to current state\n        vector<Pos> target_next_crane_pos_planned(N);\n        vector<int> target_next_crane_holding_planned(N);\n        for (int k = 0; k < N; ++k) {\n            target_next_crane_pos_planned[k] = current_state.cranes[k].pos;\n            target_next_crane_holding_planned[k] = current_state.cranes[k].holding_container_id;\n        }\n\n        // 1. Incoming containers (Before crane planning so cranes can react to them)\n        for (int i = 0; i < N; ++i) {\n            if (current_state.incoming_idx[i] < N) {\n                bool gate_has_container = (current_state.board[i][0] != -1);\n                bool gate_has_crane = false;\n                for(int k=0; k<N; ++k) {\n                    // Check actual crane positions from current_state before they move\n                    if (!current_state.cranes[k].is_bombed && current_state.cranes[k].pos.r == i && current_state.cranes[k].pos.c == 0) {\n                        gate_has_crane = true;\n                        break;\n                    }\n                }\n                if (!gate_has_container && !gate_has_crane) {\n                    int container_id = current_state.A[i][current_state.incoming_idx[i]];\n                    current_state.board[i][0] = container_id;\n                    current_state.container_locations[container_id] = {i,0};\n                    current_state.incoming_idx[i]++;\n                }\n            }\n        }\n\n        // 2. Crane actions planning (prioritized by crane ID 0 to N-1)\n        vector<char> current_turn_actions_char(N, '.');\n        \n        for (int k = 0; k < N; ++k) { \n            if (current_state.cranes[k].is_bombed) {\n                current_turn_actions_char[k] = '.';\n                continue;\n            }\n\n            Pos crane_curr_pos = current_state.cranes[k].pos;\n            int holding_id = current_state.cranes[k].holding_container_id;\n\n            // If holding a container, find best release spot and move towards it\n            if (holding_id != -1) {\n                Pos desired_release_pos = find_best_release_pos(current_state, k, holding_id, crane_curr_pos);\n                \n                if (desired_release_pos.r != -1) { // Found a place to move to/release\n                    if (crane_curr_pos == desired_release_pos) { // Already at the target spot and it's empty, release\n                        current_turn_actions_char[k] = 'Q';\n                        target_next_crane_holding_planned[k] = -1; // Released\n                    } else { // Move towards desired_release_pos\n                        int cost;\n                        Pos dir = get_next_step(current_state, k, crane_curr_pos, desired_release_pos, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                        if (cost != -1) {\n                            current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                            target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                        } else {\n                            current_turn_actions_char[k] = '.'; // Cannot reach even best empty spot\n                        }\n                    }\n                } else { // No empty spot found for release\n                    current_turn_actions_char[k] = '.'; // Wait\n                }\n                continue; // Crane has a container, its action is determined\n            }\n\n            // If not holding a container, find a task\n            int best_cost = MAX_TURNS + 1; // High value\n            Pos best_pick_pos = {-1,-1};\n            int best_item_id = -1;\n            Pos best_item_release_pos = {-1,-1}; // The determined release position if picked up\n\n            // Define lambda here for 'calculate_cost'\n            auto calculate_cost = [&](Pos target_for_pickup) {\n                int cost;\n                get_next_step(current_state, k, crane_curr_pos, target_for_pickup, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                return cost;\n            };\n            \n            // Check if a container is already targeted by a higher-priority crane or held\n            auto is_container_busy = [&](int container_id) {\n                if (container_id == -1) return true;\n                for (int j = 0; j < N; ++j) {\n                    if (current_state.cranes[j].id != k && target_next_crane_holding_planned[j] == container_id) return true;\n                }\n                return false;\n            };\n\n            // Task search priorities (high to low):\n\n            // Option 1: Pick up 'next_dispatch_val'\n            for (int i = 0; i < N; ++i) {\n                int C = current_state.next_dispatch_val[i];\n                if (current_state.container_locations.count(C) && current_state.container_locations[C].r != -1) { \n                    Pos c_pos = current_state.container_locations[C];\n                    if (c_pos.r == i && c_pos.c == N - 1) continue; \n                    if (is_container_busy(C)) continue;\n                    if (!current_state.cranes[k].is_large && c_pos.r != k) continue;\n\n                    // Ensure the final dispatch spot is free (or about to be free, if current_board state)\n                    if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != C) continue;\n\n                    int cost = calculate_cost(c_pos);\n                    if (cost != -1 && cost < best_cost) {\n                        best_cost = cost;\n                        best_pick_pos = c_pos;\n                        best_item_id = C;\n                        best_item_release_pos = {i, N-1}; // Directly to dispatch\n                    }\n                }\n            }\n            \n            // NEW Option 2: LARGE CRANE ONLY: Clear Blocked Mid-Row Drop-off for Small Crane\n            if (current_state.cranes[k].is_large) { \n                for (int r = 0; r < N; ++r) {\n                    Pos drop_pos = {r, N/2};\n                    if (current_state.board[drop_pos.r][drop_pos.c] != -1) { \n                        int C_blocker = current_state.board[drop_pos.r][drop_pos.c];\n                        if (is_container_busy(C_blocker)) continue; \n\n                        bool small_crane_needs_drop_off = false;\n                        for (int j = 1; j < N; ++j) { // Iterate small cranes\n                            if (!current_state.cranes[j].is_bombed && \n                                current_state.cranes[j].holding_container_id != -1 &&\n                                current_state.cranes[j].pos.r == r && \n                                current_state.cranes[j].holding_container_id / N != r) { \n                                small_crane_needs_drop_off = true;\n                                break;\n                            }\n                        }\n\n                        if (small_crane_needs_drop_off) {\n                            Pos temp_release_pos = find_best_release_pos(current_state, k, C_blocker, drop_pos); \n                            if (temp_release_pos.r != -1) { // Found a place to move the blocker\n                                int cost = calculate_cost(drop_pos);\n                                if (cost != -1 && cost < best_cost) {\n                                    best_cost = cost;\n                                    best_pick_pos = drop_pos;\n                                    best_item_id = C_blocker;\n                                    best_item_release_pos = temp_release_pos; \n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Option 3 (was 2): Clear receiving gate (row i, col 0)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.incoming_idx[i] < N && current_state.board[i][0] != -1) {\n                    int C = current_state.board[i][0];\n                    if (is_container_busy(C)) continue;\n\n                    if (!current_state.cranes[k].is_large && i != k) continue; // Small crane not in its row, skip\n                    \n                    Pos target_release_pos = find_best_release_pos(current_state, k, C, {i,0});\n\n                    if (target_release_pos.r != -1) { // Only pick up if a valid release spot is free\n                        int cost = calculate_cost({i,0});\n                        if (cost != -1 && cost < best_cost) { \n                            best_cost = cost;\n                            best_pick_pos = {i,0};\n                            best_item_id = C;\n                            best_item_release_pos = target_release_pos;\n                        }\n                    }\n                }\n            }\n\n            // Option 4 (was 3): Clear dispatch gate (row i, col N-1)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != current_state.next_dispatch_val[i]) {\n                    int C = current_state.board[i][N-1];\n                    if (is_container_busy(C)) continue;\n\n                    if (!current_state.cranes[k].is_large && i != k) continue; \n                    \n                    Pos target_release_pos = find_best_release_pos(current_state, k, C, {i,N-1});\n\n                    if (target_release_pos.r != -1) { // Only pick up if valid release spot is free\n                        int cost = calculate_cost({i,N-1});\n                        if (cost != -1 && cost < best_cost) {\n                            best_cost = cost;\n                            best_pick_pos = {i,N-1};\n                            best_item_id = C;\n                            best_item_release_pos = target_release_pos;\n                        }\n                    }\n                }\n            }\n            \n            // Option 5 (was 4): Move container to its staging area (row, N-2) if in correct row but too far left\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N-2; ++c) { \n                    int C = current_state.board[r][c];\n                    if (C != -1 && C/N == r && C != current_state.next_dispatch_val[r]) {\n                        if (is_container_busy(C)) continue;\n                        if (!current_state.cranes[k].is_large && r != k) continue;\n\n                        if (current_state.board[r][N-2] == -1) { // Only pick up if target N-2 is empty\n                            int cost = calculate_cost({r,c});\n                            if (cost != -1 && cost < best_cost) {\n                                best_cost = cost;\n                                best_pick_pos = {r,c};\n                                best_item_id = C;\n                                best_item_release_pos = {r,N-2};\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Option 6 (was 5): Move container to its row's middle column (C/N, N/2) - for cross-row moves (Large crane only).\n            if (current_state.cranes[k].is_large) { \n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        int C = current_state.board[r][c];\n                        if (C != -1 && C/N != r) { \n                            if (is_container_busy(C)) continue;\n                            \n                            if (current_state.board[C/N][N/2] == -1) { // Only pick up if target N/2 is empty\n                                int cost = calculate_cost({r,c});\n                                if (cost != -1 && cost < best_cost) {\n                                    best_cost = cost;\n                                    best_pick_pos = {r,c};\n                                    best_item_id = C;\n                                    best_item_release_pos = {C/N,N/2};\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Execute the chosen task\n            if (best_cost != MAX_TURNS + 1) { \n                if (crane_curr_pos == best_pick_pos) {\n                    current_turn_actions_char[k] = 'P';\n                    target_next_crane_holding_planned[k] = best_item_id;\n                    current_state.container_locations[best_item_id] = {-1,-1}; \n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, best_pick_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.'; \n                    }\n                }\n            } else { \n                Pos parking_pos = current_state.cranes[k].is_large ? Pos{0, N/2} : Pos{k, 1}; \n                if (crane_curr_pos == parking_pos) {\n                    current_turn_actions_char[k] = '.';\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, parking_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n            }\n        }\n\n        // Apply all planned actions simultaneously\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) continue;\n\n            char action = current_turn_actions_char[k];\n            all_crane_actions[k] += action;\n\n            if (action == 'P') {\n                int container_id = current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c];\n                current_state.cranes[k].holding_container_id = container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = -1;\n            } else if (action == 'Q') {\n                int container_id = current_state.cranes[k].holding_container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = container_id;\n                current_state.cranes[k].holding_container_id = -1;\n                current_state.container_locations[container_id] = current_state.cranes[k].pos; // Container back on board\n            } else if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n                current_state.cranes[k].pos = target_next_crane_pos_planned[k];\n            }\n        }\n        \n        // 3. Dispatch containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] == current_state.next_dispatch_val[i]) {\n                int dispatched_id = current_state.board[i][N-1];\n                current_state.board[i][N-1] = -1;\n                current_state.container_locations.erase(dispatched_id); // Container removed from the game\n                current_state.next_dispatch_val[i]++; // Advance expectation for this gate\n                dispatched_count++;\n            }\n        }\n    }\n\n    // Output results\n    for (int i = 0; i < N; ++i) {\n        cout << all_crane_actions[i] << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <limits> // Required for std::numeric_limits\n\n// N is fixed at 20 for this problem\nconst int N = 20;\n\n// Global variables to store the current state\nint H[N][N]; // Current heights of the grid cells\nint current_r = 0; // Current row of the dump truck\nint current_c = 0; // Current column of the dump truck\nlong long truck_load = 0; // Current amount of soil loaded on the truck\nstd::vector<std::string> ops; // Stores the sequence of operations\n\n// Calculates Manhattan distance between two cells\nlong long manhattan_dist(int r1, int c1, int r2, int c2) {\n    return std::abs(r1 - r2) + std::abs(c1 - c2);\n}\n\n// Moves the truck to the target coordinates and records the movement operations\nvoid move_truck_to(int target_r, int target_c) {\n    while (current_r < target_r) {\n        ops.push_back(\"D\");\n        current_r++;\n    }\n    while (current_r > target_r) {\n        ops.push_back(\"U\");\n        current_r--;\n    }\n    while (current_c < target_c) {\n        ops.push_back(\"R\");\n        current_c++;\n    }\n    while (current_c > target_c) {\n        ops.push_back(\"L\");\n        current_c--;\n    }\n}\n\n// Structure to hold cell coordinates and a calculated distance, used for sorting candidates\nstruct CandidateCell {\n    int r, c;\n    long long dist;\n\n    // Operator< for sorting by distance\n    bool operator<(const CandidateCell& other) const {\n        return dist < other.dist;\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int dummy_N; // Read N, but it's fixed at 20\n    std::cin >> dummy_N;\n\n    long long total_initial_positive_soil = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> H[i][j];\n            if (H[i][j] > 0) {\n                total_initial_positive_soil += H[i][j];\n            }\n        }\n    }\n\n    long long soil_moved_to_level_sinks = 0; // Tracks the total soil moved to fulfill negative heights\n    const int K_CANDIDATES = 30; // Increased number of closest sources/sinks to consider (from 20 to 30)\n\n    // Timer for execution time limit\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds to be safe (total limit is 2.0 sec)\n\n    // Main loop: continues until all soil is leveled or operation/time limits are reached\n    while (soil_moved_to_level_sinks < total_initial_positive_soil) {\n        if (ops.size() >= 99000) { // Max 100000 turns, stop early to avoid exceeding\n            break;\n        }\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) {\n            break;\n        }\n\n        std::vector<CandidateCell> all_sources; // List of all cells with H > 0\n        std::vector<CandidateCell> all_sinks;   // List of all cells with H < 0\n\n        // Populate sources and sinks lists\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (H[i][j] > 0) {\n                    // For sources, calculate distance from current truck position\n                    all_sources.push_back({i, j, manhattan_dist(current_r, current_c, i, j)});\n                } else if (H[i][j] < 0) {\n                    all_sinks.push_back({i, j, 0}); // Distance for sinks will be calculated later from a potential source\n                }\n            }\n        }\n\n        // If no sources or sinks remain, the leveling is complete (or stuck)\n        if (all_sources.empty() || all_sinks.empty()) {\n            break;\n        }\n\n        // Partially sort sources by their distance from the current truck position\n        int num_source_candidates_to_process = std::min((int)all_sources.size(), K_CANDIDATES);\n        if (num_source_candidates_to_process > 0) {\n            std::partial_sort(all_sources.begin(), all_sources.begin() + num_source_candidates_to_process, all_sources.end());\n        }\n\n        // Variables to track the best transfer based on MINIMUM ABSOLUTE TOTAL COST\n        long long min_total_cost = std::numeric_limits<long long>::max(); \n\n        int best_sr = -1, best_sc = -1, best_dr = -1, best_dc = -1; // Coordinates of the best source/sink\n        long long best_D_value = 0; // Amount of soil for the best transfer\n\n        // Iterate through a limited number of closest source candidates\n        for (int i = 0; i < num_source_candidates_to_process; ++i) {\n            int sr = all_sources[i].r;\n            int sc = all_sources[i].c;\n\n            // Create a temporary list of sinks, calculating their distance from the current source candidate\n            std::vector<CandidateCell> current_sink_candidates;\n            for (const auto& sink : all_sinks) {\n                current_sink_candidates.push_back({sink.r, sink.c, manhattan_dist(sr, sc, sink.r, sink.c)});\n            }\n            \n            // Partially sort these sinks by their distance from the current source candidate\n            int num_sink_candidates_to_process = std::min((int)current_sink_candidates.size(), K_CANDIDATES);\n            if (num_sink_candidates_to_process > 0) {\n                std::partial_sort(current_sink_candidates.begin(), current_sink_candidates.begin() + num_sink_candidates_to_process, current_sink_candidates.end());\n            }\n\n            // Iterate through a limited number of closest sink candidates for this source\n            for (int j = 0; j < num_sink_candidates_to_process; ++j) {\n                int dr = current_sink_candidates[j].r;\n                int dc = current_sink_candidates[j].c;\n\n                // Calculate the amount of soil to transfer: min of available at source and needed at sink\n                long long D = std::min((long long)H[sr][sc], -(long long)H[dr][dc]);\n                if (D <= 0) continue; // No actual transfer possible\n\n                // Calculate the total cost for this specific (source, sink, amount) transfer\n                long long cost_to_source = manhattan_dist(current_r, current_c, sr, sc) * 100LL;\n                long long cost_source_to_sink = manhattan_dist(sr, sc, dr, dc) * (100LL + D);\n                long long current_total_cost = cost_to_source + cost_source_to_sink + 2LL * D;\n\n                // Update if this transfer is cheaper based on MINIMUM ABSOLUTE TOTAL COST\n                if (current_total_cost < min_total_cost) {\n                    min_total_cost = current_total_cost;\n                    best_sr = sr; best_sc = sc;\n                    best_dr = dr; best_dc = dc;\n                    best_D_value = D;\n                }\n            }\n        }\n\n        // If no valid transfer was found in this iteration (min_total_cost is still its initial max value), break the loop\n        if (min_total_cost == std::numeric_limits<long long>::max()) {\n            break;\n        }\n\n        // Execute the operations for the chosen best transfer\n        \n        // 1. Move truck to the best source\n        move_truck_to(best_sr, best_sc);\n        \n        // 2. Load soil\n        ops.push_back(\"+\" + std::to_string(best_D_value));\n        truck_load += best_D_value;\n        H[best_sr][best_sc] -= best_D_value; // Update source cell's height\n        \n        // 3. Move truck to the best sink\n        move_truck_to(best_dr, best_dc);\n        \n        // 4. Unload soil\n        ops.push_back(\"-\" + std::to_string(best_D_value));\n        truck_load -= best_D_value;\n        H[best_dr][best_dc] += best_D_value; // Update sink cell's height\n        soil_moved_to_level_sinks += best_D_value; // Increment total soil leveled\n    }\n\n    // Output all recorded operations\n    for (const std::string& op : ops) {\n        std::cout << op << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <cmath>   // For std::exp\n\n// --- Global variables for N, M, T and X_seeds ---\nint N_global, M_global, T_global;\nstd::vector<std::vector<int>> X_seeds_global; // Current seeds available for planting\nstd::vector<int> initial_X_max_global;       // Max value for each criterion from initial seeds\n\n// --- RNG ---\n// Use std::mt19937_64 for potentially better randomness and larger range.\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper function to calculate potential for a pair ---\n// Returns the sum of max values for each criterion between two seeds.\n// seed_idx1 and seed_idx2 are indices into X_seeds_global.\nlong long calculate_pair_potential(int seed_idx1, int seed_idx2) {\n    long long potential = 0;\n    for (int l = 0; l < M_global; ++l) {\n        potential += std::max(X_seeds_global[seed_idx1][l], X_seeds_global[seed_idx2][l]);\n    }\n    return potential;\n}\n\n// --- Helper function to get adjacent coordinates ---\n// Returns a vector of {row, col} pairs for direct neighbors of (r, c).\n// For N=6, this will return at most 4 pairs.\nstd::vector<std::pair<int, int>> get_adjacent_coords(int r, int c) {\n    std::vector<std::pair<int, int>> adj;\n    adj.reserve(4); // Reserve capacity to avoid reallocations, N is small and fixed\n    int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n    int dc[] = {0, 0, -1, 1};\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_global && nc >= 0 && nc < N_global) {\n            adj.push_back({nr, nc});\n        }\n    }\n    return adj;\n}\n\n// --- Function to calculate total score for a grid configuration ---\n// Sum of potential values for all adjacent pairs in the grid.\nlong long calculate_grid_score(const std::vector<std::vector<int>>& A) {\n    long long total_score = 0;\n    // Horizontal adjacencies\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global - 1; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i][j+1]);\n        }\n    }\n    // Vertical adjacencies\n    for (int i = 0; i < N_global - 1; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i+1][j]);\n        }\n    }\n    return total_score;\n}\n\nvoid solve() {\n    std::cin >> N_global >> M_global >> T_global;\n\n    int seed_count = 2 * N_global * (N_global - 1); // For N=6, this is 2*6*5 = 60 seeds\n    X_seeds_global.resize(seed_count, std::vector<int>(M_global));\n    initial_X_max_global.resize(M_global, 0);\n\n    // Read initial seeds and compute initial_X_max_global\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M_global; ++j) {\n            std::cin >> X_seeds_global[i][j];\n            initial_X_max_global[j] = std::max(initial_X_max_global[j], X_seeds_global[i][j]);\n        }\n    }\n\n    // Main simulation loop for T turns\n    for (int turn = 0; turn < T_global; ++turn) {\n        // TUNING: Reverted alpha_value back to 300LL, as it previously yielded the highest total score.\n        // This value seems to strike the best balance for seed selection.\n        long long alpha_value = 300LL; \n        \n        // 1. Select seeds for planting:\n        // Calculate a combined score for all current seeds and pick the top N*N.\n        // The combined score considers V_k + a bonus for carrying initial global max traits.\n        std::vector<std::pair<long long, int>> seed_scores(seed_count); // {combined_score, seed_idx}\n        for (int i = 0; i < seed_count; ++i) {\n            long long current_Vk = 0;\n            int trait_count = 0;\n            for (int l = 0; l < M_global; ++l) {\n                current_Vk += X_seeds_global[i][l];\n                if (X_seeds_global[i][l] == initial_X_max_global[l]) {\n                    trait_count++;\n                }\n            }\n            long long combined_score = current_Vk + alpha_value * trait_count; \n            seed_scores[i] = {combined_score, i};\n        }\n        std::sort(seed_scores.rbegin(), seed_scores.rend()); // Sort descending by combined_score\n\n        std::vector<int> selected_seeds_indices(N_global * N_global); // N*N = 36 seeds\n        for (int i = 0; i < N_global * N_global; ++i) {\n            selected_seeds_indices[i] = seed_scores[i].second;\n        }\n\n        // 2. Determine placement using Simulated Annealing\n        std::vector<std::vector<int>> current_A(N_global, std::vector<int>(N_global));\n        \n        // Initial placement for SA: random permutation of selected seeds\n        std::shuffle(selected_seeds_indices.begin(), selected_seeds_indices.end(), rng);\n        int k_idx = 0;\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                current_A[i][j] = selected_seeds_indices[k_idx++];\n            }\n        }\n\n        long long current_score = calculate_grid_score(current_A);\n        std::vector<std::vector<int>> best_A = current_A;\n        long long best_score = current_score;\n\n        // SA parameters (tuned for AHC035 constraints)\n        double start_temp = 30000.0; \n        double end_temp = 50.0;    \n        long long max_iterations = 250000; // Safety upper bound, time budget is primary control\n        \n        // TUNING: Maintained time_budget at 190ms to allow more SA iterations per turn,\n        // which helps in exploring the search space more thoroughly.\n        auto start_time = std::chrono::high_resolution_clock::now();\n        std::chrono::milliseconds time_budget(190); \n\n        std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        std::uniform_int_distribution<int> dist_rc(0, N_global - 1); // For random row/col\n\n        for (long long iter = 0; iter < max_iterations; ++iter) {\n            // Check time budget\n            auto current_time = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time) > time_budget) {\n                break; \n            }\n\n            // Calculate current temperature with exponential decay\n            double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / max_iterations);\n\n            // Pick two random distinct cells to swap\n            int r1 = dist_rc(rng);\n            int c1 = dist_rc(rng);\n            int r2 = dist_rc(rng);\n            int c2 = dist_rc(rng);\n            while (r1 == r2 && c1 == c2) { // Ensure distinct cells\n                r2 = dist_rc(rng);\n                c2 = dist_rc(rng);\n            }\n\n            int seed1_idx = current_A[r1][c1]; // Original seed at (r1,c1)\n            int seed2_idx = current_A[r2][c2]; // Original seed at (r2,c2)\n\n            // Calculate change in score (delta_score) efficiently\n            long long old_adj_contrib = 0;\n            std::vector<std::pair<int, int>> neighbors_r1c1 = get_adjacent_coords(r1, c1);\n            std::vector<std::pair<int, int>> neighbors_r2c2 = get_adjacent_coords(r2, c2);\n\n            for (auto p : neighbors_r1c1) {\n                // If the other swapped cell is a neighbor, exclude it.\n                // The direct edge contribution (P(seed1, seed2)) is symmetric and\n                // does not change when the seeds are swapped, so it's not part of delta_score calculation.\n                if (!(p.first == r2 && p.second == c2)) { \n                    old_adj_contrib += calculate_pair_potential(seed1_idx, current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    old_adj_contrib += calculate_pair_potential(seed2_idx, current_A[p.first][p.second]);\n                }\n            }\n\n            // Temporarily perform the swap\n            current_A[r1][c1] = seed2_idx;\n            current_A[r2][c2] = seed1_idx;\n\n            long long new_adj_contrib = 0;\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r1][c1], current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r2][c2], current_A[p.first][p.second]);\n                }\n            }\n            \n            long long delta_score = new_adj_contrib - old_adj_contrib;\n            long long new_score = current_score + delta_score;\n\n            // Metropolis criterion for acceptance\n            if (new_score > current_score || dist_prob(rng) < std::exp(static_cast<double>(new_score - current_score) / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_A = current_A;\n                }\n            } else {\n                // Revert the swap if not accepted\n                current_A[r1][c1] = seed1_idx;\n                current_A[r2][c2] = seed2_idx;\n            }\n        }\n        \n        // Output the best placement found for this turn\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                std::cout << best_A[i][j];\n                if (j < N_global - 1) {\n                    std::cout << \" \";\n                } else {\n                    std::cout << std::endl;\n                }\n            }\n        }\n        std::cout.flush(); // Flush output to interactive judge\n\n        // 3. Read the new seeds for the next turn\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M_global; ++j) {\n                std::cin >> X_seeds_global[i][j];\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    solve();\n    \n    return 0;\n}\n","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set> // No longer used for main data, but keeping for possible local use if needed\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n// #include <map> // Not used\n\nusing namespace std;\n\n// Global variables for grid and problem parameters\nint N, M, V_MAX;\n\n// Optimized grid representation for O(1) lookups\nvector<vector<bool>> grid_has_takoyaki; // true if takoyaki at (i,j)\nvector<vector<bool>> grid_is_target_empty; // true if (i,j) is a target and needs takoyaki\n\n// Global sums and counts for O(1) centroid calculation\nlong long s_sum_x = 0, s_sum_y = 0;\nint s_count = 0;\nlong long t_sum_x = 0, t_sum_y = 0;\nint t_count = 0;\n\n// Robotic arm state\nstruct Vec2 {\n    int x, y; // x for row, y for col\n    Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }\n    Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }\n    long long dist_sq(const Vec2& other) const { return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y); }\n    bool operator==(const Vec2& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Vec2& other) const { // For use in sets/maps if needed, though pair<int,int> is typical\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n};\n\nVec2 root_pos;\nvector<Vec2> rel_vecs; // relative position of vertex u to its parent p_u\nvector<int> orient_idx; // 0:right, 1:down, 2:left, 3:up (problem's definition)\n\n// For positions calculation\nvector<Vec2> abs_pos;\nvector<bool> is_fingertip;\nvector<int> parent_map; // parent_map[u] gives parent of u\nvector<int> L_map; // L_map[u] gives length of (parent[u], u)\n\nvector<bool> fingertip_holding; // Whether each fingertip is holding a takoyaki\n\n// PROBLEM_REL_DX, PROBLEM_REL_DY for cardinal directions (0:R, 1:D, 2:L, 3:U)\n// These define the (row_diff, col_diff) for a segment pointing in that direction.\n// R: (0,1)\n// D: (1,0)\n// L: (0,-1)\n// U: (-1,0)\nconst int PROBLEM_REL_DX[] = {0, 1, 0, -1}; \nconst int PROBLEM_REL_DY[] = {1, 0, -1, 0};\n\n// Rotate a vector (dr, dc) 90 degrees clockwise (dr -> dc, dc -> -dr)\nVec2 rotate_cw_problem(const Vec2& v) { return {v.y, -v.x}; }\n// Rotate a vector (dr, dc) 90 degrees counter-clockwise (dr -> -dc, dc -> dr)\nVec2 rotate_ccw_problem(const Vec2& v) { return {-v.y, v.x}; }\n\n// Check if a coordinate is within grid boundaries\nbool is_valid_coord(const Vec2& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\n// Update absolute positions of all vertices\nvoid update_abs_pos_global() {\n    abs_pos[0] = root_pos;\n    for (size_t i = 1; i < abs_pos.size(); ++i) {\n        abs_pos[i] = abs_pos[parent_map[i]] + rel_vecs[i];\n    }\n}\n\n// Calculate centroid from global sums and counts (O(1) operation)\nVec2 calculate_centroid_fast(long long sum_x_val, long long sum_y_val, int count_val) {\n    if (count_val == 0) {\n        return {-1, -1}; // Invalid centroid\n    }\n    return {(int)round((double)sum_x_val / count_val), (int)round((double)sum_y_val / count_val)};\n}\n\n// Struct to represent a potential action for a fingertip\nstruct Action {\n    int fingertip_id;\n    int direction; // Direction the fingertip would point in\n    Vec2 cell_coord; // The actual cell (source or target) it would interact with\n    bool is_place; // True if placing, false if picking\n    int score_gain; // The score value this action provides\n};\n\n// Evaluates a potential root position based on immediate picks/places\n// Returns a score: higher is better.\nint evaluate_root_move(int V_prime, const Vec2& test_root_pos) {\n    int score = 0;\n    \n    vector<Action> possible_actions;\n\n    // Identify all possible individual actions for all fingertips\n    for (int u = 1; u < V_prime; ++u) { // Iterate fingertips (vertices 1 to V_prime-1)\n        if (fingertip_holding[u]) { // If holding, look for places\n            for (int d = 0; d < 4; ++d) {\n                Vec2 target_cell = test_root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                if (is_valid_coord(target_cell) && grid_is_target_empty[target_cell.x][target_cell.y]) {\n                    possible_actions.push_back({u, d, target_cell, true, 2}); // Weight 2 for placing\n                }\n            }\n        } else { // If not holding, look for picks\n            for (int d = 0; d < 4; ++d) {\n                Vec2 source_cell = test_root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                if (is_valid_coord(source_cell) && grid_has_takoyaki[source_cell.x][source_cell.y]) {\n                    possible_actions.push_back({u, d, source_cell, false, 1}); // Weight 1 for picking\n                }\n            }\n        }\n    }\n\n    // Sort actions by score_gain (descending) to prioritize higher value actions (placing over picking)\n    // For actions with same score_gain, secondary sorting by fingertip_id ensures deterministic tie-breaking.\n    sort(possible_actions.begin(), possible_actions.end(), [](const Action& a, const Action& b) {\n        if (a.score_gain != b.score_gain) return a.score_gain > b.score_gain;\n        return a.fingertip_id < b.fingertip_id; \n    });\n\n    vector<bool> fingertip_assigned(V_prime, false); // Tracks if a fingertip is assigned an action\n    vector<vector<bool>> occupied_cells_map(N, vector<bool>(N, false)); // Tracks cells that are claimed by an action to prevent double-targeting\n\n    // Greedily apply actions from the sorted list\n    for (const auto& action : possible_actions) {\n        // If the fingertip is not yet assigned AND the target cell is not yet claimed\n        if (!fingertip_assigned[action.fingertip_id] && \n            !occupied_cells_map[action.cell_coord.x][action.cell_coord.y]) {\n            \n            score += action.score_gain;\n            fingertip_assigned[action.fingertip_id] = true;\n            occupied_cells_map[action.cell_coord.x][action.cell_coord.y] = true;\n        }\n    }\n\n    return score;\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> V_MAX;\n\n    grid_has_takoyaki.assign(N, vector<bool>(N, false));\n    grid_is_target_empty.assign(N, vector<bool>(N, false));\n\n    // Read initial takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                grid_has_takoyaki[i][j] = true;\n                s_sum_x += i;\n                s_sum_y += j;\n                s_count++;\n            }\n        }\n    }\n\n    // Read target takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                grid_is_target_empty[i][j] = true; // Initially all target squares are empty, assuming no takoyaki is there\n                t_sum_x += i;\n                t_sum_y += j;\n                t_count++;\n            }\n        }\n    }\n\n    // Adjust grid_has_takoyaki and grid_is_target_empty by removing already satisfied takoyaki\n    // If a target square (i,j) initially has a takoyaki, then it's satisfied.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid_has_takoyaki[i][j] && grid_is_target_empty[i][j]) {\n                grid_has_takoyaki[i][j] = false; // Takoyaki removed from source\n                s_sum_x -= i; s_sum_y -= j; s_count--;\n\n                grid_is_target_empty[i][j] = false; // Target filled\n                t_sum_x -= i; t_sum_y -= j; t_count--;\n            }\n        }\n    }\n\n    // Design the robotic arm (V' = V_MAX, star graph with varied edge lengths)\n    int V_prime = V_MAX; // Number of vertices in the arm\n    cout << V_prime << endl;\n\n    parent_map.resize(V_prime);\n    L_map.resize(V_prime);\n    is_fingertip.resize(V_prime, false);\n    \n    // Root is 0. Children 1 to V_prime-1 are fingertips.\n    for (int u = 1; u < V_prime; ++u) {\n        // Parent of u is 0. Varied length (u-1)/2 + 1\n        int length = (u - 1) / 2 + 1;\n        // Clamp length to N-1 (max 29) to be safe, although for V_MAX=15, max length is 7.\n        if (length > N - 1) length = N - 1; \n        cout << 0 << \" \" << length << endl;\n        parent_map[u] = 0;\n        L_map[u] = length; \n        is_fingertip[u] = true;\n    }\n\n    // Initial root position (center of the grid)\n    root_pos = {N / 2, N / 2};\n    cout << root_pos.x << \" \" << root_pos.y << endl;\n\n    // Initialize arm state\n    abs_pos.resize(V_prime);\n    rel_vecs.resize(V_prime);\n    orient_idx.resize(V_prime, 0); // All edges initially point right (direction 0)\n\n    for (int u = 1; u < V_prime; ++u) {\n        rel_vecs[u] = {L_map[u] * PROBLEM_REL_DX[0], L_map[u] * PROBLEM_REL_DY[0]}; // (L,0) for parent-child edge\n    }\n\n    fingertip_holding.resize(V_prime, false); // No fingertip holds takoyaki initially\n\n    // Operation loop\n    for (int turn = 0; turn < 100000; ++turn) {\n        if (t_count == 0) { // Check count of remaining target spots\n            break; // All takoyaki delivered\n        }\n\n        // 1. Determine root movement\n        char best_root_move_char = '.';\n        Vec2 next_root_pos_candidate = root_pos;\n        int max_eval_score = -1; \n\n        // Options for root movement (., U, D, L, R)\n        vector<pair<char, Vec2>> move_options;\n        move_options.push_back({'.', root_pos}); // No move\n        if (root_pos.x - 1 >= 0) move_options.push_back({'U', {root_pos.x - 1, root_pos.y}});\n        if (root_pos.x + 1 < N) move_options.push_back({'D', {root_pos.x + 1, root_pos.y}});\n        if (root_pos.y - 1 >= 0) move_options.push_back({'L', {root_pos.x, root_pos.y - 1}});\n        if (root_pos.y + 1 < N) move_options.push_back({'R', {root_pos.x, root_pos.y + 1}});\n\n        // Calculate a general centroid for tie-breaking in root movement (O(1) now)\n        Vec2 overall_centroid = {-1, -1};\n        int holding_takoyaki_fingertips_count = 0;\n        for(int u = 0; u < V_prime; ++u) {\n            if (is_fingertip[u] && fingertip_holding[u]) holding_takoyaki_fingertips_count++;\n        }\n        \n        if (holding_takoyaki_fingertips_count > 0) {\n            overall_centroid = calculate_centroid_fast(t_sum_x, t_sum_y, t_count);\n        } else {\n            overall_centroid = calculate_centroid_fast(s_sum_x, s_sum_y, s_count);\n        }\n\n        // Evaluate each move option\n        for (const auto& option : move_options) {\n            char move_char = option.first;\n            Vec2 test_pos = option.second;\n            int current_eval_score = evaluate_root_move(V_prime, test_pos);\n\n            // Tie-breaking:\n            // 1. Higher immediate score is always better.\n            // 2. If scores are equal, prefer no movement ('.').\n            // 3. If scores are equal and neither is '.', prefer closer to overall centroid.\n            if (current_eval_score > max_eval_score) {\n                max_eval_score = current_eval_score;\n                best_root_move_char = move_char;\n                next_root_pos_candidate = test_pos;\n            } else if (current_eval_score == max_eval_score) {\n                if (best_root_move_char != '.' && move_char == '.') {\n                    // This case should be handled by `max_eval_score` already being the max,\n                    // but we explicitly pick '.' if available and score is equal.\n                    best_root_move_char = move_char;\n                    next_root_pos_candidate = test_pos;\n                } else if (overall_centroid.x != -1 && move_char != '.') { // If centroid is valid and not moving\n                    // Prefer move that gets closer to the centroid\n                    if (test_pos.dist_sq(overall_centroid) < next_root_pos_candidate.dist_sq(overall_centroid)) {\n                         best_root_move_char = move_char;\n                         next_root_pos_candidate = test_pos;\n                    }\n                }\n            }\n        }\n        \n        root_pos = next_root_pos_candidate; // Apply chosen root movement\n        string command_root_move_str(1, best_root_move_char);\n        \n        // Update positions after root move (needed for rotation logic)\n        update_abs_pos_global();\n\n        // 2. Determine rotations\n        string command_rotations_str(V_prime - 1, '.'); // For non-root vertices (1 to V_prime-1)\n        \n        // This time, we re-evaluate and apply rotations based on the *actual* new root_pos\n        // and current global state. This makes sure the decisions are up-to-date.\n        vector<int> desired_orient_idx(V_prime, -1); \n\n        // Use a 2D bool array to track cells claimed by a fingertip's desired rotation for this turn\n        vector<vector<bool>> cells_claimed_by_rotation(N, vector<bool>(N, false)); \n\n        // Prioritize placing takoyaki\n        // Loop through fingertips (in increasing ID order for determinism)\n        for (int u = 1; u < V_prime; ++u) { \n            if (is_fingertip[u] && fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                for (int d = 0; d < 4; ++d) { \n                    Vec2 target_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                    if (is_valid_coord(target_cell) && grid_is_target_empty[target_cell.x][target_cell.y] && \n                        !cells_claimed_by_rotation[target_cell.x][target_cell.y]) {\n                        desired_orient_idx[u] = d;\n                        cells_claimed_by_rotation[target_cell.x][target_cell.y] = true;\n                        break; // Found a target for this fingertip\n                    }\n                }\n            }\n        }\n\n        // Then assign empty fingertips to source squares\n        // Loop through fingertips (in increasing ID order for determinism)\n        for (int u = 1; u < V_prime; ++u) { \n            if (is_fingertip[u] && !fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                for (int d = 0; d < 4; ++d) { \n                    Vec2 source_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                    if (is_valid_coord(source_cell) && grid_has_takoyaki[source_cell.x][source_cell.y] &&\n                        !cells_claimed_by_rotation[source_cell.x][source_cell.y]) {\n                        desired_orient_idx[u] = d;\n                        cells_claimed_by_rotation[source_cell.x][source_cell.y] = true;\n                        break; // Found a source for this fingertip\n                    }\n                }\n            }\n        }\n        \n        // Apply rotations based on desired_orient_idx\n        for (int u = 1; u < V_prime; ++u) { // Only non-root vertices can rotate (fingertips in this design)\n            if (desired_orient_idx[u] != -1) {\n                int current_d = orient_idx[u];\n                int target_d = desired_orient_idx[u];\n\n                if (current_d == target_d) {\n                    command_rotations_str[u - 1] = '.'; \n                } else {\n                    int cw_diff = (target_d - current_d + 4) % 4; // Number of CW 90-deg turns\n                    int ccw_diff = (current_d - target_d + 4) % 4; // Number of CCW 90-deg turns\n\n                    if (cw_diff == 1) { // 90 deg CW\n                        command_rotations_str[u - 1] = 'R';\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else if (ccw_diff == 1) { // 90 deg CCW\n                        command_rotations_str[u - 1] = 'L';\n                        orient_idx[u] = (orient_idx[u] + 3) % 4;\n                        rel_vecs[u] = rotate_ccw_problem(rel_vecs[u]);\n                    } else { // 180 deg (cw_diff == 2), takes 2 turns. Take one step (arbitrarily CW).\n                        command_rotations_str[u - 1] = 'R'; \n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    }\n                }\n            } else {\n                command_rotations_str[u - 1] = '.'; // No specific target, no rotation\n            }\n        }\n        \n        // Update positions after rotations\n        update_abs_pos_global();\n\n        // 3. Determine grab/release actions\n        string command_P_actions_part(V_prime, '.'); \n        \n        // A 2D array to track cells where takoyaki are placed/picked up in this turn,\n        // to prevent multiple fingertips from targeting the same cell.\n        vector<vector<bool>> cells_acted_on_this_turn(N, vector<bool>(N, false)); \n\n        // Process fingertips in order of ID (1 to V_prime-1) as problem states vertex order.\n        // Vertex 0 (root) is not a fingertip, so command_P_actions_part[0] remains '.'\n        for (int u = 1; u < V_prime; ++u) { \n            Vec2 current_tip_pos = abs_pos[u];\n\n            // Check if fingertip is within grid boundaries\n            if (!is_valid_coord(current_tip_pos)) {\n                continue; \n            }\n\n            if (fingertip_holding[u]) { // If currently holding a takoyaki\n                if (grid_is_target_empty[current_tip_pos.x][current_tip_pos.y] && \n                    !cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y]) {\n                    // Place takoyaki on target square\n                    command_P_actions_part[u] = 'P'; \n                    grid_is_target_empty[current_tip_pos.x][current_tip_pos.y] = false; // Target filled\n                    t_sum_x -= current_tip_pos.x; t_sum_y -= current_tip_pos.y; t_count--;\n                    fingertip_holding[u] = false;\n                    cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y] = true;\n                }\n            } else { // If not holding a takoyaki\n                if (grid_has_takoyaki[current_tip_pos.x][current_tip_pos.y] &&\n                    !cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y]) {\n                    // Pick up takoyaki from source square\n                    command_P_actions_part[u] = 'P';\n                    grid_has_takoyaki[current_tip_pos.x][current_tip_pos.y] = false; // Takoyaki picked\n                    s_sum_x -= current_tip_pos.x; s_sum_y -= current_tip_pos.y; s_count--;\n                    fingertip_holding[u] = true;\n                    cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y] = true;\n                }\n            }\n        }\n        \n        // Output combined command string\n        // Format: [root_move_char][V_prime-1 rotation_chars][V_prime P_chars]\n        cout << command_root_move_str << command_rotations_str << command_P_actions_part << endl;\n    }\n\n    return 0;\n}\n","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <set>\n// #include <optional> // optional is no longer strictly needed for 'hole' but can be kept if desired\n\nusing namespace std;\n\n// Timer utility\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    double time_limit_ms;\n\n    Timer(double limit_ms) : time_limit_ms(limit_ms) {\n        start_time = chrono::high_resolution_clock::now();\n    }\n\n    bool is_time_up() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() >= time_limit_ms;\n    }\n\n    double get_elapsed_time_ms() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n    }\n};\n\n// Point structure\nstruct Point {\n    int x, y;\n};\n\n// Rectangle structure\nstruct Rect {\n    int x_min, y_min, x_max, y_max;\n    long long length() const {\n        // Degenerate rectangle (width or height is 0 or negative) has 0 length\n        if (x_min >= x_max || y_min >= y_max) return 0; \n        return 2LL * (x_max - x_min) + 2LL * (y_max - y_min);\n    }\n};\n\n// Fenwick Tree (BIT) for 2D range sum queries\ntemplate <typename T>\nstruct FenwickTree2D {\n    int max_x_idx, max_y_idx;\n    vector<vector<T>> bit;\n\n    FenwickTree2D(int mx_idx, int my_idx) : max_x_idx(mx_idx), max_y_idx(my_idx) {\n        // Fenwick tree indices are 1-based, so size mx_idx+1, my_idx+1\n        bit.assign(max_x_idx + 1, vector<T>(max_y_idx + 1, 0));\n    }\n\n    void update(int x, int y, T delta) { // x, y are 0-based compressed indices\n        for (int i = x + 1; i <= max_x_idx; i += i & -i) {\n            for (int j = y + 1; j <= max_y_idx; j += j & -j) {\n                bit[i][j] += delta;\n            }\n        }\n    }\n\n    T query(int x, int y) { // query sum from (0,0) to (x,y) inclusive (0-based compressed indices)\n        T sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i) {\n            for (int j = y + 1; j > 0; j -= j & -j) {\n                sum += bit[i][j];\n            }\n        }\n        return sum;\n    }\n\n    // query sum for rectangle [x1, x2] x [y1, y2] (0-based compressed indices)\n    T query_rect_sum(int x1, int y1, int x2, int y2) { \n        // If the rectangle is inverted or empty in terms of compressed indices, it contains no points\n        if (x1 > x2 || y1 > y2) return 0;\n\n        T sum = query(x2, y2);\n        if (x1 > 0) sum -= query(x1 - 1, y2);\n        if (y1 > 0) sum -= query(x2, y1 - 1);\n        if (x1 > 0 && y1 > 0) sum += query(x1 - 1, y1 - 1);\n        return sum;\n    }\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nvector<int> unique_xs, unique_ys;\nmap<int, int> x_to_idx, y_to_idx;\nFenwickTree2D<int>* ft_ptr = nullptr; // Pointer to FenwickTree2D\n\n// Score calculation wrapper for real coordinates using compressed FT\nlong long calculate_rect_score(const Rect& rect) {\n    // If the rectangle is degenerate (width or height is 0 or negative), it cannot contain any points.\n    if (rect.x_min >= rect.x_max || rect.y_min >= rect.y_max) return 0; \n\n    // Find compressed indices for the given real coordinate rectangle\n    auto it_x1 = lower_bound(unique_xs.begin(), unique_xs.end(), rect.x_min);\n    if (it_x1 == unique_xs.end()) return 0; // rect.x_min is beyond all unique x-coordinates\n    int x1_idx = distance(unique_xs.begin(), it_x1);\n\n    auto it_x2 = upper_bound(unique_xs.begin(), unique_xs.end(), rect.x_max);\n    if (it_x2 == unique_xs.begin()) return 0; // rect.x_max is smaller than all unique x-coordinates\n    int x2_idx = distance(unique_xs.begin(), it_x2) - 1; // Largest unique_x_coord <= rect.x_max\n\n    auto it_y1 = lower_bound(unique_ys.begin(), unique_ys.end(), rect.y_min);\n    if (it_y1 == unique_ys.end()) return 0; \n    int y1_idx = distance(unique_ys.begin(), it_y1);\n\n    auto it_y2 = upper_bound(unique_ys.begin(), unique_ys.end(), rect.y_max);\n    if (it_y2 == unique_ys.begin()) return 0; \n    int y2_idx = distance(unique_ys.begin(), it_y2) - 1;\n\n    // Check if the compressed index range itself is valid (x1_idx <= x2_idx and y1_idx <= y2_idx)\n    // This handles cases where rect.x_min > rect.x_max (after compression logic)\n    if (x1_idx > x2_idx || y1_idx > y2_idx) return 0; \n\n    return ft_ptr->query_rect_sum(x1_idx, y1_idx, x2_idx, y2_idx);\n}\n\n// Polygon state for SA: now only a single rectangle\nstruct PolygonState {\n    Rect outer;\n    long long value; // Score (mackerels - sardines)\n    long long total_len; // Total length of edges\n    vector<Point> vertices; // Actual vertices for output\n\n    PolygonState() : value(0), total_len(0), outer({0,0,0,0}) {} // Default empty state\n\n    void calculate_polygon_data() {\n        // Outer rect must be valid (x_min < x_max and y_min < y_max)\n        if (outer.x_min >= outer.x_max || outer.y_min >= outer.y_max) { \n            value = -1; // Indicate invalid state (negative value for invalid)\n            total_len = 0;\n            vertices.clear();\n            return;\n        }\n        \n        value = calculate_rect_score(outer);\n        total_len = outer.length();\n\n        vertices.clear();\n        // Generate vertices for output if score is non-negative\n        // For a valid, non-degenerate rectangle, these 4 points are always distinct.\n        // The output polygon will be a simple rectangle with 4 vertices.\n        vertices.push_back({outer.x_min, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_min});\n        vertices.push_back({outer.x_max, outer.y_max});\n        vertices.push_back({outer.x_min, outer.y_max});\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer timer(1900); // 1.9 seconds time limit for main SA loop\n\n    cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    set<int> x_coords_set, y_coords_set;\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        x_coords_set.insert(mackerels[i].x);\n        y_coords_set.insert(mackerels[i].y);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        x_coords_set.insert(sardines[i].x);\n        y_coords_set.insert(sardines[i].y);\n    }\n\n    // Coordinate compression\n    unique_xs.assign(x_coords_set.begin(), x_coords_set.end());\n    unique_ys.assign(y_coords_set.begin(), y_coords_set.end());\n\n    // Ensure 0 and 100000 are in unique_xs/ys as potential boundaries for rectangles.\n    // This is important because a rectangle might span these boundaries even if no points are exactly on them.\n    if (unique_xs.empty() || unique_xs.front() != 0) { unique_xs.insert(unique_xs.begin(), 0); }\n    if (unique_xs.back() != 100000) { unique_xs.push_back(100000); }\n    if (unique_ys.empty() || unique_ys.front() != 0) { unique_ys.insert(unique_ys.begin(), 0); }\n    if (unique_ys.back() != 100000) { unique_ys.push_back(100000); }\n    \n    // Re-sort if necessary (std::set keeps elements sorted, so unique_xs.assign copies them in order. \n    // Manual insert at begin/end might break this if elements are not at the extrema, but 0 and 100000 are extrema.)\n    // However, it's safer to ensure they are sorted if inserts were made. std::set properties ensure this is usually fine.\n    // With `insert` and `push_back` as written for 0 and 100000, `unique_xs` and `unique_ys` remain sorted.\n\n    // Populate maps for fast lookup from real coordinate to compressed index\n    for (int i = 0; i < unique_xs.size(); ++i) x_to_idx[unique_xs[i]] = i;\n    for (int i = 0; i < unique_ys.size(); ++i) y_to_idx[unique_ys[i]] = i;\n\n    // Initialize 2D Fenwick Tree using compressed indices\n    FenwickTree2D<int> ft(unique_xs.size(), unique_ys.size());\n    ft_ptr = &ft;\n\n    for (int i = 0; i < N; ++i) { // Mackerels contribute +1\n        ft.update(x_to_idx[mackerels[i].x], y_to_idx[mackerels[i].y], 1);\n    }\n    for (int i = 0; i < N; ++i) { // Sardines contribute -1\n        ft.update(x_to_idx[sardines[i].x], y_to_idx[sardines[i].y], -1);\n    }\n\n    // Initialize random number generator\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> rand_idx_x(0, unique_xs.size() - 1);\n    uniform_int_distribution<int> rand_idx_y(0, unique_ys.size() - 1);\n    uniform_real_distribution<double> rand_prob(0.0, 1.0);\n    \n    // Initial solution: a large rectangle covering the entire possible area\n    PolygonState best_polygon;\n    best_polygon.outer = {0, 0, 100000, 100000};\n    best_polygon.calculate_polygon_data(); // Calculate score and vertices for initial state\n    \n    // If the initial full map rectangle is degenerate, invalid, or yields a negative score\n    // (meaning a score of 1 in the contest, effectively), initialize with a minimal valid rectangle.\n    // The current calculate_polygon_data sets value=-1 for invalid, and total_len=0.\n    // So, if best_polygon.value is -1, it implies an invalid rectangle, or actual score < 0.\n    if (best_polygon.value < 0 || best_polygon.total_len > 400000) {\n        best_polygon.outer = {0,0,1,1}; // A minimal 1x1 rectangle at origin. Valid, length 4, 4 vertices.\n        best_polygon.calculate_polygon_data();\n    }\n\n    PolygonState current_polygon = best_polygon; // Start SA from this point\n\n    double T_start = 2000.0; // Initial temperature: A heuristic, roughly the maximum possible (mackerel - sardine) difference\n    double T_end = 1.0;      // Final temperature: Low enough to favor improvements but still allow small worsening moves\n    long long iter_count = 0;\n    long long max_iterations = 500000; // Increase iterations as calculations are faster now\n\n    while (!timer.is_time_up() && iter_count < max_iterations) {\n        iter_count++;\n        PolygonState next_polygon = current_polygon;\n\n        // Only modify the outer rectangle's boundaries\n        int dim_to_change = uniform_int_distribution<int>(0, 3)(rng); // 0:x_min, 1:y_min, 2:x_max, 3:y_max\n        int new_val_idx;\n        \n        if (dim_to_change == 0) { // Modify x_min\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_min = min(unique_xs[new_val_idx], next_polygon.outer.x_max); // Ensure x_min <= x_max\n        } else if (dim_to_change == 1) { // Modify y_min\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_min = min(unique_ys[new_val_idx], next_polygon.outer.y_max); // Ensure y_min <= y_max\n        } else if (dim_to_change == 2) { // Modify x_max\n            new_val_idx = rand_idx_x(rng);\n            next_polygon.outer.x_max = max(unique_xs[new_val_idx], next_polygon.outer.x_min); // Ensure x_max >= x_min\n        } else { // Modify y_max\n            new_val_idx = rand_idx_y(rng);\n            next_polygon.outer.y_max = max(unique_ys[new_val_idx], next_polygon.outer.y_min); // Ensure y_max >= y_min\n        }\n        \n        next_polygon.calculate_polygon_data(); // Recalculate score and other data for the new state\n        \n        // Validity check: Must result in a valid polygon (value >= 0, length within limits)\n        if (next_polygon.value < 0 || next_polygon.total_len > 400000) {\n            continue; // This move is invalid, discard and try again\n        }\n\n        // Simulated Annealing acceptance criteria\n        double current_temp = T_start * pow(T_end / T_start, timer.get_elapsed_time_ms() / timer.time_limit_ms);\n        double acceptance_prob = 1.0;\n        if (next_polygon.value < current_polygon.value) {\n            // If the new solution is worse, accept it with a probability that decreases with temperature\n            acceptance_prob = exp((double)(next_polygon.value - current_polygon.value) / current_temp);\n        }\n\n        if (rand_prob(rng) < acceptance_prob) {\n            current_polygon = next_polygon; // Accept the new solution\n            if (current_polygon.value > best_polygon.value) {\n                best_polygon = current_polygon; // Update overall best solution found\n            }\n        }\n    }\n\n    // Output the best polygon found\n    // If best_polygon.value is negative (which shouldn't happen with the fallback {0,0,1,1} initialization, \n    // but as a safeguard), output the minimal 1x1 polygon for a score of 1.\n    if (best_polygon.value < 0) {\n        cout << 4 << endl;\n        cout << \"0 0\" << endl;\n        cout << \"1 0\" << endl;\n        cout << \"1 1\" << endl;\n        cout << \"0 1\" << endl;\n    } else {\n        cout << best_polygon.vertices.size() << endl;\n        for (const auto& v : best_polygon.vertices) {\n            cout << v.x << \" \" << v.y << endl;\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <iomanip> // For std::fixed, std::setprecision\n#include <chrono> // For timing\n#include <cmath> // For std::exp, std::pow, std::sqrt\n\n// Random number generator\nstd::mt19937 rng;\n\n// Global parameters from input\nint N_GLOBAL;\nint T_TOTAL_GLOBAL;\nlong long SIGMA_GLOBAL;\nstd::vector<long long> W_PRIME_GLOBAL, H_PRIME_GLOBAL; // Initial observed dimensions\n\n// Current estimates for true widths and heights, using double for precision\nstd::vector<double> current_estimated_w, current_estimated_h;\n\n// Struct to represent a single placement operation\nstruct Operation {\n    int p;     // Rectangle index (0 to N-1)\n    int r;     // Rotation (0: no, 1: 90-deg)\n    char d;    // Direction ('U' or 'L')\n    int b;     // Reference rectangle index (-1 for origin or 0 to p-1)\n};\n\n// Struct to store details of a rectangle after it's been placed\nstruct PlacedRectInfo {\n    long long x, y, w, h; // Coordinates and dimensions\n    int p_idx;             // Original index of the rectangle\n    bool rotated;          // True if rotated\n};\n\n// Helper function for random integer generation\nint random_int(int min, int max) {\n    std::uniform_int_distribution<int> dist(min, max);\n    return dist(rng);\n}\n\n// Helper function for random char selection\nchar random_char(char c1, char c2) {\n    return (random_int(0, 1) == 0) ? c1 : c2;\n}\n\n// Helper for random double in range [0, 1)\ndouble random_double_01() {\n    std::uniform_real_distribution<double> dist(0.0, 1.0);\n    return dist(rng);\n}\n\n// Simulates the placement of rectangles given a set of operations and current dimension estimates.\n// Returns the predicted bounding box (W, H).\nstd::pair<long long, long long>\nsimulate_placement(const std::vector<Operation>& ops,\n                   const std::vector<double>& est_w,\n                   const std::vector<double>& est_h) {\n    \n    // Using a vector indexed by original rectangle index for O(1) access\n    // This is valid because rectangle indices `p` are placed in ascending order.\n    std::vector<PlacedRectInfo> p_idx_to_info_vec(N_GLOBAL); \n    \n    long long max_X = 0;\n    long long max_Y = 0;\n\n    // A list of already placed rectangle indices to iterate over.\n    // This is more efficient than iterating through the entire `p_idx_to_info_vec` if `N` is large\n    // and only a few items are placed so far.\n    std::vector<int> current_placed_indices;\n    current_placed_indices.reserve(N_GLOBAL);\n\n    for (const auto& op : ops) {\n        // Get estimated dimensions and apply rotation\n        long long current_w = static_cast<long long>(est_w[op.p]);\n        long long current_h = static_cast<long long>(est_h[op.p]);\n        \n        if (op.r == 1) { // Rotate 90 degrees\n            std::swap(current_w, current_h);\n        }\n\n        // Clamp dimensions to problem constraints [1, 10^9]\n        current_w = std::max(1LL, std::min(1000000000LL, current_w));\n        current_h = std::max(1LL, std::min(1000000000LL, current_h));\n\n        long long new_x = 0;\n        long long new_y = 0;\n\n        if (op.d == 'U') {\n            // Determine the x-coordinate of the left edge\n            long long target_x_left = 0;\n            if (op.b != -1) {\n                // op.b must be a previously placed rectangle's index, so it will be in p_idx_to_info_vec\n                target_x_left = p_idx_to_info_vec[op.b].x + p_idx_to_info_vec[op.b].w;\n            }\n            new_x = target_x_left;\n\n            // Find the highest point (max y + h) that the new rectangle would sit on\n            long long y_stop_level = 0;\n            for (int p_idx : current_placed_indices) { // Iterate only through actually placed rectangles\n                const auto& placed_r = p_idx_to_info_vec[p_idx];\n                // Check for horizontal overlap with placed_r\n                if (placed_r.x < new_x + current_w && placed_r.x + placed_r.w > new_x) {\n                    y_stop_level = std::max(y_stop_level, placed_r.y + placed_r.h);\n                }\n            }\n            new_y = y_stop_level;\n\n        } else { // op.d == 'L'\n            // Determine the y-coordinate of the top edge\n            long long target_y_top = 0;\n            if (op.b != -1) {\n                // op.b must be a previously placed rectangle's index\n                target_y_top = p_idx_to_info_vec[op.b].y + p_idx_to_info_vec[op.b].h;\n            }\n            new_y = target_y_top;\n\n            // Find the rightmost point (max x + w) that the new rectangle would push against\n            long long x_stop_level = 0;\n            for (int p_idx : current_placed_indices) { // Iterate only through actually placed rectangles\n                const auto& placed_r = p_idx_to_info_vec[p_idx];\n                // Check for vertical overlap with placed_r\n                if (placed_r.y < new_y + current_h && placed_r.y + placed_r.h > new_y) {\n                    x_stop_level = std::max(x_stop_level, placed_r.x + placed_r.w);\n                }\n            }\n            new_x = x_stop_level;\n        }\n\n        // Store info for the newly placed rectangle\n        PlacedRectInfo info = {new_x, new_y, current_w, current_h, op.p, (op.r == 1)};\n        p_idx_to_info_vec[op.p] = info;      // For quick lookup by original index\n        current_placed_indices.push_back(op.p); // Add to list of placed indices\n\n        // Update overall bounding box dimensions\n        max_X = std::max(max_X, new_x + current_w);\n        max_Y = std::max(max_Y, new_y + current_h);\n    }\n\n    return {max_X, max_Y};\n}\n\n// Generates an initial random placement strategy\nstd::vector<Operation> generate_random_strategy(int N) {\n    std::vector<Operation> ops(N);\n    for (int i = 0; i < N; ++i) {\n        ops[i].p = i; // Always place rectangles in ascending order of their original indices\n        ops[i].r = random_int(0, 1);\n        ops[i].d = random_char('U', 'L');\n        ops[i].b = random_int(-1, i - 1); // Reference rectangle must be -1 or a previously placed index\n    }\n    return ops;\n}\n\n// Main solution function\nvoid solve() {\n    // Read initial N, T, sigma and rectangle measurements\n    std::cin >> N_GLOBAL >> T_TOTAL_GLOBAL >> SIGMA_GLOBAL;\n\n    W_PRIME_GLOBAL.resize(N_GLOBAL);\n    H_PRIME_GLOBAL.resize(N_GLOBAL);\n    current_estimated_w.resize(N_GLOBAL);\n    current_estimated_h.resize(N_GLOBAL);\n\n    for (int i = 0; i < N_GLOBAL; ++i) {\n        std::cin >> W_PRIME_GLOBAL[i] >> H_PRIME_GLOBAL[i];\n        current_estimated_w[i] = static_cast<double>(W_PRIME_GLOBAL[i]);\n        current_estimated_h[i] = static_cast<double>(H_PRIME_GLOBAL[i]);\n    }\n\n    // Initialize the best strategy found so far across all turns\n    std::vector<Operation> overall_best_ops = generate_random_strategy(N_GLOBAL);\n    auto initial_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n    long long overall_best_score_predicted = initial_sim_result.first + initial_sim_result.second;\n\n    // Time management for local search\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 2.9; // Allow some buffer for I/O and final calculations\n\n    // Simulated Annealing temperature parameters (reverted to best performing config)\n    double T_GLOBAL_START = 0;\n    for(int i=0; i<N_GLOBAL; ++i) T_GLOBAL_START += (current_estimated_w[i] + current_estimated_h[i]);\n    T_GLOBAL_START /= N_GLOBAL; // Average side length sum per rectangle\n    T_GLOBAL_START *= 15.0;     // Multiplier from best performing config\n    T_GLOBAL_START = std::max(T_GLOBAL_START, 100000.0); // Minimum temp to ensure it's not too small.\n\n    const double T_GLOBAL_END_RATIO = 0.01; // Global temp decay from best performing config\n    const double T_INNER_END_RATIO = 0.01;  // Inner temp decay from best performing config\n    \n    // Dynamic adjustment of NUM_LOCAL_SEARCH_ATTEMPTS\n    const int BASE_LOCAL_SEARCH_ATTEMPTS = 50;\n    int actual_local_search_attempts = std::max(BASE_LOCAL_SEARCH_ATTEMPTS, (int)(BASE_LOCAL_SEARCH_ATTEMPTS * (100.0 / N_GLOBAL)));\n\n    for (int turn = 0; turn < T_TOTAL_GLOBAL; ++turn) {\n        // Calculate the current global temperature for this turn.\n        double turn_progress = (double)turn / T_TOTAL_GLOBAL;\n        double T_turn_start = T_GLOBAL_START * std::pow(T_GLOBAL_END_RATIO, turn_progress);\n\n        std::vector<Operation> current_ops_SA = overall_best_ops; \n        long long current_score_SA = overall_best_score_predicted;\n        \n        std::vector<Operation> best_ops_in_SA = overall_best_ops;\n        long long best_score_in_SA = overall_best_score_predicted;\n\n        for (int iter = 0; iter < actual_local_search_attempts; ++iter) { // Use dynamically adjusted attempts\n            std::vector<Operation> candidate_ops = current_ops_SA; \n            int p_idx_to_change = random_int(0, N_GLOBAL - 1); \n\n            int mutate_type = random_int(0, 2); \n\n            if (mutate_type == 0) { // Mutate rotation\n                candidate_ops[p_idx_to_change].r = 1 - candidate_ops[p_idx_to_change].r;\n            } else if (mutate_type == 1) { // Mutate direction\n                candidate_ops[p_idx_to_change].d = (candidate_ops[p_idx_to_change].d == 'U' ? 'L' : 'U');\n            } else { // Mutate reference rectangle (b_i)\n                candidate_ops[p_idx_to_change].b = random_int(-1, p_idx_to_change - 1);\n            }\n\n            auto sim_result = simulate_placement(candidate_ops, current_estimated_w, current_estimated_h);\n            long long candidate_score = sim_result.first + sim_result.second;\n\n            double inner_iter_progress = (double)iter / actual_local_search_attempts; // Use actual_local_search_attempts\n            double temp_for_this_iter = T_turn_start * std::pow(T_INNER_END_RATIO, inner_iter_progress);\n            \n            if (temp_for_this_iter < 1.0) temp_for_this_iter = 1.0; \n\n            if (candidate_score < current_score_SA) {\n                current_ops_SA = candidate_ops;\n                current_score_SA = candidate_score;\n                if (current_score_SA < best_score_in_SA) {\n                    best_ops_in_SA = current_ops_SA;\n                    best_score_in_SA = current_score_SA;\n                }\n            } else {\n                double acceptance_prob = std::exp(-(double)(candidate_score - current_score_SA) / temp_for_this_iter);\n                if (random_double_01() < acceptance_prob) {\n                    current_ops_SA = candidate_ops;\n                    current_score_SA = candidate_score;\n                }\n            }\n        } \n\n        if (best_score_in_SA < overall_best_score_predicted) {\n            overall_best_ops = best_ops_in_SA;\n            overall_best_score_predicted = best_score_in_SA;\n        }\n\n        std::cout << N_GLOBAL << std::endl;\n        for (const auto& op : overall_best_ops) {\n            std::cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << std::endl;\n        }\n        std::cout << std::flush;\n\n        long long W_observed, H_observed;\n        std::cin >> W_observed >> H_observed;\n\n        // One call to simulate_placement to update dimension estimates\n        auto sim_result_for_update = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        long long W_predicted = sim_result_for_update.first;\n        long long H_predicted = sim_result_for_update.second;\n\n        double W_ratio = static_cast<double>(W_observed) / W_predicted;\n        double H_ratio = static_cast<double>(H_observed) / H_predicted;\n\n        double learn_rate = 0.07 / std::sqrt(turn + 1.0); // Learn rate base from best performing config\n        double initial_reversion_rate = 0.01 / std::sqrt(turn + 1.0); // Reversion rate base from best performing config\n\n        for (int i = 0; i < N_GLOBAL; ++i) {\n            current_estimated_w[i] = current_estimated_w[i] * (1.0 + learn_rate * (W_ratio - 1.0));\n            current_estimated_h[i] = current_estimated_h[i] * (1.0 + learn_rate * (H_ratio - 1.0));\n\n            current_estimated_w[i] = (1.0 - initial_reversion_rate) * current_estimated_w[i] + initial_reversion_rate * W_PRIME_GLOBAL[i];\n            current_estimated_h[i] = (1.0 - initial_reversion_rate) * current_estimated_h[i] + initial_reversion_rate * H_PRIME_GLOBAL[i];\n\n            current_estimated_w[i] = std::max(1.0, std::min(1000000000.0, current_estimated_w[i]));\n            current_estimated_h[i] = std::max(1.0, std::min(1000000000.0, current_estimated_h[i]));\n        }\n\n        // Re-calculate the overall best predicted score with the new estimates\n        auto new_overall_best_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        overall_best_score_predicted = new_overall_best_sim_result.first + new_overall_best_sim_result.second;\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT_SECONDS) {\n            break; \n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    rng.seed(std::chrono::system_clock::now().time_since_epoch().count());\n\n    solve();\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <queue>\n#include <chrono>\n#include <random>\n#include <cmath> // For std::exp\n\n// Global random number generator\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Structure to hold graph and problem data\nstruct ProblemData {\n    int N, M, H_limit;\n    std::vector<int> A;\n    std::vector<std::vector<int>> adj; // Adjacency list for the original graph\n};\n\n// Structure to hold a solution candidate (parent array, score, heights)\nstruct Solution {\n    std::vector<int> parent;\n    long long score;\n    std::vector<int> heights; // Heights for current parent configuration\n\n    Solution(int N_val) : parent(N_val, -1), score(0), heights(N_val, -1) {}\n};\n\n// Function to evaluate a given parent array and compute heights\n// Returns score, and populates heights_out. Returns -1 for invalid states.\n// Invalid states include cycles or height constraint violations.\nlong long eval_score(const ProblemData& pd, const std::vector<int>& p, std::vector<int>& heights_out) {\n    int N = pd.N;\n    int H_limit = pd.H_limit;\n    const std::vector<int>& A = pd.A;\n\n    std::vector<std::vector<int>> children_lists(N);\n    std::vector<char> is_root(N, 1); // Using char for boolean (1 for true, 0 for false)\n\n    for (int v = 0; v < N; ++v) {\n        if (p[v] != -1) {\n            if (p[v] < 0 || p[v] >= N || p[v] == v) { \n                return -1; // Invalid parent reference\n            }\n            children_lists[p[v]].push_back(v);\n            is_root[v] = 0; // Node v is not a root\n        }\n    }\n\n    std::fill(heights_out.begin(), heights_out.end(), -1); // Initialize heights to -1 (unvisited)\n    long long current_total_score = 0;\n    \n    std::queue<int> q; // Queue for BFS\n\n    for (int r = 0; r < N; ++r) {\n        if (is_root[r] == 1 && heights_out[r] == -1) { \n            q.push(r);\n            heights_out[r] = 0; // Root has height 0\n            current_total_score += (1LL * (heights_out[r] + 1) * A[r]);\n\n            while (!q.empty()) {\n                int u = q.front();\n                q.pop();\n\n                if (heights_out[u] > H_limit) { \n                    return -1; \n                }\n\n                for (int v_child : children_lists[u]) {\n                    if (heights_out[v_child] == -1) { // If v_child has not yet been visited in this tree\n                        heights_out[v_child] = heights_out[u] + 1;\n                        if (heights_out[v_child] > H_limit) { // Height constraint violation for v_child\n                            return -1;\n                        }\n                        current_total_score += (1LL * (heights_out[v_child] + 1) * A[v_child]);\n                        q.push(v_child);\n                    } else {\n                        // Cycle or structural inconsistency detected\n                        return -1; \n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure all nodes have been assigned a height.\n    for(int v = 0; v < N; ++v){\n        if(heights_out[v] == -1){\n            return -1; \n        }\n    }\n\n    return current_total_score;\n}\n\n// Function to check for cycles efficiently during a proposed parent change.\nbool forms_cycle(int v, int new_p, const std::vector<int>& current_p, const ProblemData& pd) {\n    if (new_p == -1) return false; \n\n    int curr = new_p;\n    for(int i = 0; i < pd.H_limit + 2 && curr != -1; ++i) { \n        if (curr == v) {\n            return true; \n        }\n        curr = current_p[curr];\n    }\n    return false; \n}\n\nvoid solve() {\n    ProblemData pd;\n    std::cin >> pd.N >> pd.M >> pd.H_limit;\n    pd.A.resize(pd.N);\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.A[i];\n    \n    pd.adj.resize(pd.N);\n    for (int i = 0; i < pd.M; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        pd.adj[u].push_back(v);\n        pd.adj[v].push_back(u);\n    }\n    // Coordinates are not used.\n    for (int i = 0; i < pd.N; ++i) {\n        int x, y; \n        std::cin >> x >> y;\n    }\n\n    Solution current_sol(pd.N);\n    current_sol.score = eval_score(pd, current_sol.parent, current_sol.heights);\n\n    Solution best_sol = current_sol; \n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; \n    \n    double start_temp = 500.0;           \n    double end_temp = 0.1;               // Tuned: Lowered end_temp for more aggressive convergence\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> node_dist_uniform(0, pd.N - 1); \n\n    const double PROB_BIAS_DYNAMIC = 0.7; // 70% chance to pick node based on dynamic priority\n\n    // Vectors for dynamic priority calculation\n    std::vector<long long> dynamic_priorities(pd.N);\n    std::vector<long long> dynamic_priority_prefix_sum(pd.N);\n    \n    // Buffer for new heights when evaluating a candidate solution\n    std::vector<int> new_heights_buffer(pd.N);\n\n    // Main Simulated Annealing loop\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration<double, std::milli>(current_time - start_time).count();\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            break; \n        }\n\n        double progress = elapsed_ms / TIME_LIMIT_MS;\n        double temp = start_temp * (1.0 - progress) + end_temp * progress; \n\n        int v;\n        if (dist_0_1(rng) < PROB_BIAS_DYNAMIC) {\n            // Biased selection: pick node proportional to its A_v * (H_limit - h_v + 1)\n            // Recalculate dynamic priorities based on current solution's heights\n            long long total_dynamic_priority_sum = 0;\n            for(int i = 0; i < pd.N; ++i) {\n                // Prioritize nodes with high beauty and more \"room\" to increase depth (low current height)\n                dynamic_priorities[i] = 1LL * pd.A[i] * (pd.H_limit - current_sol.heights[i] + 1);\n            }\n            \n            dynamic_priority_prefix_sum[0] = dynamic_priorities[0];\n            for(int i = 1; i < pd.N; ++i) {\n                dynamic_priority_prefix_sum[i] = dynamic_priority_prefix_sum[i-1] + dynamic_priorities[i];\n            }\n            total_dynamic_priority_sum = dynamic_priority_prefix_sum[pd.N - 1];\n\n            if (total_dynamic_priority_sum <= 0) { // Safety check: if sum is zero, fall back to uniform\n                v = node_dist_uniform(rng);\n            } else {\n                std::uniform_int_distribution<long long> dist_sum_priority(0, total_dynamic_priority_sum - 1);\n                long long target_sum = dist_sum_priority(rng);\n                v = std::upper_bound(dynamic_priority_prefix_sum.begin(), dynamic_priority_prefix_sum.end(), target_sum) - dynamic_priority_prefix_sum.begin();\n            }\n\n        } else {\n            // Uniform selection: pick any node with equal probability\n            v = node_dist_uniform(rng); \n        }\n\n        // --- SA acceptance logic ---\n        // Create a candidate parent array by copying current_sol's parent.\n        std::vector<int> candidate_parent_array = current_sol.parent;\n        \n        // Determine candidate parents for 'v'\n        std::vector<int> candidate_parents_for_v;\n        candidate_parents_for_v.push_back(-1); // Option to make v a root\n        for (int neighbor : pd.adj[v]) {\n            if (neighbor != v) { \n                candidate_parents_for_v.push_back(neighbor);\n            }\n        }\n        \n        if (candidate_parents_for_v.empty()) { \n            continue; // No valid parents for v (should be rare/impossible in connected N>1 graph), skip this iteration\n        }\n        std::uniform_int_distribution<int> parent_dist(0, candidate_parents_for_v.size() - 1);\n        int new_p = candidate_parents_for_v[parent_dist(rng)];\n        \n        // Apply the proposed change to the candidate array\n        candidate_parent_array[v] = new_p;\n\n        // Perform a quick cycle check\n        if (forms_cycle(v, new_p, candidate_parent_array, pd)) {\n             continue; // Invalid move due to cycle, try next iteration\n        }\n        \n        // Evaluate the new state and its score\n        long long new_score = eval_score(pd, candidate_parent_array, new_heights_buffer);\n\n        if (new_score != -1) { // If the new state is valid\n            // Update the global best solution if the new score is higher\n            if (new_score > best_sol.score) {\n                best_sol.score = new_score;\n                best_sol.parent = candidate_parent_array;\n                best_sol.heights = new_heights_buffer; // Also update heights for best_sol\n            }\n\n            // Simulated Annealing acceptance condition:\n            // Always accept if the new score is better.\n            // Accept with a certain probability if the new score is worse, allowing escape from local optima.\n            if (new_score > current_sol.score || \n                dist_0_1(rng) < std::exp((double)(new_score - current_sol.score) / temp)) {\n                \n                // Accept the move: update current_sol with the new state\n                current_sol.score = new_score;\n                current_sol.parent = candidate_parent_array;\n                current_sol.heights = new_heights_buffer; // Also update heights for current_sol\n            } \n            // Else (move rejected): current_sol remains unchanged, as candidate_parent_array was temporary.\n        } \n        // Else (new_score == -1, invalid state): candidate_parent_array is simply discarded. current_sol remains unchanged.\n    }\n\n    // Output the parent array of the best solution found\n    for (int i = 0; i < pd.N; ++i) {\n        std::cout << best_sol.parent[i] << (i == pd.N - 1 ? \"\" : \" \");\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}\n","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <limits>  // For std::numeric_limits\n\n// Structure to store an operation\nstruct Operation {\n    char direction;\n    int index;\n\n    Operation(char d, int i) : direction(d), index(i) {}\n};\n\n// Structure to encapsulate the best choice found in an iteration\nstruct BestChoice {\n    double cost_per_oni; // Primary metric: moves / num_oni_removed (minimize)\n    int num_oni_removed; // Secondary metric: maximize\n    int moves_count;     // Tertiary metric: minimize\n    std::pair<int, int> target_oni_pos; // The specific Oni this action was calculated for\n    char direction;\n    int index;\n\n    // Default constructor for initialization to \"worst possible\" values\n    BestChoice() : cost_per_oni(std::numeric_limits<double>::max()),\n                   num_oni_removed(0), // Maximize this, so start low\n                   moves_count(std::numeric_limits<int>::max()),\n                   target_oni_pos({-1, -1}), direction(' '), index(-1) {}\n\n    // Method to check if 'this' choice is strictly better than 'other'\n    bool is_strictly_better_than(const BestChoice& other) const {\n        // 1. Compare cost_per_oni (less is better)\n        if (cost_per_oni < other.cost_per_oni) return true;\n        if (cost_per_oni > other.cost_per_oni) return false;\n\n        // 2. cost_per_oni is equal, compare num_oni_removed (more is better)\n        if (num_oni_removed > other.num_oni_removed) return true;\n        if (num_oni_removed < other.num_oni_removed) return false;\n\n        // 3. num_oni_removed is equal, compare moves_count (less is better)\n        if (moves_count < other.moves_count) return true;\n\n        return false; // Not strictly better\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N;\n    std::cin >> N;\n\n    // Store initial Fukunokami positions for constant lookup, as they never move\n    std::set<std::pair<int, int>> fuku_positions_set;\n    // Store current Oni positions. This set will be modified as Oni are removed.\n    std::set<std::pair<int, int>> current_oni_positions_set;\n\n    for (int i = 0; i < N; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                current_oni_positions_set.insert({i, j});\n            } else if (row_str[j] == 'o') {\n                fuku_positions_set.insert({i, j});\n            }\n        }\n    }\n\n    std::vector<Operation> operations;\n\n    // Continue as long as there are Oni on the board\n    while (!current_oni_positions_set.empty()) {\n        BestChoice best_overall_choice;\n\n        // Iterate through all currently present Oni to find the best action.\n        // The iteration order of std::set provides a stable tie-breaking for target_oni_pos\n        for (const auto& oni_pos : current_oni_positions_set) {\n            int r = oni_pos.first;\n            int c = oni_pos.second;\n\n            // --- Check Upward path ---\n            bool up_clear = true;\n            int oni_in_up_path_count = 0;\n            // Iterate from row 0 up to and including 'r' in column 'c'\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    up_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_up_path_count++;\n                }\n            }\n\n            if (up_clear) {\n                int moves = 2 * (r + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_up_path_count;\n                // 'num_oni_removed' is guaranteed to be at least 1 (the target Oni itself)\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_up_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'U';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Downward path ---\n            bool down_clear = true;\n            int oni_in_down_path_count = 0;\n            // Iterate from row 'r' down to and including 'N-1' in column 'c'\n            for (int k_row = r; k_row < N; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    down_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_down_path_count++;\n                }\n            }\n\n            if (down_clear) {\n                int moves = 2 * (N - r);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_down_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_down_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'D';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Leftward path ---\n            bool left_clear = true;\n            int oni_in_left_path_count = 0;\n            // Iterate from column 0 up to and including 'c' in row 'r'\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    left_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_left_path_count++;\n                }\n            }\n\n            if (left_clear) {\n                int moves = 2 * (c + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_left_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_left_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'L';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Rightward path ---\n            bool right_clear = true;\n            int oni_in_right_path_count = 0;\n            // Iterate from column 'c' down to and including 'N-1' in row 'r'\n            for (int k_col = c; k_col < N; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    right_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_right_path_count++;\n                }\n            }\n\n            if (right_clear) {\n                int moves = 2 * (N - c);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_right_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_right_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'R';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n        } // End loop over current_oni_positions_set\n\n        // Apply the best found operations and update the set of Oni\n        int r = best_overall_choice.target_oni_pos.first;\n        int c = best_overall_choice.target_oni_pos.second;\n        char chosen_direction = best_overall_choice.direction;\n        int chosen_index = best_overall_choice.index;\n\n        // The problem guarantee ensures that a valid choice is always found.\n        // If it weren't, chosen_index would be -1, indicating an error or no more Oni.\n        // For robustness, could add: if (chosen_index == -1) break;\n\n        if (chosen_direction == 'U') {\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('U', chosen_index);\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('D', chosen_index);\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'D') {\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('D', chosen_index);\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('U', chosen_index);\n            for (int k_row = r; k_row < N; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'L') {\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('L', chosen_index);\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('R', chosen_index);\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        } else if (chosen_direction == 'R') {\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('R', chosen_index);\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('L', chosen_index);\n            for (int k_col = c; k_col < N; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        }\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        std::cout << op.direction << \" \" << op.index << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric> // For std::accumulate\n#include <cmath>   // For std::abs, std::pow, std::exp\n#include <random>  // For std::mt19937, std::uniform_int_distribution, std::uniform_real_distribution, std::discrete_distribution\n#include <chrono>  // For high_resolution_clock\n#include <algorithm> // For std::min, std::max\n\n// Use a global random number generator for convenience and efficiency\n// Seeded with current time to ensure different runs produce different results\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Function to calculate the error for a given assignment\n// N: Number of employees\n// L: Total number of weeks\n// T: Target cleaning counts for each employee\n// assignments: Vector of pairs (a_i, b_i) for each employee i\nlong long calculate_error(\n    int N, int L, \n    const std::vector<int>& T, \n    const std::vector<std::pair<int, int>>& assignments\n) {\n    std::vector<long long> actual_final_counts(N, 0); // Stores the final cleaning counts for each employee\n\n    int current_cleaner = 0; // The employee who cleans in the current week (starts with employee 0)\n    // counts_in_sim tracks cleaning counts *during this specific simulation run* for cycle detection\n    std::vector<int> counts_in_sim(N, 0); \n    \n    // For cycle detection:\n    // path_cleaners stores the sequence of employees who cleaned, week by week (0-indexed)\n    // It will store at most 2N elements before a cycle is guaranteed to be detected.\n    std::vector<int> path_cleaners; \n    path_cleaners.reserve(N * 2 + 1); // Reserve space to avoid reallocations\n\n    // visited_states stores the week_idx when a state (cleaner_id * 2 + count_parity) was first observed.\n    // Initialize with -1 to indicate not visited. Max state key is (N-1)*2+1 = 2N-1. Size 2N is sufficient.\n    std::vector<int> visited_states(N * 2, -1); \n\n    // Simulate week by week until L weeks are covered or a cycle is detected\n    for (int week_idx = 0; week_idx < L; ++week_idx) {\n        int cleaner_for_this_week = current_cleaner;\n        counts_in_sim[cleaner_for_this_week]++; // Increment count for the current cleaner\n        path_cleaners.push_back(cleaner_for_this_week); // Record this week's cleaner\n\n        // A state is defined by (employee who just finished cleaning, their total cleaning count parity)\n        // Map (cleaner_id, count_parity) to a single integer key for vector lookup (O(1) access)\n        int state_key = cleaner_for_this_week * 2 + (counts_in_sim[cleaner_for_this_week] % 2);\n\n        // Check if this state has been visited before, indicating a cycle\n        if (visited_states[state_key] != -1) { // If this state_key was visited before\n            int cycle_start_idx = visited_states[state_key]; // Week index where this state first occurred\n            int cycle_length = week_idx - cycle_start_idx + 1; // Length of the detected cycle (from cycle_start_idx to current week_idx, inclusive)\n\n            // Step 1: Accumulate counts for the pre-cycle part (weeks 0 to cycle_start_idx-1)\n            for (int i = 0; i < cycle_start_idx; ++i) {\n                actual_final_counts[path_cleaners[i]]++;\n            }\n\n            // Step 2: Calculate cleaning counts within one full cycle period\n            std::vector<long long> cycle_counts_one_period(N, 0);\n            for (int i = cycle_start_idx; i <= week_idx; ++i) {\n                cycle_counts_one_period[path_cleaners[i]]++;\n            }\n\n            // Step 3: Distribute remaining weeks using the cycle counts\n            // Total weeks that need to be covered by the cycle from cycle_start_idx until L\n            long long remaining_weeks_to_fill = L - cycle_start_idx;\n            \n            if (cycle_length > 0) { // Safety check to prevent division by zero\n                long long num_full_cycles = remaining_weeks_to_fill / cycle_length;\n                for (int i = 0; i < N; ++i) {\n                    actual_final_counts[i] += num_full_cycles * cycle_counts_one_period[i];\n                }\n                // Add remaining part of a partial cycle at the very end\n                long long remaining_in_partial_cycle = remaining_weeks_to_fill % cycle_length;\n                for (int i = 0; i < remaining_in_partial_cycle; ++i) {\n                    actual_final_counts[path_cleaners[cycle_start_idx + i]]++;\n                }\n            }\n            \n            // All L weeks have been accounted for, so we can exit the simulation early\n            goto end_simulation; \n        }\n        \n        // If no cycle detected yet, record the current state and its week index\n        visited_states[state_key] = week_idx;\n\n        // Determine the next cleaner based on current cleaner's count parity and assignments\n        if (counts_in_sim[cleaner_for_this_week] % 2 != 0) { // If total count for 'cleaner_for_this_week' is odd\n            current_cleaner = assignments[cleaner_for_this_week].first;\n        } else { // If total count for 'cleaner_for_this_week' is even\n            current_cleaner = assignments[cleaner_for_this_week].second;\n        }\n    }\n\n    // This block is reached if the loop completes without finding a cycle.\n    // This happens if L is small enough that no state repeats, or if L happens to be exactly the pre-cycle length.\n    // In this case, 'path_cleaners' contains the cleaners for all L weeks, and their counts\n    // haven't been added to 'actual_final_counts' yet.\n    for (int i = 0; i < L; ++i) {\n        actual_final_counts[path_cleaners[i]]++;\n    }\n\nend_simulation:; // Label for goto\n\n    // Calculate the total absolute error\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += std::abs(actual_final_counts[i] - T[i]);\n    }\n    return error;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_val, L_val; \n    std::cin >> N_val >> L_val;\n\n    std::vector<int> T(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        std::cin >> T[i];\n    }\n\n    // Prepare a discrete distribution for selecting employees based on target counts\n    // Used *only* for initial assignment.\n    std::vector<double> T_weights(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        T_weights[i] = static_cast<double>(T[i] + 1); // Add 1 to ensure positive weights\n    }\n    std::discrete_distribution<int> weighted_dist_by_T(T_weights.begin(), T_weights.end());\n\n    // Uniform distribution for picking any employee ID [0, N-1]\n    // This will be used for SA mutations.\n    std::uniform_int_distribution<int> dist_N(0, N_val - 1); \n\n    std::vector<std::pair<int, int>> best_assignments(N_val);\n    std::vector<std::pair<int, int>> current_assignments(N_val);\n\n    // Initial random assignments for a_i and b_i using the weighted distribution\n    // This provides a potentially better starting point for SA.\n    for (int i = 0; i < N_val; ++i) {\n        current_assignments[i] = {weighted_dist_by_T(rng), weighted_dist_by_T(rng)};\n    }\n\n    // Calculate initial state error\n    long long current_error = calculate_error(N_val, L_val, T, current_assignments);\n    long long best_error = current_error;\n    best_assignments = current_assignments; // Deep copy the initial best state\n\n    // Simulated Annealing parameters\n    // Slightly increased start_temp for broader initial exploration.\n    double start_temp = 3000.0; // Adjusted\n    double end_temp = 0.01;     // Kept\n    // This iteration_limit determines the shape of the temperature curve.\n    // It should be roughly the number of iterations expected to run in total.\n    long long iteration_limit = 10000000; \n    \n    auto start_time = std::chrono::high_resolution_clock::now();\n    long long time_limit_ms = 1950; // Allot 1.95 seconds for computation\n\n    // Main Simulated Annealing loop\n    for (long long iter = 0; iter < iteration_limit; ++iter) {\n        // Check elapsed time to ensure compliance with the time limit\n        auto current_time = std::chrono::high_resolution_clock::now();\n        long long elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break; // Exit SA loop if time limit approached\n        }\n\n        // Geometric cooling schedule for temperature\n        double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / iteration_limit);\n        \n        // Generate a neighbor state by modifying one a_i or b_i\n        int employee_to_change = dist_N(rng); // Randomly pick an employee whose rule (a_i, b_i) to change\n        bool change_first_val = (rng() % 2 == 0); // Randomly decide whether to change a_i (true) or b_i (false)\n        \n        // Store the original value to allow reverting if the move is not accepted\n        int original_val_to_revert;\n        if (change_first_val) {\n            original_val_to_revert = current_assignments[employee_to_change].first;\n            // Propose a new value for a_i using uniform distribution (for SA mutations)\n            current_assignments[employee_to_change].first = dist_N(rng); \n        } else {\n            original_val_to_revert = current_assignments[employee_to_change].second;\n            // Propose a new value for b_i using uniform distribution (for SA mutations)\n            current_assignments[employee_to_change].second = dist_N(rng); \n        }\n\n        // Calculate the error for the new (modified) assignments\n        long long next_error = calculate_error(N_val, L_val, T, current_assignments);\n\n        if (next_error < current_error) {\n            // If the new solution is better, always accept it\n            current_error = next_error;\n            if (next_error < best_error) {\n                // If it's the best solution found so far, update best_assignments\n                best_error = next_error;\n                best_assignments = current_assignments; // Deep copy\n            }\n        } else {\n            // If the new solution is worse, accept it with a certain probability\n            double probability = std::exp(-(static_cast<double>(next_error - current_error)) / temp);\n            std::uniform_real_distribution<double> dist_real(0.0, 1.0); // For generating a random probability [0.0, 1.0)\n            if (dist_real(rng) < probability) {\n                current_error = next_error; // Accept the worse solution\n            } else {\n                // If the worse solution is not accepted, revert the change to the original value\n                if (change_first_val) {\n                    current_assignments[employee_to_change].first = original_val_to_revert;\n                } else {\n                    current_assignments[employee_to_change].second = original_val_to_revert;\n                }\n            }\n        }\n    }\n\n    // Output the best assignments found after the SA process\n    for (int i = 0; i < N_val; ++i) {\n        std::cout << best_assignments[i].first << \" \" << best_assignments[i].second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::sqrt, std::floor, std::ceil, std::max\n\n// Structure to hold city bounding box\nstruct Rect {\n    int lx, rx, ly, ry;\n};\n\n// Structure to hold city data\nstruct City {\n    int id;\n    int cx, cy; // Center coordinates, using integer division for consistency with sample\n    unsigned int z_order_val; // Z-order curve value for sorting\n    Rect bounds;\n};\n\n// Disjoint Set Union structure for Kruskal's algorithm\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) return i;\n        return parent[i] = find(parent[i]);\n    }\n    bool 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            return true;\n        }\n        return false;\n    }\n};\n\n// Edge structure for Kruskal's\nstruct Edge {\n    int u, v;\n    std::pair<int, long long> weight; // rank (0=queried, 1=estimated), estimated_dist_sq\n};\n\n// Helper for Z-order curve: bit interleaving (Morton code)\n// Optimized for 16-bit inputs (max value 65535) resulting in 32-bit output.\n// Coordinates up to 10000 fit into 14 bits.\n// For example, an input of 10000 will have its 14 bits interleaved into a 32-bit output.\nunsigned int morton_encode(unsigned int x, unsigned int y) {\n    x = (x | (x << 8)) & 0x00FF00FF;\n    x = (x | (x << 4)) & 0x0F0F0F0F;\n    x = (x | (x << 2)) & 0x33333333;\n    x = (x | (x << 1)) & 0x55555555;\n    y = (y | (y << 8)) & 0x00FF00FF;\n    y = (y | (y << 4)) & 0x0F0F0F0F;\n    y = (y | (y << 2)) & 0x33333333;\n    y = (y | (y << 1)) & 0x55555555;\n    return x | (y << 1);\n}\n\n// Functions to calculate min/max squared distance components along one axis\nlong long calc_min_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff;\n    if (r1_max < r2_min) { // Rect 1 is entirely before Rect 2 on this axis\n        diff = r2_min - r1_max;\n    } else if (r2_max < r1_min) { // Rect 2 is entirely before Rect 1 on this axis\n        diff = r1_min - r2_max;\n    } else { // Rectangles overlap on this axis\n        diff = 0;\n    }\n    return diff * diff;\n}\n\nlong long calc_max_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff1 = (long long)r1_max - r2_min;\n    long long diff2 = (long long)r2_max - r1_min;\n    return std::max(diff1 * diff1, diff2 * diff2);\n}\n\n// Function to calculate estimated squared distance using min/max bounds range midpoint\nlong long estimated_dist_mid_range_sq(int u_id, int v_id, const std::vector<City>& cities_data) {\n    const Rect& r_u = cities_data[u_id].bounds;\n    const Rect& r_v = cities_data[v_id].bounds;\n\n    long long min_dx_sq = calc_min_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long min_dy_sq = calc_min_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_min_sq = min_dx_sq + min_dy_sq;\n\n    long long max_dx_sq = calc_max_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long max_dy_sq = calc_max_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_max_sq = max_dx_sq + max_dy_sq;\n\n    // Use the midpoint of the possible squared distance range\n    return (d_min_sq + d_max_sq) / 2;\n}\n\n\n// Function to make a query to the judge\nstd::vector<std::pair<int, int>> make_query(const std::vector<int>& c_subset) {\n    std::cout << \"? \" << c_subset.size();\n    for (int city_id : c_subset) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl; // Flush!\n\n    std::vector<std::pair<int, int>> result;\n    result.reserve(c_subset.size() - 1);\n    for (size_t i = 0; i < c_subset.size() - 1; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        if (u > v) std::swap(u, v); // Ensure canonical form (u < v)\n        result.push_back({u, v});\n    }\n    return result;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL); // Untie cin and cout for faster I/O, though flushing is still needed for queries\n\n    int N, M, Q, L_actual, W;\n    std::cin >> N >> M >> Q >> L_actual >> 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_data(N);\n    for (int i = 0; i < N; ++i) {\n        cities_data[i].id = i;\n        std::cin >> cities_data[i].bounds.lx >> cities_data[i].bounds.rx >> cities_data[i].bounds.ly >> cities_data[i].bounds.ry;\n        \n        // Use center for Z-order calculation as well\n        cities_data[i].cx = (cities_data[i].bounds.lx + cities_data[i].bounds.rx) / 2;\n        cities_data[i].cy = (cities_data[i].bounds.ly + cities_data[i].bounds.ry) / 2;\n        cities_data[i].z_order_val = morton_encode(cities_data[i].cx, cities_data[i].cy);\n    }\n\n    // 1. Initial Grouping: Sort by Z-order curve value\n    std::vector<int> p(N); // p stores sorted city IDs\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return cities_data[i].z_order_val < cities_data[j].z_order_val;\n    });\n\n    std::vector<std::vector<int>> tentative_groups(M);\n    int current_city_idx_p = 0;\n    for (int k = 0; k < M; ++k) {\n        tentative_groups[k].reserve(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            tentative_groups[k].push_back(p[current_city_idx_p++]);\n        }\n    }\n\n    // 2. Query Phase\n    std::set<std::pair<int, int>> queried_edges;\n    int Q_rem = Q;\n\n    // Phase 1: Query small groups entirely\n    for (int k = 0; k < M; ++k) {\n        if (G[k] >= 2 && G[k] <= L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k]; // Use const ref\n            std::vector<std::pair<int, int>> res_edges = make_query(current_group);\n            for (auto edge : res_edges) {\n                queried_edges.insert(edge);\n            }\n            Q_rem--;\n        }\n    }\n\n    // Phase 2: Query large groups with adaptive step_size\n    long long num_chunks_to_query_if_step1 = 0; // Total count of (G_k - L_actual + 1) for large groups\n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual) { // This condition ensures G[k] >= L_actual + 1, so G[k] - L_actual >= 1\n            num_chunks_to_query_if_step1 += (G[k] - L_actual + 1);\n        }\n    }\n\n    int step_size = 1;\n    if (Q_rem > 0 && num_chunks_to_query_if_step1 > 0) {\n        // Calculate step_size to distribute Q_rem queries among the total chunks\n        step_size = static_cast<int>(std::ceil(static_cast<double>(num_chunks_to_query_if_step1) / Q_rem));\n        step_size = std::max(1, step_size); // Ensure step_size is at least 1\n    } else {\n        step_size = N + 1; // Effectively skip this phase if no queries left or no large groups to query\n    }\n    \n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k];\n            int last_queried_start = -1; // To track the starting index of the last query made\n            \n            for (int i = 0; i <= (int)current_group.size() - L_actual; i += step_size) {\n                if (Q_rem <= 0) break;\n                \n                std::vector<int> c_subset;\n                c_subset.reserve(L_actual);\n                for (int j = 0; j < L_actual; ++j) {\n                    c_subset.push_back(current_group[i+j]);\n                }\n                \n                std::vector<std::pair<int, int>> res_edges = make_query(c_subset);\n                for (auto edge : res_edges) {\n                    queried_edges.insert(edge);\n                }\n                Q_rem--;\n                last_queried_start = i;\n            }\n\n            // Handle cities at the end of the group that might not have been fully covered\n            // Query the last L_actual cities if the last possible window was not queried\n            // and we still have queries left.\n            if (Q_rem > 0) { // Check Q_rem again\n                int ideal_last_start_idx = (int)current_group.size() - L_actual;\n                if (ideal_last_start_idx >= 0 && last_queried_start != ideal_last_start_idx) { // Ensure ideal_last_start_idx is valid\n                    std::vector<int> c_subset_end;\n                    c_subset_end.reserve(L_actual);\n                    for(int j = ideal_last_start_idx; j < current_group.size(); ++j) {\n                        c_subset_end.push_back(current_group[j]);\n                    }\n                    if (c_subset_end.size() >= 2) { // Ensure minimum size for query\n                        std::vector<std::pair<int, int>> res_edges = make_query(c_subset_end);\n                        for (auto edge : res_edges) {\n                            queried_edges.insert(edge);\n                        }\n                        Q_rem--;\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Output Phase\n    std::cout << \"!\" << std::endl;\n\n    for (int k = 0; k < M; ++k) {\n        // Output cities in group k\n        for (int i = 0; i < G[k]; ++i) {\n            std::cout << tentative_groups[k][i] << (i == G[k] - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] == 1) { // A single city group needs no roads\n            continue;\n        }\n\n        // Prepare edges for MST\n        std::vector<Edge> edges_for_mst;\n        const std::vector<int>& current_group = tentative_groups[k];\n        \n        // Create all possible edges within the group\n        for (size_t i = 0; i < current_group.size(); ++i) {\n            for (size_t j = i + 1; j < current_group.size(); ++j) {\n                int u = current_group[i];\n                int v = current_group[j];\n                \n                // Ensure u < v for canonical form (matches queried_edges)\n                if (u > v) std::swap(u, v); \n                \n                int rank = 1; // 1 for estimated, 0 for queried\n                if (queried_edges.count({u, v})) {\n                    rank = 0;\n                }\n                \n                long long dist_sq = estimated_dist_mid_range_sq(u, v, cities_data); // Use new estimation\n                edges_for_mst.push_back({u, v, {rank, dist_sq}});\n            }\n        }\n\n        // Sort edges\n        std::sort(edges_for_mst.begin(), edges_for_mst.end(), [](const Edge& a, const Edge& b) {\n            if (a.weight.first != b.weight.first) {\n                return a.weight.first < b.weight.first;\n            }\n            // Tie-break with estimated squared distance\n            if (a.weight.second != b.weight.second) {\n                return a.weight.second < b.weight.second;\n            }\n            // Final tie-break with lexicographical order of cities\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Run Kruskal's\n        DSU dsu(N); // Initialize DSU for all N cities for simplicity\n        std::vector<std::pair<int, int>> mst_output_edges;\n        int edges_count = 0;\n        for (const auto& edge : edges_for_mst) {\n            if (edges_count == G[k] - 1) break; // Found enough edges\n            \n            if (dsu.unite(edge.u, edge.v)) {\n                mst_output_edges.push_back({edge.u, edge.v});\n                edges_count++;\n            }\n        }\n\n        // Output MST edges (lexicographically within group, as required by problem)\n        std::sort(mst_output_edges.begin(), mst_output_edges.end());\n        for (const auto& edge : mst_output_edges) {\n            std::cout << edge.first << \" \" << edge.second << std::endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int N_SIZE = 20;\n\n// Directions for movement and alter actions\n// Corresponding to U, D, L, R\nint DR[] = {-1, 1, 0, 0}; \nint DC[] = {0, 0, -1, 1}; \nchar DIR_CHARS[] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int r, c;\n    int cost;\n\n    // Custom comparator for priority queue (min-heap)\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Enum to categorize the type of action that led to a state\nenum ActionType {\n    MOVE,\n    MOVE_REMOVE_BLOCK,    // Move into a square that was blocked, removing the block first\n    SLIDE_WALL,           // Slide, stopping because of an N x N boundary wall\n    SLIDE_EXISTING_BLOCK  // Slide, stopping because of an existing block\n};\n\n// Information to reconstruct the path\nstruct ParentInfo {\n    int pr, pc; // previous row, previous column\n    ActionType type;\n    char dir_char; // direction character for the action (U, D, L, R)\n    int br, bc;   // block row, block column (relevant for SLIDE_EXISTING_BLOCK or MOVE_REMOVE_BLOCK)\n                  // For SLIDE_WALL, it's (-1,-1).\n};\n\n// Global board state, tracks currently existing blocks\nset<pair<int, int>> current_blocks;\n\n// Helper function to check if coordinates are within grid bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_SIZE && c >= 0 && c < N_SIZE;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M; // N will be 20, M will be 40 as per problem statement\n    cin >> N >> M;\n\n    vector<pair<int, int>> targets(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> targets[k].first >> targets[k].second;\n    }\n\n    vector<pair<char, char>> all_actions; // Stores the final sequence of actions to output\n\n    int current_r = targets[0].first;\n    int current_c = targets[0].second;\n\n    // Iterate through each target segment (from current_pos to next target)\n    for (int k = 0; k < M - 1; ++k) {\n        int start_r = current_r;\n        int start_c = current_c;\n        int target_r = targets[k+1].first;\n        int target_c = targets[k+1].second;\n\n        // Dijkstra's algorithm for shortest path in terms of turns\n        vector<vector<int>> dist(N, vector<int>(N, INF));\n        vector<vector<ParentInfo>> parent(N, vector<ParentInfo>(N)); \n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[start_r][start_c] = 0;\n        pq.push({start_r, start_c, 0});\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n            int d = current.cost;\n\n            // If we found a shorter path previously, skip this one\n            if (d > dist[r][c]) {\n                continue;\n            }\n            // If we reached the target, we found the shortest path for this segment\n            if (r == target_r && c == target_c) {\n                break; \n            }\n\n            // --- Explore possible Move actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                if (!is_valid(nr, nc)) continue; // Check bounds\n\n                int cost = 0;\n                ActionType type;\n                if (current_blocks.count({nr, nc})) {\n                    // Moving onto a square that currently has a block.\n                    // This costs 1 for Alter (to remove the block) + 1 for Move. Total 2 turns.\n                    cost = 2;\n                    type = MOVE_REMOVE_BLOCK;\n                } else {\n                    // Moving onto an empty square. Costs 1 for Move.\n                    cost = 1;\n                    type = MOVE;\n                }\n\n                if (d + cost < dist[nr][nc]) {\n                    dist[nr][nc] = d + cost;\n                    parent[nr][nc] = {r, c, type, dir_char, nr, nc}; // br, bc store coord of block removed for MOVE_REMOVE_BLOCK\n                    pq.push({nr, nc, d + cost});\n                }\n            }\n\n            // --- Explore possible Slide actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int dr = DR[i];\n                int dc = DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                int current_slide_r = r;\n                int current_slide_c = c;\n                \n                // This loop finds all possible valid stopping points for a slide in a given direction.\n                while (true) {\n                    // Tentatively advance one step to find the next square the slide *could* reach.\n                    int next_r = current_slide_r + dr;\n                    int next_c = current_slide_c + dc;\n\n                    // If the next square is out of bounds or blocked by an existing block,\n                    // we cannot slide *into* it. Thus, current_slide_r,c is a potential stopping point.\n                    if (!is_valid(next_r, next_c) || current_blocks.count({next_r, next_c})) {\n                        // We can only stop at current_slide_r,c if we've actually moved.\n                        // If current_slide_r,c is still (r,c), it means we can't even slide one square.\n                        if (current_slide_r == r && current_slide_c == c) {\n                             break; // Cannot slide even one square, no valid stops in this direction.\n                        }\n\n                        // current_slide_r,c is a valid stopping square.\n                        int stop_r = current_slide_r;\n                        int stop_c = current_slide_c;\n                        \n                        // The \"stopper\" is either the boundary or the existing block at (next_r, next_c)\n                        int stopper_block_r = next_r;\n                        int stopper_block_c = next_c;\n\n                        int slide_cost = 1; // All valid slides cost 1 turn\n                        ActionType type;\n\n                        if (!is_valid(stopper_block_r, stopper_block_c)) {\n                            type = SLIDE_WALL;\n                            stopper_block_r = -1; stopper_block_c = -1; // Sentinel\n                        } else { // It must be an existing block at (stopper_block_r, stopper_block_c)\n                            type = SLIDE_EXISTING_BLOCK;\n                        }\n\n                        if (d + slide_cost < dist[stop_r][stop_c]) {\n                            dist[stop_r][stop_c] = d + slide_cost;\n                            parent[stop_r][stop_c] = {r, c, type, dir_char, stopper_block_r, stopper_block_c};\n                            pq.push({stop_r, stop_c, d + slide_cost});\n                        }\n                        break; // This slide path ends here, either at boundary or existing block\n                    }\n\n                    // If next_r,c is valid and not blocked, we slide past current_slide_r,c.\n                    // So, current_slide_r,c itself cannot be a stopping point (because nothing stops us there).\n                    // Update current_slide_r,c to next_r,c and continue to find further stops.\n                    current_slide_r = next_r;\n                    current_slide_c = next_c;\n                }\n            }\n        }\n\n        // --- Path reconstruction and action recording ---\n        vector<tuple<int,int,ActionType,char,int,int>> path_segments_info;\n        int curr_r = target_r;\n        int curr_c = target_c;\n\n        // Traverse parent pointers backwards from target to start, storing segment info.\n        // This gives actions in reverse order of execution.\n        while (curr_r != start_r || curr_c != start_c) {\n            ParentInfo p = parent[curr_r][curr_c];\n            path_segments_info.emplace_back(p.pr, p.pc, p.type, p.dir_char, p.br, p.bc);\n            curr_r = p.pr;\n            curr_c = p.pc;\n        }\n        // Reverse to get actions in the correct execution order.\n        reverse(path_segments_info.begin(), path_segments_info.end()); \n\n        // Process each action segment in forward order and update global blocks and the action list\n        for (const auto& info : path_segments_info) {\n            int pr, pc, br, bc;\n            ActionType type;\n            char dir_char;\n            tie(pr, pc, type, dir_char, br, bc) = info;\n\n            if (type == MOVE) {\n                all_actions.emplace_back('M', dir_char);\n            } else if (type == MOVE_REMOVE_BLOCK) {\n                all_actions.emplace_back('A', dir_char); // First Alter to remove block at (br,bc)\n                current_blocks.erase({br, bc});           // Update global block state (remove it)\n                all_actions.emplace_back('M', dir_char); // Then Move\n            } else if (type == SLIDE_WALL || type == SLIDE_EXISTING_BLOCK) {\n                // No Alter action needed for these slide types, just the Slide itself.\n                // The block for SLIDE_EXISTING_BLOCK is already there and isn't toggled by us.\n                all_actions.emplace_back('S', dir_char);\n            }\n        }\n\n        // Update current player position for the next segment\n        current_r = target_r;\n        current_c = target_c;\n    }\n    \n    // Output all recorded actions\n    for (const auto& action : all_actions) {\n        cout << action.first << \" \" << action.second << endl;\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // for std::iota\n\n// Global random number generator (seeded once in main)\n// Used to seed per-run RNGs for multi-start.\nstd::mt19937_64 global_mt_rand(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Company data structure\nstruct Company {\n    int id;\n    int x, y, r; // desired location (cell x,y) and desired area\n};\n\n// Rectangle structure\nstruct Rect {\n    int x1, y1, x2, y2; // [x1, x2) x [y1, y2)\n    long long area() const {\n        return (long long)(x2 - x1) * (y2 - y1);\n    }\n    // Check if point (px, py) is contained (for 0.5 offset points, this means cell (px, py) is contained)\n    bool contains(int px, int py) const {\n        return x1 <= px && px < x2 && y1 <= py && py < y2;\n    }\n};\n\n// Node in the D&C tree\nstruct Node {\n    Rect rect; // The bounding box for this node\n    bool is_leaf;\n    int company_id; // Valid if is_leaf is true, stores original company index\n    bool is_vertical_cut; // True for vertical, false for horizontal\n    int cut_coord; // The coordinate of the cut\n    std::vector<int> company_indices; // Indices of companies that fall into this node's rectangle\n    int parent_idx; // Index to parent node\n    int left_child_idx; // Index to left/bottom child\n    int right_child_idx; // Index to right/top child\n\n    // Added fields for SA optimization: min/max coordinates of companies in children subtrees\n    int left_comp_min_x, left_comp_max_x;\n    int left_comp_min_y, left_comp_max_y;\n    int right_comp_min_x, right_comp_max_x;\n    int right_comp_min_y, right_comp_max_y;\n\n    Node(Rect r, bool leaf, int id, const std::vector<int>& indices)\n        : rect(r), is_leaf(leaf), company_id(id), is_vertical_cut(false), cut_coord(-1),\n          company_indices(indices), parent_idx(-1), left_child_idx(-1), right_child_idx(-1),\n          left_comp_min_x(10001), left_comp_max_x(-1), left_comp_min_y(10001), left_comp_max_y(-1),\n          right_comp_min_x(10001), right_comp_max_x(-1), right_comp_min_y(10001), right_comp_max_y(-1) {}\n};\n\nstd::vector<Company> companies_data_global; // Store company data globally\nint N_global; // Store N globally\n\n// These vectors will be local to a single run. They are declared globally to avoid reallocations\n// on the stack for large N, but conceptually managed per-run.\nstd::vector<Rect> current_final_ad_rects;\nstd::vector<Node> current_tree_nodes;\nstd::vector<int> current_internal_node_indices;\n\n// Calculate satisfaction for a single company\ndouble calculate_satisfaction(const Company& company, const Rect& ad_rect) {\n    if (!ad_rect.contains(company.x, company.y)) {\n        return 0.0;\n    }\n    long long s_i = ad_rect.area();\n    long long r_i = company.r;\n    if (s_i == 0) return 0.0; // Area must be positive as per problem statement\n    double ratio = (double)std::min(r_i, s_i) / std::max(r_i, s_i);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Helper function to collect company IDs in a subtree\nvoid get_companies_in_subtree(int node_idx, std::vector<int>& company_ids_in_subtree) {\n    const Node& node = current_tree_nodes[node_idx];\n    if (node.is_leaf) {\n        if (node.company_id != -1) {\n            company_ids_in_subtree.push_back(node.company_id);\n        }\n        return;\n    }\n    get_companies_in_subtree(node.left_child_idx, company_ids_in_subtree);\n    get_companies_in_subtree(node.right_child_idx, company_ids_in_subtree);\n}\n\n// Recursive function to build the D&C tree and determine initial rectangle placements\nvoid build_tree_and_solve(int node_idx, int x1, int y1, int x2, int y2, std::vector<int>&& indices, std::mt19937_64& rng) {\n    current_tree_nodes[node_idx].rect = {x1, y1, x2, y2};\n    current_tree_nodes[node_idx].company_indices = indices; // Store indices for SA bounds calculation later\n\n    if (indices.empty()) {\n        current_tree_nodes[node_idx].is_leaf = true; // Mark as leaf, no company\n        return;\n    }\n    if (indices.size() == 1) {\n        current_tree_nodes[node_idx].is_leaf = true;\n        current_tree_nodes[node_idx].company_id = indices[0];\n        current_final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n    \n    // This is an internal node\n    current_internal_node_indices.push_back(node_idx);\n\n    int best_v_cut_coord = -1;\n    long long min_v_area_diff = -1;\n    int best_v_split_point_idx = -1;\n\n    int best_h_cut_coord = -1;\n    long long min_h_area_diff = -1;\n    int best_h_split_point_idx = -1;\n\n    long long total_r_sum = 0;\n    for (int idx : indices) total_r_sum += companies_data_global[idx].r;\n\n    // Try Vertical Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data_global[i].x < companies_data_global[j].x;\n    });\n    long long current_left_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_left_r_sum += companies_data_global[indices[k]].r;\n        int max_x_left_group = companies_data_global[indices[k]].x;\n        int min_x_right_group = companies_data_global[indices[k+1]].x;\n        \n        // The cut coordinate `C` must satisfy: max_x_left_group < C <= min_x_right_group\n        // And also `x1 < C < x2`\n        int candidate_cut_coord = max_x_left_group + 1;\n        \n        if (candidate_cut_coord > min_x_right_group || candidate_cut_coord < x1 + 1 || candidate_cut_coord > x2 - 1) {\n             continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_left_r_sum - (total_r_sum - current_left_r_sum));\n        if (best_v_cut_coord == -1 || diff < min_v_area_diff) {\n            min_v_area_diff = diff;\n            best_v_cut_coord = candidate_cut_coord;\n            best_v_split_point_idx = k + 1;\n        }\n    }\n\n    // Try Horizontal Cut\n    std::sort(indices.begin(), indices.end(), [](int i, int j) {\n        return companies_data_global[i].y < companies_data_global[j].y;\n    });\n    long long current_bottom_r_sum = 0;\n    for (int k = 0; k < indices.size() - 1; ++k) {\n        current_bottom_r_sum += companies_data_global[indices[k]].r;\n        int max_y_bottom_group = companies_data_global[indices[k]].y;\n        int min_y_top_group = companies_data_global[indices[k+1]].y;\n        \n        int candidate_cut_coord = max_y_bottom_group + 1;\n\n        if (candidate_cut_coord > min_y_top_group || candidate_cut_coord < y1 + 1 || candidate_cut_coord > y2 - 1) {\n            continue; // Invalid cut position\n        }\n\n        long long diff = std::abs(current_bottom_r_sum - (total_r_sum - current_bottom_r_sum));\n        if (best_h_cut_coord == -1 || diff < min_h_area_diff) {\n            min_h_area_diff = diff;\n            best_h_cut_coord = candidate_cut_coord;\n            best_h_split_point_idx = k + 1;\n        }\n    }\n    \n    // Choose the best cut among vertical and horizontal\n    int final_cut_coord = -1;\n    int final_split_point_idx = -1;\n    bool is_vertical_cut_chosen = false;\n\n    // Random choice if area differences are equal for v/h cuts\n    std::uniform_int_distribution<int> dist_01_int(0, 1);\n\n    if (best_v_cut_coord != -1 && best_h_cut_coord != -1) {\n        if (min_v_area_diff < min_h_area_diff) {\n            final_cut_coord = best_v_cut_coord;\n            final_split_point_idx = best_v_split_point_idx;\n            is_vertical_cut_chosen = true;\n        } else if (min_h_area_diff < min_v_area_diff) {\n            final_cut_coord = best_h_cut_coord;\n            final_split_point_idx = best_h_split_point_idx;\n            is_vertical_cut_chosen = false;\n        } else { // min_v_area_diff == min_h_area_diff: random choice\n            if (dist_01_int(rng) == 0) { // 50/50 chance\n                final_cut_coord = best_v_cut_coord;\n                final_split_point_idx = best_v_split_point_idx;\n                is_vertical_cut_chosen = true;\n            } else {\n                final_cut_coord = best_h_cut_coord;\n                final_split_point_idx = best_h_split_point_idx;\n                is_vertical_cut_chosen = false;\n            }\n        }\n    } else if (best_v_cut_coord != -1) {\n        final_cut_coord = best_v_cut_coord;\n        final_split_point_idx = best_v_split_point_idx;\n        is_vertical_cut_chosen = true;\n    } else if (best_h_cut_coord != -1) {\n        final_cut_coord = best_h_cut_coord;\n        final_split_point_idx = best_h_split_point_idx;\n        is_vertical_cut_chosen = false;\n    } else {\n        // Fallback: If no valid cut is found, assign the entire region to the first company.\n        // This should only happen for very small regions or degenerate point distributions\n        // where it's impossible to make a valid cut for multiple companies.\n        current_tree_nodes[node_idx].is_leaf = true; \n        current_tree_nodes[node_idx].company_id = indices[0];\n        current_final_ad_rects[indices[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    current_tree_nodes[node_idx].cut_coord = final_cut_coord;\n    current_tree_nodes[node_idx].is_vertical_cut = is_vertical_cut_chosen;\n\n    // Re-sort indices based on the chosen cut dimension for partitioning\n    if (is_vertical_cut_chosen) {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data_global[i].x < companies_data_global[j].x;\n        });\n    } else {\n        std::sort(indices.begin(), indices.end(), [](int i, int j) {\n            return companies_data_global[i].y < companies_data_global[j].y;\n        });\n    }\n\n    std::vector<int> left_indices(indices.begin(), indices.begin() + final_split_point_idx);\n    std::vector<int> right_indices(indices.begin() + final_split_point_idx, indices.end());\n\n    current_tree_nodes[node_idx].left_child_idx = current_tree_nodes.size();\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    current_tree_nodes.back().parent_idx = node_idx;\n\n    current_tree_nodes[node_idx].right_child_idx = current_tree_nodes.size();\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{});\n    current_tree_nodes.back().parent_idx = node_idx;\n\n    if (is_vertical_cut_chosen) {\n        build_tree_and_solve(current_tree_nodes[node_idx].left_child_idx, x1, y1, final_cut_coord, y2, std::move(left_indices), rng);\n        build_tree_and_solve(current_tree_nodes[node_idx].right_child_idx, final_cut_coord, y1, x2, y2, std::move(right_indices), rng);\n    } else { // Horizontal cut\n        build_tree_and_solve(current_tree_nodes[node_idx].left_child_idx, x1, y1, x2, final_cut_coord, std::move(left_indices), rng); // 'left' means bottom here\n        build_tree_and_solve(current_tree_nodes[node_idx].right_child_idx, x1, final_cut_coord, x2, y2, std::move(right_indices), rng); // 'right' means top here\n    }\n}\n\n// Function to calculate and store min/max company coordinates for children\nvoid calculate_child_company_bounds_recursive(int node_idx) {\n    Node& node = current_tree_nodes[node_idx];\n\n    if (node.is_leaf) {\n        return;\n    }\n\n    // Recursively call for children first (post-order traversal)\n    calculate_child_company_bounds_recursive(node.left_child_idx);\n    calculate_child_company_bounds_recursive(node.right_child_idx);\n\n    // Calculate bounds for left child's companies\n    int current_min_x_left = 10001, current_max_x_left = -1;\n    int current_min_y_left = 10001, current_max_y_left = -1;\n    Node& left_child_node = current_tree_nodes[node.left_child_idx];\n    if (left_child_node.is_leaf && left_child_node.company_id != -1) { // It's a leaf and contains a company\n        current_min_x_left = companies_data_global[left_child_node.company_id].x;\n        current_max_x_left = companies_data_global[left_child_node.company_id].x;\n        current_min_y_left = companies_data_global[left_child_node.company_id].y;\n        current_max_y_left = companies_data_global[left_child_node.company_id].y;\n    } else if (!left_child_node.company_indices.empty()){ // It's an internal node or a leaf that split an empty region\n        for (int company_idx : left_child_node.company_indices) {\n            current_min_x_left = std::min(current_min_x_left, companies_data_global[company_idx].x);\n            current_max_x_left = std::max(current_max_x_left, companies_data_global[company_idx].x);\n            current_min_y_left = std::min(current_min_y_left, companies_data_global[company_idx].y);\n            current_max_y_left = std::max(current_max_y_left, companies_data_global[company_idx].y);\n        }\n    }\n    node.left_comp_min_x = current_min_x_left;\n    node.left_comp_max_x = current_max_x_left;\n    node.left_comp_min_y = current_min_y_left;\n    node.left_comp_max_y = current_max_y_left;\n\n    // Calculate bounds for right child's companies\n    int current_min_x_right = 10001, current_max_x_right = -1;\n    int current_min_y_right = 10001, current_max_y_right = -1;\n    Node& right_child_node = current_tree_nodes[node.right_child_idx];\n    if (right_child_node.is_leaf && right_child_node.company_id != -1) {\n        current_min_x_right = companies_data_global[right_child_node.company_id].x;\n        current_max_x_right = companies_data_global[right_child_node.company_id].x;\n        current_min_y_right = companies_data_global[right_child_node.company_id].y;\n        current_max_y_right = companies_data_global[right_child_node.company_id].y;\n    } else if (!right_child_node.company_indices.empty()){\n        for (int company_idx : right_child_node.company_indices) {\n            current_min_x_right = std::min(current_min_x_right, companies_data_global[company_idx].x);\n            current_max_x_right = std::max(current_max_x_right, companies_data_global[company_idx].x);\n            current_min_y_right = std::min(current_min_y_right, companies_data_global[company_idx].y);\n            current_max_y_right = std::max(current_max_y_right, companies_data_global[company_idx].y);\n        }\n    }\n    node.right_comp_min_x = current_min_x_right;\n    node.right_comp_max_x = current_max_x_right;\n    node.right_comp_min_y = current_min_y_right;\n    node.right_comp_max_y = current_max_y_right;\n}\n\n// Function to update rectangles in a subtree after a cut coordinate changes\nvoid update_subtree_rects(int node_idx, int x1, int y1, int x2, int y2) {\n    Node& node = current_tree_nodes[node_idx];\n    node.rect = {x1, y1, x2, y2};\n\n    if (node.is_leaf) {\n        if (node.company_id != -1) { \n            current_final_ad_rects[node.company_id] = {x1, y1, x2, y2};\n        }\n        return;\n    }\n\n    if (node.is_vertical_cut) {\n        update_subtree_rects(node.left_child_idx, x1, y1, node.cut_coord, y2);\n        update_subtree_rects(node.right_child_idx, node.cut_coord, y1, x2, y2);\n    } else { // Horizontal cut\n        update_subtree_rects(node.left_child_idx, x1, y1, x2, node.cut_coord);\n        update_subtree_rects(node.right_child_idx, x1, node.cut_coord, x2, y2);\n    }\n}\n\nvoid simulated_annealing(double time_limit_ms_per_run, std::mt19937_64& rng) {\n    auto start_time = std::chrono::steady_clock::now();\n    \n    // Calculate initial score once here\n    double current_score = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        current_score += calculate_satisfaction(companies_data_global[i], current_final_ad_rects[i]);\n    }\n\n    double best_score = current_score;\n    std::vector<Rect> best_ad_rects_for_this_run = current_final_ad_rects;\n\n    // SA parameters (tuned values)\n    double T_start = 0.02; // Adjusted (lower) based on analysis for shorter runs\n    double T_end = 1e-9;\n    \n    std::uniform_real_distribution<double> dist_01(0.0, 1.0);\n    \n    // Ensure internal_node_indices is not empty before creating distribution\n    if (current_internal_node_indices.empty()) {\n        return; \n    }\n    std::uniform_int_distribution<int> dist_internal_node_idx(0, current_internal_node_indices.size() - 1);\n\n    while (true) {\n        auto current_time = std::chrono::steady_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms >= time_limit_ms_per_run) {\n            break;\n        }\n\n        // Cooling schedule (exponential)\n        double T = T_start * std::pow(T_end / T_start, elapsed_ms / time_limit_ms_per_run);\n\n        // Pick a random internal node to modify its cut\n        int node_idx_to_modify = current_internal_node_indices[dist_internal_node_idx(rng)];\n        Node& node_to_modify = current_tree_nodes[node_idx_to_modify];\n        \n        // Parent's rect boundaries are stored in node_to_modify.rect\n        int parent_x1 = node_to_modify.rect.x1;\n        int parent_y1 = node_to_modify.rect.y1;\n        int parent_x2 = node_to_modify.rect.x2;\n        int parent_y2 = node_to_modify.rect.y2;\n        \n        int min_cut_coord_bound, max_cut_coord_bound;\n\n        if (node_to_modify.is_vertical_cut) {\n            // Use precomputed bounds\n            int max_x_in_left_subtree = node_to_modify.left_comp_max_x;\n            int min_x_in_right_subtree = node_to_modify.right_comp_min_x;\n            \n            min_cut_coord_bound = std::max(parent_x1 + 1, max_x_in_left_subtree + 1);\n            max_cut_coord_bound = std::min(parent_x2 - 1, min_x_in_right_subtree);\n\n        } else { // Horizontal cut\n            // Use precomputed bounds\n            int max_y_in_bottom_subtree = node_to_modify.left_comp_max_y; // Left child refers to bottom here\n            int min_y_in_top_subtree = node_to_modify.right_comp_min_y;   // Right child refers to top here\n            \n            min_cut_coord_bound = std::max(parent_y1 + 1, max_y_in_bottom_subtree + 1);\n            max_cut_coord_bound = std::min(parent_y2 - 1, min_y_in_top_subtree);\n        }\n\n        if (min_cut_coord_bound > max_cut_coord_bound) {\n            continue; // Cannot move this cut, its position is fixed by point constraints\n        }\n\n        // Store old cut_coord for backtracking\n        int original_cut_coord = node_to_modify.cut_coord;\n        \n        // Generate new cut_coord randomly within valid range\n        std::uniform_int_distribution<int> dist_cut(min_cut_coord_bound, max_cut_coord_bound);\n        node_to_modify.cut_coord = dist_cut(rng);\n        \n        if (original_cut_coord == node_to_modify.cut_coord) { // If random pick same as old, no change\n            continue;\n        }\n\n        // --- Incremental Score Update ---\n        std::vector<int> affected_company_ids;\n        get_companies_in_subtree(node_idx_to_modify, affected_company_ids);\n        \n        double old_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            old_affected_score_sum += calculate_satisfaction(companies_data_global[comp_id], current_final_ad_rects[comp_id]);\n        }\n        \n        // Update rectangles for the subtree\n        update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n        \n        double new_affected_score_sum = 0.0;\n        for (int comp_id : affected_company_ids) {\n            new_affected_score_sum += calculate_satisfaction(companies_data_global[comp_id], current_final_ad_rects[comp_id]);\n        }\n\n        double new_total_score = current_score - old_affected_score_sum + new_affected_score_sum;\n\n        if (new_total_score > current_score || dist_01(rng) < std::exp((new_total_score - current_score) / T)) {\n            // Accept new state\n            current_score = new_total_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ad_rects_for_this_run = current_final_ad_rects;\n            }\n        } else {\n            // Revert to old state\n            node_to_modify.cut_coord = original_cut_coord;\n            // Revert the rectangles in the subtree to their previous state\n            update_subtree_rects(node_idx_to_modify, parent_x1, parent_y1, parent_x2, parent_y2);\n            // current_score remains unchanged\n        }\n    }\n    \n    current_final_ad_rects = best_ad_rects_for_this_run; // Save the best rectangles found in this run\n}\n\n// Function to perform a single D&C + SA run\n// Returns the best score found in this run\ndouble solve_single_run(double time_limit_ms_per_run, std::mt19937_64& rng) {\n    // Clear and resize global/shared state for this run\n    current_final_ad_rects.assign(N_global, Rect{}); // Reset all rects\n    current_tree_nodes.clear();\n    current_tree_nodes.reserve(2 * N_global); // Reserve memory to prevent frequent reallocations\n    current_internal_node_indices.clear();\n    \n    // Initial D&C\n    current_tree_nodes.emplace_back(Rect{}, false, -1, std::vector<int>{}); // Root node\n    std::vector<int> initial_company_indices(N_global);\n    std::iota(initial_company_indices.begin(), initial_company_indices.end(), 0);\n    \n    build_tree_and_solve(0, 0, 0, 10000, 10000, std::move(initial_company_indices), rng);\n    \n    // Precompute min/max company coordinates for children of each internal node\n    // Only if the root is not a leaf (i.e., N_global > 1)\n    if (!current_tree_nodes[0].is_leaf) { \n        calculate_child_company_bounds_recursive(0);\n    }\n    \n    // Simulated Annealing\n    simulated_annealing(time_limit_ms_per_run, rng);\n\n    // Calculate the final score for the best solution found in this run\n    double final_score = 0.0;\n    for (int i = 0; i < N_global; ++i) {\n        final_score += calculate_satisfaction(companies_data_global[i], current_final_ad_rects[i]);\n    }\n    return final_score;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N_global;\n\n    companies_data_global.resize(N_global);\n    for (int i = 0; i < N_global; ++i) {\n        companies_data_global[i].id = i;\n        std::cin >> companies_data_global[i].x >> companies_data_global[i].y >> companies_data_global[i].r;\n    }\n\n    double total_time_limit_ms = 4950.0; // Slightly less than 5 seconds\n    int num_runs = 10; // Increased number of independent SA runs\n    double time_per_run_ms = total_time_limit_ms / num_runs;\n\n    double overall_best_score = -1.0;\n    std::vector<Rect> overall_best_ad_rects(N_global);\n\n    for (int run = 0; run < num_runs; ++run) {\n        // Create a new RNG for each run, seeded from the global_mt_rand.\n        // This ensures different random walks for each run.\n        std::mt19937_64 run_rng(global_mt_rand()); \n        \n        // Call the single run solver\n        double current_run_score = solve_single_run(time_per_run_ms, run_rng);\n        \n        if (current_run_score > overall_best_score) {\n            overall_best_score = current_run_score;\n            overall_best_ad_rects = current_final_ad_rects; // Copy the best rects from this run\n        }\n    }\n    \n    // Output the overall best results\n    for (int i = 0; i < N_global; ++i) {\n        std::cout << overall_best_ad_rects[i].x1 << \" \" << overall_best_ad_rects[i].y1 << \" \"\n                  << overall_best_ad_rects[i].x2 << \" \" << overall_best_ad_rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <bitset>\n#include <random>\n#include <numeric>\n\n// Using standard namespace for convenience in competitive programming\nusing namespace std;\n\n// Constants\nconst int GRID_SIZE = 50;\nconst int MAX_TILES = GRID_SIZE * GRID_SIZE; // Max possible number of tiles (all 1x1)\n\n// Global variables to store input data\nint si, sj; // Start row, start column\nint tile_id_grid[GRID_SIZE][GRID_SIZE]; // tile_id_grid[i][j] stores the tile ID for square (i,j)\nint p_grid[GRID_SIZE][GRID_SIZE];       // p_grid[i][j] stores the score value for square (i,j)\n\n// Global variables for best path found so far\nlong long max_score_global = 0;\nstring best_path_string_global = \"\";\n\n// Random number generator. Using std::mt19937 for better randomness than rand().\nmt19937 rng;\n\n// Structure to represent a potential move\nstruct Move {\n    int r, c;           // Next square's row and column\n    char move_char;     // Character representing the move ('U', 'D', 'L', 'R')\n    int score_value;    // Score obtained by moving to (r, c)\n    int tile_id;        // Tile ID of the next square\n    long long total_priority; // Heuristic value for move selection (immediate score)\n};\n\n// Function to get all valid next moves from the current position (r, c)\n// A move is valid if it stays within grid boundaries and leads to an unvisited tile.\nvector<Move> get_valid_moves(int r, int c, const bitset<MAX_TILES>& visited_tiles) {\n    vector<Move> valid_moves;\n    // Possible movements: Up, Down, Left, Right\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1}; \n    char move_chars[] = {'U', 'D', 'L', 'R'};\n\n    for (int k = 0; k < 4; ++k) {\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n\n        // Check if the next position is within grid boundaries\n        if (nr >= 0 && nr < GRID_SIZE && nc >= 0 && nc < GRID_SIZE) {\n            int next_tile_id = tile_id_grid[nr][nc];\n            // Check if the tile has not been visited yet\n            if (!visited_tiles[next_tile_id]) {\n                // Heuristic: The priority for a move is simply the score of the square it leads to.\n                valid_moves.push_back({nr, nc, move_chars[k], p_grid[nr][nc], next_tile_id, (long long)p_grid[nr][nc]});\n            }\n        }\n    }\n    return valid_moves;\n}\n\n// Function to generate a single path using a randomized greedy approach with dynamic bias.\npair<long long, string> generate_path(chrono::high_resolution_clock::time_point global_start_time, chrono::milliseconds total_time_limit) {\n    long long current_score = p_grid[si][sj]; // Start with score of initial square\n    string current_path_str = \"\";\n    bitset<MAX_TILES> visited_tiles; // Keep track of visited tiles\n    visited_tiles[tile_id_grid[si][sj]] = true; // Mark initial tile as visited\n    int curr_r = si;\n    int curr_c = sj;\n\n    // Use a local random number generator for path generation, seeded by the global one.\n    mt19937 local_rng(rng()); \n    uniform_real_distribution<double> prob_dist(0.0, 1.0); // For generating random value [0, 1)\n\n    // Parameters for dynamic bias and beam width\n    // START_BIAS adjusted from 60.0 to 65.0 for slightly more initial exploration.\n    const double START_BIAS = 65.0; // Initial bias (adds to scores, making choices more random)\n    const double END_BIAS = 0.0;     // Final bias (no additional bias, purely greedy based on score)\n    const int BEAM_WIDTH = 5;       // Number of top moves to consider\n\n    // Continue extending the path until no more moves or global time limit is approached\n    while (true) {\n        // Periodically check remaining time\n        auto current_duration = chrono::high_resolution_clock::now() - global_start_time;\n        // Convert current_duration (which is `duration` of `high_resolution_clock`, typically nanoseconds) to milliseconds\n        auto current_duration_ms = chrono::duration_cast<chrono::milliseconds>(current_duration);\n\n        if (current_duration >= total_time_limit - chrono::milliseconds(10)) { // Small buffer for output\n            break; \n        }\n\n        vector<Move> moves = get_valid_moves(curr_r, curr_c, visited_tiles);\n        if (moves.empty()) {\n            break; // No more valid moves from current position\n        }\n\n        // Sort valid moves by their `total_priority` (immediate score) in descending order.\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.total_priority > b.total_priority;\n        });\n\n        // Calculate current time ratio (0.0 to 1.0)\n        // Ensure both numerator and denominator are in the same time units (milliseconds here).\n        double time_ratio = (double)current_duration_ms.count() / total_time_limit.count();\n        // Clamp time_ratio to [0, 1] for robustness against minor timing differences or overflows\n        time_ratio = max(0.0, min(1.0, time_ratio)); \n\n        // Calculate current bias with linear decay\n        double current_bias = START_BIAS * (1.0 - time_ratio) + END_BIAS * time_ratio;\n\n        // Weighted probabilistic selection among the top BEAM_WIDTH moves\n        vector<double> weights;\n        double total_weight = 0.0;\n\n        int effective_beam_width = min((int)moves.size(), BEAM_WIDTH);\n        for (int i = 0; i < effective_beam_width; ++i) {\n            // Add current_bias to the move's score.\n            // When bias is high, scores are \"flattened\" (more exploration).\n            // When bias is low, score differences become more pronounced (more exploitation).\n            // Ensure weight is positive, as scores p_grid are non-negative.\n            double weight = (double)moves[i].total_priority + current_bias;\n            weights.push_back(weight);\n            total_weight += weight;\n        }\n\n        // Select a move based on calculated weights\n        int choice_idx = 0; // Default to best move if total_weight is zero or an issue\n        if (total_weight > 1e-9) { // Avoid division by zero or near-zero\n            double rand_val = prob_dist(local_rng) * total_weight;\n            for (int i = 0; i < effective_beam_width; ++i) {\n                rand_val -= weights[i];\n                if (rand_val <= 0) {\n                    choice_idx = i;\n                    break;\n                }\n            }\n        }\n        \n        const Move& chosen_move = moves[choice_idx];\n\n        // Update current state based on the chosen move\n        curr_r = chosen_move.r;\n        curr_c = chosen_move.c;\n        current_score += chosen_move.score_value;\n        current_path_str += chosen_move.move_char;\n        visited_tiles[chosen_move.tile_id] = true;\n    }\n    return {current_score, current_path_str};\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Seed the random number generator using the current time.\n    rng.seed(chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Read input: starting position (si, sj)\n    cin >> si >> sj;\n\n    // Read tile IDs for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> tile_id_grid[i][j];\n        }\n    }\n\n    // Read score values for the 50x50 grid\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            cin >> p_grid[i][j];\n        }\n    }\n\n    // Initialize global best score with the score of the starting square.\n    max_score_global = p_grid[si][sj];\n    best_path_string_global = \"\"; \n\n    // Record the start time of the entire program execution\n    auto global_start_time = chrono::high_resolution_clock::now();\n    // Set a total time limit slightly less than 2 seconds (e.g., 1950 ms) to ensure output completes.\n    const auto TOTAL_TIME_LIMIT = chrono::milliseconds(1950); \n\n    // Iteratively generate paths and keep the best one found within the time limit.\n    while (chrono::high_resolution_clock::now() - global_start_time < TOTAL_TIME_LIMIT) {\n        // Call generate_path with the global start time and total time limit.\n        // The path generation function itself will manage its internal time checking.\n        pair<long long, string> result = generate_path(global_start_time, TOTAL_TIME_LIMIT);\n        \n        // If the newly generated path has a higher score, update the global best.\n        if (result.first > max_score_global) {\n            max_score_global = result.first;\n            best_path_string_global = result.second;\n        }\n    }\n\n    // Output the sequence of moves for the highest scoring path found.\n    cout << best_path_string_global << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <algorithm> // For std::reverse\n\n// Constants\nconst int GRID_SIZE = 30;\nconst int NUM_VERTICES = GRID_SIZE * GRID_SIZE;\nconst int NUM_QUERIES = 1000; // Total number of queries\n\n// Parameters for learning and exploration\nconst double INITIAL_EDGE_ESTIMATE = 5000.0; // Average of possible edge lengths\n\n// C_ALPHA (for learning rate): alpha = 1.0 / (usage_count + C_ALPHA)\n// Higher C_ALPHA -> slower learning, more stable estimates against noise.\n// Decreased from 20.0 to 15.0 for slightly faster individual edge learning.\nconst double C_ALPHA = 15.0;                 \n\n// INITIAL_EXPLORATION_BONUS: Initial bonus for less-used edges in Dijkstra's.\n// This bonus will decay over time.\nconst double INITIAL_EXPLORATION_BONUS = 200.0; \n\n// Smoothing parameter: applies a small pull towards row/column average.\n// Increased from 0.005 to 0.01 for a stronger smoothing effect.\nconst double SMOOTHING_BETA = 0.01; \n\n// Clamping ranges for estimated edge lengths and effective weights\nconst double MIN_CLAMP_ESTIMATE = 900.0;   // Based on problem constraints (min ~1000)\nconst double MAX_CLAMP_ESTIMATE = 9100.0;  // Based on problem constraints (max ~9000)\nconst double MIN_CLAMP_EFFECTIVE_WEIGHT = 1.0; // To prevent negative effective effective weights in Dijkstra\n\n// Edge structures\n// h_len[i][j] is edge between (i,j) and (i,j+1)\n// v_len[i][j] is edge between (i,j) and (i+1,j)\n// These arrays store estimated lengths and usage counts for each individual edge.\ndouble estimated_h_len[GRID_SIZE][GRID_SIZE - 1];\ndouble estimated_v_len[GRID_SIZE - 1][GRID_SIZE];\n\nlong long usage_h_count[GRID_SIZE][GRID_SIZE - 1];\nlong long usage_v_count[GRID_SIZE - 1][GRID_SIZE];\n\n// Node to index mapping for Dijkstra's\nint node_to_idx(int r, int c) {\n    return r * GRID_SIZE + c;\n}\n\n// Index to node mapping\nstd::pair<int, int> idx_to_node(int idx) {\n    return {idx / GRID_SIZE, idx % GRID_SIZE};\n}\n\n// Function to clamp a double value within a specified range\ndouble clamp(double val, double min_val, double max_val) {\n    if (val < min_val) return min_val;\n    if (val > max_val) return max_val;\n    return val;\n}\n\n// Dijkstra's algorithm to find the shortest path based on current estimates\n// Takes current_exploration_bonus_val to apply time-decaying exploration.\nstd::string find_path(int start_r, int start_c, int end_r, int end_c, double& path_estimated_len, double current_exploration_bonus_val) {\n    int start_idx = node_to_idx(start_r, start_c);\n    int end_idx = node_to_idx(end_r, end_c);\n\n    std::vector<double> dist(NUM_VERTICES, 1e18); // Stores cumulative effective weights\n    std::vector<int> prev_node(NUM_VERTICES, -1);\n    std::vector<char> prev_dir(NUM_VERTICES, ' ');\n\n    std::priority_queue<std::pair<double, int>, std::vector<std::pair<double, int>>, std::greater<std::pair<double, int>>> pq;\n\n    dist[start_idx] = 0;\n    pq.push({0, start_idx});\n\n    while (!pq.empty()) {\n        double d = pq.top().first;\n        int u_idx = pq.top().second;\n        pq.pop();\n\n        if (d > dist[u_idx]) continue;\n        if (u_idx == end_idx) break;\n\n        int ur = idx_to_node(u_idx).first;\n        int uc = idx_to_node(u_idx).second;\n\n        // Explore neighbors (Up, Down, Left, Right)\n        // U: (ur-1, uc) from (ur, uc)\n        if (ur > 0) {\n            int v_idx = node_to_idx(ur - 1, uc);\n            // Edge is v_len[ur-1][uc]\n            double current_estimate = estimated_v_len[ur - 1][uc];\n            long long current_usage = usage_v_count[ur - 1][uc];\n            // Apply exploration bonus for this edge\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE); // Clamp effective weight\n            \n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'U';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // D: (ur+1, uc) from (ur, uc)\n        if (ur < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur + 1, uc);\n            // Edge is v_len[ur][uc]\n            double current_estimate = estimated_v_len[ur][uc];\n            long long current_usage = usage_v_count[ur][uc];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'D';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // L: (ur, uc-1) from (ur, uc)\n        if (uc > 0) {\n            int v_idx = node_to_idx(ur, uc - 1);\n            // Edge is h_len[ur][uc-1]\n            double current_estimate = estimated_h_len[ur][uc - 1];\n            long long current_usage = usage_h_count[ur][uc - 1];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'L';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n        // R: (ur, uc+1) from (ur, uc)\n        if (uc < GRID_SIZE - 1) {\n            int v_idx = node_to_idx(ur, uc + 1);\n            // Edge is h_len[ur][uc]\n            double current_estimate = estimated_h_len[ur][uc];\n            long long current_usage = usage_h_count[ur][uc];\n            double effective_weight = current_estimate - current_exploration_bonus_val / std::sqrt(static_cast<double>(current_usage));\n            effective_weight = clamp(effective_weight, MIN_CLAMP_EFFECTIVE_WEIGHT, MAX_CLAMP_ESTIMATE);\n\n            if (dist[u_idx] + effective_weight < dist[v_idx]) {\n                dist[v_idx] = dist[u_idx] + effective_weight;\n                prev_node[v_idx] = u_idx;\n                prev_dir[v_idx] = 'R';\n                pq.push({dist[v_idx], v_idx});\n            }\n        }\n    }\n\n    std::string path_str = \"\";\n    int curr_idx = end_idx;\n    double actual_path_len_sum = 0.0; // Sum of actual estimated edge lengths (without exploration bonus)\n\n    // Reconstruct path and calculate sum of actual estimated edge lengths\n    while (curr_idx != start_idx && curr_idx != -1) {\n        if (prev_node[curr_idx] == -1) {\n             path_estimated_len = 1e18; \n             return \"\"; // Path not found or error\n        }\n        path_str += prev_dir[curr_idx];\n        \n        int prev_idx = prev_node[curr_idx];\n        int pr = idx_to_node(prev_idx).first;\n        int pc = idx_to_node(prev_idx).second;\n\n        // Add the *actual estimated length* of the edge\n        if (prev_dir[curr_idx] == 'U') { // Means we moved from (pr,pc) to (pr-1,pc), so edge is v_len[pr-1][pc]\n            actual_path_len_sum += estimated_v_len[pr-1][pc];\n        } else if (prev_dir[curr_idx] == 'D') { // Means we moved from (pr,pc) to (pr+1,pc), so edge is v_len[pr][pc]\n            actual_path_len_sum += estimated_v_len[pr][pc];\n        } else if (prev_dir[curr_idx] == 'L') { // Means we moved from (pr,pc) to (pr,pc-1), so edge is h_len[pr][pc-1]\n            actual_path_len_sum += estimated_h_len[pr][pc-1];\n        } else { // prev_dir[curr_idx] == 'R' // Means we moved from (pr,pc) to (pr,pc+1), so edge is h_len[pr][pc]\n            actual_path_len_sum += estimated_h_len[pr][pc];\n        }\n        curr_idx = prev_node[curr_idx];\n    }\n    std::reverse(path_str.begin(), path_str.end());\n    \n    path_estimated_len = actual_path_len_sum; // This is the total estimated length of the path without exploration bonus\n    return path_str;\n}\n\nvoid solve() {\n    // Initialize estimated edge lengths and usage counts\n    for (int i = 0; i < GRID_SIZE; ++i) {\n        for (int j = 0; j < GRID_SIZE - 1; ++j) {\n            estimated_h_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_h_count[i][j] = 1; // Initialize usage count to 1\n        }\n    }\n    for (int i = 0; i < GRID_SIZE - 1; ++i) {\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            estimated_v_len[i][j] = INITIAL_EDGE_ESTIMATE;\n            usage_v_count[i][j] = 1; // Initialize usage count to 1\n        }\n    }\n\n    // Main query loop\n    for (int k = 0; k < NUM_QUERIES; ++k) {\n        int si, sj, ti, tj;\n        std::cin >> si >> sj >> ti >> tj;\n\n        // Calculate the current exploration bonus, decaying linearly.\n        // The divisor (NUM_QUERIES * 2.0) ensures that at k=NUM_QUERIES-1 (i.e. query 999),\n        // the bonus is approx. 1/2 of INITIAL_EXPLORATION_BONUS.\n        double current_exploration_bonus_val = INITIAL_EXPLORATION_BONUS * (1.0 - static_cast<double>(k) / (NUM_QUERIES * 2.0)); \n        current_exploration_bonus_val = std::max(0.0, current_exploration_bonus_val); // Ensure non-negative\n\n        double current_path_estimated_len; \n        std::string path = find_path(si, sj, ti, tj, current_path_estimated_len, current_exploration_bonus_val);\n        \n        std::cout << path << std::endl;\n        std::cout.flush();\n\n        int observed_path_len_int;\n        std::cin >> observed_path_len_int;\n        double observed_path_len = static_cast<double>(observed_path_len_int);\n\n        // Update edge length estimates\n        // Ensure current_path_estimated_len is not too small to avoid division by zero or extreme scaling.\n        if (current_path_estimated_len < 1.0) current_path_estimated_len = 1.0; \n        double scaling_factor = observed_path_len / current_path_estimated_len;\n        \n        int curr_r = si;\n        int curr_c = sj;\n\n        for (char dir : path) {\n            double* edge_len_ptr;\n            long long* usage_count_ptr;\n            int r_idx, c_idx; // Indices for the specific edge in the respective array\n\n            // Determine which edge was used and its current stats using pre-move coordinates\n            if (dir == 'U') {\n                r_idx = curr_r - 1; // Edge (curr_r-1, curr_c) to (curr_r, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r--; // Move to the new node\n            } else if (dir == 'D') {\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r+1, curr_c)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_v_len[r_idx][c_idx];\n                usage_count_ptr = &usage_v_count[r_idx][c_idx];\n                curr_r++; // Move to the new node\n            } else if (dir == 'L') {\n                r_idx = curr_r; // Edge (curr_r, curr_c-1) to (curr_r, curr_c)\n                c_idx = curr_c - 1;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c--; // Move to the new node\n            } else { // dir == 'R'\n                r_idx = curr_r; // Edge (curr_r, curr_c) to (curr_r, curr_c+1)\n                c_idx = curr_c;\n                edge_len_ptr = &estimated_h_len[r_idx][c_idx];\n                usage_count_ptr = &usage_h_count[r_idx][c_idx];\n                curr_c++; // Move to the new node\n            }\n\n            // Apply weighted average update\n            double alpha = 1.0 / (static_cast<double>(*usage_count_ptr) + C_ALPHA);\n            double new_estimate_value = (*edge_len_ptr) * scaling_factor;\n            *edge_len_ptr = clamp((1.0 - alpha) * (*edge_len_ptr) + alpha * new_estimate_value, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            \n            // Increment usage count for the updated edge\n            (*usage_count_ptr)++;\n        }\n\n        // --- Neighborhood Smoothing ---\n        // This attempts to leverage the implicit structure (M=1 or M=2) by pulling estimates\n        // towards the average of their respective row/column.\n        \n        // Horizontal edges smoothing\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            double row_sum = 0.0;\n            // No need for row_count, it's always GRID_SIZE-1\n            for (int j = 0; j < GRID_SIZE - 1; ++j) {\n                row_sum += estimated_h_len[i][j];\n            }\n            double row_average = row_sum / (GRID_SIZE - 1);\n            for (int j = 0; j < GRID_SIZE - 1; ++j) {\n                estimated_h_len[i][j] = clamp((1.0 - SMOOTHING_BETA) * estimated_h_len[i][j] + SMOOTHING_BETA * row_average, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            }\n        }\n\n        // Vertical edges smoothing\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            double col_sum = 0.0;\n            // No need for col_count, it's always GRID_SIZE-1\n            for (int i = 0; i < GRID_SIZE - 1; ++i) {\n                col_sum += estimated_v_len[i][j];\n            }\n            double col_average = col_sum / (GRID_SIZE - 1);\n            for (int i = 0; i < GRID_SIZE - 1; ++i) {\n                estimated_v_len[i][j] = clamp((1.0 - SMOOTHING_BETA) * estimated_v_len[i][j] + SMOOTHING_BETA * col_average, MIN_CLAMP_ESTIMATE, MAX_CLAMP_ESTIMATE);\n            }\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set> // Temporarily for unique s_idx/pm_idx collection, will replace with boolean arrays\n#include <tuple> \n\n// Global constants\nconst int N_MATRIX = 20; // N is fixed to 20\nint M;\nstd::vector<std::string> S; // Input strings\n\n// Character to integer mapping for internal use (A=0, ..., H=7, .=8)\nstd::map<char, int> char_to_int_map;\nstd::vector<char> int_to_char_map;\n\n// Simulated Annealing parameters\nlong long MAX_ITERATIONS = 100000000; \ndouble START_TEMP = 2.0;\ndouble END_TEMP = 1e-9;\n\n// Random number generator\nstd::mt19937 mt;\n\n// Time measurement\nstd::chrono::high_resolution_clock::time_point start_time;\nconst double TIME_LIMIT = 2.95; // seconds\n\n// --- State Variables for SA ---\nstd::vector<std::string> current_grid;\nint num_dots; \nint num_matched_strings; \n\nstd::vector<int> num_actual_matches_for_string; \n\nstd::vector<int> unmatched_string_indices;\nstd::vector<int> s_idx_to_unmatched_list_pos; \n\n// SNAPSHOTS for revert: These will be copied once per SA iteration to guarantee correctness\nstd::vector<std::string> prev_grid;\nint prev_num_dots;\nint prev_num_matched_strings;\nstd::vector<int> prev_num_actual_matches_for_string;\nstd::vector<int> prev_num_mismatches_for_potential_match;\nstd::vector<bool> prev_is_potential_match_active;\nstd::vector<int> prev_unmatched_string_indices_vec; // Renamed to avoid conflict\nstd::vector<int> prev_s_idx_to_unmatched_list_pos_vec; // Renamed to avoid conflict\n\n\n// --- Precomputed data structures for efficient updates ---\nstruct PotentialMatchInfoBase {\n    int s_idx;\n    int sr, sc; \n    int dir;    \n};\n\nstd::vector<PotentialMatchInfoBase> all_potential_match_info_bases; \nstd::vector<std::pair<int, int>> cell_covers[N_MATRIX][N_MATRIX];\nstd::vector<int> num_mismatches_for_potential_match_global; // Renamed for clarity in context of snapshots\nstd::vector<bool> is_potential_match_active_global; // Renamed for clarity\nstd::vector<std::vector<int>> potential_matches_for_string;\n\n// For tracking affected elements in current iteration (optimization over std::set)\nstd::vector<bool> s_idx_is_affected_this_iter;\nstd::vector<int> affected_s_idx_list_this_iter;\nstd::vector<bool> pm_idx_is_affected_this_iter;\nstd::vector<int> affected_pm_idx_list_this_iter;\n\n\nint mod(int i, int n) {\n    return (i % n + n) % n;\n}\n\nvoid init_char_maps() {\n    char_to_int_map['A'] = 0; char_to_int_map['B'] = 1; char_to_int_map['C'] = 2; char_to_int_map['D'] = 3;\n    char_to_int_map['E'] = 4; char_to_int_map['F'] = 5; char_to_int_map['G'] = 6; char_to_int_map['H'] = 7;\n    char_to_int_map['.'] = 8;\n\n    int_to_char_map.resize(9);\n    int_to_char_map[0] = 'A'; int_to_char_map[1] = 'B'; int_to_char_map[2] = 'C'; int_to_char_map[3] = 'D';\n    int_to_char_map[4] = 'E'; int_to_char_map[5] = 'F'; int_to_char_map[6] = 'G'; int_to_char_map[7] = 'H';\n    int_to_char_map[8] = '.';\n}\n\ndouble calculate_objective(int c, int d) {\n    if (c < M) {\n        return (double)c / M;\n    } else {\n        return 1.0 + (double)(2.0 * N_MATRIX * N_MATRIX) / (2.0 * N_MATRIX * N_MATRIX - d);\n    }\n}\n\nvoid precompute_potential_matches() {\n    potential_matches_for_string.resize(M);\n    std::map<std::tuple<int, int, int, int>, int> potential_match_key_to_idx; \n    int pm_counter = 0; \n\n    for (int s_idx = 0; s_idx < M; ++s_idx) {\n        for (int sr = 0; sr < N_MATRIX; ++sr) {\n            for (int sc = 0; sc < N_MATRIX; ++sc) {\n                std::tuple<int, int, int, int> pm_key_h = {s_idx, sr, sc, 0}; \n                if (potential_match_key_to_idx.find(pm_key_h) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_h] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 0});\n                }\n                int pm_idx_h = potential_match_key_to_idx[pm_key_h];\n                potential_matches_for_string[s_idx].push_back(pm_idx_h); \n\n                std::tuple<int, int, int, int> pm_key_v = {s_idx, sr, sc, 1}; \n                if (potential_match_key_to_idx.find(pm_key_v) == potential_match_key_to_idx.end()) {\n                    potential_match_key_to_idx[pm_key_v] = pm_counter++;\n                    all_potential_match_info_bases.push_back({s_idx, sr, sc, 1});\n                }\n                int pm_idx_v = potential_match_key_to_idx[pm_key_v];\n                potential_matches_for_string[s_idx].push_back(pm_idx_v); \n            }\n        }\n    }\n\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        int k = S[pm_info_base.s_idx].length();\n        for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n            cell_covers[r][c].push_back({pm_idx, p_in_s});\n        }\n    }\n\n    num_mismatches_for_potential_match_global.resize(pm_counter);\n    is_potential_match_active_global.resize(pm_counter, false);\n    \n    s_idx_is_affected_this_iter.resize(M, false);\n    pm_idx_is_affected_this_iter.resize(pm_counter, false);\n}\n\nvoid initialize_state() {\n    current_grid.assign(N_MATRIX, std::string(N_MATRIX, '.')); \n    \n    std::uniform_int_distribution<int> dist_char_AH(0, 7); \n    for (int r = 0; r < N_MATRIX; ++r) {\n        for (int c = 0; c < N_MATRIX; ++c) {\n            current_grid[r][c] = int_to_char_map[dist_char_AH(mt)];\n        }\n    }\n    num_dots = 0; \n\n    num_matched_strings = 0;\n    num_actual_matches_for_string.assign(M, 0);\n\n    unmatched_string_indices.reserve(M); \n    s_idx_to_unmatched_list_pos.assign(M, -1); \n    for (int i = 0; i < M; ++i) {\n        unmatched_string_indices.push_back(i);\n        s_idx_to_unmatched_list_pos[i] = i;\n    }\n\n    for (int pm_idx = 0; pm_idx < all_potential_match_info_bases.size(); ++pm_idx) {\n        const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n        const std::string& s = S[pm_info_base.s_idx];\n        int k = s.length();\n        int mismatches = 0;\n\n        for (int p = 0; p < k; ++p) {\n            int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n            int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n            \n            if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                mismatches++;\n            }\n        }\n        num_mismatches_for_potential_match_global[pm_idx] = mismatches;\n\n        if (mismatches == 0) { \n            is_potential_match_active_global[pm_idx] = true;\n            if (num_actual_matches_for_string[pm_info_base.s_idx] == 0) { \n                num_matched_strings++;\n                int s_idx = pm_info_base.s_idx;\n                int pos = s_idx_to_unmatched_list_pos[s_idx];\n                if (pos != -1) { \n                    int last_s_idx_in_list = unmatched_string_indices.back();\n                    unmatched_string_indices[pos] = last_s_idx_in_list;\n                    s_idx_to_unmatched_list_pos[last_s_idx_in_list] = pos;\n                    unmatched_string_indices.pop_back();\n                    s_idx_to_unmatched_list_pos[s_idx] = -1;\n                }\n            }\n            num_actual_matches_for_string[pm_info_base.s_idx]++;\n        }\n    }\n\n    // Initialize snapshot vectors to correct sizes\n    prev_grid.resize(N_MATRIX);\n    prev_num_actual_matches_for_string.resize(M);\n    prev_num_mismatches_for_potential_match.resize(all_potential_match_info_bases.size());\n    prev_is_potential_match_active.resize(all_potential_match_info_bases.size());\n    prev_unmatched_string_indices_vec.reserve(M);\n    prev_s_idx_to_unmatched_list_pos_vec.resize(M);\n}\n\nvoid solve() {\n    start_time = std::chrono::high_resolution_clock::now();\n    \n    init_char_maps();\n    precompute_potential_matches();\n    initialize_state();\n\n    std::uniform_int_distribution<int> dist_rc(0, N_MATRIX - 1);\n    std::uniform_int_distribution<int> dist_char_all(0, int_to_char_map.size() - 1); \n    std::uniform_int_distribution<int> dist_char_AH(0, 7); \n    std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n\n    double best_score = calculate_objective(num_matched_strings, num_dots);\n    std::vector<std::string> best_grid = current_grid;\n\n    double p_aggressive_targeted_fix_attempt = 0.7; \n    double p_single_cell_targeted_fix_attempt = 0.3; \n\n    struct CellChangeInfo {\n        int r, c;\n        char old_char;\n        char new_char;\n    };\n    std::vector<CellChangeInfo> current_perturbation_cells; \n\n    for (long long iter = 0; iter < MAX_ITERATIONS; ++iter) {\n        double current_time = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            std::chrono::high_resolution_clock::now() - start_time).count() / 1e9;\n        if (current_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = START_TEMP * std::pow(END_TEMP / START_TEMP, (double)iter / MAX_ITERATIONS);\n\n        current_perturbation_cells.clear();\n        bool is_perturbation_generated = false;\n\n        // --- Perturbation Logic ---\n        if (num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_aggressive_targeted_fix_attempt) {\n            int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            std::vector<int> candidates_pm_idx_for_s_with_mismatches;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match_global[pm_idx] > 0) { \n                    candidates_pm_idx_for_s_with_mismatches.push_back(pm_idx);\n                }\n            }\n\n            if (!candidates_pm_idx_for_s_with_mismatches.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s_with_mismatches[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s_with_mismatches.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                bool changes_made = false;\n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    char required_char = s_to_fix[p_in_s];\n                    if (current_grid[r_p][c_p] != required_char) {\n                        current_perturbation_cells.push_back({r_p, c_p, current_grid[r_p][c_p], required_char});\n                        changes_made = true;\n                    }\n                }\n                if (changes_made) is_perturbation_generated = true;\n            }\n        }\n\n        if (!is_perturbation_generated && num_matched_strings < M && !unmatched_string_indices.empty() && dist_prob(mt) < p_single_cell_targeted_fix_attempt) {\n             int s_idx_to_fix = unmatched_string_indices[std::uniform_int_distribution<int>(0, unmatched_string_indices.size() - 1)(mt)];\n            \n            std::vector<int> candidates_pm_idx_for_s_with_mismatches;\n            for (int pm_idx : potential_matches_for_string[s_idx_to_fix]) {\n                if (num_mismatches_for_potential_match_global[pm_idx] > 0) {\n                    candidates_pm_idx_for_s_with_mismatches.push_back(pm_idx);\n                }\n            }\n            if (!candidates_pm_idx_for_s_with_mismatches.empty()) {\n                int pm_idx_to_fix = candidates_pm_idx_for_s_with_mismatches[std::uniform_int_distribution<int>(0, candidates_pm_idx_for_s_with_mismatches.size() - 1)(mt)];\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx_to_fix];\n                const std::string& s_to_fix = S[s_idx_to_fix];\n                int k = s_to_fix.length();\n\n                std::vector<std::pair<int, int>> mismatched_cells_coords; \n                for (int p_in_s = 0; p_in_s < k; ++p_in_s) {\n                    int r_p = (pm_info_base.sr + (pm_info_base.dir == 1 ? p_in_s : 0)) % N_MATRIX;\n                    int c_p = (pm_info_base.sc + (pm_info_base.dir == 0 ? p_in_s : 0)) % N_MATRIX;\n                    if (current_grid[r_p][c_p] != s_to_fix[p_in_s] || current_grid[r_p][c_p] == '.') {\n                        mismatched_cells_coords.push_back({r_p, c_p});\n                    }\n                }\n\n                if (!mismatched_cells_coords.empty()) {\n                    auto target_cell = mismatched_cells_coords[std::uniform_int_distribution<int>(0, mismatched_cells_coords.size() - 1)(mt)];\n                    int r_changed_candidate = target_cell.first;\n                    int c_changed_candidate = target_cell.second;\n                    char old_char = current_grid[r_changed_candidate][c_changed_candidate];\n                    \n                    int p_in_s_for_target = (pm_info_base.dir == 0) ? \n                                             mod(c_changed_candidate - pm_info_base.sc, N_MATRIX) : \n                                             mod(r_changed_candidate - pm_info_base.sr, N_MATRIX);\n\n                    char new_char = s_to_fix[p_in_s_for_target];\n                    if (new_char != old_char) { \n                        current_perturbation_cells.push_back({r_changed_candidate, c_changed_candidate, old_char, new_char});\n                        is_perturbation_generated = true;\n                    }\n                }\n            }\n        }\n\n        if (!is_perturbation_generated) {\n            int r_changed_candidate = dist_rc(mt);\n            int c_changed_candidate = dist_rc(mt);\n            char old_char = current_grid[r_changed_candidate][c_changed_candidate];\n            char new_char;\n            \n            if (num_matched_strings == M) {\n                if (dist_prob(mt) < 0.8) { \n                    new_char = '.';\n                } else {\n                    new_char = int_to_char_map[dist_char_all(mt)]; \n                }\n            } else {\n                new_char = int_to_char_map[dist_char_AH(mt)]; \n            }\n            if (new_char == old_char) continue; \n            current_perturbation_cells.push_back({r_changed_candidate, c_changed_candidate, old_char, new_char});\n            is_perturbation_generated = true;\n        }\n\n        if (!is_perturbation_generated || current_perturbation_cells.empty()) continue; \n\n\n        // --- TAKE FULL STATE SNAPSHOT ---\n        prev_grid = current_grid; // O(N^2)\n        prev_num_dots = num_dots;\n        prev_num_matched_strings = num_matched_strings;\n        prev_num_actual_matches_for_string = num_actual_matches_for_string; // O(M)\n        prev_num_mismatches_for_potential_match = num_mismatches_for_potential_match_global; // O(MAX_PM)\n        prev_is_potential_match_active = is_potential_match_active_global; // O(MAX_PM)\n        prev_unmatched_string_indices_vec = unmatched_string_indices; // O(M)\n        prev_s_idx_to_unmatched_list_pos_vec = s_idx_to_unmatched_list_pos; // O(M)\n        \n\n        // --- Apply proposed changes to current_grid and update all dependent state variables ---\n        // This is where current_grid and all derived states are directly modified.\n        // If rejected, everything is reverted from snapshots.\n\n        affected_s_idx_list_this_iter.clear();\n        for (int s_idx : affected_s_idx_list_this_iter) s_idx_is_affected_this_iter[s_idx] = false; // reset flags\n\n        affected_pm_idx_list_this_iter.clear();\n        for (int pm_idx : affected_pm_idx_list_this_iter) pm_idx_is_affected_this_iter[pm_idx] = false; // reset flags\n\n\n        for(const auto& cell_change : current_perturbation_cells) {\n            int r = cell_change.r;\n            int c = cell_change.c;\n            char old_char = current_grid[r][c]; // Use current_grid's char as it may have been changed by a prior cell in this multi-cell perturbation\n            char new_char = cell_change.new_char;\n\n            // Apply change to grid (temporarily)\n            current_grid[r][c] = new_char;\n\n            // Update num_dots\n            if (old_char == '.' && new_char != '.') { num_dots--; }\n            else if (old_char != '.' && new_char == '.') { num_dots++; }\n            \n            for (auto const& p : cell_covers[r][c]) {\n                int pm_idx = p.first;\n                int p_in_s = p.second; \n\n                if (!pm_idx_is_affected_this_iter[pm_idx]) {\n                    affected_pm_idx_list_this_iter.push_back(pm_idx);\n                    pm_idx_is_affected_this_iter[pm_idx] = true;\n                }\n\n                const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n                int s_idx = pm_info_base.s_idx;\n                char required_char = S[s_idx][p_in_s];\n\n                if (!s_idx_is_affected_this_iter[s_idx]) {\n                    affected_s_idx_list_this_iter.push_back(s_idx);\n                    s_idx_is_affected_this_iter[s_idx] = true;\n                }\n            }\n        }\n\n        // Re-calculate all affected num_mismatches_for_potential_match_global and is_potential_match_active_global\n        // This is safe because current_grid reflects the *proposed* state.\n        // We use the temporary list of affected pm_idx to avoid recalculating everything.\n        for(int pm_idx : affected_pm_idx_list_this_iter) {\n            const auto& pm_info_base = all_potential_match_info_bases[pm_idx];\n            const std::string& s = S[pm_info_base.s_idx];\n            int k = s.length();\n            int mismatches = 0;\n\n            for (int p = 0; p < k; ++p) {\n                int r = (pm_info_base.sr + (pm_info_base.dir == 1 ? p : 0)) % N_MATRIX;\n                int c = (pm_info_base.sc + (pm_info_base.dir == 0 ? p : 0)) % N_MATRIX;\n                \n                if (current_grid[r][c] != s[p] || current_grid[r][c] == '.') {\n                    mismatches++;\n                }\n            }\n            num_mismatches_for_potential_match_global[pm_idx] = mismatches;\n            is_potential_match_active_global[pm_idx] = (mismatches == 0);\n        }\n\n        // Re-calculate affected num_actual_matches_for_string and unmatched_string_indices\n        // Use a temporary list for unmatched_string_indices construction.\n        // This is complex, so for now, we'll iterate through all M strings.\n        // The previous simple O(M) copy for unmatched_string_indices and s_idx_to_unmatched_list_pos\n        // is actually done by the full snapshot/revert. This part is simplified.\n        \n        // Reset counts for affected strings\n        for(int s_idx : affected_s_idx_list_this_iter) {\n            num_actual_matches_for_string[s_idx] = 0;\n        }\n\n        // Recompute counts for affected strings based on new pm_active states\n        for(int pm_idx : affected_pm_idx_list_this_iter) {\n            if (is_potential_match_active_global[pm_idx]) {\n                num_actual_matches_for_string[all_potential_match_info_bases[pm_idx].s_idx]++;\n            }\n        }\n\n        // Recalculate global num_matched_strings and update unmatched_string_indices/s_idx_to_unmatched_list_pos\n        num_matched_strings = 0;\n        unmatched_string_indices.clear();\n        std::fill(s_idx_to_unmatched_list_pos.begin(), s_idx_to_unmatched_list_pos.end(), -1);\n\n        for(int s_idx = 0; s_idx < M; ++s_idx) {\n            if (num_actual_matches_for_string[s_idx] > 0) {\n                num_matched_strings++;\n            } else {\n                s_idx_to_unmatched_list_pos[s_idx] = unmatched_string_indices.size();\n                unmatched_string_indices.push_back(s_idx);\n            }\n        }\n\n\n        // --- Decision (Accept/Revert) ---\n        double current_obj_val = calculate_objective(prev_num_matched_strings, prev_num_dots);\n        double proposed_obj_val = calculate_objective(num_matched_strings, num_dots);\n\n        if (proposed_obj_val >= current_obj_val || dist_prob(mt) < std::exp((proposed_obj_val - current_obj_val) / T)) {\n            // Accept. All current_grid and derived state variables are already in the proposed state.\n        } else {\n            // Revert ALL state variables from snapshots\n            current_grid = prev_grid;\n            num_dots = prev_num_dots;\n            num_matched_strings = prev_num_matched_strings;\n            num_actual_matches_for_string = prev_num_actual_matches_for_string;\n            num_mismatches_for_potential_match_global = prev_num_mismatches_for_potential_match;\n            is_potential_match_active_global = prev_is_potential_match_active;\n            unmatched_string_indices = prev_unmatched_string_indices_vec;\n            s_idx_to_unmatched_list_pos = prev_s_idx_to_unmatched_list_pos_vec;\n        }\n        \n        double current_final_obj_val = calculate_objective(num_matched_strings, num_dots);\n        if (current_final_obj_val > best_score) {\n            best_score = current_final_obj_val;\n            best_grid = current_grid;\n        }\n    }\n\n    current_grid = best_grid; \n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N_input; \n    std::cin >> N_input >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) {\n        std::cin >> S[i];\n    }\n\n    solve();\n\n    for (int i = 0; i < N_MATRIX; ++i) {\n        std::cout << current_grid[i] << std::endl;\n    }\n\n    return 0;\n}\n","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm> // For std::reverse\n#include <tuple>     // For returning multiple values from find_best_next_node\n#include <limits>    // For numeric_limits\n#include <set>       // REQUIRED for std::set\n\nusing namespace std;\n\n// Global variables to store map data and current state for convenience\nint N_global;\nint SI_global, SJ_global;\nvector<string> grid_global;\nvector<vector<int>> costs_global; \nvector<vector<bool>> is_road_global; \nvector<vector<int>> visible_left_global, visible_right_global, visible_up_global, visible_down_global; \nint total_road_squares_global = 0; \nvector<vector<bool>> covered_status_global; \nint current_covered_count_global = 0; \n\n// New global: how many road squares can see this square (r,c)\nvector<vector<int>> can_be_seen_by_count; \n// Removed max_can_be_seen_by_count as it's not strictly needed for the new weighting formula.\n\n// Structure for Dijkstra's priority queue state\nstruct State {\n    int r, c;\n    long long cost;\n    bool operator>(const State& other) const {\n        return cost > other.cost; \n    }\n};\n\nvoid precompute_visibility() {\n    visible_left_global.assign(N_global, vector<int>(N_global));\n    visible_right_global.assign(N_global, vector<int>(N_global));\n    visible_up_global.assign(N_global, vector<int>(N_global));\n    visible_down_global.assign(N_global, vector<int>(N_global));\n    \n    can_be_seen_by_count.assign(N_global, vector<int>(N_global, 0));\n\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            if (!is_road_global[i][j]) continue; \n            \n            // Calculate direct visibility ranges for (i,j)\n            int left_bound = j;\n            while (left_bound > 0 && is_road_global[i][left_bound - 1]) {\n                left_bound--;\n            }\n            visible_left_global[i][j] = left_bound;\n\n            int right_bound = j;\n            while (right_bound < N_global - 1 && is_road_global[i][right_bound + 1]) {\n                right_bound++;\n            }\n            visible_right_global[i][j] = right_bound;\n\n            int up_bound = i;\n            while (up_bound > 0 && is_road_global[up_bound - 1][j]) {\n                up_bound--;\n            }\n            visible_up_global[i][j] = up_bound;\n\n            int down_bound = i;\n            while (down_bound < N_global - 1 && is_road_global[down_bound + 1][j]) {\n                down_bound++;\n            }\n            visible_down_global[i][j] = down_bound;\n            \n            // Corrected can_be_seen_by_count logic:\n            // For each source (i,j), find all unique cells it can see, then increment their counts.\n            set<pair<int, int>> visible_from_current_source;\n            // Add horizontal visible squares\n            for (int k_col = visible_left_global[i][j]; k_col <= visible_right_global[i][j]; ++k_col) {\n                if (is_road_global[i][k_col]) {\n                    visible_from_current_source.insert({i, k_col});\n                }\n            }\n            // Add vertical visible squares\n            for (int k_row = visible_up_global[i][j]; k_row <= visible_down_global[i][j]; ++k_row) {\n                if (is_road_global[k_row][j]) {\n                    visible_from_current_source.insert({k_row, j});\n                }\n            }\n\n            for (const auto& cell : visible_from_current_source) {\n                can_be_seen_by_count[cell.first][cell.second]++;\n            }\n        }\n    }\n}\n\n\nint update_coverage_and_count_new(int r, int c) {\n    int newly_covered_count = 0;\n    set<pair<int, int>> unique_newly_visible_cells; \n\n    // Collect newly visible squares horizontally\n    for (int k = visible_left_global[r][c]; k <= visible_right_global[r][c]; ++k) {\n        if (is_road_global[r][k] && !covered_status_global[r][k]) {\n            unique_newly_visible_cells.insert({r, k});\n        }\n    }\n    // Collect newly visible squares vertically\n    for (int k = visible_up_global[r][c]; k <= visible_down_global[r][c]; ++k) {\n        if (is_road_global[k][c] && !covered_status_global[k][c]) {\n            unique_newly_visible_cells.insert({k, c});\n        }\n    }\n\n    // Mark them as covered and count\n    for (const auto& cell : unique_newly_visible_cells) {\n        covered_status_global[cell.first][cell.second] = true;\n        newly_covered_count++;\n    }\n    return newly_covered_count;\n}\n\n// Reconstruct path segment using a provided prev_map (no Dijkstra run here)\nstring reconstruct_path_from_prev(int start_r, int start_c, int end_r, int end_c, const vector<vector<pair<int, int>>>& prev_map) {\n    if (start_r == end_r && start_c == end_c) return \"\"; \n\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    \n    // Check for reachability and reconstruct path\n    vector<pair<int, int>> temp_path_nodes;\n    int temp_curr_r = end_r, temp_curr_c = end_c;\n    while (temp_curr_r != start_r || temp_curr_c != start_c) {\n        if (temp_curr_r < 0 || temp_curr_r >= N_global || temp_curr_c < 0 || temp_curr_c >= N_global || \n            (prev_map[temp_curr_r][temp_curr_c].first == -1 && prev_map[temp_curr_r][temp_curr_c].second == -1)) {\n             return \"\"; // Not reachable or invalid path.\n        }\n        temp_path_nodes.push_back({temp_curr_r, temp_curr_c});\n        pair<int, int> p_node = prev_map[temp_curr_r][temp_curr_c];\n        temp_curr_r = p_node.first;\n        temp_curr_c = p_node.second;\n    }\n    reverse(temp_path_nodes.begin(), temp_path_nodes.end());\n\n    curr_r = start_r;\n    curr_c = start_c;\n    for(const auto& node : temp_path_nodes) {\n        int next_r = node.first;\n        int next_c = node.second;\n\n        if (next_r == curr_r - 1 && next_c == curr_c) path_segment += 'U';\n        else if (next_r == curr_r + 1 && next_c == curr_c) path_segment += 'D';\n        else if (next_r == curr_r && next_c == curr_c - 1) path_segment += 'L';\n        else if (next_r == curr_r && next_c == curr_c + 1) path_segment += 'R';\n        else { \n            return \"\"; // Logic error, unexpected move direction\n        }\n        curr_r = next_r;\n        curr_c = next_c;\n    }\n\n    return path_segment;\n}\n\n// Finds the shortest path between start and end using Dijkstra, returns path string\nstring find_path_with_dijkstra(int start_r, int start_c, int end_r, int end_c) {\n    if (start_r == end_r && start_c == end_c) return \"\";\n\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1));\n    vector<vector<pair<int, int>>> prev(N_global, vector<pair<int, int>>(N_global, {-1, -1}));\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (r == end_r && c == end_c) break; \n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev[nr][nc] = {r, c};\n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n    \n    if (dist[end_r][end_c] == -1) return \"\"; \n\n    string path_segment = \"\";\n    int curr_r = end_r;\n    int curr_c = end_c;\n    while (curr_r != start_r || curr_c != start_c) {\n        int pr = prev[curr_r][curr_c].first;\n        int pc = prev[curr_r][curr_c].second;\n        if (pr == -1 || pc == -1) return \"\"; \n        if (pr == curr_r - 1 && pc == curr_c) path_segment += 'D'; \n        else if (pr == curr_r + 1 && pc == curr_c) path_segment += 'U'; \n        else if (pr == curr_r && pc == curr_c - 1) path_segment += 'R'; \n        else if (pr == curr_r && pc == curr_c + 1) path_segment += 'L'; \n        curr_r = pr;\n        curr_c = pc;\n    }\n    reverse(path_segment.begin(), path_segment.end()); \n    return path_segment;\n}\n\n\n// Dijkstra from start_r, start_c to find the next best node to visit\n// This function returns the best target, its cost, and the prev_map generated by Dijkstra.\ntuple<int, int, long long, vector<vector<pair<int, int>>>> find_best_next_node(int start_r, int start_c) {\n    vector<vector<long long>> dist(N_global, vector<long long>(N_global, -1)); \n    vector<vector<pair<int, int>>> prev_map(N_global, vector<pair<int, int>>(N_global, {-1, -1})); \n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist[start_r][start_c] = 0;\n    pq.push({start_r, start_c, 0});\n\n    int best_r = -1, best_c = -1;\n    double max_score = -1.0; \n    long long min_cost_to_best_target = -1; \n    double max_weighted_coverage_gain_best = -1.0; \n\n    int dr[] = {-1, 1, 0, 0}; \n    int dc[] = {0, 0, -1, 1};\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        int r = current.r;\n        int c = current.c;\n        long long cost = current.cost;\n\n        if (dist[r][c] != -1 && cost > dist[r][c]) continue;\n\n        double weighted_coverage_gain_current_node = 0.0; \n        \n        set<pair<int, int>> unique_newly_visible_cells; \n\n        // Collect newly visible squares horizontally\n        for (int k_col = visible_left_global[r][c]; k_col <= visible_right_global[r][c]; ++k_col) {\n            if (is_road_global[r][k_col] && !covered_status_global[r][k_col]) {\n                unique_newly_visible_cells.insert({r, k_col});\n            }\n        }\n        // Collect newly visible squares vertically\n        for (int k_row = visible_up_global[r][c]; k_row <= visible_down_global[r][c]; ++k_row) {\n            if (is_road_global[k_row][c] && !covered_status_global[k_row][c]) {\n                unique_newly_visible_cells.insert({k_row, c});\n            }\n        }\n\n        // Sum their weighted contributions\n        for(const auto& cell : unique_newly_visible_cells) {\n            // New weighting: directly prioritize cells that are seen by fewer other cells\n            // Smaller can_be_seen_by_count means higher difficulty_factor\n            double difficulty_factor = 1.0 / (can_be_seen_by_count[cell.first][cell.second] + 0.5); \n            weighted_coverage_gain_current_node += difficulty_factor;\n        }\n        \n        if (weighted_coverage_gain_current_node > 0.0 && cost > 0) { \n            double score = weighted_coverage_gain_current_node / cost;\n\n            if (score > max_score || \n                (score == max_score && weighted_coverage_gain_current_node > max_weighted_coverage_gain_best) ||\n                (score == max_score && weighted_coverage_gain_current_node == max_weighted_coverage_gain_best && cost < min_cost_to_best_target)) \n            {\n                max_score = score;\n                best_r = r;\n                best_c = c;\n                min_cost_to_best_target = cost;\n                max_weighted_coverage_gain_best = weighted_coverage_gain_current_node;\n            }\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (nr >= 0 && nr < N_global && nc >= 0 && nc < N_global && is_road_global[nr][nc]) {\n                long long new_cost = cost + costs_global[nr][nc];\n                if (dist[nr][nc] == -1 || new_cost < dist[nr][nc]) {\n                    dist[nr][nc] = new_cost;\n                    prev_map[nr][nc] = {r, c}; \n                    pq.push({nr, nc, new_cost});\n                }\n            }\n        }\n    }\n\n    if (best_r == -1) { \n        return make_tuple(start_r, start_c, 0LL, vector<vector<pair<int, int>>>()); \n    }\n\n    return make_tuple(best_r, best_c, min_cost_to_best_target, std::move(prev_map));\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false); \n    cin.tie(NULL);\n\n    cin >> N_global >> SI_global >> SJ_global;\n\n    grid_global.resize(N_global);\n    costs_global.assign(N_global, vector<int>(N_global));\n    is_road_global.assign(N_global, vector<bool>(N_global, false));\n    covered_status_global.assign(N_global, vector<bool>(N_global, false));\n\n    for (int i = 0; i < N_global; ++i) {\n        cin >> grid_global[i];\n        for (int j = 0; j < N_global; ++j) {\n            if (grid_global[i][j] == '#') {\n                is_road_global[i][j] = false;\n            } else {\n                is_road_global[i][j] = true;\n                costs_global[i][j] = grid_global[i][j] - '0'; \n                total_road_squares_global++; \n            }\n        }\n    }\n\n    precompute_visibility(); \n\n    current_covered_count_global += update_coverage_and_count_new(SI_global, SJ_global);\n\n    if (current_covered_count_global == total_road_squares_global) {\n        string initial_move_path = \"\";\n        if (SJ_global + 1 < N_global && is_road_global[SI_global][SJ_global + 1]) {\n            initial_move_path += 'R';\n            initial_move_path += 'L';\n        } \n        else if (SI_global + 1 < N_global && is_road_global[SI_global + 1][SJ_global]) {\n            initial_move_path += 'D';\n            initial_move_path += 'U';\n        } \n        cout << initial_move_path << endl;\n        return 0; \n    }\n\n    int current_r = SI_global;\n    int current_c = SJ_global;\n    string full_path = \"\";\n\n    while (current_covered_count_global < total_road_squares_global) {\n        auto [next_target_r, next_target_c, path_cost_to_next_node, prev_map_for_segment] = find_best_next_node(current_r, current_c);\n\n        if (next_target_r == current_r && next_target_c == current_c) {\n            break; \n        }\n\n        string segment_str = reconstruct_path_from_prev(current_r, current_c, next_target_r, next_target_c, prev_map_for_segment);\n        \n        int temp_r = current_r;\n        int temp_c = current_c;\n        string current_segment_moves = \"\";\n\n        for (char move_char : segment_str) {\n            current_segment_moves += move_char;\n            \n            if (move_char == 'U') temp_r--;\n            else if (move_char == 'D') temp_r++;\n            else if (move_char == 'L') temp_c--;\n            else if (move_char == 'R') temp_c++;\n            \n            current_covered_count_global += update_coverage_and_count_new(temp_r, temp_c);\n\n            if (current_covered_count_global == total_road_squares_global) {\n                full_path += current_segment_moves; \n                string final_return_segment = find_path_with_dijkstra(temp_r, temp_c, SI_global, SJ_global);\n                full_path += final_return_segment;\n                cout << full_path << endl;\n                return 0; \n            }\n        }\n        \n        full_path += segment_str; \n        current_r = next_target_r; \n        current_c = next_target_c;\n    }\n\n    string return_segment = find_path_with_dijkstra(current_r, current_c, SI_global, SJ_global);\n    full_path += return_segment;\n\n    cout << full_path << endl; \n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <iomanip>\n#include <map>\n#include <cmath> // For std::round, std::clamp\n\n// Global constants and variables\nconst int MAX_SKILL_VAL = 100; // Upper bound for skills, based on problem generation info\nconst double INITIAL_S_GUESS = 20.0; // Initial guess for skill levels (from s_i,j generation range [20,60])\nconst double LEARNING_RATE_DENOM = 2.0; // Denominator for learning rate. Smaller value means faster learning.\n\nint N, M, K, R;\nstd::vector<std::vector<int>> D; // Task difficulties D[N][K]\nstd::vector<std::vector<int>> adj; // Adjacency list for dependencies: adj[u] lists tasks v that depend on u\nstd::vector<int> in_degree; // Number of prerequisites not yet completed for each task\n\nenum TaskStatus { NOT_STARTED, IN_PROGRESS, COMPLETED };\nstd::vector<TaskStatus> task_status;\nint total_tasks_completed = 0;\n\nstruct AssignedTask {\n    int task_id;\n    int start_day;\n};\n\nstd::vector<bool> member_is_free;\nstd::vector<AssignedTask> assigned_task_info; // assigned_task_info[member_idx]\nstd::vector<double> S_sum_D_task_difficulty; // Sum of D values for a task\n\n// Skill estimation\nstd::vector<std::vector<double>> S; // Estimated skill levels S[M][K]\nstd::vector<std::vector<double>> S_lower_bound; // Conservative lower bounds for skills\n\nint current_day = 0;\n\n// Set of ready tasks (in_degree is 0 and NOT_STARTED)\nstd::set<int> ready_tasks_set; // Stores task_id\n\n// Helper functions\ndouble calculate_w_internal(int member_idx, int task_idx) {\n    double w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += std::max(0.0, (double)D[task_idx][k] - S[member_idx][k]);\n    }\n    return w;\n}\n\nint calculate_t_estimated(int member_idx, int task_idx) {\n    double w = calculate_w_internal(member_idx, task_idx);\n    return std::max(1, (int)std::round(w)); // Round to nearest int, minimum 1\n}\n\n// Function to flush standard output\nvoid flush_stdout() {\n    std::cout << std::flush;\n}\n\n// Struct for candidate assignments to sort them\nstruct AssignmentCandidate {\n    int estimated_time;\n    int member_id;\n    int task_id;\n    // For tie-breaking\n    int out_degree; // Number of tasks unlocked by this task\n    double total_task_difficulty; // Sum of D values for the task\n\n    bool operator<(const AssignmentCandidate& other) const {\n        if (estimated_time != other.estimated_time) {\n            return estimated_time < other.estimated_time; // Prioritize shortest estimated time\n        }\n        // Tie-breaking for estimated_time\n        if (out_degree != other.out_degree) {\n            return out_degree > other.out_degree; // Prioritize tasks that unlock more tasks\n        }\n        if (total_task_difficulty != other.total_task_difficulty) {\n            return total_task_difficulty > other.total_task_difficulty; // Prioritize harder tasks\n        }\n        return task_id < other.task_id; // Stable sort by task_id\n    }\n};\n\nint main() {\n    // Faster I/O\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> K >> R;\n\n    D.resize(N, std::vector<int>(K));\n    S_sum_D_task_difficulty.resize(N);\n    for (int i = 0; i < N; ++i) {\n        double current_sum_D = 0;\n        for (int k = 0; k < K; ++k) {\n            std::cin >> D[i][k];\n            current_sum_D += D[i][k];\n        }\n        S_sum_D_task_difficulty[i] = current_sum_D;\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        --u; --v; // 0-indexed\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    task_status.resize(N, NOT_STARTED);\n    member_is_free.resize(M, true);\n    assigned_task_info.resize(M);\n\n    S.resize(M, std::vector<double>(K, INITIAL_S_GUESS));\n    S_lower_bound.resize(M, std::vector<double>(K, 0.0));\n\n    // Initialize ready_tasks_set: tasks with no dependencies or all dependencies met\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            ready_tasks_set.insert(i);\n        }\n    }\n\n    while (true) {\n        current_day++;\n\n        // Process daily input (completed tasks)\n        int n_completed;\n        std::cin >> n_completed;\n\n        if (n_completed == -1) {\n            break; // All tasks completed or max days reached, exit program\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_idx;\n            std::cin >> member_idx;\n            --member_idx; // 0-indexed\n\n            int completed_task_id = assigned_task_info[member_idx].task_id;\n            int start_day = assigned_task_info[member_idx].start_day;\n            int actual_t_ij = current_day - start_day + 1; // Actual days taken\n\n            // Update task status\n            task_status[completed_task_id] = COMPLETED;\n            total_tasks_completed++;\n\n            // Skill Estimation Update for member_idx\n            // Infer w_ij from actual_t_ij. If actual_t_ij == 1, assume w_ij=0 (most optimistic).\n            // Otherwise, assume w_ij = actual_t_ij, ignoring small random noise.\n            double observed_w = (actual_t_ij == 1) ? 0.0 : (double)actual_t_ij;\n            double current_predicted_w = calculate_w_internal(member_idx, completed_task_id);\n\n            // Strong evidence for S_lower_bound if task completed in 1 day\n            if (actual_t_ij == 1) { \n                for (int k = 0; k < K; ++k) {\n                    S_lower_bound[member_idx][k] = std::max(S_lower_bound[member_idx][k], (double)D[completed_task_id][k]);\n                }\n            } else { // actual_t_ij > 1, adjust S based on difference between predicted and observed w\n                double error = current_predicted_w - observed_w; // Positive if predicted was too high, negative if too low\n                int active_skills_count = 0; // Count skills where d_ik > S_jk currently\n                for (int k = 0; k < K; ++k) {\n                    if (D[completed_task_id][k] > S[member_idx][k]) {\n                        active_skills_count++;\n                    }\n                }\n\n                if (active_skills_count > 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (D[completed_task_id][k] > S[member_idx][k]) {\n                            // Adjust S[member_idx][k] to reduce the error.\n                            // If error > 0 (predicted w was too high), S[member_idx][k] needs to increase\n                            // If error < 0 (predicted w was too low), S[member_idx][k] needs to decrease\n                            S[member_idx][k] -= error / (active_skills_count * LEARNING_RATE_DENOM);\n                            S[member_idx][k] = std::clamp(S[member_idx][k], 0.0, (double)MAX_SKILL_VAL);\n                        }\n                    }\n                }\n            }\n\n            // Always apply lower bounds after any other adjustments to maintain consistency\n            for (int k = 0; k < K; ++k) {\n                S[member_idx][k] = std::max(S[member_idx][k], S_lower_bound[member_idx][k]);\n            }\n            \n            // Output skill predictions for visualization (round to nearest integer for output)\n            std::cout << \"#s \" << member_idx + 1;\n            for (int k = 0; k < K; ++k) {\n                std::cout << \" \" << static_cast<int>(std::round(S[member_idx][k]));\n            }\n            std::cout << std::endl;\n\n            // Free the member\n            member_is_free[member_idx] = true;\n\n            // Update in_degree for tasks dependent on the completed task\n            for (int dependent_task_id : adj[completed_task_id]) {\n                in_degree[dependent_task_id]--;\n                if (in_degree[dependent_task_id] == 0 && task_status[dependent_task_id] == NOT_STARTED) {\n                    ready_tasks_set.insert(dependent_task_id);\n                }\n            }\n        }\n\n        // Task Assignment Phase\n        std::vector<std::pair<int, int>> assignments_today;\n        std::vector<int> current_free_members;\n        for (int m_idx = 0; m_idx < M; ++m_idx) {\n            if (member_is_free[m_idx]) {\n                current_free_members.push_back(m_idx);\n            }\n        }\n\n        // Prioritize a subset of ready tasks to consider for efficiency\n        std::vector<int> tasks_to_consider;\n        if (!ready_tasks_set.empty()) {\n            // Priority for selecting tasks to consider:\n            // High out_degree (unlocks more tasks), high average skill difficulty, then lower task_id\n            std::vector<std::pair<int, int>> sorted_ready_tasks; // (priority_score, task_id)\n            for(int tid : ready_tasks_set) {\n                // Heuristic score: combine out_degree (weighted) and average task difficulty\n                // Multiplying by 100 ensures out_degree has significant impact\n                int score = adj[tid].size() * 100 + static_cast<int>(S_sum_D_task_difficulty[tid] / K); \n                sorted_ready_tasks.push_back({score, tid});\n            }\n            std::sort(sorted_ready_tasks.rbegin(), sorted_ready_tasks.rend()); // Sort descending by score\n\n            // Limit the number of tasks considered to avoid O(M * N_ready * K) complexity\n            // Choose M * (some factor) or a fixed max (e.g., 200)\n            int num_to_consider = std::min((int)sorted_ready_tasks.size(), M * 15); \n            for (int i = 0; i < num_to_consider; ++i) {\n                tasks_to_consider.push_back(sorted_ready_tasks[i].second);\n            }\n        }\n\n        std::vector<AssignmentCandidate> candidates;\n        for (int m_idx : current_free_members) {\n            for (int t_idx : tasks_to_consider) {\n                if (task_status[t_idx] == NOT_STARTED) { // Double check task isn't assigned concurrently\n                    candidates.push_back({\n                        calculate_t_estimated(m_idx, t_idx),\n                        m_idx,\n                        t_idx,\n                        (int)adj[t_idx].size(),\n                        S_sum_D_task_difficulty[t_idx]\n                    });\n                }\n            }\n        }\n        std::sort(candidates.begin(), candidates.end());\n\n        // Greedily assign tasks based on sorted candidates\n        for (const auto& candidate : candidates) {\n            int m_idx = candidate.member_id;\n            int t_idx = candidate.task_id;\n\n            if (member_is_free[m_idx] && task_status[t_idx] == NOT_STARTED) {\n                assignments_today.push_back({m_idx + 1, t_idx + 1});\n                member_is_free[m_idx] = false;\n                task_status[t_idx] = IN_PROGRESS;\n                assigned_task_info[m_idx] = {t_idx, current_day}; // Store start day and task ID\n                ready_tasks_set.erase(t_idx); // Remove from ready set as it's now in progress\n            }\n            \n            // Break conditions: if all free members have been assigned OR all remaining tasks are assigned\n            if (assignments_today.size() == current_free_members.size() || \n                total_tasks_completed + assignments_today.size() == N) {\n                break; \n            }\n        }\n\n        // Output assignments for the day\n        std::cout << assignments_today.size();\n        for (const auto& p : assignments_today) {\n            std::cout << \" \" << p.first << \" \" << p.second;\n        }\n        std::cout << std::endl;\n        flush_stdout(); // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc006":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <map>\n#include <unordered_set>\n#include <tuple> // For std::tie\n#include <limits> // For std::numeric_limits\n\n// --- Structs ---\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    int id; // 1-indexed original ID\n    Point p; // pickup\n    Point d; // delivery\n};\n\nenum NodeType {\n    PICKUP_TYPE = 0,\n    DELIVERY_TYPE = 1\n};\n\nstruct RouteNode {\n    int order_id;\n    NodeType type;\n    Point coord;\n};\n\n// --- Global Constants ---\nconst Point OFFICE = {400, 400};\nconst int NUM_TOTAL_ORDERS = 1000;\nconst int NUM_DELIVERIES_QUOTA = 50;\n\n// --- Random Number Generator ---\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper Functions ---\nlong long manhattan_dist(Point p1, Point p2) {\n    return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);\n}\n\n// Calculate total distance for a route represented by a sequence of RouteNodes\nlong long calculate_total_route_distance(const std::vector<RouteNode>& route_nodes) {\n    long long total_dist = 0;\n    if (route_nodes.empty()) {\n        return manhattan_dist(OFFICE, OFFICE);\n    }\n\n    total_dist += manhattan_dist(OFFICE, route_nodes[0].coord);\n    for (size_t i = 0; i < route_nodes.size() - 1; ++i) {\n        total_dist += manhattan_dist(route_nodes[i].coord, route_nodes[i+1].coord);\n    }\n    total_dist += manhattan_dist(route_nodes.back().coord, OFFICE);\n    return total_dist;\n}\n\n// Generates an initial route using a greedy Nearest Neighbor heuristic.\nstd::vector<RouteNode> generate_nearest_neighbor_route(const std::vector<int>& selected_order_ids, \n                                                       const std::map<int, Order>& all_orders_map) {\n    std::vector<RouteNode> route;\n    std::unordered_set<int> unpicked_order_ids(selected_order_ids.begin(), selected_order_ids.end());\n    std::unordered_set<int> un_delivered_order_ids;\n\n    Point current_pos = OFFICE;\n\n    while (!unpicked_order_ids.empty() || !un_delivered_order_ids.empty()) {\n        std::vector<std::pair<long long, RouteNode>> candidates; \n\n        for (int order_id : unpicked_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.p), {order_id, PICKUP_TYPE, order.p}});\n        }\n\n        for (int order_id : un_delivered_order_ids) {\n            const Order& order = all_orders_map.at(order_id);\n            candidates.push_back({manhattan_dist(current_pos, order.d), {order_id, DELIVERY_TYPE, order.d}});\n        }\n\n        if (candidates.empty()) break;\n\n        long long min_dist = candidates[0].first;\n        for (size_t i = 1; i < candidates.size(); ++i) {\n            if (candidates[i].first < min_dist) {\n                min_dist = candidates[i].first;\n            }\n        }\n\n        std::vector<RouteNode> best_candidates_nodes;\n        for (const auto& cand : candidates) {\n            if (cand.first == min_dist) {\n                best_candidates_nodes.push_back(cand.second);\n            }\n        }\n        \n        std::uniform_int_distribution<int> dist_cand_idx(0, best_candidates_nodes.size() - 1);\n        RouteNode chosen_node = best_candidates_nodes[dist_cand_idx(rng)];\n\n        route.push_back(chosen_node);\n        current_pos = chosen_node.coord;\n\n        if (chosen_node.type == PICKUP_TYPE) {\n            unpicked_order_ids.erase(chosen_node.order_id);\n            un_delivered_order_ids.insert(chosen_node.order_id);\n        } else { // DELIVERY_TYPE\n            un_delivered_order_ids.erase(chosen_node.order_id);\n        }\n    }\n    return route;\n}\n\n// Calculates delta cost for removing a node at `idx` from `current_route`.\nlong long calculate_removal_delta(const std::vector<RouteNode>& current_route, int idx) {\n    if (current_route.empty()) return 0; \n    if (current_route.size() == 1) { \n        return -(manhattan_dist(OFFICE, current_route[0].coord) + manhattan_dist(current_route[0].coord, OFFICE));\n    }\n\n    Point p_before = (idx == 0) ? OFFICE : current_route[idx - 1].coord;\n    Point p_node = current_route[idx].coord;\n    Point p_after = (idx == current_route.size() - 1) ? OFFICE : current_route[idx + 1].coord;\n    \n    long long dist_removed_segment = manhattan_dist(p_before, p_node) + manhattan_dist(p_node, p_after);\n    long long dist_merged_segment = manhattan_dist(p_before, p_after);\n    return dist_merged_segment - dist_removed_segment;\n}\n\n// Calculates delta cost for inserting a node at `insert_idx` into `current_route`.\nlong long calculate_insertion_delta(const std::vector<RouteNode>& current_route, int insert_idx, const RouteNode& node_to_insert) {\n    if (current_route.empty()) { \n        return manhattan_dist(OFFICE, node_to_insert.coord) + manhattan_dist(node_to_insert.coord, OFFICE);\n    }\n    \n    Point p_before = (insert_idx == 0) ? OFFICE : current_route[insert_idx - 1].coord;\n    Point p_after = (insert_idx == current_route.size()) ? OFFICE : current_route[insert_idx].coord;\n    \n    long long dist_new_segment = manhattan_dist(p_before, node_to_insert.coord) + manhattan_dist(node_to_insert.coord, p_after);\n    long long dist_old_at_insert_point = manhattan_dist(p_before, p_after);\n    return dist_new_segment - dist_old_at_insert_point;\n}\n\n\n// Applies a node relocation local search operator (1-opt equivalent).\n// Returns the new route and the new total distance.\nstd::pair<std::vector<RouteNode>, long long> apply_1opt_relocation(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist) {\n\n    if (current_route.empty()) return {current_route, current_total_dist};\n\n    std::uniform_int_distribution<int> dist_move_idx(0, current_route.size() - 1);\n    int move_idx = dist_move_idx(rng);\n    RouteNode node_to_move = current_route[move_idx];\n\n    long long delta_from_removal = calculate_removal_delta(current_route, move_idx);\n\n    // Create a temporary route with the node removed (copying to new vector)\n    std::vector<RouteNode> new_route_temp;\n    new_route_temp.reserve(current_route.size() - 1);\n    for (size_t i = 0; i < current_route.size(); ++i) {\n        if (i == (size_t)move_idx) continue;\n        new_route_temp.push_back(current_route[i]);\n    }\n    \n    int min_insert_idx = 0;\n    int max_insert_idx = new_route_temp.size(); \n\n    if (node_to_move.type == PICKUP_TYPE) {\n        int Di_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == DELIVERY_TYPE) {\n                Di_pos = i;\n                break;\n            }\n        }\n        if (Di_pos != -1) { \n            max_insert_idx = Di_pos;\n        }\n    } else { // DELIVERY_TYPE\n        int Pi_pos = -1;\n        for (size_t i = 0; i < new_route_temp.size(); ++i) {\n            if (new_route_temp[i].order_id == node_to_move.order_id && new_route_temp[i].type == PICKUP_TYPE) {\n                Pi_pos = i;\n                break;\n            }\n        }\n        if (Pi_pos != -1) { \n            min_insert_idx = Pi_pos + 1;\n        }\n    }\n    \n    if (min_insert_idx > max_insert_idx) { \n         min_insert_idx = 0; \n         max_insert_idx = new_route_temp.size();\n    }\n    if (new_route_temp.empty()) { \n        min_insert_idx = 0;\n        max_insert_idx = 0;\n    }\n\n    std::uniform_int_distribution<int> dist_insert_pos(min_insert_idx, max_insert_idx);\n    int insert_pos = dist_insert_pos(rng); \n    \n    long long delta_from_insertion = calculate_insertion_delta(new_route_temp, insert_pos, node_to_move);\n\n    new_route_temp.insert(new_route_temp.begin() + insert_pos, node_to_move);\n\n    long long new_total_dist = current_total_dist + delta_from_removal + delta_from_insertion;\n\n    return {new_route_temp, new_total_dist};\n}\n\n// Applies a 2-opt operation to the route with O(1) distance calculation and precedence validation.\n// Returns the new route and the new total distance, or original route if invalid.\nstd::pair<std::vector<RouteNode>, long long> apply_2opt_swap(\n    const std::vector<RouteNode>& current_route,\n    long long current_total_dist,\n    const std::vector<int>& selected_order_ids) {\n\n    if (current_route.size() < 4) return {current_route, current_total_dist}; // Need at least 4 nodes for non-trivial 2-opt\n\n    std::uniform_int_distribution<int> dist_i(0, current_route.size() - 3); // i up to size-3 to ensure j can be i+2 to size-1\n    int i = dist_i(rng); // first break point (node i)\n\n    std::uniform_int_distribution<int> dist_j(i + 2, current_route.size() - 1); // j from i+2 to size-1\n    int j = dist_j(rng); // second break point (node j)\n    \n    // Points for distance calculation, considering boundary (OFFICE)\n    Point p_i_minus_1 = (i == 0) ? OFFICE : current_route[i - 1].coord;\n    Point p_i         = current_route[i].coord;\n    Point p_j         = current_route[j].coord;\n    Point p_j_plus_1  = (j == current_route.size() - 1) ? OFFICE : current_route[j + 1].coord;\n\n    // Calculate incremental distance change\n    long long delta_dist = -manhattan_dist(p_i_minus_1, p_i) \n                           -manhattan_dist(p_j, p_j_plus_1)  \n                           +manhattan_dist(p_i_minus_1, p_j) \n                           +manhattan_dist(p_i, p_j_plus_1); \n    \n    std::vector<RouteNode> new_route_candidate = current_route;\n    \n    // Reverse the segment [i, j]\n    std::reverse(new_route_candidate.begin() + i, new_route_candidate.begin() + j + 1);\n\n    // Validate precedence constraints after the swap\n    // Use vectors for quick mapping of order_id to index\n    std::vector<int> p_pos_map(NUM_TOTAL_ORDERS + 1, -1);\n    std::vector<int> d_pos_map(NUM_TOTAL_ORDERS + 1, -1);\n    \n    for (size_t k = 0; k < new_route_candidate.size(); ++k) {\n        if (new_route_candidate[k].type == PICKUP_TYPE) {\n            p_pos_map[new_route_candidate[k].order_id] = k;\n        } else {\n            d_pos_map[new_route_candidate[k].order_id] = k;\n        }\n    }\n\n    for (int order_id : selected_order_ids) {\n        if (p_pos_map[order_id] != -1 && d_pos_map[order_id] != -1) { // Should always be true for selected orders\n            if (p_pos_map[order_id] > d_pos_map[order_id]) {\n                return {current_route, current_total_dist}; // Invalid move\n            }\n        }\n    }\n\n    long long new_total_dist = current_total_dist + delta_dist;\n    return {new_route_candidate, new_total_dist};\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // --- Input Reading ---\n    std::vector<Order> all_orders_orig(NUM_TOTAL_ORDERS); \n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        all_orders_orig[i].id = i + 1; // 1-indexed\n        std::cin >> all_orders_orig[i].p.x >> all_orders_orig[i].p.y >> all_orders_orig[i].d.x >> all_orders_orig[i].d.y;\n    }\n\n    // --- Initial Selection (Greedy based on standalone cost) ---\n    std::vector<std::pair<long long, int>> order_costs(NUM_TOTAL_ORDERS); \n    for (int i = 0; i < NUM_TOTAL_ORDERS; ++i) {\n        long long cost = manhattan_dist(OFFICE, all_orders_orig[i].p) +\n                         manhattan_dist(all_orders_orig[i].p, all_orders_orig[i].d) +\n                         manhattan_dist(all_orders_orig[i].d, OFFICE);\n        order_costs[i] = {cost, all_orders_orig[i].id};\n    }\n    std::sort(order_costs.begin(), order_costs.end());\n\n    std::vector<int> current_selected_order_ids_vec;\n    std::map<int, Order> current_selected_orders_map; \n    std::vector<int> unselected_order_ids_vec;\n\n    for (int i = 0; i < NUM_DELIVERIES_QUOTA; ++i) {\n        int order_id = order_costs[i].second;\n        current_selected_order_ids_vec.push_back(order_id);\n        current_selected_orders_map[order_id] = all_orders_orig[order_id - 1]; \n    }\n    for (int i = NUM_DELIVERIES_QUOTA; i < NUM_TOTAL_ORDERS; ++i) {\n        unselected_order_ids_vec.push_back(order_costs[i].second);\n    }\n\n    // --- Initial Route Generation ---\n    std::vector<RouteNode> current_route_nodes = generate_nearest_neighbor_route(current_selected_order_ids_vec, current_selected_orders_map);\n    long long current_total_dist = calculate_total_route_distance(current_route_nodes);\n\n    // --- Best Solution Tracking ---\n    long long best_total_dist = current_total_dist;\n    std::vector<RouteNode> best_route_nodes = current_route_nodes;\n    std::vector<int> best_selected_order_ids = current_selected_order_ids_vec;\n\n    // --- Simulated Annealing Parameters ---\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SEC = 1.95; \n    const double T_START = 5000.0;     \n    const double T_END = 0.5;          // Adjusted from 1.0\n    const double PROB_ORDER_SWAP = 0.12; // Adjusted from 0.10\n    const double PROB_2OPT_ROUTE_MOVE = 0.20; // Unchanged\n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> dist_selected_idx(0, NUM_DELIVERIES_QUOTA - 1);\n    \n    // --- Simulated Annealing Loop ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_sec = std::chrono::duration<double>(current_time - start_time).count();\n\n        if (elapsed_sec >= TIME_LIMIT_SEC) {\n            break;\n        }\n\n        double progress = elapsed_sec / TIME_LIMIT_SEC;\n        double current_T = T_START * std::pow(T_END / T_START, progress);\n\n        long long new_total_dist;\n        std::vector<RouteNode> new_route_nodes_candidate; \n\n        bool orders_swapped_this_iter = false; \n        int out_vec_idx = -1; \n        int in_vec_idx = -1;\n        \n        double op_choice = dist_0_1(rng);\n\n        if (op_choice < PROB_ORDER_SWAP && !unselected_order_ids_vec.empty()) {\n            orders_swapped_this_iter = true;\n            out_vec_idx = dist_selected_idx(rng);\n            int order_out_id = current_selected_order_ids_vec[out_vec_idx];\n\n            std::uniform_int_distribution<int> dist_unselected_idx(0, unselected_order_ids_vec.size() - 1);\n            in_vec_idx = dist_unselected_idx(rng);\n            int order_in_id = unselected_order_ids_vec[in_vec_idx];\n\n            // 1. Create a temporary route by removing order_out_id's nodes\n            std::vector<RouteNode> temp_route_after_removal;\n            temp_route_after_removal.reserve(current_route_nodes.size() - 2);\n            for(const auto& node : current_route_nodes) {\n                if(node.order_id != order_out_id) {\n                    temp_route_after_removal.push_back(node);\n                }\n            }\n            long long dist_after_removal = calculate_total_route_distance(temp_route_after_removal);\n\n            // 2. Insert order_in_id's nodes (P_in, D_in) greedily\n            const Order& order_in = all_orders_orig[order_in_id - 1];\n            RouteNode p_in_node = {order_in_id, PICKUP_TYPE, order_in.p};\n            RouteNode d_in_node = {order_in_id, DELIVERY_TYPE, order_in.d};\n\n            // Find best insertion for P_in\n            std::vector<RouteNode> route_working_copy = temp_route_after_removal;\n            long long dist_working_copy = dist_after_removal;\n            int best_p_in_insert_pos = 0;\n            long long min_p_in_delta = std::numeric_limits<long long>::max(); \n\n            for (int i = 0; i <= route_working_copy.size(); ++i) {\n                long long current_delta = calculate_insertion_delta(route_working_copy, i, p_in_node);\n                if (current_delta < min_p_in_delta) {\n                    min_p_in_delta = current_delta;\n                    best_p_in_insert_pos = i;\n                }\n            }\n            route_working_copy.insert(route_working_copy.begin() + best_p_in_insert_pos, p_in_node);\n            dist_working_copy += min_p_in_delta;\n            \n            int p_in_actual_pos = best_p_in_insert_pos; \n\n            // Find best insertion for D_in (after P_in's actual position)\n            int best_d_in_insert_pos = p_in_actual_pos + 1; \n            long long min_d_in_delta = std::numeric_limits<long long>::max(); \n\n            for (int i = p_in_actual_pos + 1; i <= route_working_copy.size(); ++i) {\n                 long long current_delta = calculate_insertion_delta(route_working_copy, i, d_in_node);\n                if (current_delta < min_d_in_delta) {\n                    min_d_in_delta = current_delta;\n                    best_d_in_insert_pos = i;\n                }\n            }\n            \n            new_route_nodes_candidate = route_working_copy; \n            new_route_nodes_candidate.insert(new_route_nodes_candidate.begin() + best_d_in_insert_pos, d_in_node);\n            new_total_dist = dist_working_copy + min_d_in_delta;\n            \n            // --- Temporarily Apply the swap to selected order list for acceptance check ---\n            current_selected_order_ids_vec[out_vec_idx] = order_in_id;\n            unselected_order_ids_vec[in_vec_idx] = order_out_id;\n            current_selected_orders_map.erase(order_out_id);\n            current_selected_orders_map[order_in_id] = all_orders_orig[order_in_id - 1];\n\n        } else if (op_choice < PROB_ORDER_SWAP + PROB_2OPT_ROUTE_MOVE) { // 2-opt move\n             std::tie(new_route_nodes_candidate, new_total_dist) = apply_2opt_swap(current_route_nodes, current_total_dist, current_selected_order_ids_vec);\n        }\n        else { // 1-opt (node relocation)\n            std::tie(new_route_nodes_candidate, new_total_dist) = apply_1opt_relocation(current_route_nodes, current_total_dist);\n        }\n\n        // --- Acceptance Criteria ---\n        if (new_total_dist < current_total_dist) {\n            current_total_dist = new_total_dist;\n            current_route_nodes = new_route_nodes_candidate; \n        } else {\n            double prob_acceptance = std::exp((double)(current_total_dist - new_total_dist) / current_T);\n            if (dist_0_1(rng) < prob_acceptance) {\n                current_total_dist = new_total_dist;\n                current_route_nodes = new_route_nodes_candidate; \n            } else {\n                // Reject: if orders were swapped, revert them\n                if (orders_swapped_this_iter) {\n                    int order_in_id_to_revert = current_selected_order_ids_vec[out_vec_idx]; \n                    int order_out_id_to_revert = unselected_order_ids_vec[in_vec_idx];     \n\n                    current_selected_order_ids_vec[out_vec_idx] = order_out_id_to_revert;\n                    unselected_order_ids_vec[in_vec_idx] = order_in_id_to_revert;\n                    \n                    current_selected_orders_map.erase(order_in_id_to_revert);\n                    current_selected_orders_map[order_out_id_to_revert] = all_orders_orig[order_out_id_to_revert - 1];\n                }\n            }\n        }\n\n        // --- Update Best Solution ---\n        if (current_total_dist < best_total_dist) {\n            best_total_dist = current_total_dist;\n            best_route_nodes = current_route_nodes;\n            best_selected_order_ids = current_selected_order_ids_vec; \n        }\n    }\n\n    // --- Output ---\n    std::cout << NUM_DELIVERIES_QUOTA;\n    for (int id : best_selected_order_ids) {\n        std::cout << \" \" << id;\n    }\n    std::cout << std::endl;\n\n    std::cout << best_route_nodes.size() + 2; \n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    for (const auto& node : best_route_nodes) {\n        std::cout << \" \" << node.coord.x << \" \" << node.coord.y;\n    }\n    std::cout << \" \" << OFFICE.x << \" \" << OFFICE.y;\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric> \n#include <iomanip>\n#include <algorithm>\n\n#include <atcoder/dsu>\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    long long d; // Precomputed rounded Euclidean distance\n};\n\n// Global constants for problem size\nconst int N_NODES = 400;\nconst int M_EDGES = 1995;\n\n// Function to calculate rounded Euclidean distance\nlong long calculate_d(const Point& p1, const Point& p2) {\n    long long dx = p1.x - p2.x;\n    long long dy = p1.y - p2.y;\n    // dx*dx + dy*dy can be up to 800^2 + 800^2 = 1,280,000. Fits in long long.\n    // sqrt of 1,280,000 is approx 1131.\n    return std::round(std::sqrt(static_cast<double>(dx * dx + dy * dy)));\n}\n\n// Heuristic parameters for tuning\n// TAU_MIN: Initial strictness for cost ratio l_i / d_i\n// Decreased from 1.3 to 1.2 to be more selective early on.\nconst double TAU_MIN = 1.2; \n// TAU_MAX: Final leniency for cost ratio l_i / d_i when close to connecting all nodes\n// Kept at 3.0 to ensure connectivity at the very end.\nconst double TAU_MAX = 3.0; \n\n// BASE_REDUNDANCY_FACTOR: M_EDGES / (N_NODES - 1) is the factual average redundancy.\n// For N=400, M=1995, this is 1995 / 399 = 5.0.\nconst double BASE_REDUNDANCY_FACTOR = static_cast<double>(M_EDGES) / (N_NODES - 1.0);\n\n// EFFECTIVE_REDUNDANCY_DENOMINATOR: A tuning parameter. Lowering this makes\n// `potential_useful_remaining` larger, delaying the urgency trigger.\n// Decreased from 6.0 to 5.5 to be less aggressive with urgency (more cost-sensitive).\nconst double EFFECTIVE_REDUNDANCY_DENOMINATOR = 5.5; \n\n// URGENCY_SAFETY_MARGIN: A small buffer for the urgency condition.\n// Kept at 0.0 to ensure strict urgency when it does trigger.\nconst double URGENCY_SAFETY_MARGIN = 0.0; \n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(nullptr);\n\n    std::vector<Point> vertices(N_NODES);\n    for (int i = 0; i < N_NODES; ++i) {\n        std::cin >> vertices[i].x >> vertices[i].y;\n    }\n\n    std::vector<EdgeInfo> edges(M_EDGES);\n    for (int i = 0; i < M_EDGES; ++i) {\n        std::cin >> edges[i].u >> edges[i].v;\n        edges[i].d = calculate_d(vertices[edges[i].u], vertices[edges[i].v]);\n    }\n\n    atcoder::dsu dsu(N_NODES);\n    int edges_taken_count = 0;\n\n    for (int i = 0; i < M_EDGES; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        long long d_val = edges[i].d;\n\n        long long l_val;\n        std::cin >> l_val;\n\n        int decision = 0; // Default: reject\n\n        if (!dsu.same(u, v)) {\n            int needed_to_connect = dsu.groups().size() - 1; \n            int remaining_candidates = M_EDGES - (i + 1);\n            double cost_ratio = static_cast<double>(l_val) / d_val;\n\n            double potential_useful_remaining = 0.0;\n            // Guard against division by zero. EFFECTIVE_REDUNDANCY_DENOMINATOR is constant > 0.\n            if (EFFECTIVE_REDUNDANCY_DENOMINATOR > 0) { \n                 potential_useful_remaining = static_cast<double>(remaining_candidates) / EFFECTIVE_REDUNDANCY_DENOMINATOR;\n            }\n            \n            // --- Urgency Check ---\n            // If the number of merges needed is greater than or equal to the (pessimistic)\n            // estimate of useful edges remaining, then we must take this edge.\n            if (needed_to_connect >= potential_useful_remaining - URGENCY_SAFETY_MARGIN) {\n                decision = 1;\n            } else {\n                // --- Adaptive Threshold Check ---\n                // progress_ratio_taken is (edges_taken_count / (N_NODES - 1.0)), which is also\n                // equivalent to ((N_NODES - dsu.groups().size()) / (N_NODES - 1.0)),\n                // measuring how much of the MST has been completed.\n                double progress_ratio_taken = static_cast<double>(edges_taken_count) / (N_NODES - 1.0);\n                // current_tau interpolates between TAU_MIN (at start) and TAU_MAX (at completion).\n                double current_tau = TAU_MIN + (TAU_MAX - TAU_MIN) * progress_ratio_taken;\n\n                if (cost_ratio <= current_tau) {\n                    decision = 1;\n                }\n            }\n        }\n\n        if (decision == 1) {\n            dsu.merge(u, v);\n            edges_taken_count++;\n        }\n\n        std::cout << decision << std::endl;\n    }\n\n    return 0;\n}\n","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <set>\n#include <algorithm>\n#include <tuple> // For std::tie\n#include <map>   // For BFS path reconstruction\n\nusing namespace std;\n\n// Global constants\nconst int GRID_SIZE = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: U, D, L, R\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    // Overload operators for use in sets/maps and comparisons\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    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\n// Game state variables\nint N, M;\nvector<Point> pet_pos;\nvector<int> pet_type; // Not used for movement prediction in this solution\nvector<Point> human_pos;\n\n// Board state: 0=passable, 1=impassable (wall)\nvector<vector<int>> board(GRID_SIZE, vector<int>(GRID_SIZE, 0));\n\n// Global BFS data structures (re-used each time BFS is called)\nvector<vector<int>> dist_bfs;\nvector<vector<Point>> parent_bfs;\n\n// Function to check if a point is within grid boundaries\nbool is_valid(int r, int c) {\n    return r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE;\n}\n\n// BFS to find shortest path distance from start to target_dest_for_human.\n// Also stores parent pointers to reconstruct the first step of the path.\n// `start`: The starting point for BFS (human's current position).\n// `target_dest_for_human`: The specific cell the human wants to move to.\n// `current_blocked_this_turn`: Set of cells that will become walls this turn by other humans.\n// `current_moved_to_this_turn_targets`: Set of cells that other humans are planning to move to this turn.\n// `all_human_current_pos`: Current positions of all humans (to avoid pathfinding through other humans' current spots).\n// `self_idx`: Index of the human for whom BFS is being run (to allow passing through its own start cell).\nint bfs(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n        const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    dist_bfs.assign(GRID_SIZE, vector<int>(GRID_SIZE, -1));\n    parent_bfs.assign(GRID_SIZE, vector<Point>(GRID_SIZE, {-1, -1}));\n    queue<Point> q;\n\n    q.push(start);\n    dist_bfs[start.r][start.c] = 0;\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        if (curr == target_dest_for_human) {\n            return dist_bfs[curr.r][curr.c]; // Target reached\n        }\n\n        // Explore 4 cardinal neighbors\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.r + DR[i];\n            int nc = curr.c + DC[i];\n            Point next = {nr, nc};\n\n            // Basic checks: within bounds, not visited yet\n            if (!is_valid(nr, nc) || dist_bfs[nr][nc] != -1) continue;\n\n            // Check if 'next' cell is impassable due to existing walls or planned blocks\n            if (board[nr][nc] == 1) continue; // Existing permanent wall\n            if (current_blocked_this_turn.count(next)) continue; // Blocked by another human this turn\n\n            // Check if 'next' cell is a target for another human's move this turn\n            if (current_moved_to_this_turn_targets.count(next)) continue;\n            \n            // Check if 'next' cell is currently occupied by another human (who isn't moving out of it)\n            bool is_other_human_current_pos = false;\n            for(int h_idx_other = 0; h_idx_other < M; ++h_idx_other) {\n                if (h_idx_other == self_idx) continue; // Current human can pass through its own start\n                if (all_human_current_pos[h_idx_other] == next) {\n                    is_other_human_current_pos = true;\n                    break;\n                }\n            }\n            if (is_other_human_current_pos) continue; // Impassable if another human is currently there\n\n            // If all checks pass, 'next' is a valid step\n            dist_bfs[nr][nc] = dist_bfs[curr.r][curr.c] + 1;\n            parent_bfs[nr][nc] = curr;\n            q.push(next);\n        }\n    }\n    return -1; // Target not reachable\n}\n\n// Reconstructs the character for the first move from 'start' to 'target_dest_for_human' based on BFS path.\nchar get_move_char(Point start, Point target_dest_for_human, const set<Point>& current_blocked_this_turn,\n                   const set<Point>& current_moved_to_this_turn_targets, const vector<Point>& all_human_current_pos, int self_idx) {\n    if (bfs(start, target_dest_for_human, current_blocked_this_turn, current_moved_to_this_turn_targets, all_human_current_pos, self_idx) == -1) {\n        return '.'; // No path found\n    }\n\n    // Path reconstruction: find the first step from 'start' towards 'target_dest_for_human'\n    Point curr = target_dest_for_human;\n    // Walk back from target until we find the child of 'start'\n    while (parent_bfs[curr.r][curr.c] != start) {\n        curr = parent_bfs[curr.r][curr.c];\n        if (curr.r == -1 || curr.c == -1) return '.'; // Safety break for invalid parent\n    }\n\n    // 'curr' is now the first step from 'start'\n    for (int i = 0; i < 4; ++i) {\n        if (start.r + DR[i] == curr.r && start.c + DC[i] == curr.c) {\n            return MOVE_CHARS[i]; // Return corresponding move character\n        }\n    }\n    return '.'; // Should not be reached if BFS found a path\n}\n\n// Structure to represent a rectangle (inclusive coordinates, 0-indexed)\nstruct Rect {\n    int r1, c1, r2, c2;\n    int area() const { \n        if (r1 < 0 || c1 < 0 || r2 >= GRID_SIZE || c2 >= GRID_SIZE || r1 > r2 || c1 > c2) return 0; // Handle invalid rectangles\n        return (r2 - r1 + 1) * (c2 - c1 + 1); \n    }\n    // Check if a point is inside the rectangle\n    bool contains(Point p) const {\n        return p.r >= r1 && p.r <= r2 && p.c >= c1 && p.c <= c2;\n    }\n};\n\nRect target_rect = {0, 0, 0, 0}; // The main region humans will try to enclose\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read initial pet information\n    cin >> N;\n    pet_pos.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].r >> pet_pos[i].c >> pet_type[i];\n        pet_pos[i].r--; // Convert to 0-indexed\n        pet_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // Read initial human information\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].r >> human_pos[i].c;\n        human_pos[i].r--; // Convert to 0-indexed\n        human_pos[i].c--; // Convert to 0-indexed\n    }\n\n    // --- Initialization Phase: Find the best target rectangle ---\n    long long max_heuristic_score = -2e18; // Initialize with a very small number\n    Rect best_initial_rect = {-1, -1, -1, -1}; // Initialize with an invalid rectangle\n\n    // Brute force search for the best pet-free rectangle\n    for (int r1 = 0; r1 < GRID_SIZE; ++r1) {\n        for (int c1 = 0; c1 < GRID_SIZE; ++c1) {\n            for (int r2 = r1; r2 < GRID_SIZE; ++r2) {\n                for (int c2 = c1; c2 < GRID_SIZE; ++c2) {\n                    Rect current_rect = {r1, c1, r2, c2};\n                    bool is_pet_free = true;\n                    // Check if any pet is inside the current rectangle\n                    for (int i = 0; i < N; ++i) {\n                        if (current_rect.contains(pet_pos[i])) {\n                            is_pet_free = false;\n                            break;\n                        }\n                    }\n\n                    if (is_pet_free) {\n                        long long current_area = current_rect.area();\n                        if (current_area == 0) continue; // Skip 0-area rectangles\n                        \n                        // 1. Calculate sum of Manhattan distances from humans to perimeter of current_rect itself\n                        long long dist_sum_to_human_perimeter = 0;\n                        vector<Point> perimeter_of_rect_itself;\n                        for (int c = c1; c <= c2; ++c) {\n                            perimeter_of_rect_itself.push_back({r1, c});\n                            if (r1 != r2) perimeter_of_rect_itself.push_back({r2, c});\n                        }\n                        for (int r = r1 + 1; r < r2; ++r) { // Start from r1+1 to avoid double-counting corners with top/bottom rows\n                            perimeter_of_rect_itself.push_back({r, c1});\n                            if (c1 != c2) perimeter_of_rect_itself.push_back({r, c2});\n                        }\n                        \n                        if (!perimeter_of_rect_itself.empty()) {\n                            for (int i = 0; i < M; ++i) {\n                                int min_dist = 100000; \n                                for (const auto& p_cell : perimeter_of_rect_itself) {\n                                    min_dist = min(min_dist, abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c));\n                                }\n                                dist_sum_to_human_perimeter += min_dist;\n                            }\n                        } else { \n                            dist_sum_to_human_perimeter = 100000 * M; // High penalty for unapproachable/empty perimeter\n                        }\n\n                        // 2. Calculate initial \"vulnerability\" (number of unblockable wall cells around it)\n                        int vulnerability_score = 0;\n                        // Find potential wall cells (adjacent to current_rect, outside it)\n                        for (int r_outer = 0; r_outer < GRID_SIZE; ++r_outer) {\n                            for (int c_outer = 0; c_outer < GRID_SIZE; ++c_outer) {\n                                Point p_outer = {r_outer, c_outer};\n                                if (current_rect.contains(p_outer)) continue; // Can't block inside target rect\n                                bool adjacent_to_rect_internal = false;\n                                for (int d = 0; d < 4; ++d) {\n                                    Point neighbor_internal = {r_outer + DR[d], c_outer + DC[d]};\n                                    if (current_rect.contains(neighbor_internal)) {\n                                        adjacent_to_rect_internal = true;\n                                        break;\n                                    }\n                                }\n                                if (adjacent_to_rect_internal) { // p_outer is a candidate wall cell\n                                    // Check if this wall cell is initially unblockable due to pets\n                                    bool is_unblockable_by_pet_influence = false;\n                                    for (int p_idx = 0; p_idx < N; ++p_idx) {\n                                        Point pet = pet_pos[p_idx];\n                                        if (pet == p_outer) { // Pet is on the wall cell itself\n                                            is_unblockable_by_pet_influence = true;\n                                            break;\n                                        }\n                                        for (int d_pet = 0; d_pet < 4; ++d_pet) {\n                                            Point pet_neighbor = {pet.r + DR[d_pet], pet.c + DC[d_pet]};\n                                            if (pet_neighbor == p_outer) { // Wall cell is adjacent to a pet\n                                                is_unblockable_by_pet_influence = true;\n                                                break;\n                                            }\n                                        }\n                                        if (is_unblockable_by_pet_influence) break;\n                                    }\n                                    if (is_unblockable_by_pet_influence) {\n                                        vulnerability_score++;\n                                    }\n                                }\n                            }\n                        }\n                        \n                        // Heuristic score: Area - W1 * Sum_of_Distances - W2 * Vulnerability_Score\n                        // W1 = 1 to value proximity to humans\n                        // W2 = 10 to strongly penalize walls that are hard to build initially due to pets\n                        long long current_heuristic_score = current_area - dist_sum_to_human_perimeter * 1 - (long long)vulnerability_score * 10; \n\n                        if (current_heuristic_score > max_heuristic_score) {\n                            max_heuristic_score = current_heuristic_score;\n                            best_initial_rect = current_rect;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fallback: If no good pet-free rectangle found or area is too small.\n    // Use an arbitrary threshold of 25 cells for \"too small\" for M=5 humans.\n    if (best_initial_rect.area() == 0 || best_initial_rect.area() < (long long)M * 5) { \n        target_rect = {5, 5, 24, 24}; // Default to 20x20 central square (0-indexed)\n        // Ensure this fallback is also pet-free, if not, then the entire score will be zero anyway.\n        // It's assumed inputs guarantee at least some viable region.\n    } else {\n        target_rect = best_initial_rect;\n    }\n\n    // Generate the set of actual target wall cells that humans will block\n    // These are cells adjacent to target_rect, but outside target_rect.\n    set<Point> wall_target_cells_set;\n    for (int r_cell = 0; r_cell < GRID_SIZE; ++r_cell) {\n        for (int c_cell = 0; c_cell < GRID_SIZE; ++c_cell) {\n            Point p = {r_cell, c_cell};\n            if (target_rect.contains(p)) continue; // Cannot block inside the target rect\n            bool is_adjacent_to_target_rect_internal = false;\n            for (int d = 0; d < 4; ++d) {\n                Point neighbor = {r_cell + DR[d], c_cell + DC[d]};\n                if (target_rect.contains(neighbor)) {\n                    is_adjacent_to_target_rect_internal = true;\n                    break;\n                }\n            }\n            if (is_adjacent_to_target_rect_internal) {\n                wall_target_cells_set.insert(p);\n            }\n        }\n    }\n    // Convert to vector for easier iteration with indices.\n    vector<Point> target_wall_goals_vector(wall_target_cells_set.begin(), wall_target_cells_set.end());\n    \n    // `human_target_wall_goals[i]` stores the specific wall cell that human 'i' is trying to block.\n    vector<Point> human_target_wall_goals(M, {-1,-1}); \n\n    // --- Main Loop: 300 turns of human actions and pet movements ---\n    for (int turn = 0; turn < MAX_TURNS; ++turn) {\n        // 1. Determine `can_block_grid`: which cells are valid to block this turn.\n        // Initialize to true, then mark invalid ones.\n        vector<vector<bool>> can_block_grid(GRID_SIZE, vector<bool>(GRID_SIZE, true));\n        // Pets make cells unblockable\n        for (int i = 0; i < N; ++i) {\n            Point p = pet_pos[i];\n            // Cell containing pet is unblockable\n            if(is_valid(p.r, p.c)) can_block_grid[p.r][p.c] = false; \n            // Cells adjacent to a pet are unblockable\n            for (int d = 0; d < 4; ++d) { \n                int nr = p.r + DR[d];\n                int nc = p.c + DC[d];\n                if (is_valid(nr, nc)) {\n                    can_block_grid[nr][nc] = false;\n                }\n            }\n        }\n        // Humans make cells unblockable (their own position)\n        for (int i = 0; i < M; ++i) {\n            Point h = human_pos[i];\n            if(is_valid(h.r, h.c)) can_block_grid[h.r][h.c] = false; \n        }\n\n        // 2. Human Action Planning\n        vector<char> actions_output(M, '.'); // Stores the final action character for each human\n        vector<Point> next_human_pos_candidates(M); // Stores each human's position AFTER actions\n        for(int i=0; i<M; ++i) next_human_pos_candidates[i] = human_pos[i]; // Default: stay put\n\n        set<Point> current_blocked_this_turn;       // Cells chosen to be blocked by humans THIS turn\n        set<Point> current_moved_to_this_turn_targets; // Cells chosen to be moved into by humans THIS turn\n\n        // 2.1. Update each human's block goal\n        // Humans greedily pick the best available wall target cell based on a score.\n        for (int i = 0; i < M; ++i) {\n            // Re-assign goal if current goal is completed, invalid, or already blocked\n            if (human_target_wall_goals[i].r == -1 || \n                !is_valid(human_target_wall_goals[i].r, human_target_wall_goals[i].c) ||\n                board[human_target_wall_goals[i].r][human_target_wall_goals[i].c] == 1) { \n                \n                Point best_goal = {-1,-1};\n                long long max_current_cell_score_for_human = -2e18; // Initialize with a very small number\n\n                // Temporarily track goals assigned to other humans (within this turn's assignment phase)\n                set<Point> temp_assigned_goals;\n                for(int j=0; j<M; ++j) {\n                    if (j != i && human_target_wall_goals[j].r != -1) {\n                        temp_assigned_goals.insert(human_target_wall_goals[j]);\n                    }\n                }\n\n                for (const auto& p_cell : target_wall_goals_vector) { // Iterate over actual wall target cells\n                    // Check if the wall target cell is currently:\n                    //   1. Passable (not already a permanent wall)\n                    //   2. Blockable (no pets nearby, not occupied by human/pet)\n                    //   3. Not already being blocked by another human this turn (from current_blocked_this_turn)\n                    //   4. Not already assigned as a goal to another human (for current goal assignment phase)\n                    if (board[p_cell.r][p_cell.c] == 0 && can_block_grid[p_cell.r][p_cell.c] && \n                        !current_blocked_this_turn.count(p_cell) && !temp_assigned_goals.count(p_cell)) {\n                        \n                        long long current_cell_score = 0;\n                        int dist_to_human = abs(human_pos[i].r - p_cell.r) + abs(human_pos[i].c - p_cell.c); \n                        \n                        // Penalty for distance from human (lower dist is better, so subtract dist)\n                        current_cell_score -= (long long)dist_to_human * 1; \n\n                        // Bonus for blocking cells that are near pets (higher danger is better to block)\n                        int pet_danger_score = 0;\n                        for (int p_idx = 0; p_idx < N; ++p_idx) {\n                            Point pet = pet_pos[p_idx];\n                            if (target_rect.contains(pet)) continue; // Only consider pets outside target_rect\n                            \n                            int pet_dist = abs(pet.r - p_cell.r) + abs(pet.c - p_cell.c);\n                            if (pet_dist == 1) { // Manhattan dist 1 means adjacent\n                                pet_danger_score += 100; // Significant bonus for blocking a cell directly adjacent to a pet\n                            } else if (pet_dist == 2) { // Manhattan dist 2\n                                pet_danger_score += 10; // Moderate bonus\n                            } else if (pet_dist == 3) {\n                                pet_danger_score += 1; // Small bonus\n                            }\n                        }\n                        current_cell_score += pet_danger_score;\n\n                        if (current_cell_score > max_current_cell_score_for_human) {\n                            max_current_cell_score_for_human = current_cell_score;\n                            best_goal = p_cell;\n                        }\n                    }\n                }\n                human_target_wall_goals[i] = best_goal; // Assign the new best goal\n            }\n        }\n        \n        // 2.2. Phase 1: Determine BLOCK actions\n        // Humans who are adjacent to their block goal perform the block action.\n        for (int i = 0; i < M; ++i) {\n            if (human_target_wall_goals[i].r != -1) {\n                Point goal_to_block = human_target_wall_goals[i]; // This is the cell to make impassable\n                for (int d = 0; d < 4; ++d) { // Check if human is adjacent to this goal_to_block\n                    if (human_pos[i].r + DR[d] == goal_to_block.r && human_pos[i].c + DC[d] == goal_to_block.c) { \n                        // Human is adjacent to goal_to_block. Can they block it?\n                        if (board[goal_to_block.r][goal_to_block.c] == 0 && can_block_grid[goal_to_block.r][goal_to_block.c] && !current_blocked_this_turn.count(goal_to_block)) {\n                            actions_output[i] = BLOCK_CHARS[d]; // Set block action\n                            current_blocked_this_turn.insert(goal_to_block); // Mark as blocked for this turn\n                            board[goal_to_block.r][goal_to_block.c] = 1; // Temporarily update board for pathfinding in Phase 2\n                            human_target_wall_goals[i] = {-1,-1}; // Goal achieved, reset\n                        }\n                        break; // A human can only perform one action (block or move)\n                    }\n                }\n            }\n        }\n        \n        // 2.3. Phase 2: Determine MOVE actions for humans who did not block.\n        // Use a priority queue to resolve conflicts for moving to the same cell.\n        struct MoveCandidate {\n            int human_idx;\n            Point next_pos; // The cell human will move TO\n            char move_char;\n            int priority; // Higher priority (e.g., closer to goal) is better\n            bool operator<(const MoveCandidate& other) const {\n                return priority < other.priority; // Min-priority queue for default, so this makes it max-priority.\n            }\n        };\n        priority_queue<MoveCandidate> move_queue;\n\n        for (int i = 0; i < M; ++i) {\n            if (actions_output[i] == '.') { // Only if human didn't block in Phase 1\n                Point wall_cell_to_block = human_target_wall_goals[i];\n                if (wall_cell_to_block.r != -1) { // If there's still a wall target to move towards\n                    // Find the best position for the human to *stand* in order to block 'wall_cell_to_block'.\n                    // This means finding a cell adjacent to 'wall_cell_to_block' that is pathable for the human.\n                    Point target_human_stand_pos = {-1,-1};\n                    int min_dist_to_stand_pos = 100000;\n\n                    for(int d=0; d<4; ++d) {\n                        Point candidate_stand_pos = {wall_cell_to_block.r + DR[d], wall_cell_to_block.c + DC[d]};\n                        \n                        // Preliminary checks for a valid 'stand_pos' (more thorough check in BFS)\n                        if (is_valid(candidate_stand_pos.r, candidate_stand_pos.c) &&\n                            board[candidate_stand_pos.r][candidate_stand_pos.c] == 0 && // Not existing wall\n                            !current_blocked_this_turn.count(candidate_stand_pos)) { // Not blocked this turn\n                            \n                            int dist = abs(human_pos[i].r - candidate_stand_pos.r) + abs(human_pos[i].c - candidate_stand_pos.c); // Manhattan distance\n                            if (dist < min_dist_to_stand_pos) {\n                                min_dist_to_stand_pos = dist;\n                                target_human_stand_pos = candidate_stand_pos;\n                            }\n                        }\n                    }\n\n                    if (target_human_stand_pos.r != -1 && target_human_stand_pos != human_pos[i]) { // Found a valid stand position, and it's not current position\n                        // Use BFS to get the first move character towards target_human_stand_pos\n                        char move_c = get_move_char(human_pos[i], target_human_stand_pos, \n                                                    current_blocked_this_turn, current_moved_to_this_turn_targets, \n                                                    human_pos, i); \n                        if (move_c != '.') { // If a path was found\n                            Point first_step = human_pos[i]; // Will be updated\n                            for (int d_idx = 0; d_idx < 4; ++d_idx) {\n                                if (MOVE_CHARS[d_idx] == move_c) {\n                                    first_step = {human_pos[i].r + DR[d_idx], human_pos[i].c + DC[d_idx]};\n                                    break;\n                                }\n                            }\n                            // Priority is based on negative distance to target_human_stand_pos. Smaller distance means higher priority\n                            move_queue.push({i, first_step, move_c, -min_dist_to_stand_pos}); \n                        }\n                    }\n                }\n            }\n        }\n\n        // Process the move_queue to resolve conflicts (multiple humans wanting to move to the same cell)\n        while (!move_queue.empty()) {\n            MoveCandidate mc = move_queue.top();\n            move_queue.pop();\n\n            if (actions_output[mc.human_idx] == '.') { // If human hasn't been assigned an action yet\n                // Check if the target cell for this move is free (not blocked or targeted by another human)\n                if (!current_blocked_this_turn.count(mc.next_pos) && !current_moved_to_this_turn_targets.count(mc.next_pos)) {\n                    actions_output[mc.human_idx] = mc.move_char; // Assign the move action\n                    next_human_pos_candidates[mc.human_idx] = mc.next_pos; // Update planned position\n                    current_moved_to_this_turn_targets.insert(mc.next_pos); // Mark as targeted\n                }\n                // Else: Conflict occurred, the human stays put (action remains '.')\n            }\n        }\n\n        // 3. Output actions for all humans\n        for (int i = 0; i < M; ++i) {\n            cout << actions_output[i];\n        }\n        cout << endl; // Newline after all actions\n        fflush(stdout); // Crucial for interactive problems\n\n        // 4. Update game state (board and human_pos) based on actions\n        for (int i = 0; i < M; ++i) {\n            // If the action was a block, update the board state permanently\n            // Check if it's not a '.' and not one of the move characters ('U', 'D', 'L', 'R')\n            if (actions_output[i] != '.' && string(MOVE_CHARS).find(actions_output[i]) == string::npos) {\n                Point blocked_cell = human_pos[i]; // Default value\n                char block_char = actions_output[i];\n                for(int d=0; d<4; ++d) {\n                    if (BLOCK_CHARS[d] == block_char) {\n                        blocked_cell = {human_pos[i].r + DR[d], human_pos[i].c + DC[d]};\n                        break;\n                    }\n                }\n                if (is_valid(blocked_cell.r, blocked_cell.c)) { // Sanity check for blocked_cell\n                    board[blocked_cell.r][blocked_cell.c] = 1; // Mark cell as impassable\n                }\n            }\n            human_pos[i] = next_human_pos_candidates[i]; // Update human positions\n        }\n\n        // 5. Read pet movements and update pet positions\n        string pet_moves_str;\n        for (int i = 0; i < N; ++i) {\n            cin >> pet_moves_str;\n            if (pet_moves_str == \".\") continue; // Pet did not move\n            \n            for (char move_char : pet_moves_str) {\n                for (int d = 0; d < 4; ++d) {\n                    if (MOVE_CHARS[d] == move_char) {\n                        pet_pos[i].r += DR[d];\n                        pet_pos[i].c += DC[d];\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int H = 20;\nconst int W = 20;\nconst int MAX_PATH_LENGTH = 200;\n\n// Global variables for problem input\nint start_r, start_c, target_r, target_c;\ndouble p_forget_val;\nbool has_wall_right[H][W - 1]; // wall between (r,c) and (r,c+1)\nbool has_wall_down[H - 1][W];  // wall between (r,c) and (r+1,c)\n\n// Directions for movement\nint dr[] = {-1, 1, 0, 0}; // U, D, L, R\nint dc[] = {0, 0, -1, 1};\nchar move_chars[] = {'U', 'D', 'L', 'R'};\n\n// Helper function to calculate next position, staying if wall or boundary\npair<int, int> get_next_pos(int r, int c, char move_char) {\n    int nr = r, nc = c; // Default to staying\n    if (move_char == 'U') {\n        if (r > 0 && !has_wall_down[r - 1][c]) {\n            nr = r - 1;\n        }\n    } else if (move_char == 'D') {\n        if (r < H - 1 && !has_wall_down[r][c]) {\n            nr = r + 1;\n        }\n    } else if (move_char == 'L') {\n        if (c > 0 && !has_wall_right[r][c - 1]) {\n            nc = c - 1;\n        }\n    } else if (move_char == 'R') {\n        if (c < W - 1 && !has_wall_right[r][c]) {\n            nc = c + 1;\n        }\n    }\n    return {nr, nc};\n}\n\n// DP states (declared globally to avoid reallocations and for performance)\nvector<vector<double>> current_dp_state(H, vector<double>(W));\nvector<vector<double>> next_dp_state(H, vector<double>(W));\n\n// Evaluates a given path string\ndouble evaluate(const string& path) {\n    // Reset initial state for a new path evaluation\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_dp_state[i][j] = 0.0;\n        }\n    }\n    current_dp_state[start_r][start_c] = 1.0;\n\n    double total_expected_score = 0.0;\n\n    for (int k = 0; k < path.length(); ++k) {\n        // Clear next_dp_state for this turn's calculations\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                next_dp_state[i][j] = 0.0;\n            }\n        }\n\n        double prob_reach_this_turn = 0.0;\n        char move_char = path[k];\n\n        for (int r = 0; r < H; ++r) {\n            for (int c = 0; c < W; ++c) {\n                // Use a small epsilon for double comparison\n                if (current_dp_state[r][c] < 1e-18) continue; \n\n                // Option 1: Forgets char (prob p_forget_val), stays at (r,c)\n                next_dp_state[r][c] += current_dp_state[r][c] * p_forget_val;\n\n                // Option 2: Remembers char (prob 1-p_forget_val), moves according to move_char\n                pair<int, int> next_pos = get_next_pos(r, c, move_char);\n                int nr = next_pos.first;\n                int nc = next_pos.second;\n\n                if (nr == target_r && nc == target_c) {\n                    // Reached target at turn k+1\n                    prob_reach_this_turn += current_dp_state[r][c] * (1.0 - p_forget_val);\n                } else {\n                    // Did not reach target\n                    next_dp_state[nr][nc] += current_dp_state[r][c] * (1.0 - p_forget_val);\n                }\n            }\n        }\n\n        total_expected_score += prob_reach_this_turn * (401.0 - (k + 1));\n        current_dp_state.swap(next_dp_state); // Efficiently update current_dp_state\n    }\n    return total_expected_score;\n}\n\n// BFS to find the shortest path\nstring get_bfs_path() {\n    vector<vector<int>> dist(H, vector<int>(W, -1));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> move_to_parent(H, vector<char>(W, ' '));\n    queue<pair<int, int>> q;\n\n    q.push({start_r, start_c});\n    dist[start_r][start_c] = 0;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        if (r == target_r && c == target_c) break; // Found target\n\n        for (int i = 0; i < 4; ++i) { // For each direction (U, D, L, R)\n            int potential_nr = r + dr[i];\n            int potential_nc = c + dc[i];\n            char move_char = move_chars[i];\n\n            bool can_move = true;\n            if (move_char == 'U') {\n                if (r == 0 || has_wall_down[r - 1][c]) can_move = false;\n            } else if (move_char == 'D') {\n                if (r == H - 1 || has_wall_down[r][c]) can_move = false;\n            } else if (move_char == 'L') {\n                if (c == 0 || has_wall_right[r][c - 1]) can_move = false;\n            } else if (move_char == 'R') {\n                if (c == W - 1 || has_wall_right[r][c]) can_move = false;\n            }\n\n            if (!can_move) continue;\n            \n            // If can_move, the next valid position is (potential_nr, potential_nc)\n            if (dist[potential_nr][potential_nc] == -1) { // If not visited\n                dist[potential_nr][potential_nc] = dist[r][c] + 1;\n                parent[potential_nr][potential_nc] = {r, c};\n                move_to_parent[potential_nr][potential_nc] = move_char;\n                q.push({potential_nr, potential_nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path_str = \"\";\n    int curr_r = target_r;\n    int curr_c = target_c;\n    \n    // Problem guarantees start and target are different and reachable.\n    while (curr_r != start_r || curr_c != start_c) {\n        path_str += move_to_parent[curr_r][curr_c];\n        pair<int, int> p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    reverse(path_str.begin(), path_str.end());\n    return path_str;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read input\n    cin >> start_r >> start_c >> target_r >> target_c >> p_forget_val;\n\n    for (int i = 0; i < H; ++i) {\n        string row_h;\n        cin >> row_h;\n        for (int j = 0; j < W - 1; ++j) {\n            has_wall_right[i][j] = (row_h[j] == '1');\n        }\n    }\n    for (int i = 0; i < H - 1; ++i) {\n        string row_v;\n        cin >> row_v;\n        for (int j = 0; j < W; ++j) {\n            has_wall_down[i][j] = (row_v[j] == '1');\n        }\n    }\n\n    // Timer setup\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1950.0; // Use 1.95 seconds to be safe\n\n    // Initial path (BFS shortest path)\n    string best_path_str = get_bfs_path();\n    double best_score = evaluate(best_path_str);\n    string current_path_str = best_path_str;\n    double current_score = best_score;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    \n    // SA parameters: T_start reverted to 2000.0, which yielded highest score.\n    double T_start = 2000.0; \n    double T_end = 1.0;     \n\n    // Cache BFS path length for mutation probability calculation\n    int bfs_path_length = best_path_str.length();\n\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_ms = chrono::duration_cast<chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) break;\n\n        double T = T_start * pow(T_end / T_start, elapsed_ms / TIME_LIMIT_MS);\n        \n        string new_path_str = current_path_str;\n        \n        // Adaptive Operation Selection Probabilities\n        double current_len = new_path_str.length();\n        \n        // Base weights for different operations\n        double change_char_weight = 2.0;\n        double insert_char_weight = 1.0;\n        double delete_char_weight = 1.0;\n        double duplicate_segment_weight = 1.0;\n\n        // Scale p_forget_val from [0.1, 0.5] to [0, 1]\n        double p_scaled = (p_forget_val - 0.1) / (0.5 - 0.1); \n\n        // Adjust weights based on p_forget_val (coefficients from 1.62B score)\n        // Higher p_forget_val -> more need for redundancy (insert/duplicate)\n        duplicate_segment_weight += p_scaled * 2.5; \n        insert_char_weight += p_scaled * 1.5;      \n        delete_char_weight -= p_scaled * 0.7;      \n\n        // Estimated \"optimal\" path length\n        // Multiplier for p_forget_val, encouraging longer paths for higher p (reverted to 4.0 from 1.62B score)\n        // Removed the p_multiplier_bonus.\n        double estimated_optimal_len = min((double)MAX_PATH_LENGTH, (double)bfs_path_length * (1.0 + p_forget_val * 4.0)); \n        \n        // Adjust weights based on current path length relative to estimated optimal (coefficients from 1.62B score)\n        double len_diff_normalized = (current_len - estimated_optimal_len) / (MAX_PATH_LENGTH - bfs_path_length + 1e-9);\n        len_diff_normalized = max(-1.0, min(1.0, len_diff_normalized)); \n\n        insert_char_weight -= len_diff_normalized * 1.5; \n        duplicate_segment_weight -= len_diff_normalized * 1.5;\n        delete_char_weight += len_diff_normalized * 2.0; \n        \n        // Floor weights to ensure they are at least a small positive value\n        change_char_weight = max(0.01, change_char_weight);\n        insert_char_weight = max(0.01, insert_char_weight);\n        delete_char_weight = max(0.01, delete_char_weight);\n        duplicate_segment_weight = max(0.01, duplicate_segment_weight);\n        \n        // Calculate total weight and normalize to probabilities\n        double total_weight = change_char_weight + insert_char_weight + delete_char_weight + duplicate_segment_weight;\n        double p_change = change_char_weight / total_weight;\n        double p_insert = insert_char_weight / total_weight;\n        double p_delete = delete_char_weight / total_weight;\n        double p_duplicate = duplicate_segment_weight / total_weight;\n\n        // Cumulative probabilities for random choice\n        double cum_p_change = p_change;\n        double cum_p_insert = cum_p_change + p_insert;\n        double cum_p_delete = cum_p_insert + p_delete;\n        \n        double op_choice_rand = prob_dist(rng);\n\n        if (op_choice_rand < cum_p_change) { \n            // --- Operation 1: Change character ---\n            if (new_path_str.empty()) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            char original_char = new_path_str[idx];\n            \n            char new_char;\n            do {\n                uniform_int_distribution<int> char_dist(0, 3);\n                new_char = move_chars[char_dist(rng)];\n            } while (new_char == original_char); \n            \n            new_path_str[idx] = new_char;\n        } else if (op_choice_rand < cum_p_insert) {\n            // --- Operation 2: Insert character ---\n            if (new_path_str.length() >= MAX_PATH_LENGTH) continue; \n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length()); \n            int idx = idx_dist(rng);\n            uniform_int_distribution<int> char_dist(0, 3);\n            char char_to_insert = move_chars[char_dist(rng)];\n            \n            new_path_str.insert(idx, 1, char_to_insert);\n        } else if (op_choice_rand < cum_p_delete) { \n            // --- Operation 3: Delete character ---\n            if (new_path_str.empty() || new_path_str.length() == 1) continue; \n\n            uniform_int_distribution<int> idx_dist(0, (int)new_path_str.length() - 1);\n            int idx = idx_dist(rng);\n            \n            new_path_str.erase(idx, 1);\n        } else {\n            // --- Operation 4: Duplicate/Repeat Segment ---\n            if (new_path_str.length() < 2) continue; \n\n            uniform_int_distribution<int> seg_start_idx_dist(0, (int)new_path_str.length() - 2); \n            int seg_start_idx = seg_start_idx_dist(rng);\n            \n            int max_possible_seg_len_from_start = new_path_str.length() - seg_start_idx;\n            uniform_int_distribution<int> seg_len_dist(2, min(max_possible_seg_len_from_start, 20)); \n            int seg_len = seg_len_dist(rng);\n            \n            string segment = new_path_str.substr(seg_start_idx, seg_len);\n\n            if (new_path_str.length() + segment.length() > MAX_PATH_LENGTH) {\n                segment = segment.substr(0, MAX_PATH_LENGTH - new_path_str.length());\n                if (segment.length() < 2) continue; \n            }\n            if (segment.empty()) continue; \n\n            uniform_int_distribution<int> insert_idx_dist(0, (int)new_path_str.length()); \n            int insert_idx = insert_idx_dist(rng);\n            \n            new_path_str.insert(insert_idx, segment);\n        }\n\n        // Evaluate new path\n        double new_score = evaluate(new_path_str);\n\n        // SA acceptance criterion\n        if (new_score > current_score || prob_dist(rng) < exp((new_score - current_score) / T)) {\n            current_score = new_score;\n            current_path_str = new_path_str;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_path_str = current_path_str;\n            }\n        }\n    }\n\n    cout << best_path_str << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <tuple> // For std::tuple\n\n// Define grid dimensions\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0=Left, 1=Up, 2=Right, 3=Down\n// di, dj: changes in row and column for each direction\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// initial_to[tile_type][entry_direction] -> exit_direction\n// Provided by problem statement\nconst int initial_to[8][4] = {\n    {1, 0, -1, -1}, // Type 0: L-U curve (0-1)\n    {-1, 2, 1, -1}, // Type 1: U-R curve (1-2)\n    {-1, -1, 3, 2}, // Type 2: R-D curve (2-3)\n    {3, -1, -1, 0}, // Type 3: D-L curve (3-0)\n    {1, 0, 3, 2},   // Type 4: L-U and R-D (0-1, 2-3)\n    {3, 2, 1, 0},   // Type 5: U-R and D-L (1-2, 3-0)\n    {2, -1, 0, -1}, // Type 6: horizontal straight (0-2)\n    {-1, 3, -1, 1}  // Type 7: vertical straight (1-3)\n};\n\n// Stores the initial tile types read from input\nstd::vector<std::vector<int>> initial_tiles(H, std::vector<int>(W));\n// Stores the current rotation for each tile (0-3)\nstd::vector<std::vector<int>> current_rotations(H, std::vector<int>(W));\n\n// Precompute effective_to table for faster lookup\n// effective_to[initial_tile_type][rotation_count][entry_direction] -> exit_direction\nint effective_to[8][4][4];\n\nvoid precompute_effective_to() {\n    for (int t_initial = 0; t_initial < 8; ++t_initial) {\n        for (int r_rot = 0; r_rot < 4; ++r_rot) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // 1. Convert absolute entry direction to tile's original orientation\n                int d_base = (d_entry - r_rot + 4) % 4;\n                \n                // 2. Find exit direction in tile's original orientation\n                int exit_base = initial_to[t_initial][d_base];\n                \n                // 3. If broken, mark as -1\n                if (exit_base == -1) {\n                    effective_to[t_initial][r_rot][d_entry] = -1;\n                } else {\n                    // 4. Convert exit direction back to absolute orientation\n                    effective_to[t_initial][r_rot][d_entry] = (exit_base + r_rot) % 4;\n                }\n            }\n        }\n    }\n}\n\n// Function to calculate the exit direction for a given tile and entry\ninline int get_exit_dir(int r, int c, int d_entry) {\n    return effective_to[initial_tiles[r][c]][current_rotations[r][c]][d_entry];\n}\n\nstruct VisitedState {\n    int id;  // Unique ID for the current calculate_score() call or active path\n    int len; // Path length when this state was first visited in current active path\n};\n// Use static to initialize once to {0,0} for all entries\nstatic VisitedState visited_tracking[H][W][4];\nstatic int current_search_id = 0; // Incremented for each calculate_score() call\n\n// Global/static vector to avoid repeated allocations in calculate_score\nstatic std::vector<std::tuple<int, int, int>> nodes_in_current_path_segment_global;\n\nlong long calculate_score() {\n    std::vector<long long> loop_lengths;\n    current_search_id++; // New unique ID for this score calculation\n\n    // `active_path_id` is used to mark nodes *currently in the path exploration*.\n    // `current_search_id` is used to mark nodes that have been *fully processed*\n    // (either part of a completed cycle or a path that dead-ended/merged into an already processed segment).\n    int active_path_id = current_search_id + 1; // Unique ID for current path traversal\n\n    for (int r = 0; r < H; ++r) {\n        for (int c = 0; c < W; ++c) {\n            for (int d_entry = 0; d_entry < 4; ++d_entry) {\n                // Skip if this state has already been part of a fully processed path/cycle\n                if (visited_tracking[r][c][d_entry].id == current_search_id) {\n                    continue; \n                }\n\n                int curr_r = r;\n                int curr_c = c;\n                int curr_d_entry = d_entry;\n                long long path_len = 0;\n                \n                nodes_in_current_path_segment_global.clear(); // Clear for current path exploration\n\n                while (true) {\n                    // Check if current node is out of bounds\n                    if (curr_r < 0 || curr_r >= H || curr_c < 0 || curr_c >= W) {\n                        break; // Out of bounds, path broken\n                    }\n                    \n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == active_path_id) {\n                        // Cycle detected! Current node was visited in this active path.\n                        // The length of the loop is the current path length minus the length\n                        // when this node was first visited in this active path.\n                        long long cycle_start_len = visited_tracking[curr_r][curr_c][curr_d_entry].len;\n                        loop_lengths.push_back(path_len - cycle_start_len);\n                        break;\n                    }\n                    if (visited_tracking[curr_r][curr_c][curr_d_entry].id == current_search_id) {\n                        // Merged into an already processed path/cycle. This means this path segment\n                        // doesn't form a new distinct loop starting from `(r,c,d_entry)`.\n                        break;\n                    }\n\n                    // Mark current node as 'in active path' and record its length\n                    visited_tracking[curr_r][curr_c][curr_d_entry] = {active_path_id, (int)path_len};\n                    nodes_in_current_path_segment_global.emplace_back(curr_r, curr_c, curr_d_entry); // Store nodes for later global marking\n\n                    int d_exit = get_exit_dir(curr_r, curr_c, curr_d_entry);\n                    if (d_exit == -1) {\n                        break; // Broken line\n                    }\n\n                    int next_r = curr_r + di[d_exit];\n                    int next_c = curr_c + dj[d_exit];\n                    // The train enters the next tile from the opposite direction it exited.\n                    int next_d_entry = (d_exit + 2) % 4; \n                    path_len++;\n\n                    curr_r = next_r;\n                    curr_c = next_c;\n                    curr_d_entry = next_d_entry;\n                }\n\n                // After path ends (break from loop), mark all nodes visited in `nodes_in_current_path_segment_global`\n                // as 'processed for current_search_id'. This ensures they are not re-evaluated as starting points\n                // for new paths within the same `calculate_score` call.\n                for (const auto& node : nodes_in_current_path_segment_global) {\n                    visited_tracking[std::get<0>(node)][std::get<1>(node)][std::get<2>(node)].id = current_search_id;\n                }\n            }\n        }\n    }\n\n    if (loop_lengths.size() < 2) {\n        return 0; // Score is 0 if less than two loop lines\n    }\n\n    std::sort(loop_lengths.rbegin(), loop_lengths.rend()); // Sort descending\n    return loop_lengths[0] * loop_lengths[1]; // Product of two longest loops\n}\n\n// Random number generator\nstd::mt19937 mt;\n\nvoid solve() {\n    auto start_time = std::chrono::high_resolution_clock::now();\n\n    // Read initial tile types\n    for (int i = 0; i < H; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < W; ++j) {\n            initial_tiles[i][j] = row_str[j] - '0';\n        }\n    }\n\n    precompute_effective_to();\n\n    // Initialize random number generator using current time\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\n    mt.seed(seed);\n\n    // Initial solution: assign random rotations to all tiles\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            current_rotations[i][j] = mt() % 4;\n        }\n    }\n\n    std::vector<std::vector<int>> best_rotations = current_rotations;\n    long long current_score = calculate_score();\n    long long best_score = current_score;\n\n    // Simulated Annealing parameters\n    // T_START reverted to 5000.0, which previously yielded the highest score.\n    double T_START = 5000.0; \n    // TIME_LIMIT_MS set to fully utilize the time for SA.\n    const double TIME_LIMIT_MS = 1995.0; // Use 1.995 seconds out of 2.0s total\n\n    // Store the changed tile and its old rotation for easy reversion\n    int r_idx_changed, c_idx_changed, old_rot_changed;\n\n    // --- Simulated Annealing Phase (full time) ---\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) { \n            break; // Time limit exceeded, terminate SA\n        }\n\n        // Linear cooling schedule: temperature decreases over time\n        double T = T_START * (1.0 - elapsed_ms / TIME_LIMIT_MS);\n        if (T < 0.1) T = 0.1; // Prevent T from becoming too small, avoiding `exp()` issues or division by zero\n\n        // Generate neighbor state: change only ONE random tile\n        r_idx_changed = mt() % H;\n        c_idx_changed = mt() % W;\n        old_rot_changed = current_rotations[r_idx_changed][c_idx_changed];\n        int new_rot = (old_rot_changed + (mt() % 3) + 1) % 4; // Ensures new_rot is different from old_rot\n        \n        current_rotations[r_idx_changed][c_idx_changed] = new_rot;\n\n        long long neighbor_score = calculate_score();\n        \n        long long delta_score = neighbor_score - current_score;\n\n        // Acceptance criteria based on Metropolis-Hastings:\n        // Always accept if score improves (delta_score > 0).\n        // Otherwise, accept with probability exp(delta_score / T).\n        if (delta_score > 0 || std::uniform_real_distribution<double>(0.0, 1.0)(mt) < std::exp(delta_score / T)) {\n            current_score = neighbor_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_rotations = current_rotations; // Update overall best solution\n            }\n        } else {\n            // Revert to old rotation if new state is not accepted\n            current_rotations[r_idx_changed][c_idx_changed] = old_rot_changed;\n        }\n    }\n\n    // Output the rotations corresponding to the best score found\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            std::cout << best_rotations[i][j];\n        }\n    }\n    std::cout << std::endl;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\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 <random>\n#include <chrono>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <limits> // For numeric_limits\n\nusing namespace std;\n\n// --- Constants and Global Variables ---\nconst long long TOTAL_TIME_LIMIT_MS = 2800; // 2.8 seconds for computation\nconst double T_START = 1000.0;       // Initial temperature (optimal from 11.98M score)\nconst double T_END = 200.0;          // Final temperature (optimal from 11.98M score)\nconst int NUM_SA_RUNS = 20;          // Number of iterated SA runs (optimal from 11.98M score)\n\nint N;               // Board size\nint MAX_S_VALUE;     // Maximum possible S value (N*N - 1)\nlong long MAX_MOVES; // Maximum allowed operations (T = 2 * N^3)\n\n// Energy function weights\nlong double W_S_CRITICAL; // Huge weight for (MAX_S_VALUE - S) when S < MAX_S_VALUE\nlong double W_K = 1.0;    // Weight for K\n\n// Directions for empty square movement\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_char[] = {'U', 'D', 'L', 'R'};\nint opposite_dir[] = {1, 0, 3, 2}; // e.g., opposite of U(0) is D(1)\n\n// Global random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// --- DSU Structure for Score Calculation ---\nstruct DSU {\n    vector<int> parent;\n    vector<int> comp_size;\n    vector<int> num_edges;\n    vector<bool> has_cycle;\n    int num_cells;\n\n    DSU(int n_squared) : num_cells(n_squared) {\n        parent.resize(num_cells);\n        iota(parent.begin(), parent.end(), 0); // Initialize parent[i] = i\n        comp_size.assign(num_cells, 1);        // Each cell starts as a component of size 1\n        num_edges.assign(num_cells, 0);        // Each component starts with 0 edges\n        has_cycle.assign(num_cells, false);    // No cycles initially\n    }\n\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\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            // Union by size/rank: attach smaller tree to larger tree\n            if (comp_size[root_i] < comp_size[root_j])\n                swap(root_i, root_j);\n            parent[root_j] = root_i;\n            comp_size[root_i] += comp_size[root_j];\n            num_edges[root_i] += num_edges[root_j]; // Add edges from merged component\n            num_edges[root_i]++;                     // Add the new edge\n            has_cycle[root_i] = has_cycle[root_i] || has_cycle[root_j]; // Propagate cycle info\n        } else {\n            num_edges[root_i]++;         // Edge added within the same component\n            has_cycle[root_i] = true;    // This implies a cycle\n        }\n    }\n};\n\n// --- BoardState Structure ---\nstruct BoardState {\n    vector<vector<int>> board;\n    int empty_r, empty_c;\n    string moves;\n    int last_move_idx; // Index of the last move (0:U, 1:D, 2:L, 3:R), -1 if no previous move\n\n    BoardState(int n_val) : board(n_val, vector<int>(n_val)), empty_r(-1), empty_c(-1), last_move_idx(-1) {}\n\n    // Calculate the score S for the current board configuration\n    // S is the number of vertices in the largest tree component (connected and acyclic)\n    int calculate_S() const {\n        DSU dsu(N * N);\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // The empty cell is not part of the graph formed by tiles\n                if (r == empty_r && c == empty_c) continue;\n\n                int current_tile = board[r][c];\n                int current_idx = r * N + c;\n\n                // Check downward connection with (r+1, c)\n                if (r + 1 < N) {\n                    if (!(r + 1 == empty_r && c == empty_c)) { \n                        int neighbor_tile = board[r+1][c];\n                        int neighbor_idx = (r+1) * N + c;\n                        if ((current_tile & 8) && (neighbor_tile & 2)) { // Down line on current, Up line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n                // Check rightward connection with (r, c+1)\n                if (c + 1 < N) {\n                    if (!(r == empty_r && c + 1 == empty_c)) {\n                        int neighbor_tile = board[r][c+1];\n                        int neighbor_idx = r * N + (c+1);\n                        if ((current_tile & 4) && (neighbor_tile & 1)) { // Right line on current, Left line on neighbor\n                            dsu.unite(current_idx, neighbor_idx);\n                        }\n                    }\n                }\n            }\n        }\n\n        int max_S = 0;\n        for (int i = 0; i < N * N; ++i) {\n            if (i == empty_r * N + empty_c) continue; // Skip empty square\n\n            if (dsu.parent[i] == i) { // If 'i' is the root of a component\n                if (!dsu.has_cycle[i]) {\n                    max_S = max(max_S, dsu.comp_size[i]);\n                }\n            }\n        }\n        return max_S;\n    }\n};\n\n// Function to calculate energy for SA\nlong double calculate_energy(int current_S, int current_K) {\n    if (current_S == MAX_S_VALUE) {\n        return (long double)current_K * W_K;\n    } else {\n        return (long double)(MAX_S_VALUE - current_S) * W_S_CRITICAL + (long double)current_K * W_K;\n    }\n}\n\n// Function to run a single Simulated Annealing iteration\nBoardState run_sa_iteration(const BoardState& initial_board_state, long long iteration_time_limit_ms, int& iter_count_out) {\n    BoardState current_state = initial_board_state;\n    int current_S = current_state.calculate_S();\n    int current_K = current_state.moves.length(); // Initial K from previous state, could be 0\n\n    BoardState best_local_state = current_state;\n    int best_local_S = current_S;\n    int best_local_K = current_K;\n\n    auto iteration_start_time = chrono::steady_clock::now();\n    \n    uniform_real_distribution<long double> dist_prob(0.0, 1.0);\n    iter_count_out = 0;\n\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - iteration_start_time).count() < iteration_time_limit_ms) {\n        iter_count_out++;\n\n        long double progress = (long double)chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - iteration_start_time).count() / iteration_time_limit_ms;\n        long double temp = T_START * pow(T_END / T_START, progress);\n        \n        if (temp < 1e-12) temp = 1e-12; // Safety net for extremely low temperatures\n\n        long double current_energy = calculate_energy(current_S, current_K);\n\n        vector<int> possible_moves_indices;\n        for (int i = 0; i < 4; ++i) {\n            int next_empty_r = current_state.empty_r + dr[i];\n            int next_empty_c = current_state.empty_c + dc[i];\n\n            if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                if (current_state.last_move_idx == -1 || i != opposite_dir[current_state.last_move_idx]) {\n                    possible_moves_indices.push_back(i);\n                }\n            }\n        }\n        \n        if (possible_moves_indices.empty()) { \n            for (int i = 0; i < 4; ++i) {\n                int next_empty_r = current_state.empty_r + dr[i];\n                int next_empty_c = current_state.empty_c + dc[i];\n                if (next_empty_r >= 0 && next_empty_r < N && next_empty_c >= 0 && next_empty_c < N) {\n                     possible_moves_indices.push_back(i);\n                }\n            }\n            if (possible_moves_indices.empty()) { \n                 continue;\n            }\n        }\n\n        uniform_int_distribution<int> dist_valid_dir(0, possible_moves_indices.size() - 1);\n        int move_idx = possible_moves_indices[dist_valid_dir(rng)];\n\n        int prev_empty_r = current_state.empty_r;\n        int prev_empty_c = current_state.empty_c;\n        int moved_tile_r = prev_empty_r + dr[move_idx];\n        int moved_tile_c = prev_empty_c + dc[move_idx];\n        \n        BoardState next_state = current_state; \n        \n        next_state.board[prev_empty_r][prev_empty_c] = next_state.board[moved_tile_r][moved_tile_c];\n        next_state.board[moved_tile_r][moved_tile_c] = 0;\n        next_state.empty_r = moved_tile_r;\n        next_state.empty_c = moved_tile_c;\n        next_state.moves += dir_char[move_idx];\n        next_state.last_move_idx = move_idx;\n\n        int next_K = next_state.moves.length();\n        if (next_K > MAX_MOVES) { \n            continue; \n        }\n\n        int next_S = next_state.calculate_S();\n        long double next_energy = calculate_energy(next_S, next_K);\n\n        long double delta_E = next_energy - current_energy;\n\n        if (delta_E < 0 || dist_prob(rng) < exp(-delta_E / temp)) {\n            current_state = next_state;\n            current_S = next_S;\n            current_K = next_K;\n            \n            if (current_S > best_local_S) {\n                best_local_S = current_S;\n                best_local_K = current_K;\n                best_local_state = current_state;\n            } else if (current_S == best_local_S && current_K < best_local_K) { \n                best_local_K = current_K;\n                best_local_state = current_state;\n            }\n        }\n    }\n    return best_local_state;\n}\n\n\n// --- Main Function ---\nint main() {\n    ios_base::sync_with_stdio(false); // Faster I/O\n    cin.tie(NULL);\n\n    cin >> N >> MAX_MOVES;\n\n    MAX_S_VALUE = N * N - 1; // Total number of tiles, excluding the empty one\n    W_S_CRITICAL = (long double)MAX_MOVES + 1.0; \n\n    BoardState initial_input_state(N);\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            initial_input_state.board[i][j] = stoi(string(1, row_str[j]), nullptr, 16);\n            if (initial_input_state.board[i][j] == 0) { // Found the empty square\n                initial_input_state.empty_r = i;\n                initial_input_state.empty_c = j;\n            }\n        }\n    }\n    initial_input_state.moves = \"\"; // Ensure moves are empty for the starting point of each SA run\n    initial_input_state.last_move_idx = -1;\n\n    // Initialize global best state with the initial state\n    BoardState global_best_state = initial_input_state;\n    int global_best_S = initial_input_state.calculate_S();\n    int global_best_K = 0;\n\n    // Allocate time per run, leaving a small margin for main loop overhead\n    long long time_for_sa_runs_ms = TOTAL_TIME_LIMIT_MS * 98 / 100; // 2% margin\n    long long time_per_run_ms = time_for_sa_runs_ms / NUM_SA_RUNS;\n    if (time_per_run_ms == 0) time_per_run_ms = 1; // Ensure at least 1ms per run to avoid division by zero or negative time\n\n    long long total_iter_count_sum = 0; // To sum iterations from all runs\n\n    for (int run = 0; run < NUM_SA_RUNS; ++run) {\n        int current_run_iter_count = 0;\n        BoardState current_run_best_state = run_sa_iteration(initial_input_state, time_per_run_ms, current_run_iter_count);\n        total_iter_count_sum += current_run_iter_count;\n\n        int current_run_S = current_run_best_state.calculate_S(); \n        int current_run_K = current_run_best_state.moves.length();\n        \n        // Update global best\n        if (current_run_S > global_best_S) {\n            global_best_S = current_run_S;\n            global_best_K = current_run_K;\n            global_best_state = current_run_best_state;\n        } else if (current_run_S == global_best_S && current_run_K < global_best_K) { \n            global_best_K = current_run_K;\n            global_best_state = current_run_best_state;\n        }\n    }\n\n    // Output debug information to stderr\n    cerr << \"Total Iterations across \" << NUM_SA_RUNS << \" runs: \" << total_iter_count_sum << endl;\n    cerr << \"Global Best S: \" << global_best_S << \" / \" << MAX_S_VALUE << endl;\n    cerr << \"Global Best K: \" << global_best_K << \" / \" << MAX_MOVES << endl;\n    \n    // Calculate final score for the best found state based on problem formula\n    long long final_score;\n    if (global_best_S == MAX_S_VALUE) {\n        final_score = round(500000.0 * (2.0 - (long double)global_best_K / MAX_MOVES));\n    } else {\n        final_score = round(500000.0 * ((long double)global_best_S / MAX_S_VALUE));\n    }\n    cerr << \"Final Score: \" << final_score << endl;\n\n    cout << global_best_state.moves << endl;\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric> // For std::gcd\n#include <algorithm> // For std::min, std::max\n#include <unordered_map>\n#include <bitset>    // For std::bitset\n#include <cassert>   // For debugging assertions\n#include <set>       // For tracking used strawberry pairs\n\n// Using long long for coordinates and intermediate calculations for lines\n// Max value for Ax + By + C can be large but fits in long long.\n\nusing namespace std;\n\n// --- Constants and Type Definitions ---\nconst int K_MAX_CUTS_CONST = 100; // K is fixed at 100\nconst long long MAX_INITIAL_LINE_COORD = 100000LL; // Range for line points (10x cake radius)\nconst long long MAX_PERTURB_MAG = 50000LL; // Max perturbation magnitude (5x cake radius)\n\n// --- Random Number Generator ---\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<long long> dist_line_coord(-MAX_INITIAL_LINE_COORD, MAX_INITIAL_LINE_COORD); \nuniform_int_distribution<int> dist_k_idx(0, K_MAX_CUTS_CONST - 1); \nuniform_int_distribution<int> dist_coord_choice(0, 3); // 0=px, 1=py, 2=qx, 3=qy\nuniform_real_distribution<double> dist_01(0.0, 1.0); // For SA acceptance probability\nuniform_int_distribution<int> dist_strawberry_idx; // Will be initialized with N_strawberries\n\n// --- Global variables ---\nint N_strawberries;\nint K_max_cuts; \nvector<int> a_attendees(11); // a_d for d=1 to 10. a_attendees[0] unused.\nlong long total_attendees_demand = 0; // Sum of a_d\n\nstruct Strawberry {\n    long long x, y;\n};\nvector<Strawberry> strawberries;\n\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C; // Line equation Ax + By + C = 0\n\n    Line(long long p1x, long long p1y, long long p2x, long long p2y) :\n        px(p1x), py(p1y), qx(p2x), qy(p2y) {\n        // Points (p1x, p1y) and (p2x, p2y) are guaranteed to be distinct by the caller.\n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n        \n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero, points were identical or other issue.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        \n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n    Line() : px(0), py(0), qx(1), qy(0), A(0), B(-1), C(0) {} // Default horizontal line y=0\n\n    void perturb(double decrease_factor) { // decrease_factor goes from 1.0 to 0.0 over time\n        long long perturb_magnitude = (long long)(MAX_PERTURB_MAG * decrease_factor) + 1; \n        \n        long long old_px = px, old_py = py, old_qx = qx, old_qy = qy; \n        \n        long long *coord_ptr;\n        switch (dist_coord_choice(rng)) {\n            case 0: coord_ptr = &px; break;\n            case 1: coord_ptr = &py; break;\n            case 2: coord_ptr = &qx; break;\n            default: coord_ptr = &qy; break;\n        }\n        long long new_coord_val = *coord_ptr + uniform_int_distribution<long long>(-perturb_magnitude, perturb_magnitude)(rng);\n        *coord_ptr = max(-MAX_INITIAL_LINE_COORD, min(MAX_INITIAL_LINE_COORD, new_coord_val));\n\n        if (px == qx && py == qy) { // If perturbation makes points identical, revert to original.\n            px = old_px; py = old_py; qx = old_qx; qy = old_qy;\n        }\n        \n        A = py - qy;\n        B = qx - px;\n        C = (long long)px * qy - (long long)qx * py;\n\n        long long common_divisor = std::gcd(std::gcd(A, B), C);\n        assert(common_divisor != 0 && \"Common divisor is zero after perturbation.\");\n        A /= common_divisor;\n        B /= common_divisor;\n        C /= common_divisor;\n        if (A < 0 || (A == 0 && B < 0)) {\n            A = -A;\n            B = -B;\n            C = -C;\n        }\n    }\n};\n\n// Using std::bitset for piece signatures. Faster hashing and comparison than std::vector<char>.\n// A 'true' bit represents a positive side, 'false' a negative side.\nusing PieceSignature = std::bitset<K_MAX_CUTS_CONST>;\n\n// Custom hash for std::bitset (using std::hash for bitset)\nstruct BitsetHash {\n    std::size_t operator()(const PieceSignature& b) const {\n        return std::hash<std::bitset<K_MAX_CUTS_CONST>>{}(b);\n    }\n};\n\n// State variables for Simulated Annealing\nvector<PieceSignature> strawberry_line_sides_current_bits; \nvector<short> num_lines_passing_through_strawberry_current; \nunordered_map<PieceSignature, int, BitsetHash> piece_strawberry_counts_current; \nvector<long long> b_d_current(11, 0); \nlong long current_score = 0; \nvector<Line> current_lines; \n\n// Function to calculate the score based on a given b_d vector.\nlong long calculate_score(const vector<long long>& b_d_vec) {\n    long long actual_distributed = 0;\n    for (int d = 1; d <= 10; ++d) {\n        actual_distributed += min(a_attendees[d], (int)b_d_vec[d]);\n    }\n    if (total_attendees_demand == 0) return 0; // Should not happen given problem constraints (N > 0).\n    return round(1e6 * (double)actual_distributed / total_attendees_demand);\n}\n\n// Function to generate a purely random line\nLine generate_random_line() {\n    long long p1x, p1y, p2x, p2y;\n    do {\n        p1x = dist_line_coord(rng);\n        p1y = dist_line_coord(rng);\n        p2x = dist_line_coord(rng);\n        p2y = dist_line_coord(rng);\n    } while (p1x == p2x && p1y == p2y); \n    return Line(p1x, p1y, p2x, p2y);\n}\n\n// Function to generate a line passing through two specific strawberries\nLine generate_line_through_strawberries(int idx1, int idx2) {\n    return Line(strawberries[idx1].x, strawberries[idx1].y, strawberries[idx2].x, strawberries[idx2].y);\n}\n\n\n// Performs a full evaluation of the given set of lines.\nvoid full_evaluate(const vector<Line>& lines) {\n    strawberry_line_sides_current_bits.assign(N_strawberries, PieceSignature());\n    num_lines_passing_through_strawberry_current.assign(N_strawberries, 0); \n    piece_strawberry_counts_current.clear();\n    fill(b_d_current.begin(), b_d_current.end(), 0);\n\n    for (int j = 0; j < N_strawberries; ++j) {\n        for (int i = 0; i < K_max_cuts; ++i) {\n            long long val = lines[i].A * strawberries[j].x + lines[i].B * strawberries[j].y + lines[i].C;\n            if (val == 0) {\n                num_lines_passing_through_strawberry_current[j]++;\n                strawberry_line_sides_current_bits[j].set(i, true); // Arbitrary: set to true if on line\n            } else {\n                strawberry_line_sides_current_bits[j].set(i, val > 0); // true for >0, false for <0\n            }\n        }\n        if (num_lines_passing_through_strawberry_current[j] == 0) { \n            piece_strawberry_counts_current[strawberry_line_sides_current_bits[j]]++;\n        }\n    }\n\n    for (const auto& pair : piece_strawberry_counts_current) {\n        if (pair.second > 0 && pair.second <= 10) { \n            b_d_current[pair.second]++;\n        }\n    }\n    current_score = calculate_score(b_d_current);\n}\n\nvoid solve() {\n    cin >> N_strawberries >> K_max_cuts;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a_attendees[d];\n        total_attendees_demand += a_attendees[d];\n    }\n    strawberries.resize(N_strawberries);\n    dist_strawberry_idx = uniform_int_distribution<int>(0, N_strawberries - 1); // Initialize distribution for strawberry indices\n    num_lines_passing_through_strawberry_current.resize(N_strawberries); \n    for (int i = 0; i < N_strawberries; ++i) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n\n    current_lines.resize(K_max_cuts);\n    \n    // --- Smarter Initial Line Generation ---\n    // Generate K/2 lines connecting two random strawberries, K - K/2 purely random.\n    int num_strategic_lines = K_max_cuts / 2;\n    set<pair<int, int>> used_strawberry_pairs; // To avoid duplicate lines or lines through same strawberry pair\n    \n    for (int i = 0; i < num_strategic_lines; ++i) {\n        int idx1, idx2;\n        int attempts = 0;\n        do { // Ensure unique, distinct strawberry pair\n            idx1 = dist_strawberry_idx(rng);\n            idx2 = dist_strawberry_idx(rng);\n            if (idx1 > idx2) swap(idx1, idx2);\n            attempts++;\n            if (attempts > 1000 && N_strawberries < 200) { // If N_strawberries is small, can run out of unique pairs.\n                // Fallback to random if too hard to find unique pair\n                current_lines[i] = generate_random_line(); \n                idx1 = -1; idx2 = -1; // Mark as non-strawberry line\n                break;\n            }\n        } while (idx1 == idx2 || used_strawberry_pairs.count({idx1, idx2}));\n        \n        if (idx1 != -1) { // If a valid strawberry pair was found\n            current_lines[i] = generate_line_through_strawberries(idx1, idx2);\n            used_strawberry_pairs.insert({idx1, idx2});\n        }\n    }\n\n    for (int i = num_strategic_lines; i < K_max_cuts; ++i) {\n        current_lines[i] = generate_random_line();\n    }\n    // --- End Smarter Initial Line Generation ---\n    \n    full_evaluate(current_lines);\n\n    vector<Line> best_lines = current_lines;\n    long long best_score = current_score;\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.95; \n\n    double T_start = 1e7; \n    double T_end = 1e-1;   \n\n    while (true) {\n        auto current_time = chrono::steady_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double temp_ratio = elapsed_time / TIME_LIMIT; \n        double T = T_start * pow(T_end / T_start, temp_ratio); \n\n        int line_idx_to_perturb = dist_k_idx(rng);\n        Line original_line_at_idx = current_lines[line_idx_to_perturb];\n        Line candidate_line = original_line_at_idx;\n\n        // --- Perturbation Strategy: Local adjustment OR Full replacement ---\n        if (dist_01(rng) < 0.05) { // 5% chance to completely replace the line\n            candidate_line = generate_random_line();\n        } else { // 95% chance for local adjustment\n            candidate_line.perturb(1.0 - temp_ratio); \n        }\n        // --- End Perturbation Strategy ---\n\n        vector<long long> temp_b_d = b_d_current;\n        unordered_map<PieceSignature, int, BitsetHash> temp_piece_strawberry_counts = piece_strawberry_counts_current;\n        \n        vector<bool> next_line_side_values_at_idx_bit(N_strawberries);\n        vector<short> next_num_lines_passing_through_commit(N_strawberries);\n\n\n        for (int j = 0; j < N_strawberries; ++j) {\n            long long val_original_line_k = original_line_at_idx.A * strawberries[j].x + original_line_at_idx.B * strawberries[j].y + original_line_at_idx.C;\n            long long val_candidate_line_k = candidate_line.A * strawberries[j].x + candidate_line.B * strawberries[j].y + candidate_line.C;\n\n            bool was_on_original_line_k = (val_original_line_k == 0);\n            bool is_on_candidate_line_k = (val_candidate_line_k == 0);\n\n            short temp_num_lines_passing_for_j = num_lines_passing_through_strawberry_current[j];\n            if (was_on_original_line_k && !is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j--;\n            } else if (!was_on_original_line_k && is_on_candidate_line_k) {\n                temp_num_lines_passing_for_j++;\n            }\n            next_num_lines_passing_through_commit[j] = temp_num_lines_passing_for_j; \n\n            bool was_lost_j = (num_lines_passing_through_strawberry_current[j] > 0);\n            bool is_lost_j_candidate = (temp_num_lines_passing_for_j > 0);\n\n            bool new_side_k_value_for_key = (val_candidate_line_k > 0);\n            if (is_on_candidate_line_k) { \n                 new_side_k_value_for_key = true; \n            }\n            next_line_side_values_at_idx_bit[j] = new_side_k_value_for_key; \n            \n            // --- Update temp_b_d and temp_piece_strawberry_counts ---\n            \n            // Step 1: Remove strawberry j from its previous piece (if it was in one).\n            if (!was_lost_j) {\n                PieceSignature old_piece_key = strawberry_line_sides_current_bits[j];\n                int count_in_old_piece = temp_piece_strawberry_counts[old_piece_key]; \n                \n                temp_piece_strawberry_counts[old_piece_key]--;\n                if (count_in_old_piece >= 1 && count_in_old_piece <= 10) {\n                    temp_b_d[count_in_old_piece]--; \n                }\n                if (count_in_old_piece - 1 >= 1 && count_in_old_piece - 1 <= 10) { \n                    temp_b_d[count_in_old_piece - 1]++; \n                }\n            }\n\n            // Step 2: Add strawberry j to its new piece (if it will be in one).\n            if (!is_lost_j_candidate) {\n                PieceSignature new_piece_key = strawberry_line_sides_current_bits[j]; \n                new_piece_key.set(line_idx_to_perturb, new_side_k_value_for_key); \n                \n                int count_in_new_piece_before_add = temp_piece_strawberry_counts[new_piece_key];\n                temp_piece_strawberry_counts[new_piece_key]++;\n                \n                if (count_in_new_piece_before_add >= 1 && count_in_new_piece_before_add <= 10) {\n                    temp_b_d[count_in_new_piece_before_add]--;\n                }\n                if (count_in_new_piece_before_add + 1 >= 1 && count_in_new_piece_before_add + 1 <= 10) {\n                    temp_b_d[count_in_new_piece_before_add + 1]++;\n                }\n            }\n        } // End of strawberry loop\n        \n        long long new_score = calculate_score(temp_b_d);\n\n        if (new_score > current_score || dist_01(rng) < exp((double)(new_score - current_score) / T)) {\n            // Accept the change\n            current_lines[line_idx_to_perturb] = candidate_line;\n            b_d_current = temp_b_d;\n            piece_strawberry_counts_current = temp_piece_strawberry_counts;\n            current_score = new_score;\n\n            // Commit changes to global strawberry state variables.\n            for (int j = 0; j < N_strawberries; ++j) {\n                num_lines_passing_through_strawberry_current[j] = next_num_lines_passing_through_commit[j];\n                strawberry_line_sides_current_bits[j].set(line_idx_to_perturb, next_line_side_values_at_idx_bit[j]);\n            }\n\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_lines = current_lines;\n            }\n        }\n    }\n\n    cout << K_max_cuts << endl;\n    for (const auto& line : best_lines) {\n        cout << line.px << \" \" << line.py << \" \" << line.qx << \" \" << line.qy << endl;\n    }\n}\n\n// Main function to run the solution.\nint main() {\n    ios_base::sync_with_stdio(false); \n    cin.tie(NULL); \n    solve();\n    return 0;\n}\n","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n\n// To manage execution time\nstd::chrono::high_resolution_clock::time_point start_time;\ndouble time_limit_ms = 4900.0; // 4.9 seconds to be safe\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        return !(*this == other);\n    }\n    // operator< is only needed if Point objects are used in ordered containers like std::set or std::map keys.\n    // While not explicitly used for that in the current core logic, it's a good practice to have for completeness\n    // and can be silently relied upon by other parts of the standard library if, for example, pair comparison uses it.\n    bool operator<(const Point& other) const { \n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\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\nstruct RectangleOp {\n    Point p1, p2, p3, p4; \n};\n\nint N_global;\nint center_x_coord; \nint center_y_coord; \nstd::vector<std::vector<bool>> has_dot;\n\n// For condition 3: tracking drawn segments\n// horizontal_drawn[y][x]: segment (x,y)-(x+1,y)\nstd::vector<std::vector<bool>> horizontal_drawn;\n// vertical_drawn[x][y]: segment (x,y)-(x,y+1)\nstd::vector<std::vector<bool>> vertical_drawn; \n// diag_up_drawn[x][y]: segment (x,y)-(x+1,y+1) (slope +1)\nstd::vector<std::vector<bool>> diag_up_drawn;\n// diag_down_drawn[x][y]: segment (x,y+1)-(x+1,y) (slope -1)\nstd::vector<std::vector<bool>> diag_down_drawn;\n\n// Weights precomputation\nstd::vector<std::vector<double>> point_weights;\n\nbool is_in_bounds(const Point& p) { // Pass by const ref\n    return p.x >= 0 && p.x < N_global && p.y >= 0 && p.y < N_global;\n}\n\nvoid precompute_weights() {\n    point_weights.resize(N_global, std::vector<double>(N_global));\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            point_weights[i][j] = (double)((long long)(i - center_x_coord) * (i - center_x_coord) + \n                                           (long long)(j - center_y_coord) * (j - center_y_coord) + 1);\n        }\n    }\n}\n\ndouble get_weight(const Point& p) { // Pass by const ref\n    if (!is_in_bounds(p)) return -1.0; \n    return point_weights[p.x][p.y];\n}\n\nbool is_allowed_dot(const Point& p, const Point& p2, const Point& p3, const Point& p4) { // Pass by const ref\n    return p == p2 || p == p3 || p == p4;\n}\n\nbool check_perimeter_dots(const Point& p1_new, const Point& p2, const Point& p3, const Point& p4) { // All by const ref\n    auto check_segment = [&](const Point& start, const Point& end) { // All by const ref\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        int steps = std::max(std::abs(dx), std::abs(dy));\n\n        if (steps == 0) return true; \n\n        for (int i = 1; i < steps; ++i) { \n            Point p = {start.x + dx * i / steps, start.y + dy * i / steps};\n            \n            if (has_dot[p.x][p.y] && !is_allowed_dot(p, p2, p3, p4)) { \n                return false;\n            }\n        }\n        return true;\n    };\n\n    if (!check_segment(p1_new, p2)) return false;\n    if (!check_segment(p2, p3)) return false;\n    if (!check_segment(p3, p4)) return false;\n    if (!check_segment(p4, p1_new)) return false;\n    return true;\n}\n\nbool check_shared_segments(const Point& p1_new, const Point& p2, const Point& p3, const Point& p4, bool dry_run) { // All by const ref\n    auto process_segment = [&](const Point& start, const Point& end, bool dry_run_local) { // All by const ref\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n\n        if (dx == 0 && dy == 0) return true; \n\n        if (dx == 0) { // Vertical segment\n            int x = start.x;\n            for (int y = std::min(start.y, end.y); y < std::max(start.y, end.y); ++y) {\n                if (dry_run_local) {\n                    if (vertical_drawn[x][y]) return false;\n                } else {\n                    vertical_drawn[x][y] = true;\n                }\n            }\n        } else if (dy == 0) { // Horizontal segment\n            int y = start.y;\n            for (int x = std::min(start.x, end.x); x < std::max(start.x, end.x); ++x) {\n                if (dry_run_local) {\n                    if (horizontal_drawn[y][x]) return false;\n                } else {\n                    horizontal_drawn[y][x] = true;\n                }\n            }\n        } else if (dx == dy) { // Diagonal (slope +1)\n            int min_x = std::min(start.x, end.x);\n            int min_y = std::min(start.y, end.y);\n            for (int i = 0; i < std::abs(dx); ++i) {\n                if (dry_run_local) {\n                    if (diag_up_drawn[min_x + i][min_y + i]) return false;\n                } else {\n                    diag_up_drawn[min_x + i][min_y + i] = true;\n                }\n            }\n        } else if (dx == -dy) { // Diagonal (slope -1)\n            Point current_start = start;\n            Point current_end = end;\n            if (start.x > end.x) std::swap(current_start, current_end); \n\n            for (int i = 0; i < std::abs(dx); ++i) {\n                int x_curr = current_start.x + i;\n                int y_curr = current_start.y - i - 1; \n\n                if (dry_run_local) {\n                    if (diag_down_drawn[x_curr][y_curr]) return false;\n                } else {\n                    diag_down_drawn[x_curr][y_curr] = true;\n                }\n            }\n        }\n        return true;\n    };\n\n    if (!process_segment(p1_new, p2, dry_run)) return false;\n    if (!process_segment(p2, p3, dry_run)) return false;\n    if (!process_segment(p3, p4, dry_run)) return false;\n    if (!process_segment(p4, p1_new, dry_run)) return false;\n\n    return true; \n}\n\n// Function to calculate perimeter segment count for tie-breaking\nint get_perimeter_segment_count(const Point& p1, const Point& p2, const Point& p3, const Point& p4) {\n    int count = 0;\n    auto add_segment_length = [&](const Point& start, const Point& end) {\n        int dx = end.x - start.x;\n        int dy = end.y - start.y;\n        count += std::max(std::abs(dx), std::abs(dy)); // For axis-aligned and 45-deg\n    };\n    add_segment_length(p1, p2);\n    add_segment_length(p2, p3);\n    add_segment_length(p3, p4);\n    add_segment_length(p4, p1);\n    return count;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    start_time = std::chrono::high_resolution_clock::now();\n\n    int M;\n    std::cin >> N_global >> M;\n\n    center_x_coord = (N_global - 1) / 2; \n    center_y_coord = (N_global - 1) / 2; \n\n    has_dot.resize(N_global, std::vector<bool>(N_global, false));\n    horizontal_drawn.resize(N_global, std::vector<bool>(N_global - 1, false));\n    vertical_drawn.resize(N_global, std::vector<bool>(N_global - 1, false)); \n    diag_up_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n    diag_down_drawn.resize(N_global - 1, std::vector<bool>(N_global - 1, false));\n\n    std::vector<Point> current_dots_list;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        std::cin >> x >> y;\n        current_dots_list.push_back({x, y});\n        has_dot[x][y] = true;\n    }\n\n    precompute_weights();\n\n    std::vector<RectangleOp> operations;\n    \n    while (true) {\n        // Update elapsed_ms here at the start of each major iteration\n        auto current_time_outer = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time_outer - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break;\n        }\n\n        double best_P1_weight = -1.0;\n        RectangleOp best_op;\n        int best_perimeter_segments = N_global * 4 * 2 + 1; // Initialize with a value larger than any possible perimeter\n        bool found_op = false;\n\n        std::vector<Point> sorted_dots = current_dots_list;\n        std::sort(sorted_dots.begin(), sorted_dots.end(), [&](const Point& a, const Point& b) {\n            return get_weight(a) > get_weight(b);\n        });\n\n        // Maximum number of M^2 checks per outer loop.\n        const size_t max_m_squared_pairs_to_check = 1500000; \n        size_t pairs_checked = 0;\n\n        for (size_t i = 0; i < sorted_dots.size(); ++i) {\n            const Point& p_adj1 = sorted_dots[i]; // Pass by const ref\n            for (size_t j = 0; j < sorted_dots.size(); ++j) {\n                // Update elapsed_ms within inner loop for more precise time checks\n                elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();\n                if (elapsed_ms > time_limit_ms) goto end_loops; \n                if (pairs_checked >= max_m_squared_pairs_to_check) goto end_loops; \n\n                if (i == j) continue; \n                const Point& p_adj2 = sorted_dots[j]; // Pass by const ref\n                pairs_checked++;\n\n                // --- Try Axis-aligned rectangle ---\n                Point p1_new_aa = {p_adj1.x, p_adj2.y};\n                Point p_opp_aa = {p_adj2.x, p_adj1.y}; \n\n                if (p_adj1.x == p_adj2.x || p_adj1.y == p_adj2.y) continue; \n\n                if (is_in_bounds(p1_new_aa) && !has_dot[p1_new_aa.x][p1_new_aa.y] && \n                    is_in_bounds(p_opp_aa) && has_dot[p_opp_aa.x][p_opp_aa.y] &&    \n                    p1_new_aa != p_adj1 && p1_new_aa != p_opp_aa && p1_new_aa != p_adj2) \n                {\n                    if (check_perimeter_dots(p1_new_aa, p_adj1, p_opp_aa, p_adj2) &&\n                        check_shared_segments(p1_new_aa, p_adj1, p_opp_aa, p_adj2, true)) { \n                        double current_weight = get_weight(p1_new_aa);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_aa, p_adj1, p_opp_aa, p_adj2};\n                            best_perimeter_segments = get_perimeter_segment_count(p1_new_aa, p_adj1, p_opp_aa, p_adj2);\n                            found_op = true;\n                        } else if (current_weight == best_P1_weight) {\n                            // Tie-breaking: prefer smaller perimeter\n                            int current_perimeter = get_perimeter_segment_count(p1_new_aa, p_adj1, p_opp_aa, p_adj2);\n                            if (current_perimeter < best_perimeter_segments) {\n                                best_op = {p1_new_aa, p_adj1, p_opp_aa, p_adj2};\n                                best_perimeter_segments = current_perimeter;\n                            }\n                        }\n                    }\n                }\n\n                // --- Try 45-degree inclined rectangle ---\n                int u_adj1 = p_adj1.x + p_adj1.y;\n                int v_adj1 = p_adj1.x - p_adj1.y;\n                int u_adj2 = p_adj2.x + p_adj2.y;\n                int v_adj2 = p_adj2.x - p_adj2.y;\n\n                if (u_adj1 == u_adj2 || v_adj1 == v_adj2) continue;\n                \n                int u1_new = u_adj1; \n                int v1_new = v_adj2; \n                int u3_opp = u_adj2; \n                int v3_opp = v_adj1; \n\n                if (((u1_new + v1_new) % 2 != 0) || ((u1_new - v1_new) % 2 != 0) ||\n                    ((u3_opp + v3_opp) % 2 != 0) || ((u3_opp - v3_opp) % 2 != 0)) {\n                    continue; \n                }\n\n                Point p1_new_45 = {(u1_new + v1_new) / 2, (u1_new - v1_new) / 2};\n                Point p_opp_45 = {(u3_opp + v3_opp) / 2, (u3_opp - v3_opp) / 2};\n\n                if (is_in_bounds(p1_new_45) && !has_dot[p1_new_45.x][p1_new_45.y] &&\n                    is_in_bounds(p_opp_45) && has_dot[p_opp_45.x][p_opp_45.y] &&\n                    p1_new_45 != p_adj1 && p1_new_45 != p_opp_45 && p1_new_45 != p_adj2) {\n                    if (check_perimeter_dots(p1_new_45, p_adj1, p_opp_45, p_adj2) &&\n                        check_shared_segments(p1_new_45, p_adj1, p_opp_45, p_adj2, true)) { \n                        double current_weight = get_weight(p1_new_45);\n                        if (current_weight > best_P1_weight) {\n                            best_P1_weight = current_weight;\n                            best_op = {p1_new_45, p_adj1, p_opp_45, p_adj2};\n                            best_perimeter_segments = get_perimeter_segment_count(p1_new_45, p_adj1, p_opp_45, p_adj2);\n                            found_op = true;\n                        } else if (current_weight == best_P1_weight) {\n                            // Tie-breaking: prefer smaller perimeter\n                            int current_perimeter = get_perimeter_segment_count(p1_new_45, p_adj1, p_opp_45, p_adj2);\n                            if (current_perimeter < best_perimeter_segments) {\n                                best_op = {p1_new_45, p_adj1, p_opp_45, p_adj2};\n                                best_perimeter_segments = current_perimeter;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n    end_loops:; \n\n        if (!found_op) {\n            break; \n        }\n\n        operations.push_back(best_op);\n        has_dot[best_op.p1.x][best_op.p1.y] = true;\n        current_dots_list.push_back(best_op.p1); \n        check_shared_segments(best_op.p1, best_op.p2, best_op.p3, best_op.p4, false); \n    }\n\n    std::cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        std::cout << op.p1.x << \" \" << op.p1.y << \" \"\n                  << op.p2.x << \" \" << op.p2.y << \" \"\n                  << op.p3.x << \" \" << op.p3.y << \" \"\n                  << op.p4.x << \" \" << op.p4.y << \"\\n\";\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#include <queue> // For BFS in component calculation\n\n// Using std namespace for convenience in competitive programming context\nusing namespace std;\n\n// Constants for board size\nconst int N = 10; \n\n// Global board state\nvector<vector<int>> board(N, vector<int>(N, 0)); // 0: empty, 1,2,3: flavors\n\n// Stores the flavors of candies in the order they are received (f_1 to f_100)\nvector<int> flavors_data(100);\n\n// For the tie-breaker heuristic:\n// Maps original flavor index (1,2,3) to its assigned region index (0,1,2)\nmap<int, int> flavor_to_region_idx;\n// Maps assigned region index (0,1,2) back to its original flavor index (1,2,3)\nvector<int> region_idx_to_flavor(3); \n// Stores start and end rows for each assigned region (0,1,2)\nvector<int> region_rows_start(3); \nvector<int> region_rows_end(3);   \n\n// Directions for BFS and neighbor checks (4-way adjacency)\nconst int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\nconst int dc[] = {0, 0, -1, 1};\n\n\n// Function to find the (r, c) coordinates of the p-th empty cell\npair<int, int> get_coords_from_p_idx(int p_idx) {\n    int count = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) {\n                count++;\n                if (count == p_idx) {\n                    return {r, c};\n                }\n            }\n        }\n    }\n    return {-1, -1}; // Should not happen in a valid problem scenario\n}\n\n// Function to apply a tilt operation to a given board\nvoid apply_tilt(vector<vector<int>>& current_board, char dir) {\n    if (dir == 'F') { // Forward (up, towards row 0)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = 0; r < N; ++r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = 0; r < N; ++r) {\n                if (r < candies_in_col.size()) {\n                    current_board[r][c] = candies_in_col[r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'B') { // Backward (down, towards row N-1)\n        for (int c = 0; c < N; ++c) {\n            vector<int> candies_in_col;\n            for (int r = N - 1; r >= 0; --r) {\n                if (current_board[r][c] != 0) {\n                    candies_in_col.push_back(current_board[r][c]);\n                }\n            }\n            for (int r = N - 1; r >= 0; --r) {\n                if ((N - 1 - r) < candies_in_col.size()) { // Fill from bottom up\n                    current_board[r][c] = candies_in_col[N - 1 - r];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'L') { // Left (towards col 0)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = 0; c < N; ++c) {\n                if (c < candies_in_row.size()) {\n                    current_board[r][c] = candies_in_row[c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    } else if (dir == 'R') { // Right (towards col N-1)\n        for (int r = 0; r < N; ++r) {\n            vector<int> candies_in_row;\n            for (int c = N - 1; c >= 0; --c) {\n                if (current_board[r][c] != 0) {\n                    candies_in_row.push_back(current_board[r][c]);\n                }\n            }\n            for (int c = N - 1; c >= 0; --c) {\n                if ((N - 1 - c) < candies_in_row.size()) { // Fill from right to left\n                    current_board[r][c] = candies_in_row[N - 1 - c];\n                } else {\n                    current_board[r][c] = 0; // Clear remaining cells\n                }\n            }\n        }\n    }\n}\n\n// Helper function to calculate the sum of n_i^2 for a given board state\nlong long calculate_sum_n_sq(const vector<vector<int>>& current_board) {\n    long long total_n_sq = 0;\n    \n    for (int flavor_to_check = 1; flavor_to_check <= 3; ++flavor_to_check) {\n        vector<vector<bool>> visited_for_flavor(N, vector<bool>(N, false));\n        \n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (current_board[r][c] == flavor_to_check && !visited_for_flavor[r][c]) {\n                    int current_component_size = 0;\n                    queue<pair<int, int>> q; \n                    q.push({r, c});\n                    visited_for_flavor[r][c] = true;\n                    \n                    while(!q.empty()){\n                        pair<int, int> curr = q.front();\n                        q.pop();\n                        current_component_size++;\n\n                        for (int i = 0; i < 4; ++i) {\n                            int nr = curr.first + dr[i];\n                            int nc = curr.second + dc[i];\n\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N &&\n                                current_board[nr][nc] == flavor_to_check && !visited_for_flavor[nr][nc]) {\n                                visited_for_flavor[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                    total_n_sq += (long long)current_component_size * current_component_size;\n                }\n            }\n        }\n    }\n    return total_n_sq;\n}\n\n// Function to get the target flavor for a given cell (r, c) based on region partitioning\n// This function is for the tie-breaker heuristic\nint get_target_flavor_for_pos(int r, int c) {\n    int assigned_region_idx;\n    if (r >= region_rows_start[0] && r <= region_rows_end[0]) {\n        assigned_region_idx = 0;\n    } else if (r >= region_rows_start[1] && r <= region_rows_end[1]) {\n        assigned_region_idx = 1;\n    } else { // r must be in region 2\n        assigned_region_idx = 2;\n    }\n    return region_idx_to_flavor[assigned_region_idx];\n}\n\n// Function to calculate the score for the tie-breaker.\n// Rewards candies in correct regions (+1.0), penalizes those in wrong regions (-1.0),\n// and adds a bonus for same-flavor neighbors.\ndouble calculate_regional_match_score(const vector<vector<int>>& current_board) {\n    double match_score = 0.0;\n    const double neighbor_bonus_weight = 0.01; // Small bonus for each same-flavor neighbor\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (current_board[r][c] != 0) { // If there's a candy in this cell\n                int candy_flavor = current_board[r][c];\n                int target_flavor = get_target_flavor_for_pos(r, c); \n                \n                if (candy_flavor == target_flavor) {\n                    match_score += 1.0; \n                } else {\n                    match_score -= 1.0; // Penalty for being in the wrong region\n                }\n\n                // Add bonus for same-flavor neighbors (4-direction)\n                int same_flavor_neighbors = 0;\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                        current_board[nr][nc] == candy_flavor) {\n                        same_flavor_neighbors++;\n                    }\n                }\n                match_score += same_flavor_neighbors * neighbor_bonus_weight;\n            }\n        }\n    }\n    return match_score;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read all candy flavors (f_1 to f_100)\n    vector<int> d_counts(4, 0); // d_counts[0] unused, d_counts[1,2,3] for flavors 1,2,3\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors_data[i];\n        d_counts[flavors_data[i]]++;\n    }\n\n    // Determine region assignment based on flavor counts (for tie-breaker)\n    vector<pair<int, int>> flavor_data_sorted; \n    flavor_data_sorted.push_back({d_counts[1], 1});\n    flavor_data_sorted.push_back({d_counts[2], 2});\n    flavor_data_sorted.push_back({d_counts[3], 3});\n\n    sort(flavor_data_sorted.rbegin(), flavor_data_sorted.rend()); \n\n    for (int i = 0; i < 3; ++i) {\n        flavor_to_region_idx[flavor_data_sorted[i].second] = i;\n        region_idx_to_flavor[i] = flavor_data_sorted[i].second;\n    }\n\n    vector<int> row_counts(3);\n    int assigned_total_rows = 0;\n    for (int i = 0; i < 2; ++i) { \n        row_counts[i] = round(flavor_data_sorted[i].first * static_cast<double>(N) / 100.0);\n        row_counts[i] = max(1, row_counts[i]); \n        assigned_total_rows += row_counts[i];\n    }\n    row_counts[2] = max(1, N - assigned_total_rows); \n\n    int current_sum_row_counts = row_counts[0] + row_counts[1] + row_counts[2];\n    int diff = current_sum_row_counts - N;\n    if (diff > 0) { \n        for (int i = 0; i < 3 && diff > 0; ++i) {\n            if (row_counts[i] > 1) { \n                int decrement_val = min(diff, row_counts[i] - 1);\n                row_counts[i] -= decrement_val;\n                diff -= decrement_val;\n            }\n        }\n    }\n\n    int current_row_idx = 0;\n    for (int i = 0; i < 3; ++i) {\n        region_rows_start[i] = current_row_idx;\n        region_rows_end[i] = current_row_idx + row_counts[i] - 1;\n        current_row_idx += row_counts[i];\n    }\n    \n    // Main loop: process each candy one by one\n    char directions[] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p_t;\n        cin >> p_t; // Read the index of the empty cell for the current candy\n\n        // Find coordinates for the new candy\n        pair<int, int> new_candy_coords = get_coords_from_p_idx(p_t);\n        int r_new = new_candy_coords.first;\n        int c_new = new_candy_coords.second;\n\n        // Place the new candy on the board\n        board[r_new][c_new] = flavors_data[t];\n\n        long long best_tilt_score_n_sq = -1; // Initialize with a small number, scores are non-negative\n        double best_tie_breaker_score = -1e18; // Initialize tie-breaker score with a very small number (can be negative)\n        char best_dir = ' ';\n\n        // Evaluate each of the four possible tilt directions\n        for (char dir : directions) {\n            vector<vector<int>> temp_board = board; // Create a copy of the board for simulation\n            apply_tilt(temp_board, dir); // Simulate the tilt\n\n            // Primary metric: sum of n_i^2\n            long long current_tilt_score_n_sq = calculate_sum_n_sq(temp_board);\n            \n            // Secondary metric (for tie-breaking): regional match score with neighbor bonus\n            double current_tie_breaker_score = calculate_regional_match_score(temp_board);\n\n            // Update best direction if current tilt yields a higher primary score,\n            // or if primary scores are equal and secondary score is higher.\n            if (current_tilt_score_n_sq > best_tilt_score_n_sq) {\n                best_tilt_score_n_sq = current_tilt_score_n_sq;\n                best_tie_breaker_score = current_tie_breaker_score;\n                best_dir = dir;\n            } else if (current_tilt_score_n_sq == best_tilt_score_n_sq) {\n                if (current_tie_breaker_score > best_tie_breaker_score) {\n                    best_tie_breaker_score = current_tie_breaker_score;\n                    best_dir = dir;\n                }\n            }\n        }\n\n        // Apply the chosen best tilt to the actual board\n        apply_tilt(board, best_dir);\n\n        // Output the chosen direction and flush stdout\n        cout << best_dir << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <map>\n#include <iomanip>\n#include <cmath> // For std::round, std::abs, std::pow\n\n// Adjacency matrix representation\nusing AdjMatrix = std::vector<std::vector<bool>>;\n\n// Function to convert adjacency matrix to string representation\nstd::string graph_to_string(const AdjMatrix& adj, int N) {\n    std::string s = \"\";\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Function to convert string representation to adjacency matrix\nAdjMatrix string_to_graph(const std::string& s, int N) {\n    AdjMatrix adj(N, std::vector<bool>(N, false));\n    int k_str = 0; // Index for the string s\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[k_str] == '1') {\n                adj[i][j] = adj[j][i] = true;\n            }\n            k_str++;\n        }\n    }\n    return adj;\n}\n\n// Computes WL refinement color histogram (fingerprint) of a graph\nstd::map<int, int> compute_wl_fingerprint(const AdjMatrix& adj, int N, int wl_iters) {\n    std::vector<int> colors(N);\n    // Initial colors based on degrees\n    for (int i = 0; i < N; ++i) {\n        int degree = 0;\n        for (int j = 0; j < N; ++j) {\n            if (adj[i][j]) {\n                degree++;\n            }\n        }\n        colors[i] = degree;\n    }\n\n    // If wl_iters is 0, just return the degree distribution as fingerprint\n    if (wl_iters == 0) {\n        std::map<int, int> histogram;\n        for (int c : colors) {\n            histogram[c]++;\n        }\n        return histogram;\n    }\n\n    // For WL iterations > 0\n    // Use a unique color_map for each iteration to avoid global state issues.\n    // Or, more efficiently, reset/clear the map for each graph's WL computation.\n    // However, the current structure means 'color_map' is local to compute_wl_fingerprint,\n    // so it's fresh for each graph processed. The 'next_color_idx' ensures unique IDs within one graph's WL processing.\n    std::map<std::vector<int>, int> color_map; // Maps unique (current_color, sorted_neighbor_colors) to a new integer color\n    int next_color_idx = 0; // Counter for assigning new unique colors for this iteration\n\n    for (int iter = 0; iter < wl_iters; ++iter) {\n        // Clear color_map and reset next_color_idx for each iteration for distinctness\n        // No, this is incorrect. The colors are global for all N vertices within ONE graph.\n        // It's 'colors' (the vector) that holds the current iteration's state.\n        // `color_map` is used to map combinations of old_color+neighbor_colors to NEW_color.\n        // This mapping has to be consistent within one iteration for all vertices.\n        // The implementation already correctly uses a single color_map and next_color_idx for a full WL computation for one graph.\n        std::vector<int> new_colors(N);\n        for (int i = 0; i < N; ++i) {\n            std::vector<int> neighbor_colors;\n            for (int j = 0; j < N; ++j) {\n                if (adj[i][j]) {\n                    neighbor_colors.push_back(colors[j]);\n                }\n            }\n            std::sort(neighbor_colors.begin(), neighbor_colors.end());\n\n            // Construct key for color_map: current color + sorted list of neighbor colors\n            std::vector<int> current_key = {colors[i]};\n            current_key.insert(current_key.end(), neighbor_colors.begin(), neighbor_colors.end());\n            \n            // Assign a new unique color if this key hasn't been seen before\n            if (color_map.find(current_key) == color_map.end()) {\n                color_map[current_key] = next_color_idx++;\n            }\n            new_colors[i] = color_map[current_key];\n        }\n        colors = new_colors; // Update colors for the next iteration\n    }\n\n    // Compute histogram of final colors\n    std::map<int, int> histogram;\n    for (int c : colors) {\n        histogram[c]++;\n    }\n    return histogram;\n}\n\n// Calculates squared Euclidean distance between two color histograms\ndouble histogram_distance(const std::map<int, int>& h1, const std::map<int, int>& h2) {\n    double dist_sq = 0;\n    \n    // Collect all unique colors present in either histogram\n    std::vector<int> all_colors_keys;\n    for(const auto& pair : h1) all_colors_keys.push_back(pair.first);\n    for(const auto& pair : h2) all_colors_keys.push_back(pair.first);\n    std::sort(all_colors_keys.begin(), all_colors_keys.end());\n    all_colors_keys.erase(std::unique(all_colors_keys.begin(), all_colors_keys.end()), all_colors_keys.end());\n\n    for (int color : all_colors_keys) {\n        int count1 = h1.count(color) ? h1.at(color) : 0;\n        int count2 = h2.count(color) ? h2.at(color) : 0;\n        dist_sq += (double)(count1 - count2) * (count1 - count2);\n    }\n    return dist_sq;\n}\n\n// Global variables for problem parameters and generated graphs\nint M_param;\ndouble EPSILON_param;\nint N_chosen;\nstd::vector<AdjMatrix> G_graphs;\nstd::vector<std::map<int, int>> G_fingerprints; // Precomputed fingerprints for G_graphs\nstd::vector<int> G_edge_counts; // Precomputed edge counts for G_graphs\nint WL_ITERS_chosen; // Number of WL iterations to use\nint E_total_possible; // Total possible edges for N_chosen vertices\n\n// Function to precompute N and all M graphs G_k\nvoid precompute_graphs() {\n    // Determine N based on M and epsilon. Refined heuristic choice.\n    // Aims for a smaller N to minimize score penalty, while still providing enough capacity.\n    N_chosen = std::min(100, std::max(4, (int)(M_param * 0.3 + 10 + EPSILON_param * 20))); // Adjusted factors\n\n    // Determine WL_ITERS based on epsilon. Heuristic choice.\n    // Fewer iterations for higher epsilon to prevent noise from propagating too much.\n    // wl_iters can be 0, meaning only initial degree distribution is used.\n    WL_ITERS_chosen = std::max(0, 3 - (int)(EPSILON_param * 5));\n\n    E_total_possible = N_chosen * (N_chosen - 1) / 2; // Total possible edges\n    \n    G_graphs.resize(M_param);\n    G_fingerprints.resize(M_param);\n    G_edge_counts.resize(M_param);\n\n    // List all possible edges to facilitate random selection\n    std::vector<std::pair<int, int>> all_possible_edges;\n    for (int i = 0; i < N_chosen; ++i) {\n        for (int j = i + 1; j < N_chosen; ++j) {\n            all_possible_edges.push_back({i, j});\n        }\n    }\n\n    for (int k = 0; k < M_param; ++k) {\n        AdjMatrix current_G(N_chosen, std::vector<bool>(N_chosen, false));\n        \n        // Target number of edges for G_k.\n        // Distributed from 0 to E_total across M graphs.\n        int target_edges_count = std::round((double)k / (M_param - 1) * E_total_possible);\n        if (M_param == 1) target_edges_count = 0; // Special case for M=1 to avoid division by zero\n        \n        // Generate edges using a pseudo-random approach.\n        // A fixed seed 'k' ensures G_k is deterministic and distinct for each k.\n        std::mt19937 rng(k); \n        std::vector<std::pair<int, int>> shuffled_edges = all_possible_edges;\n        std::shuffle(shuffled_edges.begin(), shuffled_edges.end(), rng);\n\n        // Add the target number of edges\n        int actual_edges = 0;\n        for (int i = 0; i < target_edges_count; ++i) {\n            auto edge = shuffled_edges[i];\n            current_G[edge.first][edge.second] = true;\n            current_G[edge.second][edge.first] = true;\n            actual_edges++;\n        }\n        G_graphs[k] = current_G;\n        G_edge_counts[k] = actual_edges; // Store precomputed edge count\n        \n        // Precompute fingerprint for efficiency\n        G_fingerprints[k] = compute_wl_fingerprint(current_G, N_chosen, WL_ITERS_chosen);\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read M and epsilon\n    std::cin >> M_param >> EPSILON_param;\n\n    // Perform precomputation (determine N, generate G_k graphs and their fingerprints)\n    precompute_graphs();\n\n    // Output N and the M generated graphs\n    std::cout << N_chosen << std::endl;\n    for (int k = 0; k < M_param; ++k) {\n        std::cout << graph_to_string(G_graphs[k], N_chosen) << std::endl;\n    }\n    std::cout << std::flush; // Crucial for interactive problems\n\n    // Calculate normalization factor for WL distance. Max possible squared difference in a histogram of N vertices.\n    // If N is very small (e.g., N=4), 2.0 * N_chosen * N_chosen could be too large relative to max actual diff.\n    // For N_chosen vertices, the sum of counts in a histogram is N_chosen.\n    // Max diff for any single bucket is N_chosen. Max sum of squared diffs is 2*N_chosen^2.\n    // This value seems okay for normalization.\n    double wl_norm_factor = 2.0 * N_chosen * N_chosen;\n    if (N_chosen <= 1) wl_norm_factor = 1.0; // Defensive check, N_chosen >= 4\n\n    // Calculate weight alpha for combining distances.\n    // Alpha scales from 0 (pure WL) to 1 (pure edge count diff) as epsilon goes from 0 to 0.4.\n    // Using a square root power ensures edge_diff becomes relevant more quickly for intermediate epsilon.\n    double alpha_weight_base = EPSILON_param / 0.4;\n    double alpha_weight = std::pow(alpha_weight_base, 0.5); // Using sqrt to adjust weighting curve\n    \n    // Clamp alpha_weight to [0, 1] for robustness against floating point errors or edge cases.\n    alpha_weight = std::max(0.0, std::min(1.0, alpha_weight));\n\n    // For very small epsilon, ensure alpha_weight is 0 to prioritize WL.\n    if (EPSILON_param < 0.001) alpha_weight = 0.0;\n    // For very large epsilon, ensure alpha_weight is 1 to prioritize edge count.\n    if (EPSILON_param > 0.399) alpha_weight = 1.0;\n\n    // Process 100 queries\n    for (int q = 0; q < 100; ++q) {\n        std::string H_str;\n        std::cin >> H_str; // Read the received graph H_k\n        \n        // Compute fingerprint for H_k\n        AdjMatrix H_adj = string_to_graph(H_str, N_chosen);\n        std::map<int, int> H_fingerprint = compute_wl_fingerprint(H_adj, N_chosen, WL_ITERS_chosen);\n        \n        // Count edges in H_k\n        int H_edge_count = 0;\n        for (char c : H_str) {\n            if (c == '1') {\n                H_edge_count++;\n            }\n        }\n\n        double min_total_dist = -1.0;\n        int best_t = -1;\n\n        // Compare H_k's fingerprint and edge count with all precomputed G_t\n        for (int t = 0; t < M_param; ++t) {\n            // WL distance\n            double wl_dist = histogram_distance(H_fingerprint, G_fingerprints[t]);\n            double normalized_wl_dist = wl_dist / wl_norm_factor;\n\n            // Edge count difference distance\n            double edge_diff = std::abs((double)H_edge_count - G_edge_counts[t]);\n            double normalized_edge_diff = edge_diff / (double)E_total_possible;\n            if (E_total_possible == 0) normalized_edge_diff = 0.0; // Should not happen with N_chosen>=4, but for safety.\n\n            // Combined distance\n            double current_total_dist = (1.0 - alpha_weight) * normalized_wl_dist + alpha_weight * normalized_edge_diff;\n            \n            if (best_t == -1 || current_total_dist < min_total_dist) {\n                min_total_dist = current_total_dist;\n                best_t = t;\n            }\n        }\n        std::cout << best_t << std::endl; // Output the prediction\n        std::cout << std::flush; // Crucial for interactive problems\n    }\n\n    return 0;\n}\n","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <limits>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <map>\n#include <iomanip> // For setprecision\n#include <random>\n\nusing namespace std;\n\n// Using long long for distances to avoid overflow for sums\nconst long long INF = numeric_limits<long long>::max() / 2; // A sufficiently large value that avoids overflow when added to\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Node {\n    long long dist;\n    int u;\n    bool operator>(const Node& other) const {\n        return dist > other.dist;\n    }\n};\n\nstruct EdgeInfo {\n    int u, v, w, id;\n    long double val; // combined importance score: extra_dist * edge_betweenness\n};\n\nvector<vector<pair<int, int>>> adj; // adj[u] = list of {v, edge_id}\nvector<Edge> edges_data;\nint N_global, M_global, D_global, K_global;\n\n// Dijkstra's algorithm to find shortest paths from a source s\n// Optionally excludes a specific edge for extra_dist calculation\n// Returns a vector of distances from s to all other vertices.\nvector<long long> dijkstra(int s, const vector<vector<pair<int, int>>>& current_adj, int excluded_edge_id = -1) {\n    vector<long long> dist(N_global, INF);\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n    dist[s] = 0;\n    pq.push({0, s});\n\n    while (!pq.empty()) {\n        long long d = pq.top().dist;\n        int u = pq.top().u;\n        pq.pop();\n\n        if (d > dist[u]) continue; // Already found a shorter path\n\n        for (auto& edge_pair : current_adj[u]) {\n            int v = edge_pair.first;\n            int edge_id = edge_pair.second;\n\n            if (edge_id == excluded_edge_id) continue;\n\n            long long weight = edges_data[edge_id].w;\n            if (dist[u] != INF && dist[u] + weight < dist[v]) { // dist[u] != INF check to prevent overflow\n                dist[v] = dist[u] + weight;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Brandes' algorithm for Edge Betweenness Centrality\n// Returns a vector where element i is the betweenness centrality of edge_data[i]\nvector<long double> calculate_edge_betweenness() {\n    vector<long double> edge_betweenness(M_global, 0.0);\n\n    for (int s = 0; s < N_global; ++s) {\n        vector<long long> dist(N_global, INF);\n        vector<long long> num_shortest_paths(N_global, 0); // Count of shortest paths from s to v\n        vector<vector<int>> predecessors(N_global); // For each v, a list of vertices u that precede v on shortest paths from s\n        vector<int> stack; // To process vertices in decreasing order of distance\n\n        priority_queue<Node, vector<Node>, greater<Node>> pq;\n\n        dist[s] = 0;\n        num_shortest_paths[s] = 1;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            long long d = pq.top().dist;\n            int u = pq.top().u;\n            pq.pop();\n\n            if (d > dist[u]) continue; \n            \n            stack.push_back(u); // Add to stack for processing in reverse order of distance\n\n            for (auto& edge_pair : adj[u]) {\n                int v = edge_pair.first;\n                int edge_id = edge_pair.second;\n                long long weight = edges_data[edge_id].w;\n\n                if (dist[u] != INF) { // Only consider paths from reachable u\n                    if (dist[u] + weight < dist[v]) {\n                        dist[v] = dist[u] + weight;\n                        num_shortest_paths[v] = num_shortest_paths[u];\n                        predecessors[v].clear();\n                        predecessors[v].push_back(u);\n                        pq.push({dist[v], v});\n                    } else if (dist[u] + weight == dist[v]) {\n                        num_shortest_paths[v] += num_shortest_paths[u];\n                        predecessors[v].push_back(u);\n                    }\n                }\n            }\n        }\n\n        vector<long double> delta(N_global, 0.0); // Dependency of s on v\n        while (!stack.empty()) {\n            int v = stack.back();\n            stack.pop_back();\n\n            for (int u_pred : predecessors[v]) {\n                // Fraction of shortest paths from s to v that pass through u_pred\n                // num_shortest_paths[v] must be > 0 here, because v is reachable from s\n                long double path_fraction = (long double)num_shortest_paths[u_pred] / num_shortest_paths[v];\n                long double contribution = path_fraction * (1.0 + delta[v]);\n                \n                // Find edge_id for (u_pred, v)\n                int found_edge_id = -1;\n                for(const auto& edge_pair : adj[u_pred]) {\n                    if (edge_pair.first == v) {\n                        found_edge_id = edge_pair.second;\n                        break; \n                    }\n                }\n                \n                if (found_edge_id != -1) { // Should always be found for edges on shortest paths\n                    edge_betweenness[found_edge_id] += contribution;\n                }\n                delta[u_pred] += contribution;\n            }\n        }\n    }\n    return edge_betweenness;\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    cin >> N_global >> M_global >> D_global >> K_global;\n\n    adj.resize(N_global);\n    edges_data.resize(M_global);\n\n    for (int i = 0; i < M_global; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v; // 0-indexed\n        edges_data[i] = {u, v, w, i};\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i}); // Add edge for both directions\n    }\n\n    // Skip coordinates input as they are not used in this solution\n    for (int i = 0; i < N_global; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge betweenness centrality for each edge\n    vector<long double> edge_betweenness = calculate_edge_betweenness();\n\n    // 2. Precompute extra_dist for each edge (d'(u,v) - w when edge (u,v) is removed)\n    vector<long long> extra_dist(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        int u = edges_data[i].u;\n        int v = edges_data[i].v;\n        int w = edges_data[i].w;\n        vector<long long> dist_from_u_without_edge = dijkstra(u, adj, i);\n        // If u and v become disconnected, consider the path effectively infinite (10^9 from problem)\n        // Ensure extra_dist is non-negative\n        extra_dist[i] = (dist_from_u_without_edge[v] == INF) ? (1000000000LL - w) : (dist_from_u_without_edge[v] - w);\n        if (extra_dist[i] < 0) extra_dist[i] = 0; \n    }\n    \n    // 3. Combine scores: val[e_idx] = extra_dist[e_idx] * edge_betweenness[e_idx]\n    vector<EdgeInfo> edge_infos(M_global);\n    for (int i = 0; i < M_global; ++i) {\n        edge_infos[i] = {edges_data[i].u, edges_data[i].v, edges_data[i].w, i, (long double)extra_dist[i] * edge_betweenness[i]};\n    }\n    \n    // 4. Initial assignment (r[M]): Sort edges by combined importance (val) and assign round-robin\n    sort(edge_infos.begin(), edge_infos.end(), [](const EdgeInfo& a, const EdgeInfo& b) {\n        return a.val > b.val;\n    });\n\n    vector<int> r(M_global); // repair day for each edge (1-indexed)\n    vector<int> day_load(D_global + 1, 0); // Number of edges assigned to each day\n    vector<long double> current_sum_val(D_global + 1, 0.0); // Sum of val for edges assigned to each day\n\n    for (int i = 0; i < M_global; ++i) {\n        int edge_id = edge_infos[i].id;\n        int day = (i % D_global) + 1; // Round-robin assignment based on sorted importance\n        r[edge_id] = day;\n        day_load[day]++;\n        current_sum_val[day] += edge_infos[i].val;\n    }\n    \n    // Calculate initial estimated frustration score (sum of average vals per day)\n    long double current_total_approx_score = 0.0;\n    for (int k = 1; k <= D_global; ++k) {\n        if (day_load[k] > 0) {\n            current_total_approx_score += current_sum_val[k] / day_load[k];\n        }\n    }\n\n    vector<int> best_r = r;\n    long double best_total_approx_score = current_total_approx_score;\n\n    // Simulated Annealing parameters\n    double time_limit_sec = 5.9; // Allocate 5.9 seconds for SA\n    long double T_start = 1e12; // Starting temperature\n    long double T_end = 1e-4;   // Ending temperature\n    \n    // Random number generation setup\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_edge(0, M_global - 1);\n    uniform_int_distribution<int> dist_day(1, D_global);\n    uniform_real_distribution<long double> dist_01(0.0, 1.0);\n\n    // SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time_sec = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time_sec > time_limit_sec) {\n            break;\n        }\n\n        // Linear cooling schedule\n        long double current_T = T_start * (1.0 - elapsed_time_sec / time_limit_sec);\n        if (current_T < T_end) current_T = T_end;\n\n        int edge_idx = dist_edge(rng); // Randomly pick an edge to move\n        int day_from = r[edge_idx];\n        int day_to = dist_day(rng); // Randomly pick a target day\n\n        // Check feasibility and efficiency constraints\n        if (day_from == day_to || day_load[day_to] >= K_global) {\n            continue; // Cannot move to same day or to an already full day\n        }\n\n        long double val_e = edge_infos[edge_idx].val; // Importance value of the edge being moved\n\n        // Calculate old average frustration for affected days\n        long double old_f_from = current_sum_val[day_from] / day_load[day_from];\n        long double old_f_to = (day_load[day_to] > 0) ? (current_sum_val[day_to] / day_load[day_to]) : 0.0; // If day_to is empty, old frustration is 0\n\n        // Calculate new average frustration if move is accepted\n        long double new_f_from = (day_load[day_from] > 1) ? ((current_sum_val[day_from] - val_e) / (day_load[day_from] - 1.0)) : 0.0; // If day_from becomes empty, new frustration is 0\n        long double new_f_to = (current_sum_val[day_to] + val_e) / (day_load[day_to] + 1.0);\n        \n        long double delta_score = (new_f_from - old_f_from) + (new_f_to - old_f_to);\n\n        // Acceptance criteria for Simulated Annealing\n        if (delta_score < 0 || dist_01(rng) < exp(-delta_score / current_T)) {\n            // Accept the move\n            r[edge_idx] = day_to;\n            day_load[day_from]--;\n            day_load[day_to]++;\n            current_sum_val[day_from] -= val_e;\n            current_sum_val[day_to] += val_e;\n            current_total_approx_score += delta_score;\n\n            // Update best solution found so far\n            if (current_total_approx_score < best_total_approx_score) {\n                best_total_approx_score = current_total_approx_score;\n                best_r = r;\n            }\n        }\n    }\n\n    // Output the best assignment found\n    for (int i = 0; i < M_global; ++i) {\n        cout << best_r[i] << (i == M_global - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}\n","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <queue>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\n// Global D for convenience\nint D;\n\n// Struct for 3D point\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& 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 Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n};\n\n// Represents a polycube shape as a vector of relative points\nusing Shape = vector<Point>;\n\n// Function to apply a rotation to a point relative to its origin (0,0,0)\nPoint rotate_point(const Point& p, int rot_idx) {\n    // This defines the 24 unique rotations\n    // Each case maps (x,y,z) to a permutation of (+/-x, +/-y, +/-z)\n    switch (rot_idx) {\n        case 0: return {p.x, p.y, p.z};\n        case 1: return {p.x, p.z, -p.y};\n        case 2: return {p.x, -p.y, -p.z};\n        case 3: return {p.x, -p.z, p.y};\n        \n        case 4: return {-p.x, -p.y, p.z};\n        case 5: return {-p.x, -p.z, -p.y};\n        case 6: return {-p.x, p.y, -p.z};\n        case 7: return {-p.x, p.z, p.y};\n\n        case 8: return {p.y, p.x, -p.z};\n        case 9: return {p.y, p.z, p.x};\n        case 10: return {p.y, -p.x, p.z};\n        case 11: return {p.y, -p.z, -p.x};\n\n        case 12: return {-p.y, p.x, p.z};\n        case 13: return {-p.y, p.z, -p.x};\n        case 14: return {-p.y, -p.x, -p.z};\n        case 15: return {-p.y, -p.z, p.x};\n        \n        case 16: return {p.z, p.x, p.y};\n        case 17: return {p.z, p.y, -p.x};\n        case 18: return {p.z, -p.x, -p.y};\n        case 19: return {p.z, -p.y, p.x};\n        \n        case 20: return {-p.z, p.x, p.y};\n        case 21: return {-p.z, p.y, -p.x};\n        case 22: return {-p.z, -p.x, -p.y};\n        case 23: return {-p.z, -p.y, p.x};\n    }\n    return p; // Should not be reached\n}\n\n// Function to canonicalize a shape (vector of relative points)\nShape get_canonical_form(const Shape& shape) {\n    if (shape.empty()) return {};\n\n    Shape canonical_shape = shape;\n    sort(canonical_shape.begin(), canonical_shape.end()); // Initial sort\n\n    for (int rot_idx = 0; rot_idx < 24; ++rot_idx) {\n        Shape rotated_shape_temp;\n        for (const auto& p : shape) {\n            rotated_shape_temp.push_back(rotate_point(p, rot_idx));\n        }\n\n        // Translate to (0,0,0) origin\n        int min_x = D, min_y = D, min_z = D;\n        for (const auto& p : rotated_shape_temp) {\n            min_x = min(min_x, p.x);\n            min_y = min(min_y, p.y);\n            min_z = min(min_z, p.z);\n        }\n        for (auto& p : rotated_shape_temp) {\n            p.x -= min_x;\n            p.y -= min_y;\n            p.z -= min_z;\n        }\n\n        sort(rotated_shape_temp.begin(), rotated_shape_temp.end());\n        if (rotated_shape_temp < canonical_shape) {\n            canonical_shape = rotated_shape_temp;\n        }\n    }\n    return canonical_shape;\n}\n\n// BFS to find a connected component and return its absolute points.\n// Also modifies `grid_to_search` by setting visited cells to 0.\n// Returns a pair: {vector of absolute points, relative shape}\npair<vector<Point>, Shape> find_and_extract_component(vector<vector<vector<int>>>& grid_to_search, int start_x, int start_y, int start_z) {\n    vector<Point> absolute_points;\n    Shape relative_shape;\n\n    if (start_x < 0 || start_x >= D || start_y < 0 || start_y >= D || start_z < 0 || start_z >= D || grid_to_search[start_x][start_y][start_z] == 0) {\n        return {absolute_points, relative_shape};\n    }\n\n    queue<Point> q;\n    q.push({start_x, start_y, start_z});\n    grid_to_search[start_x][start_y][start_z] = 0; // Mark as visited and remove from current grid\n    absolute_points.push_back({start_x, start_y, start_z});\n\n    int dx[] = {0, 0, 0, 0, 1, -1};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {1, -1, 0, 0, 0, 0};\n\n    while (!q.empty()) {\n        Point curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 6; ++i) {\n            int nx = curr.x + dx[i];\n            int ny = curr.y + dy[i];\n            int nz = curr.z + dz[i];\n\n            if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D && grid_to_search[nx][ny][nz] == 1) {\n                grid_to_search[nx][ny][nz] = 0; // Mark as visited\n                q.push({nx, ny, nz});\n                absolute_points.push_back({nx, ny, nz});\n            }\n        }\n    }\n    \n    // Translate the component points to be relative to their bounding box min corner\n    if (absolute_points.empty()) return {absolute_points, relative_shape};\n\n    int min_x = D, min_y = D, min_z = D;\n    for (const auto& p : absolute_points) {\n        min_x = min(min_x, p.x);\n        min_y = min(min_y, p.y);\n        min_z = min(min_z, p.z);\n    }\n    \n    for (const auto& p : absolute_points) {\n        relative_shape.push_back({p.x - min_x, p.y - min_y, p.z - min_z});\n    }\n    sort(relative_shape.begin(), relative_shape.end());\n    \n    return {absolute_points, relative_shape};\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> D;\n\n    vector<string> f1_str(D), r1_str(D), f2_str(D), r2_str(D);\n    for (int i = 0; i < D; ++i) cin >> f1_str[i];\n    for (int i = 0; i < D; ++i) cin >> r1_str[i];\n    for (int i = 0; i < D; ++i) cin >> f2_str[i];\n    for (int i = 0; i < D; ++i) cin >> r2_str[i];\n\n    // U_i_grid_initial[x][y][z] == 1 if (x,y,z) can be occupied based on silhouettes\n    // These grids are the \"ground truth\" and are not modified during component extraction.\n    vector<vector<vector<int>>> U1_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> U2_grid_initial(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (f1_str[z][x] == '1' && r1_str[z][y] == '1') U1_grid_initial[x][y][z] = 1;\n                if (f2_str[z][x] == '1' && r2_str[z][y] == '1') U2_grid_initial[x][y][z] = 1;\n            }\n        }\n    }\n\n    // b_raw grids store temporary IDs for blocks discovered for each object independently.\n    // They are populated to fully cover U_grid_initial for their respective objects.\n    vector<vector<vector<int>>> b1_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_raw(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Stores (canonical_shape, volume) for each temporary block in b1_raw and b2_raw\n    // 1-indexed, so push a dummy element at index 0.\n    vector<tuple<Shape, int>> b1_temp_blocks_info; \n    b1_temp_blocks_info.emplace_back(Shape{}, 0); \n    vector<tuple<Shape, int>> b2_temp_blocks_info; \n    b2_temp_blocks_info.emplace_back(Shape{}, 0); \n    \n    int current_temp_id_b1 = 1;\n    int current_temp_id_b2 = 1;\n\n    // Phase 1: Fill b1_raw completely based on U1_grid_initial\n    // Use a mutable copy for BFS, as it modifies the grid by setting visited cells to 0.\n    vector<vector<vector<int>>> U1_grid_mutable = U1_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U1_grid_mutable[x][y][z] == 1) { \n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U1_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n\n                    if (!absolute_points.empty()) { \n                        int temp_id = current_temp_id_b1++;\n                        for (const auto& p_abs : absolute_points) {\n                            b1_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b1_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 2: Fill b2_raw completely based on U2_grid_initial\n    // Similar to Phase 1, but for object 2.\n    vector<vector<vector<int>>> U2_grid_mutable = U2_grid_initial; \n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (U2_grid_mutable[x][y][z] == 1) {\n                    pair<vector<Point>, Shape> component_data = find_and_extract_component(U2_grid_mutable, x, y, z);\n                    const vector<Point>& absolute_points = component_data.first;\n                    const Shape& relative_shape = component_data.second;\n                    \n                    if (!absolute_points.empty()) {\n                        int temp_id = current_temp_id_b2++;\n                        for (const auto& p_abs : absolute_points) {\n                            b2_raw[p_abs.x][p_abs.y][p_abs.z] = temp_id;\n                        }\n                        b2_temp_blocks_info.emplace_back(get_canonical_form(relative_shape), absolute_points.size());\n                    }\n                }\n            }\n        }\n    }\n\n    // Phase 3: Consolidate temporary blocks into final block set and IDs\n    vector<int> map_b1_to_final_id(current_temp_id_b1, 0); // Maps b1_raw temp_id to final_id\n    vector<int> map_b2_to_final_id(current_temp_id_b2, 0); // Maps b2_raw temp_id to final_id\n    \n    int current_final_id = 1; // Start final block IDs from 1\n    \n    // These vectors store info about the *final* set of unique blocks.\n    // They are not directly used for output, but for score calculation logic.\n    // Kept for clarity and potential future optimizations.\n    vector<Shape> final_block_shapes;\n    vector<int> final_block_volumes;\n    vector<bool> final_block_used_in_1;\n    vector<bool> final_block_used_in_2;\n\n    // Dummy entries for 1-indexed final_ids\n    final_block_shapes.push_back({});\n    final_block_volumes.push_back(0);\n    final_block_used_in_1.push_back(false);\n    final_block_used_in_2.push_back(false);\n\n    // Group temporary blocks by their canonical shape\n    map<Shape, vector<int>> temp_ids_b1_by_shape; // canonical_shape -> list of b1_raw temp_id\n    map<Shape, vector<int>> temp_ids_b2_by_shape; // canonical_shape -> list of b2_raw temp_id\n\n    for (int i = 1; i < b1_temp_blocks_info.size(); ++i) {\n        temp_ids_b1_by_shape[get<0>(b1_temp_blocks_info[i])].push_back(i);\n    }\n    for (int i = 1; i < b2_temp_blocks_info.size(); ++i) {\n        temp_ids_b2_by_shape[get<0>(b2_temp_blocks_info[i])].push_back(i);\n    }\n\n    set<Shape> processed_shapes; // To avoid processing same shape twice (from b1 and b2 loops)\n\n    // First, process shapes that appear in b1_raw. Try to match them with b2_raw blocks.\n    for (auto const& [shape, b1_raw_ids_for_shape] : temp_ids_b1_by_shape) {\n        processed_shapes.insert(shape); // Mark this shape as processed\n        \n        auto it_b2 = temp_ids_b2_by_shape.find(shape);\n        vector<int> b2_raw_ids_for_shape;\n        if (it_b2 != temp_ids_b2_by_shape.end()) {\n            b2_raw_ids_for_shape = it_b2->second;\n        }\n\n        // Match as many b1 blocks with b2 blocks of the same shape as possible\n        int num_to_match = min(b1_raw_ids_for_shape.size(), b2_raw_ids_for_shape.size());\n        for (int i = 0; i < num_to_match; ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n            \n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]])); // Volume is same for same shape\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(true);\n        }\n\n        // Remaining b1_raw blocks (only used in Object 1)\n        for (int i = num_to_match; i < b1_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b1_to_final_id[b1_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b1_temp_blocks_info[b1_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(true);\n            final_block_used_in_2.push_back(false);\n        }\n\n        // Remaining b2_raw blocks (only used in Object 2), for this shape\n        for (int i = num_to_match; i < b2_raw_ids_for_shape.size(); ++i) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_raw_ids_for_shape[i]] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_raw_ids_for_shape[i]]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n\n    // Process shapes that were only present in b2_raw (not in b1_raw)\n    for (auto const& [shape, b2_raw_ids_for_shape] : temp_ids_b2_by_shape) {\n        if (processed_shapes.count(shape)) continue; // Already handled if present in b1_raw\n        \n        for (int b2_id : b2_raw_ids_for_shape) {\n            int final_id = current_final_id++;\n            map_b2_to_final_id[b2_id] = final_id;\n\n            final_block_shapes.push_back(shape);\n            final_block_volumes.push_back(get<1>(b2_temp_blocks_info[b2_id]));\n            final_block_used_in_1.push_back(false);\n            final_block_used_in_2.push_back(true);\n        }\n    }\n    \n    // Phase 4: Populate final b1 and b2 grids with assigned final IDs\n    vector<vector<vector<int>>> b1_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    vector<vector<vector<int>>> b2_final_output(D, vector<vector<int>>(D, vector<int>(D, 0)));\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (b1_raw[x][y][z] != 0) {\n                    b1_final_output[x][y][z] = map_b1_to_final_id[b1_raw[x][y][z]];\n                }\n                if (b2_raw[x][y][z] != 0) {\n                    b2_final_output[x][y][z] = map_b2_to_final_id[b2_raw[x][y][z]];\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << current_final_id - 1 << endl; // Total number of unique final blocks\n\n    // Output b1_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b1_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    // Output b2_final\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                cout << b2_final_output[x][y][z] << (x == D - 1 && y == D - 1 && z == D - 1 ? \"\" : \" \");\n            }\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <tuple> // For std::tuple\n\nusing namespace std;\n\nconst long long INF_LL = 4e18; // Sufficiently large infinity for long long\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\nstruct Edge {\n    int id; // original edge index (0 to M-1)\n    int u, v;\n    long long w;\n};\n\nstruct EdgeInfo { // For adjacency list\n    int to_node;\n    long long weight;\n    int original_edge_idx;\n};\n\n// For Dijkstra\nstruct State {\n    long long cost;\n    int u;\n\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\nint N, M, K;\nvector<Point> nodes;\nvector<Edge> edges_data;\nvector<Point> residents;\nvector<vector<EdgeInfo>> adj; // adjacency list for graph\n\n// Precomputed distances\nvector<vector<long long>> dist_res_node_sq; // dist_res_node_sq[k][i] = squared Euclidean distance from resident k to node i\nvector<long long> dist_from_1; // Shortest path cost from node 1 to node i\nvector<int> parent_on_spt_node; // parent_on_spt_node[i] = parent node in SPT from node 1\nvector<int> parent_on_spt_edge_idx; // parent_on_spt_edge_idx[i] = original edge index of (parent[i], i)\n\n// Global random generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Helper function to calculate squared Euclidean distance\nlong long distSq(Point p1, 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\n// Calculate rounded Euclidean distance\nint round_dist_val(long long dist_sq) {\n    return static_cast<int>(round(sqrt((long double)dist_sq))); // Cast to long double for sqrt for precision\n}\n\n// Dijkstra from node 1\nvoid run_dijkstra() {\n    dist_from_1.assign(N + 1, INF_LL);\n    parent_on_spt_node.assign(N + 1, -1);\n    parent_on_spt_edge_idx.assign(N + 1, -1);\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    dist_from_1[1] = 0;\n    pq.push({0, 1});\n\n    while (!pq.empty()) {\n        State current = pq.top();\n        pq.pop();\n\n        long long d = current.cost;\n        int u = current.u;\n\n        if (d > dist_from_1[u]) continue;\n\n        for (auto& edge_info : adj[u]) {\n            int v = edge_info.to_node;\n            long long weight = edge_info.weight;\n            int edge_idx = edge_info.original_edge_idx;\n\n            if (dist_from_1[u] + weight < dist_from_1[v]) {\n                dist_from_1[v] = dist_from_1[u] + weight;\n                parent_on_spt_node[v] = u;\n                parent_on_spt_edge_idx[v] = edge_idx;\n                pq.push({dist_from_1[v], v});\n            }\n        }\n    }\n}\n\n// Recalculates edge cost for a given set of active stations\nlong long calculate_edge_cost_from_active_stations(const set<int>& active_stations, vector<int>& B_output_temp) {\n    set<int> edges_on_idx_set;\n    long long current_edge_cost = 0;\n\n    for (int u : active_stations) {\n        if (dist_from_1[u] == INF_LL) { \n            return INF_LL; // Should not happen if `active_stations` are already filtered or cost is set to INF_LL\n        }\n        if (u == 1) continue; \n        \n        int curr = u;\n        while (curr != 1 && parent_on_spt_node[curr] != -1) {\n            int edge_idx = parent_on_spt_edge_idx[curr];\n            if (edges_on_idx_set.find(edge_idx) == edges_on_idx_set.end()) {\n                edges_on_idx_set.insert(edge_idx);\n                current_edge_cost += edges_data[edge_idx].w;\n            }\n            curr = parent_on_spt_node[curr];\n        }\n    }\n    \n    // Populate B_output_temp\n    B_output_temp.assign(M, 0);\n    for (int j = 0; j < M; ++j) {\n        if (edges_on_idx_set.count(j)) {\n            B_output_temp[j] = 1;\n        }\n    }\n\n    return current_edge_cost;\n}\n\n\nvoid solve() {\n    // Precomputation (read input, run Dijkstra, calculate resident-node distances)\n    nodes.resize(N + 1);\n    for (int i = 1; i <= N; ++i) {\n        cin >> nodes[i].x >> nodes[i].y;\n        nodes[i].id = i;\n    }\n\n    adj.resize(N + 1);\n    edges_data.resize(M);\n    for (int j = 0; j < M; ++j) {\n        cin >> edges_data[j].u >> edges_data[j].v >> edges_data[j].w;\n        edges_data[j].id = j;\n        adj[edges_data[j].u].push_back({edges_data[j].v, edges_data[j].w, j});\n        adj[edges_data[j].v].push_back({edges_data[j].u, edges_data[j].w, j});\n    }\n\n    residents.resize(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> residents[k].x >> residents[k].y;\n        residents[k].id = k;\n    }\n\n    run_dijkstra();\n\n    dist_res_node_sq.resize(K, vector<long long>(N + 1));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            dist_res_node_sq[k][i] = distSq(residents[k], nodes[i]);\n        }\n    }\n    \n    // Initial solution (Greedy approach)\n    vector<int> P_current(N + 1, 0);\n    \n    // For each resident, assign it to its closest reachable station (within 5000 radius).\n    // Then combine P values for stations.\n    for (int k = 0; k < K; ++k) {\n        int best_station_for_k = -1;\n        long long min_dist_sq_for_k = (long long)5001 * 5001; // Max guaranteed distance is 5000\n        for (int i = 1; i <= N; ++i) {\n            if (dist_from_1[i] == INF_LL) continue; // Station must be reachable from 1\n            if (dist_res_node_sq[k][i] <= (long long)5000 * 5000) {\n                if (dist_res_node_sq[k][i] < min_dist_sq_for_k) {\n                    min_dist_sq_for_k = dist_res_node_sq[k][i];\n                    best_station_for_k = i;\n                }\n            }\n        }\n        if (best_station_for_k != -1) {\n            P_current[best_station_for_k] = max(P_current[best_station_for_k], round_dist_val(min_dist_sq_for_k));\n        } else {\n             // This indicates a problem as per problem statement guarantee. Should not happen.\n        }\n    }\n    // Cap all P values at 5000\n    for(int i=1; i<=N; ++i) {\n        P_current[i] = min(P_current[i], 5000);\n    }\n    \n    vector<int> B_best(M);\n    long long best_S = INF_LL;\n    vector<int> P_best = P_current;\n\n    // State variables for SA (to allow incremental updates)\n    long long current_P_cost_SA = 0;\n    set<int> active_stations_SA;\n    vector<int> num_covering_stations_for_resident(K, 0);\n    int num_residents_fully_covered = 0;\n\n    // Initialize SA state variables from P_current\n    for (int i = 1; i <= N; ++i) {\n        if (P_current[i] > 0 && dist_from_1[i] == INF_LL) { // If an initially active station is unreachable\n            current_P_cost_SA = INF_LL; // Mark initial state as invalid\n            break;\n        }\n        current_P_cost_SA += (long long)P_current[i] * P_current[i];\n        if (P_current[i] > 0) {\n            active_stations_SA.insert(i);\n        }\n    }\n    if (current_P_cost_SA != INF_LL) { // If initial P cost is valid (all active stations reachable)\n        for (int k = 0; k < K; ++k) {\n            for (int i = 1; i <= N; ++i) {\n                if (P_current[i] > 0) {\n                    if (dist_res_node_sq[k][i] <= (long long)P_current[i] * P_current[i]) {\n                        num_covering_stations_for_resident[k]++;\n                    }\n                }\n            }\n            if (num_covering_stations_for_resident[k] > 0) {\n                num_residents_fully_covered++;\n            }\n        }\n    }\n    \n    long long current_edge_cost_SA = 0;\n    if (current_P_cost_SA != INF_LL && num_residents_fully_covered == K) {\n        vector<int> temp_B(M); // Placeholder for calculate_edge_cost_from_active_stations\n        current_edge_cost_SA = calculate_edge_cost_from_active_stations(active_stations_SA, temp_B);\n        best_S = current_P_cost_SA + current_edge_cost_SA;\n        P_best = P_current;\n    }\n\n\n    // Simulated Annealing\n    chrono::high_resolution_clock::time_point start_time = chrono::high_resolution_clock::now();\n    long double current_temp;\n    if (best_S == INF_LL) { \n        current_temp = 1e9; \n    } else {\n        current_temp = (long double)best_S / 100.0; // Dynamic initial temperature\n    }\n    long double end_temp = 1.0;\n    long double time_limit = 1.95; // seconds\n    \n    // Parameters for SA moves\n    const int P_ADJUST_RANGE = 500; \n    \n    long long iter_count = 0;\n    while (true) {\n        chrono::high_resolution_clock::time_point current_time = chrono::high_resolution_clock::now();\n        long double elapsed_time = chrono::duration_cast<chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        if (elapsed_time > time_limit) {\n            break;\n        }\n        \n        current_temp = end_temp + (current_temp - end_temp) * (1.0 - elapsed_time / time_limit);\n        \n        vector<int> P_next = P_current; // P_next is a copy for perturbation\n        long long next_P_cost = current_P_cost_SA;\n        set<int> next_active_stations = active_stations_SA;\n        vector<int> next_num_covering_stations = num_covering_stations_for_resident;\n        int next_num_residents_fully_covered = num_residents_fully_covered;\n\n        int target_node = rng() % N + 1;\n        int old_P_val = P_current[target_node]; // Use P_current for old P value\n\n        if (dist_from_1[target_node] == INF_LL) { // Don't bother with unreachable nodes\n            continue;\n        }\n\n        int move_type = rng() % 100;\n\n        if (move_type < 60) { // Type 0: Adjust P_i for a random station i (60% chance)\n            int rand_delta = (rng() % (2 * P_ADJUST_RANGE + 1)) - P_ADJUST_RANGE;\n            int new_P_val = old_P_val + rand_delta;\n            new_P_val = max(0, min(5000, new_P_val));\n            P_next[target_node] = new_P_val;\n\n            // Update incremental costs\n            next_P_cost -= (long long)old_P_val * old_P_val;\n            next_P_cost += (long long)new_P_val * new_P_val;\n\n            if (old_P_val == 0 && new_P_val > 0) { // Station became active\n                next_active_stations.insert(target_node);\n            } else if (old_P_val > 0 && new_P_val == 0) { // Station became inactive\n                next_active_stations.erase(target_node);\n            }\n\n            // Update coverage counts incrementally for O(K) complexity\n            for (int k = 0; k < K; ++k) {\n                bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                if (old_covered_by_target && !new_covered_by_target) {\n                    next_num_covering_stations[k]--;\n                    if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                } else if (!old_covered_by_target && new_covered_by_target) {\n                    next_num_covering_stations[k]++;\n                    if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                }\n            }\n\n        } else { // Type 1: Try to turn off a station and re-assign coverage (40% chance)\n            \n            // If target_node is currently OFF, try turning it ON (random P)\n            if (old_P_val == 0) { \n                int new_P_val = rng() % 5001; // Random P between 0 and 5000\n                P_next[target_node] = new_P_val;\n\n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_P_cost += (long long)new_P_val * new_P_val;\n\n                if (new_P_val > 0) {\n                    next_active_stations.insert(target_node);\n                }\n\n                // Update coverage counts incrementally\n                for (int k = 0; k < K; ++k) {\n                    bool old_covered_by_target = (old_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val);\n                    bool new_covered_by_target = (new_P_val > 0 && dist_res_node_sq[k][target_node] <= (long long)new_P_val * new_P_val);\n\n                    if (old_covered_by_target && !new_covered_by_target) {\n                        next_num_covering_stations[k]--;\n                        if (next_num_covering_stations[k] == 0) next_num_residents_fully_covered--;\n                    } else if (!old_covered_by_target && new_covered_by_target) {\n                        next_num_covering_stations[k]++;\n                        if (next_num_covering_stations[k] == 1) next_num_residents_fully_covered++;\n                    }\n                }\n\n            } else { // If target_node is currently ON, try turning it OFF and re-assign\n                // Temporarily remove target_node's coverage from next_num_covering_stations\n                // This makes it easy to find truly uncovered residents for re-assignment\n                for(int k=0; k<K; ++k){\n                    if(dist_res_node_sq[k][target_node] <= (long long)old_P_val * old_P_val){\n                        next_num_covering_stations[k]--;\n                        if(next_num_covering_stations[k] == 0){\n                            next_num_residents_fully_covered--;\n                        }\n                    }\n                }\n\n                P_next[target_node] = 0; \n                next_P_cost -= (long long)old_P_val * old_P_val;\n                next_active_stations.erase(target_node);\n\n                // For each resident that became uncovered, find the best station to cover it\n                for(int k=0; k<K; ++k){\n                    if(next_num_covering_stations[k] == 0){ // This resident is now uncovered\n                        int best_alt_station = -1;\n                        long long min_dist_sq = INF_LL; \n                        for(int i=1; i<=N; ++i){ \n                            if(dist_from_1[i] == INF_LL) continue; // Only consider reachable stations\n                            if(dist_res_node_sq[k][i] < min_dist_sq){\n                                min_dist_sq = dist_res_node_sq[k][i];\n                                best_alt_station = i;\n                            }\n                        }\n                        if(best_alt_station != -1){\n                            int old_alt_P = P_next[best_alt_station]; // Use P_next (which might already be updated)\n                            long long required_P_sq = min_dist_sq;\n                            int required_P = round_dist_val(required_P_sq);\n                            int new_alt_P = max(old_alt_P, min(5000, required_P));\n                            \n                            // Apply change to P_next and update costs incrementally\n                            P_next[best_alt_station] = new_alt_P;\n                            next_P_cost -= (long long)old_alt_P * old_alt_P;\n                            next_P_cost += (long long)new_alt_P * new_alt_P;\n                            if (old_alt_P == 0 && new_alt_P > 0) {\n                                next_active_stations.insert(best_alt_station);\n                            }\n                            // Update coverage for this resident 'k' by best_alt_station\n                            // (Only for k, not all residents affected by best_alt_station's P change)\n                            if (dist_res_node_sq[k][best_alt_station] <= (long long)new_alt_P * new_alt_P) {\n                                next_num_covering_stations[k]++;\n                                if(next_num_covering_stations[k] == 1) { // It just became covered again\n                                    next_num_residents_fully_covered++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        long long S_current_val = current_P_cost_SA + current_edge_cost_SA;\n        long long S_next = INF_LL;\n\n        if (next_num_residents_fully_covered == K) {\n            vector<int> B_temp(M);\n            long long next_edge_cost = calculate_edge_cost_from_active_stations(next_active_stations, B_temp);\n            S_next = next_P_cost + next_edge_cost;\n        }\n\n        if (S_next < best_S) {\n            P_current = P_next;\n            current_P_cost_SA = next_P_cost;\n            active_stations_SA = next_active_stations;\n            num_covering_stations_for_resident = next_num_covering_stations;\n            num_residents_fully_covered = next_num_residents_fully_covered;\n            current_edge_cost_SA = S_next - current_P_cost_SA; // derive edge cost from S_next and P_cost\n            best_S = S_next;\n            P_best = P_next;\n        } else if (S_next != INF_LL) {\n            long double prob = exp((S_current_val - S_next) / current_temp);\n            if (uniform_real_distribution<long double>(0.0, 1.0)(rng) < prob) {\n                P_current = P_next;\n                current_P_cost_SA = next_P_cost;\n                active_stations_SA = next_active_stations;\n                num_covering_stations_for_resident = next_num_covering_stations;\n                num_residents_fully_covered = next_num_residents_fully_covered;\n                current_edge_cost_SA = S_next - current_P_cost_SA;\n            }\n        }\n        \n        iter_count++;\n    }\n\n    // Final calculation for output\n    vector<int> B_final(M);\n    calculate_edge_cost_from_active_stations(active_stations_SA, B_final); \n\n    // Output\n    for (int i = 1; i <= N; ++i) {\n        cout << P_best[i] << (i == N ? \"\" : \" \");\n    }\n    cout << endl;\n    for (int j = 0; j < M; ++j) {\n        cout << B_final[j] << (j == M - 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 >> K;\n    solve();\n\n    return 0;\n}\n","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <tuple>   // For std::tuple\n\n// N is fixed to 30 for all inputs.\n// The problem defines N as the number of tiers.\n// Tiers are 0-indexed from 0 to N-1.\n// Ball coordinates are (x,y) where 0 <= x <= N-1 and 0 <= y <= x.\nconst int N = 30;\n\n// Global data structures for the pyramid state and operations.\n// The pyramid itself, storing the ball numbers.\nstd::vector<std::vector<int>> pyramid(N);\n\n// To quickly find the coordinates of a ball given its number.\n// `current_pos_of_value[ball_number]` stores `{x, y}`.\nstd::vector<std::pair<int, int>> current_pos_of_value(N * (N + 1) / 2);\n\n// Stores the sequence of swap operations.\n// Each operation is a tuple `{x1, y1, x2, y2}`.\nstd::vector<std::tuple<int, int, int, int>> operations;\n\n/**\n * @brief Performs a swap between two balls at given coordinates and records the operation.\n *\n * This function updates the `pyramid` and `current_pos_of_value` data structures\n * to reflect the swap, and adds the operation to the `operations` list.\n * The coordinates (r1, c1) and (r2, c2) must refer to adjacent balls.\n *\n * @param r1 Row coordinate of the first ball.\n * @param c1 Column coordinate of the first ball.\n * @param r2 Row coordinate of the second ball.\n * @param c2 Column coordinate of the second ball.\n */\nvoid perform_swap(int r1, int c1, int r2, int c2) {\n    int val1 = pyramid[r1][c1];\n    int val2 = pyramid[r2][c2];\n\n    // Swap values in the pyramid grid\n    pyramid[r1][c1] = val2;\n    pyramid[r2][c2] = val1;\n\n    // Update the mapping from value to its current position\n    current_pos_of_value[val1] = {r2, c2};\n    current_pos_of_value[val2] = {r1, c1};\n\n    // Record the swap operation\n    operations.emplace_back(r1, c1, r2, c2);\n}\n\n/**\n * @brief Sifts down an element at (r, c) to satisfy the min-pyramid property.\n *\n * This function repeatedly compares the ball at (r, c) with its two children\n * ((r+1, c) and (r+1, c+1)). If the parent ball is larger than either child,\n * it swaps the parent with the smallest child. This process continues until\n * the parent ball is smaller than or equal to both its children, or it reaches\n * the bottom tier.\n * This is an iterative implementation of the sift-down (or heapify-down) process.\n *\n * @param r Row coordinate of the ball to sift down.\n * @param c Column coordinate of the ball to sift down.\n */\nvoid sift_down(int r, int c) {\n    while (true) {\n        int parent_val = pyramid[r][c];\n        int min_val = parent_val; // Initialize min_val with parent's value\n        int target_r = r;         // Initialize target_r and target_c to parent's position\n        int target_c = c;\n\n        // Check left child: (r+1, c)\n        // Ensure that (r,c) is not in the last tier (N-1)\n        if (r + 1 < N) {\n            int child1_val = pyramid[r+1][c];\n            if (child1_val < min_val) {\n                min_val = child1_val;\n                target_r = r + 1;\n                target_c = c;\n            }\n        }\n\n        // Check right child: (r+1, c+1)\n        // Ensure (r,c) is not in the last tier AND (r+1, c+1) is a valid coordinate.\n        // For a tier x, valid column indices are from 0 to x.\n        // So for tier r+1, column c+1 must satisfy c+1 <= r+1.\n        if (r + 1 < N && c + 1 <= r + 1) {\n            int child2_val = pyramid[r+1][c+1];\n            // Crucially, compare against `min_val` (which might be child1_val already),\n            // not directly `parent_val`, to find the smallest among parent and both children.\n            if (child2_val < min_val) {\n                min_val = child2_val;\n                target_r = r + 1;\n                target_c = c + 1;\n            }\n        }\n\n        // If no child was smaller than the parent (or if it's a leaf node),\n        // the element is in its correct position relative to its children.\n        if (target_r == r && target_c == c) {\n            break; // Sifting process complete for this element\n        } else {\n            // Swap the current ball with the smallest child\n            perform_swap(r, c, target_r, target_c);\n\n            // Continue sifting down from the new position of the swapped element\n            r = target_r;\n            c = target_c;\n        }\n    }\n}\n\n\nint main() {\n    // Optimize C++ standard streams for competitive programming.\n    // This unties cin from cout and disables synchronization with C stdio,\n    // speeding up input/output operations.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Read the initial state of the pyramid from standard input.\n    // Each row 'i' has 'i+1' balls.\n    for (int i = 0; i < N; ++i) {\n        pyramid[i].resize(i + 1); // Allocate space for balls in tier 'i'\n        for (int j = 0; j <= i; ++j) {\n            std::cin >> pyramid[i][j];\n            // Store the initial position of each ball number.\n            current_pos_of_value[pyramid[i][j]] = {i, j};\n        }\n    }\n\n    // Apply the bottom-up heapify algorithm to satisfy the min-pyramid property.\n    // We iterate from the second-to-last tier (N-2) up to the top tier (0).\n    // For each ball in these tiers, we call sift_down to ensure it's smaller\n    // than its children. Since we process tiers bottom-up, when we sift down\n    // an element, its children's sub-pyramids are already correctly heapified.\n    for (int r = N - 2; r >= 0; --r) {\n        for (int c = 0; c <= r; ++c) {\n            sift_down(r, c);\n        }\n    }\n\n    // Output the total number of operations performed.\n    std::cout << operations.size() << std::endl;\n    // Output each swap operation in the specified format.\n    for (const auto& op : operations) {\n        std::cout << std::get<0>(op) << \" \"\n                  << std::get<1>(op) << \" \"\n                  << std::get<2>(op) << \" \"\n                  << std::get<3>(op) << std::endl;\n    }\n\n    return 0;\n}\n","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <map>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::abs\n\n// Global constants\nconst int D = 9;\nconst int DR[] = {-1, 1, 0, 0}; // delta row for neighbors (up, down, left, right)\nconst int DC[] = {0, 0, -1, 1}; // delta col for neighbors\n\n// Grid cell states\nconst int EMPTY = -1;\nconst int OBSTACLE = -2;\nconst int ENTRANCE_CELL = -3; // Renamed to avoid conflict with function entrance_r/c\nconst int UNVISITED = -1; // For BFS distance arrays\n\n// Global variables for the warehouse state\nint grid[D][D]; // Stores container ID (0 to M-1), or EMPTY/OBSTACLE/ENTRANCE_CELL\nbool is_obstacle[D][D];\nint static_dist[D][D]; // BFS distance from entrance on an empty grid\nstd::vector<std::pair<int, int>> static_ranked_squares; // Sorted by static_dist\nstd::map<std::pair<int, int>, int> square_to_static_rank; // Maps (r,c) to its rank in static_ranked_squares\n\nstd::pair<int, int> container_pos[D * D]; // Maps container ID to its (r,c) location\nint M; // Total number of containers\n\n// Coordinates of the entrance\nint entrance_r, entrance_c;\n\n// BFS utility function\n// Returns a vector of reachable empty squares (for placement phase)\n// Also populates reachable_container_ids_ptr if provided (for transport-out phase)\nstd::vector<std::pair<int, int>> bfs_reachable_info(\n    int (&current_grid)[D][D],\n    int (&current_dist)[D][D], // Output: distances from entrance\n    const bool* extracted_containers_mask_ptr, // Pointer to mask for extracted containers (nullptr for placement)\n    std::set<int>* reachable_container_ids_ptr // Output: reachable container IDs (nullptr for placement)\n) {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            current_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    current_dist[entrance_r][entrance_c] = 0;\n\n    std::vector<std::pair<int, int>> reachable_empty_squares_candidates;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue; // Out of bounds\n            if (is_obstacle[nr][nc]) continue; // Obstacle\n\n            if (current_dist[nr][nc] == UNVISITED) { // Not visited yet\n                if (current_grid[nr][nc] == EMPTY) {\n                    current_dist[nr][nc] = current_dist[r][c] + 1;\n                    q.push({nr, nc});\n                    reachable_empty_squares_candidates.push_back({nr, nc});\n                } else if (current_grid[nr][nc] == ENTRANCE_CELL) { \n                    // Entrance is traversable and starting point, already visited at dist 0.\n                    // No need to push again or add to reachable_empty_squares_candidates.\n                } else if (current_grid[nr][nc] >= 0) { // Contains a container\n                    int container_id = current_grid[nr][nc];\n                    if (extracted_containers_mask_ptr && extracted_containers_mask_ptr[container_id]) { \n                        // Container already extracted, treat as empty and traversable\n                        current_dist[nr][nc] = current_dist[r][c] + 1;\n                        q.push({nr, nc});\n                        reachable_empty_squares_candidates.push_back({nr, nc}); // Add as an available \"empty\" path square\n                    } else { \n                        // Container still present, cannot traverse, but is reachable for extraction\n                        if (reachable_container_ids_ptr) {\n                            reachable_container_ids_ptr->insert(container_id);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return reachable_empty_squares_candidates;\n}\n\n// Precomputes static distances from the entrance on an empty grid\nvoid precompute_static_distances() {\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            static_dist[i][j] = UNVISITED;\n        }\n    }\n\n    std::queue<std::pair<int, int>> q;\n    q.push({entrance_r, entrance_c});\n    static_dist[entrance_r][entrance_c] = 0;\n\n    while (!q.empty()) {\n        std::pair<int, int> curr = q.front();\n        q.pop();\n        int r = curr.first;\n        int c = curr.second;\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n\n            if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n            if (is_obstacle[nr][nc]) continue;\n\n            if (static_dist[nr][nc] == UNVISITED) {\n                static_dist[nr][nc] = static_dist[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n\n    // Collect all valid container squares and sort them by static distance\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (!is_obstacle[i][j] && (i != entrance_r || j != entrance_c)) {\n                static_ranked_squares.push_back({i, j});\n            }\n        }\n    }\n\n    // Sort by static_dist, then row, then column for consistent ranking\n    std::sort(static_ranked_squares.begin(), static_ranked_squares.end(), [](const auto& a, const auto& b) {\n        if (static_dist[a.first][a.second] != static_dist[b.first][b.second]) {\n            return static_dist[a.first][a.second] < static_dist[b.first][b.second];\n        }\n        if (a.first != b.first) {\n            return a.first < b.first;\n        }\n        return a.second < b.second;\n    });\n\n    for (int i = 0; i < static_ranked_squares.size(); ++i) {\n        square_to_static_rank[static_ranked_squares[i]] = i;\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_obstacles;\n    std::cin >> D >> N_obstacles; // D is fixed at 9, but read for generality\n\n    entrance_r = 0;\n    entrance_c = (D - 1) / 2;\n\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            grid[i][j] = EMPTY;\n            is_obstacle[i][j] = false;\n        }\n    }\n    grid[entrance_r][entrance_c] = ENTRANCE_CELL;\n\n    for (int k = 0; k < N_obstacles; ++k) {\n        int r_obs, c_obs;\n        std::cin >> r_obs >> c_obs;\n        is_obstacle[r_obs][c_obs] = true;\n        grid[r_obs][c_obs] = OBSTACLE;\n    }\n\n    M = D * D - 1 - N_obstacles; // Total number of containers\n\n    precompute_static_distances();\n\n    // Placement Phase\n    int current_dist[D][D]; // Temporary array for BFS distances in current state\n    bool dummy_extracted_mask[D*D] = {false}; // Placeholder, not used in placement phase BFS\n\n    for (int d = 0; d < M; ++d) {\n        int t_d; // Container ID\n        std::cin >> t_d;\n\n        std::vector<std::pair<int, int>> reachable_empty_squares =\n            bfs_reachable_info(grid, current_dist, dummy_extracted_mask, nullptr); // Nullptr for transport-out specific parameters\n\n        int best_score_diff = M + 1; // Max possible diff is M-1, so M+1 is a safe initial high value\n        std::pair<int, int> best_pos = {-1, -1};\n\n        for (const auto& p : reachable_empty_squares) {\n            int r = p.first;\n            int c = p.second;\n            int static_rank = square_to_static_rank[p];\n            int score_diff = std::abs(t_d - static_rank);\n\n            if (score_diff < best_score_diff) {\n                best_score_diff = score_diff;\n                best_pos = p;\n            } else if (score_diff == best_score_diff) {\n                // Tie-breaking rules for placement:\n                // 1. Prefer smaller current_dist (currently closer to entrance)\n                if (current_dist[r][c] < current_dist[best_pos.first][best_pos.second]) {\n                    best_pos = p;\n                }\n                // 2. If current_dist is also tied, prefer smaller static_dist (inherently closer)\n                else if (current_dist[r][c] == current_dist[best_pos.first][best_pos.second]) {\n                    if (static_dist[r][c] < static_dist[best_pos.first][best_pos.second]) {\n                        best_pos = p;\n                    }\n                    // 3. If static_dist is also tied, prefer smaller row, then smaller column (lexicographical)\n                    else if (static_dist[r][c] == static_dist[best_pos.first][best_pos.second]) {\n                        if (r < best_pos.first) {\n                            best_pos = p;\n                        } else if (r == best_pos.first) {\n                            if (c < best_pos.second) {\n                                best_pos = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        grid[best_pos.first][best_pos.second] = t_d;\n        container_pos[t_d] = best_pos;\n\n        std::cout << best_pos.first << \" \" << best_pos.second << std::endl;\n    }\n\n    // Transport-Out Phase\n    std::vector<int> b_sequence(M);\n    bool extracted_containers_mask[D*D]; // Tracks which containers have been extracted\n    for(int i = 0; i < D*D; ++i) extracted_containers_mask[i] = false;\n\n    for (int k = 0; k < M; ++k) {\n        std::set<int> reachable_containers;\n        // BFS to find all reachable containers given current grid state and extracted_containers_mask\n        bfs_reachable_info(grid, current_dist, extracted_containers_mask, &reachable_containers);\n\n        int min_reachable_id = -1;\n        if (!reachable_containers.empty()) {\n            min_reachable_id = *reachable_containers.begin(); // std::set keeps elements sorted, so begin() is the smallest\n        } else {\n            // This case should ideally not be reached if the problem guarantees connectivity\n            // and we always place containers in reachable spots.\n            // As a fallback, this would mean searching for the smallest unextracted ID,\n            // but this indicates a problem with logic or problem constraints.\n            // For now, assume a container is always reachable.\n            for (int id = 0; id < M; ++id) {\n                if (!extracted_containers_mask[id]) {\n                    min_reachable_id = id;\n                    break;\n                }\n            }\n        }\n\n        b_sequence[k] = min_reachable_id;\n        extracted_containers_mask[min_reachable_id] = true; // Mark container as extracted\n    }\n\n    for (int k = 0; k < M; ++k) {\n        std::pair<int, int> pos = container_pos[b_sequence[k]];\n        std::cout << pos.first << \" \" << pos.second << std::endl;\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>   // For tracking affected pairs in adjacency check\n#include <tuple> // For std::tie\n#include <cmath> // For exp\n\nusing namespace std;\n\n// Fixed grid size and number of wards\nconst int N = 50;\nconst int M = 100;\n\n// Original map from input\nint c[N][N];\n// Created map (modified during SA)\nint d[N][N];\n\n// Required adjacencies: adj_req[u][v] is true if u and v must be adjacent\nbool adj_req[M + 1][M + 1];\n\n// Current adjacencies in 'd' map: adj_count[u][v] stores number of edges between color u and color v\nint adj_count[M + 1][M + 1];\n\n// Number of cells for each color in 'd' map\nint num_cells[M + 1];\n\n// Stores coordinates of cells for each color\nvector<pair<int, int>> ward_cells[M + 1];\n// Stores the index of a cell (r,c) within ward_cells[d[r][c]].\n// This allows O(1) removal from ward_cells by swapping with the last element.\nint cell_idx_in_ward_cells[N][N];\n\n// Directions for neighbors (up, down, left, right)\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\n\n// Random number generator\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Global distributions for random selection\nuniform_int_distribution<int> dist_rc(0, N - 1); // For random row/col\nuniform_int_distribution<int> dist_color_m(1, M); // For random ward color (1 to M)\nuniform_real_distribution<double> dist_real(0.0, 1.0); // For acceptance probability\n\n\n// --- Helper Functions ---\n\n// Check if coordinates (r, c_val) are within the grid bounds\ninline bool is_valid_coord(int r, int c_val) {\n    return r >= 0 && r < N && c_val >= 0 && c_val < N;\n}\n\n// Check if a color 'k' is connected in the 'd' map.\n// If (excluded_r, excluded_c) is specified, that cell is temporarily ignored for connectivity.\n// NOTE: This function expects num_cells to reflect the state *after* the proposed change.\nbool check_color_connectivity(int k, int excluded_r = -1, int excluded_c = -1) {\n    int current_num_k_cells = num_cells[k]; // num_cells already updated to proposed state\n    if (excluded_r != -1 && d[excluded_r][excluded_c] == k) {\n        current_num_k_cells--; // Exclude the specific cell from the count if it's part of color k\n    }\n\n    if (current_num_k_cells == 0) return true; // Empty ward is trivially connected\n\n    // Find a starting point for BFS for color k\n    int start_r = -1, start_c = -1;\n    // Iterate through ward_cells to find a valid starting point that is not the excluded cell\n    for (auto p : ward_cells[k]) {\n        if (p.first == excluded_r && p.second == excluded_c) continue;\n        start_r = p.first;\n        start_c = p.second;\n        break;\n    }\n\n    if (start_r == -1) { \n        return false; // current_num_k_cells > 0 but no reachable cell implies disconnection\n    }\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_count = 0;\n\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    reachable_count++;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == k && !visited[nr][nc]) {\n                if (nr == excluded_r && nc == excluded_c) continue; // Skip the excluded cell\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_count++;\n            }\n        }\n    }\n    return reachable_count == current_num_k_cells;\n}\n\n// Check if color 0 is connected (to the outside) in the 'd' map\n// NOTE: This function expects num_cells[0] to reflect the state *after* the proposed change.\nbool check_zero_connectivity() {\n    int current_zero_count = num_cells[0]; // num_cells[0] already updated to proposed state\n    if (current_zero_count == 0) return true; // No 0s, trivially connected\n\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int reachable_zeros = 0;\n\n    // Add all boundary cells that are color 0 to the queue\n    for (int r = 0; r < N; ++r) {\n        if (d[r][0] == 0 && !visited[r][0]) {\n            q.push({r, 0});\n            visited[r][0] = true;\n            reachable_zeros++;\n        }\n        if (d[r][N - 1] == 0 && !visited[r][N - 1]) {\n            q.push({r, N - 1});\n            visited[r][N - 1] = true;\n            reachable_zeros++;\n        }\n    }\n    for (int c_val = 1; c_val < N - 1; ++c_val) { // Avoid double counting corners\n        if (d[0][c_val] == 0 && !visited[0][c_val]) {\n            q.push({0, c_val});\n            visited[0][c_val] = true;\n            reachable_zeros++;\n        }\n        if (d[N - 1][c_val] == 0 && !visited[N - 1][c_val]) {\n            q.push({N - 1, c_val});\n            visited[N - 1][c_val] = true;\n            reachable_zeros++;\n        }\n    }\n\n    // If no boundary '0' cells were found, but current_zero_count > 0, then there are isolated '0's.\n    if (current_zero_count > 0 && reachable_zeros == 0) return false;\n\n    while (!q.empty()) {\n        pair<int, int> curr = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = curr.first + DR[i];\n            int nc = curr.second + DC[i];\n\n            if (is_valid_coord(nr, nc) && d[nr][nc] == 0 && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                q.push({nr, nc});\n                reachable_zeros++;\n            }\n        }\n    }\n    return reachable_zeros == current_zero_count;\n}\n\n// Function to revert ALL temporary changes (d, adj_count, num_cells) if move is not valid or not accepted by SA\nvoid revert_changes(int r, int c_val, int original_d_rc_val, const vector<tuple<int, int, int>>& temp_adj_count_deltas, int old_color, int new_color) {\n    d[r][c_val] = original_d_rc_val;\n    for (const auto& delta : temp_adj_count_deltas) {\n        int u_d, v_d, val_d;\n        tie(u_d, v_d, val_d) = delta;\n        adj_count[u_d][v_d] += val_d;\n    }\n    num_cells[old_color]++; \n    num_cells[new_color]--; \n}\n\n// Function to try a tentative move and check all validity conditions\n// Returns true if valid, false if invalid.\n// IMPORTANT: If returning false, this function also reverts the temporary changes to d, adj_count, and num_cells.\nbool try_move(int r, int c_val, int new_color, int& original_d_rc_val, vector<tuple<int, int, int>>& temp_adj_count_deltas, set<pair<int, int>>& affected_adj_pairs) {\n    int old_color = d[r][c_val];\n    if (new_color == old_color) return false;\n\n    // Pre-check for disappearing wards (uses current num_cells, which is the count BEFORE this move is simulated)\n    if (old_color != 0 && num_cells[old_color] == 1) { \n        bool old_ward_must_remain = false;\n        for (int k_adj = 0; k_adj <= M; ++k_adj) { // Check all possible adjacencies, including with 0\n            if (k_adj == old_color) continue;\n            if (adj_req[old_color][k_adj]) { \n                old_ward_must_remain = true;\n                break;\n            }\n        }\n        if (old_ward_must_remain) return false;\n    }\n\n    // Store original state to revert if move is invalid/rejected\n    original_d_rc_val = d[r][c_val];\n    temp_adj_count_deltas.clear();\n    affected_adj_pairs.clear();\n\n    // Temporarily update adj_count based on (r,c_val) -> (new_color)\n    for (int i = 0; i < 4; ++i) {\n        int nr = r + DR[i];\n        int nc = c_val + DC[i];\n        if (is_valid_coord(nr, nc)) {\n            int neighbor_color = d[nr][nc]; \n\n            if (old_color != neighbor_color) {\n                int u = min(old_color, neighbor_color);\n                int v = max(old_color, neighbor_color);\n                adj_count[u][v]--;\n                temp_adj_count_deltas.emplace_back(u, v, 1); \n                affected_adj_pairs.insert({u, v});\n            }\n            if (new_color != neighbor_color) { \n                int u = min(new_color, neighbor_color);\n                int v = max(new_color, neighbor_color);\n                adj_count[u][v]++;\n                temp_adj_count_deltas.emplace_back(u, v, -1); \n                affected_adj_pairs.insert({u, v});\n            }\n        }\n    }\n    // Handle boundary adjacencies with color 0\n    if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n        if (old_color != 0) { \n            int u = min(old_color, 0); int v = max(old_color, 0);\n            adj_count[u][v]--;\n            temp_adj_count_deltas.emplace_back(u, v, 1);\n            affected_adj_pairs.insert({u, v});\n        }\n        if (new_color != 0) { \n            int u = min(new_color, 0); int v = max(new_color, 0);\n            adj_count[u][v]++;\n            temp_adj_count_deltas.emplace_back(u, v, -1);\n            affected_adj_pairs.insert({u, v});\n        }\n    }\n\n    // Simulate num_cells update *before* connectivity checks.\n    // If any check fails, these num_cells changes must be reverted too.\n    num_cells[old_color]--;\n    num_cells[new_color]++;\n\n    // Tentatively apply d[r][c_val] = new_color;\n    d[r][c_val] = new_color;\n\n    // --- Perform validity checks ---\n    // 1. Local Adjacency Check: STRCIT \"if and only if\" for ALL pairs (u,v), including those with 0.\n    for(auto p : affected_adj_pairs) {\n        int u = p.first;\n        int v = p.second;\n        bool current_adj_exists = (adj_count[u][v] > 0);\n        if (current_adj_exists != adj_req[u][v]) { \n            revert_changes(r, c_val, original_d_rc_val, temp_adj_count_deltas, old_color, new_color); // Revert all state\n            return false; \n        }\n    }\n\n    // 2. Connectivity check for old_color\n    if (old_color != 0 && num_cells[old_color] > 0) { // Check if old_color still exists (num_cells updated)\n        if (!check_color_connectivity(old_color, r, c_val)) { \n            revert_changes(r, c_val, original_d_rc_val, temp_adj_count_deltas, old_color, new_color); // Revert all state\n            return false; \n        }\n    }\n\n    // 3. Connectivity check for new_color\n    if (new_color != 0 && num_cells[new_color] > 0) { // Check if new_color still exists (num_cells updated)\n        if (num_cells[new_color] > 1) { // If it's the first cell, it's trivially connected\n            bool connected_to_new_color_region = false;\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc) && d[nr][nc] == new_color) {\n                    connected_to_new_color_region = true;\n                    break;\n                }\n            }\n            if (!connected_to_new_color_region) { \n                revert_changes(r, c_val, original_d_rc_val, temp_adj_count_deltas, old_color, new_color); // Revert all state\n                return false; \n            }\n        }\n    }\n\n    // 4. Connectivity check for color 0\n    if (!check_zero_connectivity()) { \n        revert_changes(r, c_val, original_d_rc_val, temp_adj_count_deltas, old_color, new_color); // Revert all state\n        return false; \n    }\n\n    return true; // All checks passed. d, adj_count, num_cells are in proposed state.\n}\n\n// Function to commit changes to ward_cells if move is accepted\nvoid commit_changes(int r, int c_val, int old_color, int new_color) {\n    // num_cells, d, adj_count are already in the new state from try_move.\n    // Only need to update ward_cells and cell_idx_in_ward_cells.\n\n    int old_idx = cell_idx_in_ward_cells[r][c_val];\n    pair<int, int> last_cell_of_old_color = ward_cells[old_color].back();\n    ward_cells[old_color][old_idx] = last_cell_of_old_color;\n    cell_idx_in_ward_cells[last_cell_of_old_color.first][last_cell_of_old_color.second] = old_idx;\n    ward_cells[old_color].pop_back();\n\n    cell_idx_in_ward_cells[r][c_val] = ward_cells[new_color].size();\n    ward_cells[new_color].push_back({r, c_val});\n}\n\n\nvoid solve() {\n    // Read input\n    int n_val, m_val;\n    cin >> n_val >> m_val; \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> c[i][j];\n        }\n    }\n\n    // Initialize d with c, and calculate initial state metrics\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            d[i][j] = c[i][j];\n            num_cells[d[i][j]]++;\n            cell_idx_in_ward_cells[i][j] = ward_cells[d[i][j]].size();\n            ward_cells[d[i][j]].push_back({i, j});\n        }\n    }\n\n    // Precompute required adjacencies (adj_req) from original map 'c'\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = c[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_req[curr_color][0] = adj_req[0][curr_color] = true;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = c[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_req[curr_color][neighbor_color] = adj_req[neighbor_color][curr_color] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initialize current adjacencies (adj_count) from 'd' (which is initially 'c')\n    for (int r = 0; r < N; ++r) {\n        for (int c_val = 0; c_val < N; ++c_val) {\n            int curr_color = d[r][c_val];\n\n            // Adjacency with 0 (outside) for boundary cells\n            if (r == 0 || r == N - 1 || c_val == 0 || c_val == N - 1) {\n                adj_count[min(curr_color, 0)][max(curr_color, 0)]++;\n            }\n\n            // Adjacency with neighbors\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + DR[i];\n                int nc = c_val + DC[i];\n                if (is_valid_coord(nr, nc)) {\n                    int neighbor_color = d[nr][nc];\n                    if (curr_color != neighbor_color) {\n                        adj_count[min(curr_color, neighbor_color)][max(curr_color, neighbor_color)]++;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int u = 1; u <= M; ++u) { \n        for (int v = u; v <= M; ++v) { \n            adj_count[u][v] /= 2;\n        }\n    }\n\n    // Start directly with the SA, with d=c (E=0 initially).\n    int current_E = num_cells[0]; \n\n    // Store best map and score. Score is number of 0-cells (E). Maximize this.\n    vector<vector<int>> best_d(N, vector<int>(N));\n    int best_E = current_E;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            best_d[i][j] = d[i][j];\n        }\n    }\n\n    // --- Simulated Annealing parameters ---\n    auto start_time = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95; \n    double T_start = 2000.0;        // Reverted T_start to 2000.0\n    double T_end = 1.0;             // Final temperature\n\n    // Main SA loop\n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed_time = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT) {\n            break;\n        }\n\n        double T = T_start * pow(T_end / T_start, elapsed_time / TIME_LIMIT);\n\n        int r = dist_rc(rng);       \n        int c_val = dist_rc(rng);   \n        int old_color = d[r][c_val]; \n        int new_color;              \n\n        // Proposal strategy: Aggressively seek to maximize E, with strong bias to keep 0s.\n        if (old_color != 0) { // Current cell is a ward.\n            if (dist_real(rng) < 0.8) { // 80% chance to try turning into 0\n                new_color = 0;\n            } else { // 20% chance to change to a neighboring color\n                vector<int> neighbor_colors;\n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc)) {\n                        neighbor_colors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!neighbor_colors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, neighbor_colors.size() - 1); \n                    new_color = neighbor_colors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); \n                }\n            }\n        } else { // Current cell is 0.\n            if (dist_real(rng) < 0.9) { // 90% chance to keep it 0 (new_color = old_color, filtered by try_move)\n                new_color = old_color; \n            } else { // 10% chance to fill it with a non-zero neighbor's color (or random ward)\n                vector<int> non_zero_neighbors; \n                for (int i = 0; i < 4; ++i) {\n                    int nr = r + DR[i];\n                    int nc = c_val + DC[i];\n                    if (is_valid_coord(nr, nc) && d[nr][nc] != 0) {\n                        non_zero_neighbors.push_back(d[nr][nc]);\n                    }\n                }\n                if (!non_zero_neighbors.empty()) {\n                    uniform_int_distribution<int> dist_neighbor_idx(0, non_zero_neighbors.size() - 1); \n                    new_color = non_zero_neighbors[dist_neighbor_idx(rng)];\n                } else {\n                    new_color = dist_color_m(rng); \n                }\n            }\n        }\n\n        // --- Execute try_move and decide on acceptance ---\n        // original_d_rc_val_for_revert and temp_adj_count_deltas_for_revert are used by try_move for internal reverting\n        // if a check fails. If try_move passes, they hold the values needed for SA's eventual revert.\n        int original_d_rc_val_for_revert; \n        vector<tuple<int, int, int>> temp_adj_count_deltas_for_revert; \n        set<pair<int, int>> affected_adj_pairs_dummy; // Dummy, not needed outside try_move\n\n        if (!try_move(r, c_val, new_color, original_d_rc_val_for_revert, temp_adj_count_deltas_for_revert, affected_adj_pairs_dummy)) {\n            // If try_move returned false, it already reverted d, adj_count, and num_cells.\n            continue;\n        }\n\n        // Move is valid. d, adj_count, num_cells are now in the proposed (tentatively accepted) state.\n        int new_E = num_cells[0]; // Score is number of 0-cells\n        \n        if (new_E > current_E || dist_real(rng) < exp((double)(new_E - current_E) / T)) {\n            commit_changes(r, c_val, old_color, new_color); // commits ward_cells\n            current_E = new_E; \n\n            if (new_E > best_E) {\n                best_E = new_E;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        best_d[i][j] = d[i][j];\n                    }\n                }\n            }\n        } else {\n            // Reject the move: revert changes from the proposed state.\n            revert_changes(r, c_val, original_d_rc_val_for_revert, temp_adj_count_deltas_for_revert, old_color, new_color);\n        }\n    } // End of SA loop\n\n    // Output the best map found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_d[i][j] << (j == N - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n#include <map>\n\n// DSU structure\nstruct DSU {\n    std::vector<int> parent;\n    std::vector<int> sz; // Stores size of component for root\n    DSU(int n) {\n        parent.resize(n);\n        std::iota(parent.begin(), parent.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int i) {\n        if (parent[i] == i)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n    // Returns true if i and j were in different sets and are now united.\n    // comp_estimated_weight must be provided to update the new root's estimated weight.\n    bool unite(int i, int j, std::vector<double>& comp_estimated_weight) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            // Union by size\n            if (sz[root_i] < sz[root_j]) std::swap(root_i, root_j);\n            \n            // Weighted average for the new component's estimated weight\n            // This averages the estimated weights of all items in the two combined components.\n            double new_weight = (comp_estimated_weight[root_i] * sz[root_i] + comp_estimated_weight[root_j] * sz[root_j]) / (sz[root_i] + sz[root_j]);\n\n            parent[root_j] = root_i;\n            sz[root_i] += sz[root_j];\n            comp_estimated_weight[root_i] = new_weight;\n            return true;\n        }\n        return false;\n    }\n};\n\n// Global random number generator\nstd::mt19937 mt;\n\n// Function to perform a query\nstd::string query(const std::vector<int>& L, const std::vector<int>& R) {\n    std::cout << L.size() << \" \" << R.size();\n    for (int item_idx : L) {\n        std::cout << \" \" << item_idx;\n    }\n    for (int item_idx : R) {\n        std::cout << \" \" << item_idx;\n    }\n    std::cout << std::endl; // Flush output\n    \n    std::string result;\n    std::cin >> result;\n    return result;\n}\n\n// Function to calculate variance for the partitioning\ndouble calculate_variance(int D, const std::vector<double>& group_sums) {\n    if (D == 0) return 0.0;\n    double sum_t = 0.0;\n    for (double t : group_sums) {\n        sum_t += t;\n    }\n    double mean_t = sum_t / D;\n    double variance = 0.0;\n    for (double t : group_sums) {\n        variance += (t - mean_t) * (t - mean_t);\n    }\n    return variance / D;\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Use current time as seed for random number generator\n    mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    int N, D, Q;\n    std::cin >> N >> D >> Q;\n\n    DSU dsu(N);\n    std::vector<double> comp_estimated_weight(N);\n    for (int i = 0; i < N; ++i) {\n        comp_estimated_weight[i] = 1.0; // Initial estimated weight for each component root\n    }\n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TOTAL_TIME_LIMIT = 1.9; // seconds\n\n    // Query parameters\n    const double initial_learning_rate = 0.05;\n    const double final_learning_rate = 0.001;\n    const int max_group_query_size = 5;\n\n    for (int q_idx = 0; q_idx < Q; ++q_idx) {\n        double current_learning_rate = initial_learning_rate - (initial_learning_rate - final_learning_rate) * q_idx / Q;\n\n        std::vector<int> active_roots;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.parent[i] == i) { // Check if 'i' is a root\n                active_roots.push_back(i);\n            }\n        }\n\n        std::vector<int> L_items, R_items;\n        int root_L_comp = -1, root_R_comp = -1; // Roots of components chosen for L and R\n\n        bool picked_from_distinct_roots = false;\n        if (active_roots.size() >= 2) {\n            std::shuffle(active_roots.begin(), active_roots.end(), mt);\n            root_L_comp = active_roots[0];\n            root_R_comp = active_roots[1];\n            picked_from_distinct_roots = true;\n        } else { // All items are already in one DSU component, or N < 2\n            // If all items are merged, we can still query, but roots will be the same.\n            // This primarily happens if all items are estimated as equal, so further comparisons may not yield much new info.\n            int item1 = mt() % N;\n            int item2 = mt() % N;\n            while (item1 == item2) {\n                item2 = mt() % N;\n            }\n            L_items.push_back(item1);\n            R_items.push_back(item2);\n            root_L_comp = dsu.find(item1);\n            root_R_comp = dsu.find(item2);\n        }\n\n        if (picked_from_distinct_roots) {\n            std::vector<int> items_in_root1_comp;\n            std::vector<int> items_in_root2_comp;\n            for (int i = 0; i < N; ++i) {\n                if (dsu.find(i) == root_L_comp) items_in_root1_comp.push_back(i);\n                if (dsu.find(i) == root_R_comp) items_in_root2_comp.push_back(i);\n            }\n            \n            int L_size = 1 + mt() % max_group_query_size;\n            int R_size = 1 + mt() % max_group_query_size;\n\n            L_size = std::min((int)items_in_root1_comp.size(), L_size);\n            R_size = std::min((int)items_in_root2_comp.size(), R_size);\n\n            if (L_size == 0 && !items_in_root1_comp.empty()) L_size = 1;\n            if (R_size == 0 && !items_in_root2_comp.empty()) R_size = 1;\n\n            if (items_in_root1_comp.empty() || items_in_root2_comp.empty()) { // Fallback, should rarely happen\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else {\n                std::shuffle(items_in_root1_comp.begin(), items_in_root1_comp.end(), mt);\n                std::shuffle(items_in_root2_comp.begin(), items_in_root2_comp.end(), mt);\n\n                for (int k = 0; k < L_size; ++k) L_items.push_back(items_in_root1_comp[k]);\n                for (int k = 0; k < R_size; ++k) R_items.push_back(items_in_root2_comp[k]);\n            }\n        }\n\n        // Safety check: ensure L and R are non-empty before query\n        if (L_items.empty() || R_items.empty()) {\n            if (N > 1) { \n                 L_items.clear(); R_items.clear();\n                 L_items.push_back(mt() % N);\n                 R_items.push_back(mt() % N);\n                 while(L_items[0] == R_items[0]) R_items[0] = mt() % N;\n                 root_L_comp = dsu.find(L_items[0]);\n                 root_R_comp = dsu.find(R_items[0]);\n            } else { \n                continue; // Cannot query with N=1\n            }\n        }\n        // Ensure root_L_comp and root_R_comp are updated to their latest roots\n        root_L_comp = dsu.find(L_items[0]);\n        root_R_comp = dsu.find(R_items[0]);\n\n        // If roots are the same, it means we compare items already believed to be equal.\n        // Such queries might not provide new information if our model is perfect,\n        // but could help refine. For now, we only update if roots are distinct for inequalities.\n        // For equality, 1-1 comparison of items from same root yields no change.\n        // Group comparison of items from same root yields no change.\n\n        std::string result = query(L_items, R_items);\n\n        // Calculate current estimated sums based on component representatives\n        double sum_L_est = 0.0;\n        for (int item_idx : L_items) sum_L_est += comp_estimated_weight[dsu.find(item_idx)];\n        double sum_R_est = 0.0;\n        for (int item_idx : R_items) sum_R_est += comp_estimated_weight[dsu.find(item_idx)];\n\n        if (result == \"=\") {\n            if (root_L_comp != root_R_comp) { // Only adjust if they are distinct components\n                if (L_items.size() == 1 && R_items.size() == 1) {\n                    // Direct merge for 1-vs-1 equality\n                    dsu.unite(L_items[0], R_items[0], comp_estimated_weight);\n                } else { // Group equality for distinct components (e.g., A+B = C+D)\n                    // Softly adjust component weights to make their estimated sums equal\n                    // Target sum per side is the average of current estimated sums\n                    double target_sum_per_side = (sum_L_est + sum_R_est) / 2.0;\n                    \n                    double target_w_L = target_sum_per_side / L_items.size();\n                    double target_w_R = target_sum_per_side / R_items.size();\n\n                    comp_estimated_weight[root_L_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_L_comp] + current_learning_rate * target_w_L;\n                    comp_estimated_weight[root_R_comp] = (1.0 - current_learning_rate) * comp_estimated_weight[root_R_comp] + current_learning_rate * target_w_R;\n                }\n            }\n        } else { // Inequality: L is lighter (<) or heavier (>) than R\n            if (root_L_comp != root_R_comp) { // Only adjust if distinct components\n                if (result == \"<\") { // Actual L < Actual R\n                    comp_estimated_weight[root_L_comp] *= (1.0 - current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 + current_learning_rate);\n                } else { // Actual L > Actual R (result == \">\")\n                    comp_estimated_weight[root_L_comp] *= (1.0 + current_learning_rate);\n                    comp_estimated_weight[root_R_comp] *= (1.0 - current_learning_rate);\n                }\n            }\n        }\n\n        // Ensure weights are positive. Minimum actual weight is 1.0, but allowing estimates slightly lower might help explore.\n        comp_estimated_weight[root_L_comp] = std::max(0.1, comp_estimated_weight[root_L_comp]);\n        comp_estimated_weight[root_R_comp] = std::max(0.1, comp_estimated_weight[root_R_comp]);\n    }\n\n    // Phase 2: Partitioning using Simulated Annealing\n    std::vector<double> final_weights(N);\n    for (int i = 0; i < N; ++i) {\n        final_weights[i] = comp_estimated_weight[dsu.find(i)];\n    }\n\n    std::vector<int> item_to_group(N);\n    std::vector<int> item_indices(N);\n    std::iota(item_indices.begin(), item_indices.end(), 0);\n\n    // Initial greedy assignment: sort items by estimated weight descending\n    std::sort(item_indices.begin(), item_indices.end(), [&](int a, int b) {\n        return final_weights[a] > final_weights[b];\n    });\n\n    std::vector<double> group_sums(D, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int item_idx = item_indices[i];\n        int min_group = 0;\n        for (int d = 1; d < D; ++d) {\n            if (group_sums[d] < group_sums[min_group]) {\n                min_group = d;\n            }\n        }\n        item_to_group[item_idx] = min_group;\n        group_sums[min_group] += final_weights[item_idx];\n    }\n    \n    // Simulated Annealing parameters\n    // Estimate initial variance for T_start scaling\n    double initial_variance = calculate_variance(D, group_sums);\n    // T_start should be large enough to allow many uphill moves, scaled by initial variance magnitude.\n    double T_start = initial_variance * 10.0; \n    if (T_start < 1.0) T_start = 1.0; // Ensure a reasonable minimum T_start to prevent division by zero or too-small steps\n    double T_end = 0.01;      // Ending temperature, low enough to allow fine convergence\n\n    auto current_time = std::chrono::high_resolution_clock::now();\n    double elapsed_time_at_sa_start = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n    \n    // Time available for SA. Ensure at least a small amount of time.\n    double sa_duration_limit = std::max(0.05, TOTAL_TIME_LIMIT - elapsed_time_at_sa_start); \n\n    double current_variance = initial_variance;\n\n    while (true) {\n        current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time_total = std::chrono::duration_cast<std::chrono::nanoseconds>(current_time - start_time).count() / 1e9;\n        \n        if (elapsed_time_total > TOTAL_TIME_LIMIT) break;\n\n        // Progress through the SA phase (0 to 1)\n        double progress = (elapsed_time_total - elapsed_time_at_sa_start) / sa_duration_limit;\n        if (progress < 0) progress = 0; // Should not happen with correct logic\n        if (progress > 1) progress = 1; // Cap progress at 1 for calculation stability\n        double T = T_start * std::pow(T_end / T_start, progress);\n\n        int item_to_move_idx = mt() % N;\n        int current_group = item_to_group[item_to_move_idx];\n        int new_group = mt() % D;\n        \n        if (new_group == current_group) {\n            continue; \n        }\n\n        // Temporarily adjust group sums to calculate next_variance\n        double old_group_sum_current = group_sums[current_group];\n        double old_group_sum_new = group_sums[new_group];\n        \n        group_sums[current_group] -= final_weights[item_to_move_idx];\n        group_sums[new_group] += final_weights[item_to_move_idx];\n        \n        double next_variance = calculate_variance(D, group_sums);\n\n        if (next_variance < current_variance) {\n            current_variance = next_variance;\n            item_to_group[item_to_move_idx] = new_group;\n        } else {\n            // Accept worse solution with probability\n            double prob = std::exp((current_variance - next_variance) / T);\n            if (std::uniform_real_distribution<double>(0.0, 1.0)(mt) < prob) {\n                current_variance = next_variance;\n                item_to_group[item_to_move_idx] = new_group;\n            } else {\n                // Revert changes if not accepted\n                group_sums[current_group] = old_group_sum_current;\n                group_sums[new_group] = old_group_sum_new;\n            }\n        }\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        std::cout << item_to_group[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n","ahc026":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <algorithm> // For std::min_element, std::min, std::max\n#include <limits>    // For std::numeric_limits\n\n// Fixed constants for N and M as per problem statement\nconst int N_BOXES = 200;\nconst int M_STACKS = 10;\nconst int SENTINEL_MIN_VAL = N_BOXES + 1; // Used for min_val_in_stack for empty stacks\n\n// Structure to hold the state of a box\nstruct BoxInfo {\n    int stack_idx;  // 0-indexed stack number (0 to M_STACKS-1)\n    int height_idx; // 0-indexed height from bottom (0 to stack.size()-1)\n};\n\n// Helper function to calculate min_val for a stack\nint calculate_min_in_stack(const std::deque<int>& stack) {\n    if (stack.empty()) {\n        return SENTINEL_MIN_VAL;\n    }\n    // std::min_element returns an iterator to the smallest element\n    return *std::min_element(stack.begin(), stack.end());\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int n_input, m_input; // Read N and M, though they are fixed\n    std::cin >> n_input >> m_input;\n\n    // stacks[i] is a deque representing stack i, from bottom to top\n    std::vector<std::deque<int>> stacks(M_STACKS);\n    // box_location[v] stores BoxInfo for box v (1-indexed box_id)\n    std::vector<BoxInfo> box_location(N_BOXES + 1);\n    // min_val_in_stack[i] stores the minimum box ID currently in stack i\n    std::vector<int> min_val_in_stack(M_STACKS);\n\n    // Initialize stacks and box_location from input\n    for (int i = 0; i < M_STACKS; ++i) {\n        for (int j = 0; j < N_BOXES / M_STACKS; ++j) {\n            int box_id;\n            std::cin >> box_id;\n            stacks[i].push_back(box_id);\n            box_location[box_id] = {i, j};\n        }\n    }\n\n    // Initialize min_val_in_stack for all stacks\n    for (int i = 0; i < M_STACKS; ++i) {\n        min_val_in_stack[i] = calculate_min_in_stack(stacks[i]);\n    }\n\n    std::vector<std::pair<int, int>> operations;\n    // long long total_energy_expended = 0; // For debugging/local testing, not required for output\n\n    // Weights for scoring function (heuristic for destination stack selection)\n    const int W1_TOP_BOX = 100;        // Weight for stack.back()\n    const int W2_MIN_BOX = 10;         // Weight for min_val_in_stack[d]\n    const int W3_STACK_SIZE = 10;      // Weight for stack.size() (negative contribution)\n    const int K_LOOKAHEAD = 15;        // Number of future boxes to check for burial penalty\n    const int W4_BADNESS = 1000;       // Weight for burying a soon-needed box\n    const long long EMPTY_STACK_SCORE = 2000000; // A score higher than any possible non-empty stack score, type long long to be safe\n\n    // Iterate for each box from 1 to N_BOXES in ascending order\n    for (int v = 1; v <= N_BOXES; ++v) {\n        int current_stack_idx = box_location[v].stack_idx;\n        int current_height_idx = box_location[v].height_idx;\n\n        // If box v is already carried out, skip (this check is mostly for robustness/debugging)\n        if (current_stack_idx == -1) {\n            continue;\n        }\n\n        // Store min_val of current_stack_idx before any modifications\n        int old_min_val_src_stack = min_val_in_stack[current_stack_idx];\n\n        // Check if box v is at the top of its stack\n        // Using `(int)stacks[current_stack_idx].size() - 1` to ensure correct comparison with int `current_height_idx`\n        if (current_height_idx == (int)stacks[current_stack_idx].size() - 1) {\n            // Box v is at the top, can be carried out\n            operations.push_back({v, 0}); // Operation 2: (v, 0)\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out (stack_idx = -1 means carried out)\n\n            // Update min_val_in_stack for the source stack\n            if (v == old_min_val_src_stack) { // If v was the minimum, recalculate\n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        } else {\n            // Box v is not at the top, need to move boxes above it\n\n            // Identify the bottom-most box of the block to be moved\n            // These are boxes from current_height_idx + 1 up to the top\n            int block_bottom_box_id = stacks[current_stack_idx][current_height_idx + 1];\n            // Calculate number of boxes to move (k in problem statement)\n            // int num_boxes_to_move = stacks[current_stack_idx].size() - (current_height_idx + 1);\n            // total_energy_expended += (long long)num_boxes_to_move + 1; // Add cost (k+1)\n\n            // Choose destination stack for Operation 1 based on heuristic scoring\n            int dest_stack_idx = -1;\n            // Use long long for score to avoid overflow with potentially large penalties\n            long long best_score = std::numeric_limits<long long>::min(); \n\n            for (int d = 0; d < M_STACKS; ++d) {\n                if (d == current_stack_idx) continue; // Cannot move to the same stack\n\n                long long current_score;\n                if (stacks[d].empty()) {\n                    current_score = EMPTY_STACK_SCORE;\n                } else {\n                    current_score = (long long)stacks[d].back() * W1_TOP_BOX + \n                                    (long long)min_val_in_stack[d] * W2_MIN_BOX - \n                                    (long long)stacks[d].size() * W3_STACK_SIZE;\n\n                    long long badness_penalty = 0;\n                    for (int future_v = v + 1; future_v <= std::min(N_BOXES, v + K_LOOKAHEAD); ++future_v) {\n                        // Check if future_v is in stack 'd' and would be buried deeper by this move\n                        // This means future_v is in stack 'd' AND its current height is below the current top of 'd'\n                        // (which is where the new block would start)\n                        if (box_location[future_v].stack_idx == d && box_location[future_v].height_idx < (int)stacks[d].size()) {\n                            // Higher penalty for boxes needed sooner (smaller future_v)\n                            badness_penalty += (N_BOXES - future_v + 1); \n                        }\n                    }\n                    current_score -= badness_penalty * W4_BADNESS;\n                }\n\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    dest_stack_idx = d;\n                }\n            }\n            \n            // At this point, dest_stack_idx must have been selected as M_STACKS >= 2.\n\n            // Perform Operation 1: move block_bottom_box_id and boxes above it to dest_stack_idx\n            // Output stack_idx as 1-indexed, so dest_stack_idx + 1\n            operations.push_back({block_bottom_box_id, dest_stack_idx + 1});\n\n            // Temporarily store boxes that will be moved\n            std::vector<int> boxes_to_move;\n            // Iterate from the box above v up to the current top of the stack\n            for (size_t i = current_height_idx + 1; i < stacks[current_stack_idx].size(); ++i) {\n                boxes_to_move.push_back(stacks[current_stack_idx][i]);\n            }\n            \n            // Resize the original stack to remove the moved boxes\n            stacks[current_stack_idx].resize(current_height_idx + 1);\n\n            // Add the moved boxes to the destination stack and update their locations\n            for (int box_id : boxes_to_move) {\n                // Update height_idx for the box_id in the new stack\n                box_location[box_id] = {dest_stack_idx, (int)stacks[dest_stack_idx].size()};\n                stacks[dest_stack_idx].push_back(box_id);\n            }\n            \n            // Update min_val_in_stack for the destination stack\n            // If dest_stack_idx was empty, its min_val_in_stack was SENTINEL_MIN_VAL,\n            // so any box_id will be smaller and correctly set the new minimum.\n            for (int box_id : boxes_to_move) {\n                min_val_in_stack[dest_stack_idx] = std::min(min_val_in_stack[dest_stack_idx], box_id);\n            }\n\n            // After moving, box v is now at the top of its original stack.\n            // Update v's height_idx to reflect its new top position\n            box_location[v].height_idx = (int)stacks[current_stack_idx].size() - 1;\n\n            // Perform Operation 2: carry out box v\n            operations.push_back({v, 0});\n            stacks[current_stack_idx].pop_back(); // Remove v from the stack\n            box_location[v] = {-1, -1}; // Mark v as carried out\n\n            // Update min_val_in_stack for the source stack after v is removed\n            // If v was the minimum, recalculate. Otherwise, min_val is unchanged because only boxes above v were removed.\n            if (v == old_min_val_src_stack) { \n                min_val_in_stack[current_stack_idx] = calculate_min_in_stack(stacks[current_stack_idx]);\n            }\n        }\n    }\n\n    // Output the sequence of operations\n    for (const auto& op : operations) {\n        std::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 <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip> // For setprecision\n#include <functional> // For std::function\n#include <queue> // For BFS\n\nusing namespace std;\n\nint N;\nvector<string> H_walls; // h[i][j] wall between (i,j) and (i+1,j)\nvector<string> V_walls; // v[i][j] wall between (i,j) and (i,j+1)\nvector<vector<int>> D_values; // d[i][j] dirt susceptibility\n\n// Directions: D, R, U, L\nint DR[] = {1, 0, -1, 0};\nint DC[] = {0, 1, 0, -1};\nchar DIR_CHARS[] = {'D', 'R', 'U', 'L'};\nchar REV_DIR_CHARS[] = {'U', 'L', 'D', 'R'};\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    // For set/map keys (not used here but good practice)\n    bool operator<(const Pos& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\n// Get next position after moving in a given direction\nPos get_next_pos(Pos current, int dir_idx) {\n    return {current.r + DR[dir_idx], current.c + DC[dir_idx]};\n}\n\n// Check if move is valid (within bounds and no wall)\nbool is_valid_move(Pos current, int dir_idx) {\n    int nr = current.r + DR[dir_idx];\n    int nc = current.c + DC[dir_idx];\n\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n        return false; // Out of bounds\n    }\n\n    if (dir_idx == 0) { // Down: from (r,c) to (r+1,c)\n        return H_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 1) { // Right: from (r,c) to (r,c+1)\n        return V_walls[current.r][current.c] == '0';\n    } else if (dir_idx == 2) { // Up: from (r,c) to (r-1,c)\n        return H_walls[nr][nc] == '0'; \n    } else if (dir_idx == 3) { // Left: from (r,c) to (r,c-1)\n        return V_walls[nr][nc] == '0';\n    }\n    return false;\n}\n\n// Helper function to calculate the contribution of a single cell to the total S_sum_terms\ndouble calculate_cell_contribution(int current_path_length, const vector<int>& cell_visits, int d_value) {\n    if (cell_visits.empty()) {\n        return 0.0; \n    }\n\n    double sum_term_for_cell = 0.0;\n    int N_ij = cell_visits.size();\n\n    for (int k = 0; k < N_ij - 1; ++k) {\n        long long T = cell_visits[k+1] - cell_visits[k];\n        sum_term_for_cell += (double)T * (T - 1) / 2.0;\n    }\n    long long T_last = current_path_length - cell_visits[N_ij-1] + cell_visits[0];\n    sum_term_for_cell += (double)T_last * (T_last - 1) / 2.0;\n\n    return d_value * sum_term_for_cell;\n}\n\n// Perform BFS to find shortest path from start_pos to end_pos, returning path as string of moves\n// And store visited cells in 'path_coords' for easy updates\nstruct BFS_Parent {\n    Pos p;\n    int dir_idx; \n};\n\nstring find_shortest_path_and_visited_cells(Pos start_pos, Pos end_pos, vector<Pos>& path_coords) {\n    vector<vector<BFS_Parent>> parent_map(N, vector<BFS_Parent>(N, {{-1, -1}, -1}));\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<Pos> q;\n\n    q.push(start_pos);\n    dist[start_pos.r][start_pos.c] = 0;\n\n    bool found = false;\n    while (!q.empty()) {\n        Pos current = q.front();\n        q.pop();\n\n        if (current == end_pos) {\n            found = true;\n            break;\n        }\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            if (is_valid_move(current, dir_idx) && dist[next.r][next.c] == -1) {\n                dist[next.r][next.c] = dist[current.r][current.c] + 1;\n                parent_map[next.r][next.c] = {current, dir_idx}; \n                q.push(next);\n            }\n        }\n    }\n\n    if (!found) {\n        return \"\"; \n    }\n\n    string path_moves = \"\";\n    Pos current = end_pos;\n    path_coords.clear(); \n    \n    while (!(current == start_pos)) {\n        path_coords.push_back(current); \n        BFS_Parent p_info = parent_map[current.r][current.c];\n        path_moves += DIR_CHARS[p_info.dir_idx];\n        current = p_info.p;\n    }\n    path_coords.push_back(start_pos); \n\n    reverse(path_moves.begin(), path_moves.end()); \n    reverse(path_coords.begin(), path_coords.end()); \n    return path_moves;\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    H_walls.resize(N - 1);\n    V_walls.resize(N);\n    D_values.resize(N, vector<int>(N));\n\n    for (int i = 0; i < N - 1; ++i) cin >> H_walls[i];\n    for (int i = 0; i < N; ++i) cin >> V_walls[i];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D_values[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    string current_path_moves_str;\n    \n    // Initial DFS path generation\n    vector<bool> dfs_visited_cells(N * N, false);\n    \n    function<void(Pos)> build_dfs_path = \n        [&](Pos current) {\n        int current_idx = current.r * N + current.c;\n        dfs_visited_cells[current_idx] = true;\n\n        for (int dir_idx = 0; dir_idx < 4; ++dir_idx) {\n            Pos next = get_next_pos(current, dir_idx);\n            int next_idx = next.r * N + next.c;\n\n            if (next.r < 0 || next.r >= N || next.c < 0 || next.c >= N) continue; \n            if (!is_valid_move(current, dir_idx)) continue; \n            if (dfs_visited_cells[next_idx]) continue; \n\n            current_path_moves_str += DIR_CHARS[dir_idx];\n            build_dfs_path(next);\n            current_path_moves_str += REV_DIR_CHARS[dir_idx];\n        }\n    };\n    \n    build_dfs_path({0,0});\n    string initial_dfs_path_moves = current_path_moves_str; \n    int current_L = current_path_moves_str.length();\n\n    // Build initial visits list from the DFS path\n    vector<vector<int>> current_visits(N * N);\n    Pos temp_pos = {0,0};\n    \n    current_visits[0].push_back(0); \n    for (int t = 0; t < current_L; ++t) {\n        char move_char = current_path_moves_str[t];\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        temp_pos = get_next_pos(temp_pos, dir_idx);\n        current_visits[temp_pos.r * N + temp_pos.c].push_back(t + 1); \n    }\n\n    // Calculate initial total sum of terms for average dirtiness numerator\n    double current_S_sum_terms = 0.0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int sq_idx = i * N + j;\n            if (current_visits[sq_idx].empty()) { \n                current_S_sum_terms = 1e18; \n                break;\n            }\n            current_S_sum_terms += calculate_cell_contribution(current_L, current_visits[sq_idx], D_values[i][j]);\n        }\n        if (current_S_sum_terms >= 1e18) break;\n    }\n    double current_score = current_S_sum_terms / current_L;\n    \n    double best_score = current_score;\n    string best_path_moves = current_path_moves_str; \n\n    mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double T_start = 2000.0; \n    double T_end = 0.01;     \n    long long max_iterations_for_temp = 1000000; \n\n    vector<Pos> all_cells;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            all_cells.push_back({i, j});\n        }\n    }\n    \n    int iter_count = 0;\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1950) {\n        iter_count++;\n        double T = T_start + (T_end - T_start) * ((double)iter_count / max_iterations_for_temp);\n        if (T < T_end) T = T_end; \n\n        string temp_new_moves = \"\"; \n        int temp_L_change = 0;\n        \n        // Dynamic Weighted random choice for ONE target cell\n        vector<double> cell_weights(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int sq_idx = i * N + j;\n                double avg_interval = (double)current_L / max(1, (int)current_visits[sq_idx].size());\n                // Use quadratic weighting for average interval to prioritize high intervals more strongly\n                cell_weights[sq_idx] = D_values[i][j] * avg_interval * avg_interval; \n                if (cell_weights[sq_idx] < 1e-9) cell_weights[sq_idx] = 1e-9; \n            }\n        }\n        discrete_distribution<int> cell_dist_discrete(cell_weights.begin(), cell_weights.end());\n        \n        int chosen_cell_idx = cell_dist_discrete(rng);\n        Pos target_pos = all_cells[chosen_cell_idx];\n\n        Pos zero_zero_pos = {0,0};\n        vector<Pos> path_coords_1;\n        string path_moves_1 = find_shortest_path_and_visited_cells(zero_zero_pos, target_pos, path_coords_1);\n        if (path_moves_1.empty()) { continue; } \n\n        vector<Pos> path_coords_2;\n        string path_moves_2 = find_shortest_path_and_visited_cells(target_pos, zero_zero_pos, path_coords_2);\n        if (path_moves_2.empty()) { continue; } \n\n        temp_new_moves = path_moves_1 + path_moves_2;\n        temp_L_change = (int)temp_new_moves.length(); \n        \n        if (current_L + temp_L_change > 100000) continue; \n\n        // Collect all unique cells affected by this added loop\n        vector<bool> is_affected_cell(N * N, false);\n        vector<int> affected_cell_indices_list; // To iterate only over affected cells\n\n        for (const auto& p : path_coords_1) {\n            int idx = p.r * N + p.c;\n            if (!is_affected_cell[idx]) {\n                is_affected_cell[idx] = true;\n                affected_cell_indices_list.push_back(idx);\n            }\n        }\n        for (const auto& p : path_coords_2) {\n            int idx = p.r * N + p.c;\n            if (!is_affected_cell[idx]) {\n                is_affected_cell[idx] = true;\n                affected_cell_indices_list.push_back(idx);\n            }\n        }\n\n        // Create temporary visits lists for affected cells by copying from current_visits\n        vector<vector<int>> temp_visits_for_affected(N * N); \n        for(int idx : affected_cell_indices_list) {\n            temp_visits_for_affected[idx] = current_visits[idx];\n        }\n\n        // Add new visit times for all cells in the loop\n        Pos current_loop_pos = zero_zero_pos; \n        int current_time_offset = current_L;\n        for (int k = 0; k < (int)temp_new_moves.length(); ++k) {\n            current_time_offset++;\n            char move_char = temp_new_moves[k];\n            int dir_idx = (move_char == 'D' ? 0 : (move_char == 'R' ? 1 : (move_char == 'U' ? 2 : 3)));\n            current_loop_pos = get_next_pos(current_loop_pos, dir_idx);\n            \n            int cell_idx = current_loop_pos.r * N + current_loop_pos.c;\n            if (is_affected_cell[cell_idx]) { \n                auto it = lower_bound(temp_visits_for_affected[cell_idx].begin(), temp_visits_for_affected[cell_idx].end(), current_time_offset);\n                temp_visits_for_affected[cell_idx].insert(it, current_time_offset);\n            }\n        }\n\n        int temp_L = current_L + temp_L_change;\n        double temp_total_S_sum_terms = 0.0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int sq_idx = i * N + j;\n                const vector<int>* visits_ptr;\n                \n                if (is_affected_cell[sq_idx]) { \n                    visits_ptr = &temp_visits_for_affected[sq_idx]; \n                } else {\n                    visits_ptr = &current_visits[sq_idx]; \n                }\n\n                temp_total_S_sum_terms += calculate_cell_contribution(temp_L, *visits_ptr, D_values[i][j]);\n            }\n        }\n        double temp_score = temp_total_S_sum_terms / temp_L;\n        \n        double delta_score = temp_score - current_score;\n\n        if (delta_score < 0 || (T > 0 && dist_real(rng) < exp(-delta_score / T))) {\n            current_path_moves_str += temp_new_moves; \n            current_L = temp_L;\n            \n            for(int idx : affected_cell_indices_list) {\n                current_visits[idx] = temp_visits_for_affected[idx];\n            }\n            current_S_sum_terms = temp_total_S_sum_terms; \n            current_score = temp_score;\n\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_path_moves = current_path_moves_str;\n            }\n        }\n    }\n\n    // Final check for the best_path_moves: ensure it truly ends at (0,0)\n    Pos final_pos_check = {0,0};\n    for (int k = 0; k < (int)best_path_moves.length(); ++k) {\n        char move_char = best_path_moves[k];\n        int dir_idx = -1;\n        if (move_char == 'D') dir_idx = 0;\n        else if (move_char == 'R') dir_idx = 1;\n        else if (move_char == 'U') dir_idx = 2;\n        else if (move_char == 'L') dir_idx = 3;\n        final_pos_check = get_next_pos(final_pos_check, dir_idx);\n    }\n\n    if (!(final_pos_check == Pos{0,0})) {\n        cerr << \"WARNING: best_path_moves does not end at (0,0). Falling back to initial DFS path.\" << endl;\n        cout << initial_dfs_path_moves << endl;\n    } else {\n        cout << best_path_moves << endl;\n    }\n\n    return 0;\n}","ahc028":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <array>\n#include <algorithm> \n#include <tuple>     \n#include <cmath>     \n\n// Aho-Corasick Node definition\nstruct ACNode {\n    std::array<int, 26> go_direct; // Stores ONLY direct transitions from this node\n    int fail;                      // Failure link\n    std::vector<int> pattern_indices; // Indices of patterns ending at this node (or via failure links)\n    int depth;                     // Length of string represented by this node\n\n    ACNode() : fail(0), depth(0) {\n        go_direct.fill(0); // Initialize all direct transitions to 0\n    }\n};\n\nstd::vector<ACNode> ac_trie;         // The Aho-Corasick automaton trie\nstd::vector<char> global_found_tks; // Tracks which of the M patterns have been found\nint M_val;                          // Stores the total number of patterns (M)\n\n// Get the next state in the Aho-Corasick automaton (dynamic traversal using fail links)\n// This is the more robust, but potentially slower, way\nint get_next_ac_state_dynamic(int current_node, char ch) {\n    int c_idx = ch - 'A';\n    // Repeatedly follow failure links until a direct transition is found or root is reached\n    while (current_node != 0 && ac_trie[current_node].go_direct[c_idx] == 0) {\n        current_node = ac_trie[current_node].fail;\n    }\n    // If a direct transition from current_node (or its fail-link ancestor) exists, take it.\n    // If not (e.g., current_node is 0 and no direct transition), stay at root (0).\n    if (ac_trie[current_node].go_direct[c_idx] != 0) {\n        return ac_trie[current_node].go_direct[c_idx];\n    }\n    return 0; // Return root if no match\n}\n\n// Builds the Aho-Corasick automaton from the given patterns\nvoid build_ac(const std::vector<std::string>& patterns) {\n    ac_trie.clear();\n    ac_trie.emplace_back(); // Root node (node 0)\n    M_val = patterns.size();\n    global_found_tks.assign(M_val, 0); // Initialize all patterns as not found (0 for false)\n\n    // 1. Build Trie structure: Insert all patterns into the trie\n    for (int p_idx = 0; p_idx < M_val; ++p_idx) {\n        int curr = 0; // Start from the root\n        for (char ch : patterns[p_idx]) {\n            int c_idx = ch - 'A';\n            if (ac_trie[curr].go_direct[c_idx] == 0) { // If direct transition doesn't exist, create a new node\n                ac_trie[curr].go_direct[c_idx] = ac_trie.size(); // Assign new node ID\n                ac_trie.emplace_back();                   // Add new node to the trie\n                ac_trie.back().depth = ac_trie[curr].depth + 1; // Set its depth\n            }\n            curr = ac_trie[curr].go_direct[c_idx]; // Move to the next node\n        }\n        ac_trie[curr].pattern_indices.push_back(p_idx); // Mark this node as an end point for pattern p_idx\n    }\n\n    // 2. Build Failure Links and propagate output patterns using BFS\n    std::queue<int> q;\n    // For all direct children of the root, their failure link points to the root (0)\n    for (int i = 0; i < 26; ++i) {\n        if (ac_trie[0].go_direct[i] != 0) {\n            ac_trie[ac_trie[0].go_direct[i]].fail = 0; // Set fail link\n            q.push(ac_trie[0].go_direct[i]);           // Add to BFS queue\n        }\n    }\n\n    while (!q.empty()) {\n        int u = q.front(); // Current node\n        q.pop();\n\n        // Propagate pattern_indices from the failure link:\n        // Any patterns found via `u`'s failure link are also considered found when at `u`\n        int f = ac_trie[u].fail;\n        for (int p_idx : ac_trie[f].pattern_indices) {\n            ac_trie[u].pattern_indices.push_back(p_idx);\n        }\n        \n        // For each character in the alphabet\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            if (ac_trie[u].go_direct[c_idx] != 0) { // If a direct child `v` exists for char `c_idx`\n                int v = ac_trie[u].go_direct[c_idx];\n                // The fail link of `v` is found by dynamically traversing from `u`'s fail link\n                ac_trie[v].fail = get_next_ac_state_dynamic(ac_trie[u].fail, 'A' + c_idx);\n                q.push(v); // Add `v` to the BFS queue\n            }\n            // Note: No `else` branch to precompute shortcuts here.\n            // `get_next_ac_state_dynamic` handles traversal dynamically.\n        }\n    }\n}\n\n// Checks for newly found patterns at the given node and updates the global_found_tks array.\nvoid check_and_update_patterns(int node_id) {\n    for (int p_idx : ac_trie[node_id].pattern_indices) {\n        if (!global_found_tks[p_idx]) { // If this pattern hasn't been marked as found yet\n            global_found_tks[p_idx] = 1; // Mark it as found (1 for true)\n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_grid, M_patterns;\n    std::cin >> N_grid >> M_patterns;\n\n    int s_i, s_j; // Initial finger position\n    std::cin >> s_i >> s_j;\n\n    std::vector<std::string> A_grid(N_grid);\n    std::vector<std::vector<std::pair<int, int>>> char_to_coords(26);\n    for (int i = 0; i < N_grid; ++i) {\n        std::cin >> A_grid[i];\n        for (int j = 0; j < N_grid; ++j) {\n            char_to_coords[A_grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    std::vector<std::string> t_patterns(M_patterns);\n    for (int k = 0; k < M_patterns; ++k) {\n        std::cin >> t_patterns[k];\n    }\n\n    build_ac(t_patterns); // Build the Aho-Corasick automaton\n\n    std::pair<int, int> current_pos = {s_i, s_j}; // Current finger position\n    int current_ac_node = 0; // Current state in the Aho-Corasick automaton (starts at root)\n    std::vector<std::pair<int, int>> operations; // List to store the sequence of operations\n\n    check_and_update_patterns(0); // Check for patterns found by empty string (usually none)\n\n    // Main greedy loop\n    while (true) {\n        int found_count = 0;\n        for (char b : global_found_tks) {\n            if (b) found_count++;\n        }\n\n        if (found_count == M_patterns) {\n            break; \n        }\n        if (operations.size() >= 5000) {\n            break; \n        }\n\n        int best_nr = -1, best_nc = -1; \n        char best_char_to_append = ' '; \n\n        // Metric for choosing the best next operation (maximize new patterns, then depth, then minimize cost)\n        std::tuple<int, int, int> best_metric = {-1, -1, 1}; \n\n        for (int c_idx = 0; c_idx < 26; ++c_idx) {\n            char c = 'A' + c_idx;\n            for (auto [nr, nc] : char_to_coords[c_idx]) { \n                int current_move_cost = std::abs(nr - current_pos.first) + std::abs(nc - current_pos.second) + 1;\n                // Use the dynamic state traversal\n                int next_node = get_next_ac_state_dynamic(current_ac_node, c); \n\n                int temp_new_tks_count = 0;\n                for (int p_idx : ac_trie[next_node].pattern_indices) {\n                    if (!global_found_tks[p_idx]) { \n                        temp_new_tks_count++;\n                    }\n                }\n                \n                std::tuple<int, int, int> current_metric = {temp_new_tks_count, ac_trie[next_node].depth, -current_move_cost};\n\n                if (current_metric > best_metric) { \n                    best_metric = current_metric;\n                    best_nr = nr;\n                    best_nc = nc;\n                    best_char_to_append = c;\n                }\n            }\n        }\n\n        if (best_nr == -1) { // Should not happen if patterns are not all found and ops < 5000\n            break;\n        }\n\n        operations.push_back({best_nr, best_nc});\n        current_pos = {best_nr, best_nc}; \n        current_ac_node = get_next_ac_state_dynamic(current_ac_node, best_char_to_append); \n        check_and_update_patterns(current_ac_node); \n    }\n\n    for (const auto& op : operations) {\n        std::cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <map>\n#include <set>\n#include <chrono>\n\n// Global variables for problem parameters\nint N, M;\ndouble EPS;\nstd::vector<std::vector<std::pair<int, int>>> poly_shapes; // M polyomino shapes, relative coordinates\n\n// Time limit management\nauto start_time = std::chrono::high_resolution_clock::now();\nlong long TIME_LIMIT_MS = 2800; // 2.8 seconds for safety, total time limit is 3.0 sec\n\nbool check_time() {\n    auto current_time = std::chrono::high_resolution_clock::now();\n    auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n    return elapsed_ms < TIME_LIMIT_MS;\n}\n\n// Coordinate struct\nstruct Coord {\n    int r, c;\n    bool operator<(const Coord& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// Polyomino bounds (max_r, max_c) relative to (0,0)\nstd::vector<Coord> poly_bounds; // Store max_r, max_c for each poly shape\n\n// Helper to flush output\nvoid flush_output() {\n    std::cout << std::flush;\n}\n\n// Query 1 (drill)\nint query_1(int r, int c) {\n    std::cout << \"q 1 \" << r << \" \" << c << std::endl;\n    flush_output();\n    int v_val;\n    std::cin >> v_val;\n    return v_val;\n}\n\n// Query k (divine)\nint query_k(const std::vector<Coord>& coords) {\n    // This function assumes coords.size() >= 2 as per problem statement\n    std::cout << \"q \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int approx_v_sum;\n    std::cin >> approx_v_sum;\n    return approx_v_sum;\n}\n\n// Answer (guess)\nbool answer(const std::vector<Coord>& coords) {\n    std::cout << \"a \" << coords.size();\n    for (const auto& p : coords) {\n        std::cout << \" \" << p.r << \" \" << p.c;\n    }\n    std::cout << std::endl;\n    flush_output();\n    int response;\n    std::cin >> response;\n    return response == 1;\n}\n\n// Cumulative distribution function for normal distribution\n// M_SQRT2 is from <cmath>, represents sqrt(2)\ndouble normalCDF(double x, double mean, double stddev) {\n    if (stddev < 1e-9) { // Handle very small standard deviation (effectively 0)\n        return x >= mean ? 1.0 : 0.0;\n    }\n    return 0.5 * (1.0 + std::erf((x - mean) / (stddev * M_SQRT2)));\n}\n\n// Particle structure\nstruct Particle {\n    std::vector<Coord> oil_field_positions; // (min_r, min_c) for each of M fields\n    std::vector<std::vector<int>> v_grid; // N x N grid for this particle's configuration\n    double weight;\n\n    Particle() : v_grid(N, std::vector<int>(N, 0)), weight(1.0) {}\n\n    void calculate_v_grid() {\n        for (int i = 0; i < N; ++i) {\n            std::fill(v_grid[i].begin(), v_grid[i].end(), 0);\n        }\n\n        for (int k = 0; k < M; ++k) {\n            const Coord& pos = oil_field_positions[k];\n            // Only process if the position is valid (not a dummy -1,-1)\n            if (pos.r == -1 && pos.c == -1) continue; \n\n            for (const auto& rel_coord : poly_shapes[k]) {\n                int r = pos.r + rel_coord.first;\n                int c = pos.c + rel_coord.second;\n                // Coordinates are guaranteed to be within N x N due to placement generation\n                v_grid[r][c]++;\n            }\n        }\n    }\n\n    int get_v_S_sum(const std::vector<Coord>& query_coords) const {\n        int sum = 0;\n        for (const auto& p : query_coords) {\n            sum += v_grid[p.r][p.c];\n        }\n        return sum;\n    }\n};\n\n// Global random number generator\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    std::cin >> N >> M >> EPS;\n\n    poly_shapes.resize(M);\n    poly_bounds.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d_k;\n        std::cin >> d_k;\n        poly_shapes[k].resize(d_k);\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d_k; ++i) {\n            std::cin >> poly_shapes[k][i].first >> poly_shapes[k][i].second;\n            max_r = std::max(max_r, poly_shapes[k][i].first);\n            max_c = std::max(max_c, poly_shapes[k][i].second);\n        }\n        poly_bounds[k] = {max_r, max_c};\n    }\n\n    // Precompute all possible top-left placements for each polyomino\n    std::vector<std::vector<Coord>> possible_poly_placements(M);\n    for (int k = 0; k < M; ++k) {\n        for (int r = 0; r <= N - 1 - poly_bounds[k].r; ++r) {\n            for (int c = 0; c <= N - 1 - poly_bounds[k].c; ++c) { \n                possible_poly_placements[k].push_back({r, c});\n            }\n        }\n    }\n\n    int NUM_PARTICLES = 5000; \n    if (N > 15) NUM_PARTICLES = 15000; // Increased\n    if (N <= 12) NUM_PARTICLES = 4000; // Increased\n    if (M >= 10 && N > 15) NUM_PARTICLES = 25000; // Increased significantly\n    else if (M >= 10 && N <= 15) NUM_PARTICLES = 10000; // New tier for many polyominos on smaller N\n\n\n    std::vector<Particle> particles(NUM_PARTICLES);\n\n    // Initialize particles: random positions, calculate v_grid, set uniform weights\n    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n        particles[p_idx].oil_field_positions.resize(M); \n        bool particle_valid = true;\n        for (int k = 0; k < M; ++k) {\n            if (possible_poly_placements[k].empty()) {\n                std::cout << \"#c WARNING: No possible placements for polyomino \" << k << \". Particle will be invalid.\\n\";\n                particle_valid = false;\n                particles[p_idx].oil_field_positions[k] = {-1, -1}; \n            } else {\n                std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n            }\n        }\n        \n        if (particle_valid) {\n            particles[p_idx].calculate_v_grid();\n            particles[p_idx].weight = 1.0 / NUM_PARTICLES; \n        } else {\n            particles[p_idx].weight = 0.0; // Invalid particles get 0 weight and will be filtered out by resampling\n        }\n    }\n\n    int ops_count = 0;\n    int MAX_OPS = 2 * N * N;\n\n    // Keep track of drilled squares and their true values\n    std::map<Coord, int> drilled_actual_v;\n\n    // ---- Initial broad queries (q N*N) ----\n    // Cheap queries for the whole grid to quickly refine the total oil count.\n    int initial_broad_queries_count = std::min(30, MAX_OPS / 10); // Increased for more initial passes\n    if (N < 15) initial_broad_queries_count = std::min(20, MAX_OPS/10); \n\n    for (int iter = 0; iter < initial_broad_queries_count; ++iter) {\n        if (!check_time() || ops_count >= MAX_OPS - 2) break; \n\n        std::vector<Coord> all_squares;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                all_squares.push_back({r, c});\n            }\n        }\n\n        int observed_sum = query_k(all_squares); \n        ops_count++;\n\n        double total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            if (particles[p_idx].weight == 0.0) continue; \n            int particle_v_sum = particles[p_idx].get_v_S_sum(all_squares);\n            \n            double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)N * N * EPS;\n            double sigma_sq = (double)N * N * EPS * (1.0 - EPS);\n            double stddev = std::sqrt(sigma_sq);\n\n            double likelihood;\n            if (observed_sum == 0) {\n                likelihood = normalCDF(0.5, mu, stddev);\n            } else {\n                likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n            }\n            if (likelihood < 1e-10) likelihood = 1e-10; \n\n            particles[p_idx].weight *= likelihood;\n            total_weight += particles[p_idx].weight;\n        }\n\n        // Resampling\n        if (total_weight > 1e-10) { \n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx]; \n                new_particles[i].weight = 1.0 / NUM_PARTICLES; \n            }\n            particles = new_particles;\n        } else {\n            std::cout << \"#c All particle weights zero, re-initializing!\\n\";\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                bool particle_valid_reinit = true;\n                for (int k = 0; k < M; ++k) {\n                    if (possible_poly_placements[k].empty()) {\n                        particle_valid_reinit = false;\n                        particles[p_idx].oil_field_positions[k] = {-1, -1};\n                    } else {\n                        std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                        particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                    }\n                }\n                if (particle_valid_reinit) {\n                    particles[p_idx].calculate_v_grid();\n                    particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n                } else {\n                    particles[p_idx].weight = 0.0;\n                }\n            }\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) total_weight += particles[p_idx].weight;\n            if (total_weight > 1e-10) { \n                 std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else {\n                std::cout << \"#c Still no particles after re-applying drilled data. Filter effectively failed.\\n\";\n                break; \n            }\n        }\n    }\n\n\n    // ---- Main particle filter loop with targeted queries ----\n    int drill_budget; \n    int k_query_budget; \n    \n    // Adjust budget based on EPS\n    if (EPS > 0.1) { // High error, prioritize drills (more budget for drills)\n        drill_budget = N*N / 8; // Increased\n        k_query_budget = N*N / 12; // Increased, but less than drill\n    } else { // Low error, more k-queries (more budget for k-queries)\n        drill_budget = N*N / 10; // Increased\n        k_query_budget = N*N / 8; // Increased\n    }\n    \n    int drills_done = 0;\n    int k_queries_done = 0;\n\n    int loop_iterations = 0;\n    const int MAX_MAIN_LOOP_ITERS = MAX_OPS - initial_broad_queries_count - 2; \n    \n    std::vector<std::vector<bool>> queried_mask(N, std::vector<bool>(N, false));\n\n    while (ops_count < MAX_OPS - 2 && loop_iterations < MAX_MAIN_LOOP_ITERS && check_time()) {\n        loop_iterations++;\n        \n        std::vector<std::vector<double>> P_has_oil(N, std::vector<double>(N, 0.0));\n        std::vector<std::vector<double>> E_v(N, std::vector<double>(N, 0.0));\n        double current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight < 1e-10) { \n            std::cout << \"#c Current total weight too small in main loop, breaking.\\n\";\n            break;\n        }\n\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            if (particles[p_idx].weight == 0.0) continue; \n            double normalized_weight = particles[p_idx].weight / current_total_weight;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (particles[p_idx].v_grid[r][c] > 0) {\n                        P_has_oil[r][c] += normalized_weight;\n                    }\n                    E_v[r][c] += normalized_weight * particles[p_idx].v_grid[r][c];\n                }\n            }\n        }\n        \n        bool queried_this_iter = false;\n\n        if (drills_done < drill_budget) {\n            double max_uncertainty = -1.0;\n            Coord best_drill_coord_uncertainty = {-1, -1};\n            double max_E_v = -1.0;\n            Coord best_drill_coord_Ev = {-1, -1};\n\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { \n                        double uncertainty = P_has_oil[r][c] * (1.0 - P_has_oil[r][c]); \n                        if (uncertainty > max_uncertainty) {\n                            max_uncertainty = uncertainty;\n                            best_drill_coord_uncertainty = current_coord;\n                        }\n                        if (E_v[r][c] > max_E_v) {\n                            max_E_v = E_v[r][c];\n                            best_drill_coord_Ev = current_coord;\n                        }\n                    }\n                }\n            }\n            \n            if (best_drill_coord_uncertainty.r != -1 && max_uncertainty > 0.05) { \n                 int actual_v = query_1(best_drill_coord_uncertainty.r, best_drill_coord_uncertainty.c);\n                 drilled_actual_v[best_drill_coord_uncertainty] = actual_v;\n                 ops_count++;\n                 drills_done++;\n                 queried_this_iter = true;\n                 for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                     if (particles[p_idx].v_grid[best_drill_coord_uncertainty.r][best_drill_coord_uncertainty.c] != actual_v) {\n                         particles[p_idx].weight = 0;\n                     }\n                 }\n            } else if (best_drill_coord_Ev.r != -1 && max_E_v > 0.2) { \n                int actual_v = query_1(best_drill_coord_Ev.r, best_drill_coord_Ev.c);\n                drilled_actual_v[best_drill_coord_Ev] = actual_v;\n                ops_count++;\n                drills_done++;\n                queried_this_iter = true;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[best_drill_coord_Ev.r][best_drill_coord_Ev.c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n        }\n        \n        if (!queried_this_iter && k_queries_done < k_query_budget) {\n            std::vector<std::pair<double, Coord>> uncertainty_list;\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Coord current_coord = {r, c};\n                    if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && !queried_mask[r][c]) {\n                        uncertainty_list.push_back({P_has_oil[r][c] * (1.0 - P_has_oil[r][c]) + E_v[r][c] / M, current_coord});\n                    }\n                }\n            }\n            std::sort(uncertainty_list.rbegin(), uncertainty_list.rend()); \n\n            if (uncertainty_list.size() >= 2) { \n                int k_val = std::min((int)uncertainty_list.size(), (int)(N * N / (10 + 50 * EPS))); \n                if (k_val < 2) k_val = 2; \n\n                std::vector<Coord> query_coords;\n                for (int i = 0; i < k_val; ++i) {\n                    query_coords.push_back(uncertainty_list[i].second);\n                    queried_mask[uncertainty_list[i].second.r][uncertainty_list[i].second.c] = true; \n                }\n                \n                int observed_sum = query_k(query_coords);\n                ops_count++;\n                k_queries_done++;\n                queried_this_iter = true;\n\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].weight == 0.0) continue; \n                    int particle_v_sum = particles[p_idx].get_v_S_sum(query_coords);\n                    double mu = (double)particle_v_sum * (1.0 - 2.0 * EPS) + (double)query_coords.size() * EPS;\n                    double sigma_sq = (double)query_coords.size() * EPS * (1.0 - EPS);\n                    double stddev = std::sqrt(sigma_sq);\n\n                    double likelihood;\n                    if (observed_sum == 0) {\n                        likelihood = normalCDF(0.5, mu, stddev);\n                    } else {\n                        likelihood = normalCDF(observed_sum + 0.5, mu, stddev) - normalCDF(observed_sum - 0.5, mu, stddev);\n                    }\n                    if (likelihood < 1e-10) likelihood = 1e-10;\n\n                    particles[p_idx].weight *= likelihood;\n                }\n            } \n        }\n\n        current_total_weight = 0.0;\n        for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n            current_total_weight += particles[p_idx].weight;\n        }\n\n        if (current_total_weight > 1e-10) {\n            std::vector<double> cumulative_weights(NUM_PARTICLES);\n            cumulative_weights[0] = particles[0].weight / current_total_weight;\n            for (int i = 1; i < NUM_PARTICLES; ++i) {\n                cumulative_weights[i] = cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n            }\n\n            std::vector<Particle> new_particles(NUM_PARTICLES);\n            std::uniform_real_distribution<double> uniform_dist(0.0, 1.0);\n            for (int i = 0; i < NUM_PARTICLES; ++i) {\n                double r_val = uniform_dist(rng);\n                auto it = std::lower_bound(cumulative_weights.begin(), cumulative_weights.end(), r_val);\n                int original_idx = std::distance(cumulative_weights.begin(), it);\n                new_particles[i] = particles[original_idx];\n                new_particles[i].weight = 1.0 / NUM_PARTICLES;\n            }\n            particles = new_particles;\n        } else {\n            std::cout << \"#c All particle weights zero in main loop, re-initializing!\\n\";\n            for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                particles[p_idx].oil_field_positions.resize(M);\n                bool particle_valid_reinit = true;\n                for (int k = 0; k < M; ++k) {\n                    if (possible_poly_placements[k].empty()) {\n                        particle_valid_reinit = false;\n                        particles[p_idx].oil_field_positions[k] = {-1, -1};\n                    } else {\n                        std::uniform_int_distribution<int> dist(0, possible_poly_placements[k].size() - 1);\n                        particles[p_idx].oil_field_positions[k] = possible_poly_placements[k][dist(rng)];\n                    }\n                }\n                if (particle_valid_reinit) {\n                    particles[p_idx].calculate_v_grid();\n                    particles[p_idx].weight = 1.0 / NUM_PARTICLES;\n                } else {\n                    particles[p_idx].weight = 0.0;\n                }\n            }\n            for(const auto& entry : drilled_actual_v) {\n                int r = entry.first.r;\n                int c = entry.first.c;\n                int actual_v = entry.second;\n                for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                    if (particles[p_idx].v_grid[r][c] != actual_v) {\n                        particles[p_idx].weight = 0;\n                    }\n                }\n            }\n            current_total_weight = 0;\n            for(int p_idx=0; p_idx<NUM_PARTICLES; ++p_idx) current_total_weight += particles[p_idx].weight;\n            if (current_total_weight > 1e-10) { \n                std::vector<double> current_cumulative_weights(NUM_PARTICLES);\n                current_cumulative_weights[0] = particles[0].weight / current_total_weight;\n                for (int i = 1; i < NUM_PARTICLES; ++i) {\n                    current_cumulative_weights[i] = current_cumulative_weights[i - 1] + particles[i].weight / current_total_weight;\n                }\n\n                std::vector<Particle> resampled_particles(NUM_PARTICLES);\n                std::uniform_real_distribution<double> new_uniform_dist(0.0, 1.0);\n                for (int i = 0; i < NUM_PARTICLES; ++i) {\n                    double r_val = new_uniform_dist(rng);\n                    auto it = std::lower_bound(current_cumulative_weights.begin(), current_cumulative_weights.end(), r_val);\n                    int original_idx = std::distance(current_cumulative_weights.begin(), it);\n                    resampled_particles[i] = particles[original_idx];\n                    resampled_particles[i].weight = 1.0 / NUM_PARTICLES;\n                }\n                particles = resampled_particles;\n            } else { \n                break;\n            }\n        }\n\n        if (loop_iterations % (N) == 0) { \n            for (int r = 0; r < N; ++r) std::fill(queried_mask[r].begin(), queried_mask[r].end(), false);\n        }\n    }\n\n\n    // Final guess attempt\n    std::set<Coord> potential_oil_squares_set;\n    for(const auto& entry : drilled_actual_v) { \n        if (entry.second > 0) {\n            potential_oil_squares_set.insert(entry.first);\n        }\n    }\n\n    double final_total_weight = 0.0;\n    for(const auto& p : particles) final_total_weight += p.weight;\n    \n    if (final_total_weight > 1e-10) { \n        double p_threshold = 0.15; // Default for very high error\n        if (EPS < 0.15) p_threshold = 0.2;\n        if (EPS < 0.10) p_threshold = 0.3; \n        if (EPS < 0.05) p_threshold = 0.4;\n        if (EPS < 0.02) p_threshold = 0.5; \n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                Coord current_coord = {r, c};\n                if (drilled_actual_v.find(current_coord) == drilled_actual_v.end()) { \n                    double P_val = 0.0;\n                    for (int p_idx = 0; p_idx < NUM_PARTICLES; ++p_idx) {\n                        if (particles[p_idx].weight == 0.0) continue; \n                        if (particles[p_idx].v_grid[r][c] > 0) {\n                            P_val += particles[p_idx].weight;\n                        }\n                    }\n                    P_val /= final_total_weight;\n                    if (P_val > p_threshold) { \n                        potential_oil_squares_set.insert(current_coord);\n                    }\n                }\n            }\n        }\n    } else { \n        std::cout << \"#c Particle filter collapsed before final guess. Relying on drilled data only.\\n\";\n    }\n\n\n    std::vector<Coord> final_oil_squares_vec(potential_oil_squares_set.begin(), potential_oil_squares_set.end());\n    std::sort(final_oil_squares_vec.begin(), final_oil_squares_vec.end()); \n\n    if (answer(final_oil_squares_vec)) {\n        return 0; \n    }\n    ops_count++;\n\n    std::cout << \"#c Initial guess incorrect. Falling back to drilling all remaining squares.\\n\";\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            Coord current_coord = {r, c};\n            if (drilled_actual_v.find(current_coord) == drilled_actual_v.end() && ops_count < MAX_OPS -1) { \n                int actual_v = query_1(r, c);\n                drilled_actual_v[current_coord] = actual_v;\n                ops_count++;\n            }\n        }\n    }\n\n    std::vector<Coord> final_fallback_squares;\n    for (const auto& entry : drilled_actual_v) {\n        if (entry.second > 0) {\n            final_fallback_squares.push_back(entry.first);\n        }\n    }\n    std::sort(final_fallback_squares.begin(), final_fallback_squares.end()); \n\n    if (!answer(final_fallback_squares)) {\n        std::cout << \"#c Fallback guess incorrect. This should not happen!\\n\";\n    }\n\n    return 0;\n}\n","ahc031":"long long calculate_delta_cost(int d, const Rect& old_r, const Rect& new_r, int k_id,\n                                 const bool H_prev_day[W+1][W], const bool V_prev_day[W][W+1],\n                                 GridManager& gm, long long current_total_cost) {\n    // 1. Calculate delta area cost:\n    long long delta_area_cost = 0;\n    // Remove old_r's contribution\n    if (old_r.area() < a_global[d][k_id]) delta_area_cost -= 100LL * (a_global[d][k_id] - old_r.area());\n    // Add new_r's contribution\n    if (new_r.area() < a_global[d][k_id]) delta_area_cost += 100LL * (a_global[d][k_id] - new_r.area());\n\n    // 2. Calculate delta partition cost:\n    long long delta_partition_cost = 0;\n    \n    // Temporarily revert the placed_rects entry for k_id to old_r\n    // (since gm.place(new_r, k_id) was already called for validation)\n    // We need the state *before* gm.place(new_r, k_id) to figure out diffs.\n    // The safest way is to manage `H_curr` and `V_curr` arrays incrementally.\n    \n    // Instead of directly calculating delta, calculate new total cost based on `gm.placed_rects`\n    // (which now includes new_r) and then subtract `current_total_cost`.\n    // This implies `calculate_day_cost` is called directly, but its performance needs to be improved\n    // beyond `O(W^2)`.\n\n    // Optimized `calculate_day_cost` for incremental SA updates:\n    // Store `H_current_sum` and `V_current_sum` (total active partitions)\n    // When `is_occupied[r][c]` changes, it affects 4 segments.\n    // For each affected segment `s = (i,j)-(i',j')`:\n    //  `old_H_curr_s = is_segment_a_border_before_change(s)`\n    //  `new_H_curr_s = is_segment_a_border_after_change(s)`\n    //  If `(old_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    //  If `(new_H_curr_s != global_H_prev[s])` add/subtract 1 from `delta_partition_cost`.\n    // This is the $O(Area)$ bottleneck.\n    // To implement `is_segment_a_border`, you need `is_occupied` state.\n\n    // A simpler way:\n    // Copy `is_occupied` state to a temporary `is_occupied_temp`\n    // Then `gm.remove(k_id, from_is_occupied_temp)`\n    // Compute `old_local_partition_status` using `is_occupied_temp` within `old_r`'s perimeter + 1 cell buffer.\n    // `gm.place(new_r, to_is_occupied_temp)`\n    // Compute `new_local_partition_status` using `is_occupied_temp` within `new_r`'s perimeter + 1 cell buffer.\n    // Then calculate the `delta_partition_cost` within these local affected regions.\n\n    // For simplicity of implementation (and hoping that AvgArea is small enough on average)\n    // just call the full `calculate_day_cost` after updating `gm.placed_rects`.\n    // With `SA_ITERATIONS` around 1000 per day, total $5 \\times 10^7$ iterations for `calculate_day_cost`.\n    // AvgArea $20000 \\approx 0.02 W^2$.\n    // If average $W^2$ operations is $2 \\times 10^4$, then $5 \\times 10^7 \\times 2 \\times 10^4 = 10^{12}$. Still too much.\n    // This is why `calculate_day_cost` *must* be O(Perimeter) in SA.\n    \n    // Let's go with the O(Perimeter) approach for SA iterations.\n    // Need to precompute `H_curr` and `V_curr` from `is_occupied` once per day.\n    // Then when a rectangle `R_k` changes, we update only the segments around its perimeter.\n    // This implies `H_curr_global[W+1][W]` and `V_curr_global[W][W+1]` must be updated incrementally.\n    \n    // `current_H_states[W+1][W]` and `current_V_states[W][W+1]` (booleans)\n    // `current_H_count`, `current_V_count` (total partition lengths)\n    // On a move:\n    //  `old_r_perimeter_segs = get_perimeter_segments(old_r)`\n    //  `new_r_perimeter_segs = get_perimeter_segments(new_r)`\n    //  For `s` in `old_r_perimeter_segs` and `new_r_perimeter_segs` (union):\n    //    `was_border = is_segment_a_border(s, is_occupied_before_change)`\n    //    `is_border = is_segment_a_border(s, is_occupied_after_change)`\n    //    If `was_border != is_border`:\n    //      if `was_border != global_H_prev[s]`: `delta_cost--`\n    //      if `is_border != global_H_prev[s]`: `delta_cost++`\n    // This `is_segment_a_border` checks `is_occupied` for neighbors of `s`, which means `O(1)` per segment.\n    // Total `O(Perimeter)` for partition cost delta. Area update is $O(Area)$.\n    // So the move is $O(Area + Perimeter)$, which becomes $O(Area)$ in worst case.\n    // Let's assume avg Area is small enough on average for $N=50$ given $W=1000$.\n    // If $W^2/N = 20000$, $Area \\sim 20000$. This is the largest factor.\n    // $50 \\times 1000 \\times 20000 = 10^9$. Maybe SA_ITERATIONS must be smaller, say 1000.\n    // $50 \\times 1000 \\times 20000 = 10^9$. This would be close to 1 second.\n    // $SA\\_ITERATIONS=1000$ per day. Total $50000$ iterations.\n    // Each is $O(Area)$, `20000`. So $50000 \\times 20000 = 10^9$. This will be slow for 3s.\n    // The input generation suggests `a_d,k` sum is around $W^2-E$. Smallest $E$ is $W^2 \\times 0.0025 = 2500$.\n    // So average desired area is typically $W^2/N \\approx 20000$.\n    // Maybe `Area` updates are sparse?\n}\n\nFinal decision: I will implement `calculate_day_cost` with `O(W^2)` per call, and reduce `SA_ITERATIONS` to a very small number (e.g., 50 per day). This makes total operations $D \\times SA\\_ITERATIONS \\times W^2 = 50 \\times 50 \\times 10^6 = 2.5 \\times 10^9$. This might barely pass, or be too slow. A hybrid: `O(Area)` based delta computation during SA, and full `O(W^2)` only once at the end of each day for `global_H_prev` update.\n","ahc032":"#include <iostream>\n#include <vector>\n#include <numeric>     // Potentially for std::accumulate, though not strictly used with the new scoring approach\n#include <algorithm>   // For std::sort, std::min, std::max\n#include <limits>      // For std::numeric_limits\n#include <chrono>      // For high_resolution_clock and duration for time limiting\n#include <random>      // For mt19937, uniform_int_distribution, and discrete_distribution\n\n// Define MOD constant\nconst int MOD = 998244353;\n\n// Structure to store an performed operation\nstruct Operation {\n    int m, p, q;\n};\n\n// Helper struct to store an option with its gain\nstruct Option {\n    long long gain;\n    int m, p, q;\n\n    // For sorting: higher gain comes first\n    bool operator<(const Option& other) const {\n        return gain > other.gain; // Sort in descending order of gain\n    }\n};\n\n// Function to calculate the total score for a given board state\n// This function sums up all b_i,j % MOD values\nlong long calculate_board_score(const std::vector<std::vector<int>>& board, int N) {\n    long long total_score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            total_score += board[i][j]; // Values in board are already modulo MOD\n        }\n    }\n    return total_score;\n}\n\n\nint main() {\n    // Optimize C++ standard streams for faster input/output.\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N, M, K;\n    std::cin >> N >> M >> K;\n\n    // Read initial board values.\n    std::vector<std::vector<int>> initial_board(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_board[i][j]; // a_i,j are guaranteed to be < MOD\n        }\n    }\n\n    // Read all stamp configurations `s_m,i,j`.\n    std::vector<std::vector<std::vector<int>>> s(M, std::vector<std::vector<int>>(3, std::vector<int>(3)));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                std::cin >> s[m][i][j]; // s_m,i,j are guaranteed to be < MOD\n            }\n        }\n    }\n\n    // Initialize random number generator using current time for varied seeds across runs.\n    std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());\n\n    // Best overall score found and the sequence of operations that produced it.\n    long long max_overall_score = calculate_board_score(initial_board, N);\n    std::vector<Operation> best_overall_operations;\n\n    // Set a time limit for the iterative process (e.g., 1.98 seconds out of 2.0s total).\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 1.98; // Adjusted time limit\n\n    // Loop for multiple attempts (Iterated Randomly Perturbed Greedy).\n    // The loop continues as long as there is time remaining.\n    while (true) {\n        auto current_chrono_time = std::chrono::high_resolution_clock::now();\n        double elapsed_seconds = std::chrono::duration<double>(current_chrono_time - start_time).count();\n        if (elapsed_seconds >= TIME_LIMIT_SECONDS) {\n            break; // Stop if time limit is reached.\n        }\n\n        // Start a new greedy run with a fresh copy of the initial board.\n        std::vector<std::vector<int>> current_board = initial_board;\n        std::vector<Operation> current_operations;\n        long long current_run_score = calculate_board_score(current_board, N); // Keep track of score incrementally\n\n        // Perform up to K operations for this specific run.\n        for (int k_idx = 0; k_idx < K; ++k_idx) {\n            std::vector<Option> possible_options; // List to store all potential operations and their gains.\n\n            // Evaluate all M * (N-2)^2 possible operations.\n            for (int m_idx = 0; m_idx < M; ++m_idx) {\n                for (int p_idx = 0; p_idx <= N - 3; ++p_idx) {\n                    for (int q_idx = 0; q_idx <= N - 3; ++q_idx) {\n                        long long current_gain = 0; // Accumulated gain for the current stamp application.\n\n                        // Calculate the score change if this stamp is applied.\n                        for (int i_s = 0; i_s < 3; ++i_s) {\n                            for (int j_s = 0; j_s < 3; ++j_s) {\n                                int r = p_idx + i_s; // Row on the board\n                                int c = q_idx + j_s; // Column on the board\n\n                                int old_val_mod = current_board[r][c];\n                                // Calculate new value modulo MOD. Use long long for addition to prevent overflow.\n                                int new_val_mod = (int)(((long long)old_val_mod + s[m_idx][i_s][j_s]) % MOD);\n                                \n                                current_gain += (new_val_mod - old_val_mod);\n                            }\n                        }\n                        \n                        // Only consider operations that provide a strict positive gain.\n                        if (current_gain > 0) {\n                             possible_options.push_back({current_gain, m_idx, p_idx, q_idx});\n                        }\n                    }\n                }\n            }\n            \n            // If no operation can increase the score, this run stops early.\n            if (possible_options.empty()) {\n                break;\n            }\n\n            // Sort options by gain in descending order. This is essential for picking top X.\n            std::sort(possible_options.begin(), possible_options.end());\n\n            // Define how many top options to consider for weighted random selection.\n            // Adaptive TOP_X: Start with a higher number of options to explore,\n            // gradually reduce it towards the end to exploit better options.\n            const int MAX_TOP_X = 100; // Adjusted from 50 to 100\n            const int MIN_TOP_X = 10;  // Adjusted from 15 to 10\n            \n            // Calculate current_TOP_X based on k_idx (operations performed so far)\n            // Linear decay from MAX_TOP_X to MIN_TOP_X over K operations\n            int current_TOP_X = MAX_TOP_X - (MAX_TOP_X - MIN_TOP_X) * k_idx / K;\n            current_TOP_X = std::max(MIN_TOP_X, current_TOP_X); // Ensure it doesn't go below MIN_TOP_X\n\n            int actual_top_x_count = std::min((int)possible_options.size(), current_TOP_X);\n\n            // Prepare weights for discrete distribution (gains of top options)\n            std::vector<long long> weights;\n            weights.reserve(actual_top_x_count); // Pre-allocate memory for efficiency\n            for (int i = 0; i < actual_top_x_count; ++i) {\n                weights.push_back(possible_options[i].gain);\n            }\n\n            // Create a discrete distribution based on weights\n            // std::discrete_distribution requires positive weights. Since we only added options with gain > 0,\n            // and `gain` can be up to 9 * (MOD-1) which is positive, this is safe.\n            std::discrete_distribution<int> dist(weights.begin(), weights.end());\n            \n            // Randomly pick an index from the top options based on weights\n            int chosen_idx_in_top_x = dist(rng);\n            Option chosen_option = possible_options[chosen_idx_in_top_x];\n\n            // Apply the chosen operation to update the board state for this run.\n            for (int i_s = 0; i_s < 3; ++i_s) {\n                for (int j_s = 0; j_s < 3; ++j_s) {\n                    int r = chosen_option.p + i_s;\n                    int c = chosen_option.q + j_s;\n                    current_board[r][c] = (int)(((long long)current_board[r][c] + s[chosen_option.m][i_s][j_s]) % MOD);\n                }\n            }\n            // Update the score for the current run incrementally.\n            current_run_score += chosen_option.gain;\n            // Record the operation performed.\n            current_operations.push_back({chosen_option.m, chosen_option.p, chosen_option.q});\n        } // End of k_idx loop for one greedy run\n\n        // After completing one full greedy run (or breaking early), check if it's the best so far.\n        if (current_run_score > max_overall_score) {\n            max_overall_score = current_run_score;\n            best_overall_operations = current_operations;\n        }\n    } // End of time-limited loop for multiple runs\n\n    // Output the number of operations in the best sequence found.\n    std::cout << best_overall_operations.size() << std::endl;\n    // Output each operation's details (stamp index, top-left row, top-left column).\n    for (const auto& op : best_overall_operations) {\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 <set>\n#include <algorithm>\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 { // For map keys (container_locations still uses map)\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint DR[] = {-1, 1, 0, 0}; // U, D, L, R\nint DC[] = {0, 0, -1, 1};\n\n// Correct way to get char from dr,dc\nchar get_dir_char(int dr, int dc) {\n    if (dr == -1 && dc == 0) return 'U';\n    if (dr == 1 && dc == 0) return 'D';\n    if (dr == 0 && dc == -1) return 'L';\n    if (dr == 0 && dc == 1) return 'R';\n    return '.'; // Should not happen for a valid move\n}\n\nstruct Crane {\n    int id;\n    Pos pos;\n    int holding_container_id; // -1 if not holding\n    bool is_large;\n    bool is_bombed;\n};\n\nstruct State {\n    vector<vector<int>> board; // container ID, -1 if empty\n    vector<Crane> cranes;\n    vector<int> incoming_idx; // next container index for each receiving gate (row)\n    vector<int> next_dispatch_val; // next container ID expected at each dispatch gate (row)\n    vector<vector<int>> A; // initial incoming container sequence\n    map<int, Pos> container_locations; // Map container_id to its (r,c) position or {-1,-1} if in crane's hand\n};\n\n// BFS to find the next step (dr, dc) and path cost\n// Returns {dr, dc} for the next step. {0,0} if no path or already at target.\n// path_cost_out will be set to the cost of the path, or -1 if no path.\nPos get_next_step(const State& current_state, int crane_id, Pos start_pos, Pos target_pos,\n                  bool is_holding_container, bool is_large_crane,\n                  const vector<Pos>& other_crane_current_pos_snapshot, // Snapshot of all crane positions before planning\n                  const vector<Pos>& target_next_crane_pos_planned, // Planned next positions for higher priority cranes (j < crane_id)\n                  int& path_cost_out) {\n\n    if (start_pos == target_pos) {\n        path_cost_out = 0;\n        return {0,0};\n    }\n\n    // Optimized BFS: use 2D array for distance and parent tracking\n    vector<vector<int>> dist_grid(N, vector<int>(N, -1)); // -1 means unvisited\n    vector<vector<Pos>> parent_grid(N, vector<Pos>(N, {-1,-1})); // Stores parent position to reconstruct path\n    queue<Pos> q;\n\n    q.push(start_pos);\n    dist_grid[start_pos.r][start_pos.c] = 0;\n\n    Pos next_step_dir = {0,0};\n    path_cost_out = -1; // Default to no path found\n\n    Pos found_target_pos = {-1,-1}; // To store the actual target_pos if found\n\n    while (!q.empty()) {\n        Pos u = q.front();\n        q.pop();\n\n        if (u == target_pos) {\n            found_target_pos = u;\n            break; // Path found\n        }\n\n        for (int i = 0; i < 4; ++i) {\n            Pos v = {u.r + DR[i], u.c + DC[i]};\n\n            if (v.r < 0 || v.r >= N || v.c < 0 || v.c >= N) continue; // Out of bounds\n\n            // If already visited, skip (or if new path isn't shorter)\n            if (dist_grid[v.r][v.c] != -1) continue;\n\n            // Check for container on destination square (for small cranes holding cargo)\n            // Small crane carrying container cannot move to occupied square.\n            // Large crane carrying container CAN move to occupied square, so this check is skipped for large cranes.\n            if (!is_large_crane && is_holding_container && current_state.board[v.r][v.c] != -1) {\n                continue; \n            }\n\n            bool collision = false;\n            for (int j = 0; j < N; ++j) {\n                if (j == crane_id || current_state.cranes[j].is_bombed) continue; // Skip self or bombed cranes\n\n                Pos other_curr_j = other_crane_current_pos_snapshot[j]; \n                \n                if (j < crane_id) { // Higher priority crane, its next position is already planned\n                    Pos other_next_j_planned = target_next_crane_pos_planned[j];\n                    \n                    if (v == other_next_j_planned) { // Target collision\n                        collision = true; break;\n                    }\n                    if (v == other_curr_j && u == other_next_j_planned) { // Swap collision\n                        collision = true; break;\n                    }\n                } else { // Lower priority crane, it hasn't planned its move yet. Consider its current position as blocked.\n                    if (v == other_curr_j) { // Target collision\n                        collision = true; break;\n                    }\n                }\n            }\n            if (collision) continue;\n\n            dist_grid[v.r][v.c] = dist_grid[u.r][u.c] + 1;\n            parent_grid[v.r][v.c] = u; // Store parent for path reconstruction\n            q.push(v);\n        }\n    }\n\n    if (found_target_pos.r != -1) { // Path found\n        path_cost_out = dist_grid[found_target_pos.r][found_target_pos.c];\n        \n        // Reconstruct the first step\n        Pos curr = found_target_pos;\n        while (parent_grid[curr.r][curr.c] != start_pos) {\n            curr = parent_grid[curr.r][curr.c];\n        }\n        next_step_dir = {curr.r - start_pos.r, curr.c - start_pos.c};\n    }\n    return next_step_dir;\n}\n\n// Helper for a crane (k) holding container C to find a suitable empty release position.\n// Returns a valid empty position or {-1,-1} if none found.\nPos find_best_release_pos(const State& state, int crane_id, int C, Pos current_crane_pos_for_context) {\n    int C_target_row = C / N;\n    bool is_large_crane = state.cranes[crane_id].is_large;\n    bool is_next_dispatch = (C == state.next_dispatch_val[C_target_row]);\n\n    // Priority 1: Direct dispatch\n    if (is_next_dispatch && state.board[C_target_row][N-1] == -1) {\n        return {C_target_row, N-1};\n    }\n    \n    // Priority 2: Primary staging for its target row\n    if (state.board[C_target_row][N-2] == -1) {\n        return {C_target_row, N-2};\n    }\n\n    // Priority 3: Mid-column for cross-row transfers (its target row)\n    if (state.board[C_target_row][N/2] == -1) {\n        return {C_target_row, N/2};\n    }\n    \n    // Priority 4: If small crane and holding cross-row cargo, its own row's mid-column for drop-off\n    // This is where a small crane trying to offload to the large crane would put it.\n    if (!is_large_crane && current_crane_pos_for_context.r != C_target_row) {\n        if (state.board[current_crane_pos_for_context.r][N/2] == -1) {\n            return {current_crane_pos_for_context.r, N/2};\n        }\n    }\n\n    // Priority 5: General in-row storage for target row (e.g. column 1), avoiding receiving gate\n    if (state.board[C_target_row][1] == -1) {\n        return {C_target_row, 1};\n    }\n\n    // For large crane, if the above are blocked, use more aggressive fallback\n    if (is_large_crane) {\n        // Option 6: Any empty spot in non-gate columns (1 to N-2), preferring target row first, then any row\n        for (int c = N-2; c >= 1; --c) { // Prioritize columns further from receiving gate\n            if (state.board[C_target_row][c] == -1) {\n                return {C_target_row, c};\n            }\n        }\n        // If still no empty spot in target row (non-gate), look for any empty spot on the grid (non-gate columns).\n        // This is the emergency dump to prevent the large crane from stalling.\n        for (int r_any = 0; r_any < N; ++r_any) {\n            for (int c_any = N-2; c_any >= 1; --c_any) { // Columns 1 to N-2\n                if (state.board[r_any][c_any] == -1) {\n                    return {r_any, c_any};\n                }\n            }\n        }\n    }\n    \n    return {-1,-1}; // No suitable empty spot found\n}\n\n\nvoid solve() {\n    State current_state;\n    current_state.board.assign(N, vector<int>(N, -1));\n    current_state.A.assign(N, vector<int>(N));\n    current_state.incoming_idx.assign(N, 0);\n    \n    // Initialize next_dispatch_val correctly\n    current_state.next_dispatch_val.resize(N);\n    for(int i = 0; i < N; ++i) {\n        current_state.next_dispatch_val[i] = N * i;\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> current_state.A[i][j];\n        }\n    }\n\n    current_state.cranes.resize(N);\n    for (int i = 0; i < N; ++i) {\n        current_state.cranes[i].id = i;\n        current_state.cranes[i].pos = {i, 0};\n        current_state.cranes[i].holding_container_id = -1;\n        current_state.cranes[i].is_large = (i == 0);\n        current_state.cranes[i].is_bombed = false;\n    }\n\n    int turns = 0;\n    int dispatched_count = 0;\n\n    vector<string> all_crane_actions(N, \"\");\n\n    while (dispatched_count < N*N && turns < MAX_TURNS) {\n        turns++;\n        \n        // 0. Store current crane positions for BFS collision detection\n        vector<Pos> other_crane_current_pos_snapshot(N);\n        for(int i=0; i<N; ++i) other_crane_current_pos_snapshot[i] = current_state.cranes[i].pos;\n\n        // Initialize planned positions and holding status to current state\n        vector<Pos> target_next_crane_pos_planned(N);\n        vector<int> target_next_crane_holding_planned(N);\n        for (int k = 0; k < N; ++k) {\n            target_next_crane_pos_planned[k] = current_state.cranes[k].pos;\n            target_next_crane_holding_planned[k] = current_state.cranes[k].holding_container_id;\n        }\n\n        // 1. Incoming containers (Before crane planning so cranes can react to them)\n        for (int i = 0; i < N; ++i) {\n            if (current_state.incoming_idx[i] < N) {\n                bool gate_has_container = (current_state.board[i][0] != -1);\n                bool gate_has_crane = false;\n                for(int k=0; k<N; ++k) {\n                    // Check actual crane positions from current_state before they move\n                    if (!current_state.cranes[k].is_bombed && current_state.cranes[k].pos.r == i && current_state.cranes[k].pos.c == 0) {\n                        gate_has_crane = true;\n                        break;\n                    }\n                }\n                if (!gate_has_container && !gate_has_crane) {\n                    int container_id = current_state.A[i][current_state.incoming_idx[i]];\n                    current_state.board[i][0] = container_id;\n                    current_state.container_locations[container_id] = {i,0};\n                    current_state.incoming_idx[i]++;\n                }\n            }\n        }\n\n        // 2. Crane actions planning (prioritized by crane ID 0 to N-1)\n        vector<char> current_turn_actions_char(N, '.');\n        \n        for (int k = 0; k < N; ++k) { \n            if (current_state.cranes[k].is_bombed) {\n                current_turn_actions_char[k] = '.';\n                continue;\n            }\n\n            Pos crane_curr_pos = current_state.cranes[k].pos;\n            int holding_id = current_state.cranes[k].holding_container_id;\n\n            // If holding a container, find best release spot and move towards it\n            if (holding_id != -1) {\n                Pos desired_release_pos = find_best_release_pos(current_state, k, holding_id, crane_curr_pos);\n                \n                if (desired_release_pos.r != -1) { // Found a place to move to/release\n                    if (crane_curr_pos == desired_release_pos) { // Already at the target spot and it's empty, release\n                        current_turn_actions_char[k] = 'Q';\n                        target_next_crane_holding_planned[k] = -1; // Released\n                    } else { // Move towards desired_release_pos\n                        int cost;\n                        Pos dir = get_next_step(current_state, k, crane_curr_pos, desired_release_pos, true, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                        if (cost != -1) {\n                            current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                            target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                        } else {\n                            current_turn_actions_char[k] = '.'; // Cannot reach even best empty spot\n                        }\n                    }\n                } else { // No empty spot found for release\n                    current_turn_actions_char[k] = '.'; // Wait\n                }\n                continue; // Crane has a container, its action is determined\n            }\n\n            // If not holding a container, find a task\n            long long best_task_overall_score = (long long)MAX_TURNS * (N * N + 1); // Max score for priority (N*N tasks + 1 for multiplier to be safe)\n            Pos best_pick_pos_for_task = {-1,-1};\n            int best_item_id_for_task = -1;\n\n            // Define lambda here for 'calculate_cost_to_pickup'\n            auto calculate_cost_to_pickup = [&](Pos target_for_pickup) {\n                int cost;\n                get_next_step(current_state, k, crane_curr_pos, target_for_pickup, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                return cost;\n            };\n            \n            // Check if a container is already targeted by a higher-priority crane or held\n            auto is_container_busy = [&](int container_id) {\n                if (container_id == -1) return true;\n                for (int j = 0; j < N; ++j) {\n                    if (current_state.cranes[j].id != k && target_next_crane_holding_planned[j] == container_id) return true;\n                }\n                return false;\n            };\n\n            // Helper to evaluate a potential pick-up task with priority\n            auto evaluate_task = [&](int C, Pos c_pos, int priority_multiplier) {\n                if (is_container_busy(C)) return; // Already busy\n\n                int pickup_cost = calculate_cost_to_pickup(c_pos);\n                if (pickup_cost == -1) return; // Cannot reach item for pickup\n\n                Pos potential_release_pos = find_best_release_pos(current_state, k, C, c_pos);\n                if (potential_release_pos.r == -1) return; // No place to release the item\n\n                long long current_task_score = (long long)priority_multiplier * MAX_TURNS + pickup_cost;\n                if (current_task_score < best_task_overall_score) {\n                    best_task_overall_score = current_task_score;\n                    best_pick_pos_for_task = c_pos;\n                    best_item_id_for_task = C;\n                }\n            };\n\n            // Task search priorities (lowest multiplier is highest priority)\n\n            // Option 1: Pick up 'next_dispatch_val' (Priority 0)\n            for (int i = 0; i < N; ++i) {\n                int C = current_state.next_dispatch_val[i];\n                if (current_state.container_locations.count(C) && current_state.container_locations[C].r != -1) { \n                    Pos c_pos = current_state.container_locations[C];\n                    if (c_pos.r == i && c_pos.c == N - 1) continue; \n                    if (!current_state.cranes[k].is_large && c_pos.r != k) continue; \n                    \n                    evaluate_task(C, c_pos, 0); \n                }\n            }\n            \n            // Option 2: LARGE CRANE ONLY: Clear Blocked Mid-Row Drop-off for Small Crane (Priority 1)\n            if (current_state.cranes[k].is_large) { \n                for (int r = 0; r < N; ++r) {\n                    Pos drop_pos = {r, N/2};\n                    if (current_state.board[drop_pos.r][drop_pos.c] != -1) { \n                        int C_blocker = current_state.board[drop_pos.r][drop_pos.c];\n                        bool small_crane_needs_drop_off = false;\n                        for (int j = 1; j < N; ++j) { \n                            if (!current_state.cranes[j].is_bombed && \n                                current_state.cranes[j].holding_container_id != -1 &&\n                                current_state.cranes[j].pos.r == r && \n                                current_state.cranes[j].holding_container_id / N != r) { \n                                small_crane_needs_drop_off = true;\n                                break;\n                            }\n                        }\n                        if (small_crane_needs_drop_off) {\n                            evaluate_task(C_blocker, drop_pos, 1); \n                        }\n                    }\n                }\n            }\n\n            // Option 3: Clear receiving gate (row i, col 0) (Priority 2)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.incoming_idx[i] < N && current_state.board[i][0] != -1) {\n                    int C = current_state.board[i][0];\n                    if (!current_state.cranes[k].is_large && i != k) continue; \n                    \n                    evaluate_task(C, {i,0}, 2); \n                }\n            }\n\n            // Option 4: Clear dispatch gate (row i, col N-1) (Priority 3)\n            for (int i = 0; i < N; ++i) {\n                if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] != current_state.next_dispatch_val[i]) {\n                    int C = current_state.board[i][N-1];\n                    if (!current_state.cranes[k].is_large && i != k) continue; \n                    \n                    evaluate_task(C, {i,N-1}, 3); \n                }\n            }\n            \n            // Option 5: Move container to its staging area (row, N-2) if in correct row but too far left (Priority 4)\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N-2; ++c) { \n                    int C = current_state.board[r][c];\n                    if (C != -1 && C/N == r && C != current_state.next_dispatch_val[r]) {\n                        if (!current_state.cranes[k].is_large && r != k) continue;\n\n                        evaluate_task(C, {r,c}, 4); \n                    }\n                }\n            }\n\n            // Option 6: Move container to its row's middle column (C/N, N/2) - for cross-row moves (Large crane only). (Priority 5)\n            if (current_state.cranes[k].is_large) { \n                for (int r = 0; r < N; ++r) {\n                    for (int c = 0; c < N; ++c) {\n                        int C = current_state.board[r][c];\n                        if (C != -1 && C/N != r) { \n                            evaluate_task(C, {r,c}, 5); \n                        }\n                    }\n                }\n            }\n\n            // Execute the chosen task\n            if (best_task_overall_score != (long long)MAX_TURNS * (N * N + 1)) { // A viable task was found\n                if (crane_curr_pos == best_pick_pos_for_task) {\n                    current_turn_actions_char[k] = 'P';\n                    target_next_crane_holding_planned[k] = best_item_id_for_task;\n                    current_state.container_locations[best_item_id_for_task] = {-1,-1}; \n                } else {\n                    int cost;\n                    Pos dir_from_bfs = get_next_step(current_state, k, crane_curr_pos, best_pick_pos_for_task, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) { \n                        current_turn_actions_char[k] = get_dir_char(dir_from_bfs.r, dir_from_bfs.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir_from_bfs.r, crane_curr_pos.c + dir_from_bfs.c};\n                    } else {\n                        current_turn_actions_char[k] = '.'; \n                    }\n                }\n            } else { // No urgent task, move to a parking spot\n                Pos parking_pos = current_state.cranes[k].is_large ? Pos{0, N/2} : Pos{k, 1}; \n                if (crane_curr_pos == parking_pos) {\n                    current_turn_actions_char[k] = '.';\n                } else {\n                    int cost;\n                    Pos dir = get_next_step(current_state, k, crane_curr_pos, parking_pos, false, current_state.cranes[k].is_large, other_crane_current_pos_snapshot, target_next_crane_pos_planned, cost);\n                    if (cost != -1) {\n                        current_turn_actions_char[k] = get_dir_char(dir.r, dir.c);\n                        target_next_crane_pos_planned[k] = {crane_curr_pos.r + dir.r, crane_curr_pos.c + dir.c};\n                    } else {\n                        current_turn_actions_char[k] = '.';\n                    }\n                }\n            }\n        }\n\n        // Apply all planned actions simultaneously\n        for (int k = 0; k < N; ++k) {\n            if (current_state.cranes[k].is_bombed) continue;\n\n            char action = current_turn_actions_char[k];\n            all_crane_actions[k] += action;\n\n            if (action == 'P') {\n                int container_id = current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c];\n                current_state.cranes[k].holding_container_id = container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = -1;\n            } else if (action == 'Q') {\n                int container_id = current_state.cranes[k].holding_container_id;\n                current_state.board[current_state.cranes[k].pos.r][current_state.cranes[k].pos.c] = container_id;\n                current_state.cranes[k].holding_container_id = -1;\n                current_state.container_locations[container_id] = current_state.cranes[k].pos; // Container back on board\n            } else if (action == 'U' || action == 'D' || action == 'L' || action == 'R') {\n                current_state.cranes[k].pos = target_next_crane_pos_planned[k];\n            }\n        }\n        \n        // 3. Dispatch containers\n        for (int i = 0; i < N; ++i) {\n            if (current_state.board[i][N-1] != -1 && current_state.board[i][N-1] == current_state.next_dispatch_val[i]) {\n                int dispatched_id = current_state.board[i][N-1];\n                current_state.board[i][N-1] = -1;\n                current_state.container_locations.erase(dispatched_id); // Container removed from the game\n                current_state.next_dispatch_val[i]++; // Advance expectation for this gate\n                dispatched_count++;\n            }\n        }\n    }\n\n    // Output results\n    for (int i = 0; i < N; ++i) {\n        cout << all_crane_actions[i] << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <limits> // Required for std::numeric_limits\n\n// N is fixed at 20 for this problem\nconst int N = 20;\n\n// Global variables to store the current state\nint H[N][N]; // Current heights of the grid cells\nint current_r = 0; // Current row of the dump truck\nint current_c = 0; // Current column of the dump truck\nlong long truck_load = 0; // Current amount of soil loaded on the truck\nstd::vector<std::string> ops; // Stores the sequence of operations\n\n// Calculates Manhattan distance between two cells\nlong long manhattan_dist(int r1, int c1, int r2, int c2) {\n    return std::abs(r1 - r2) + std::abs(c1 - c2);\n}\n\n// Moves the truck to the target coordinates and records the movement operations\nvoid move_truck_to(int target_r, int target_c) {\n    while (current_r < target_r) {\n        ops.push_back(\"D\");\n        current_r++;\n    }\n    while (current_r > target_r) {\n        ops.push_back(\"U\");\n        current_r--;\n    }\n    while (current_c < target_c) {\n        ops.push_back(\"R\");\n        current_c++;\n    }\n    while (current_c > target_c) {\n        ops.push_back(\"L\");\n        current_c--;\n    }\n}\n\n// Structure to hold cell coordinates and a calculated distance, used for sorting candidates\nstruct CandidateCell {\n    int r, c;\n    long long dist;\n\n    // Operator< for sorting by distance\n    bool operator<(const CandidateCell& other) const {\n        return dist < other.dist;\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int dummy_N; // Read N, but it's fixed at 20\n    std::cin >> dummy_N;\n\n    long long total_initial_positive_soil = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            std::cin >> H[i][j];\n            if (H[i][j] > 0) {\n                total_initial_positive_soil += H[i][j];\n            }\n        }\n    }\n\n    long long soil_moved_to_level_sinks = 0; // Tracks the total soil moved to fulfill negative heights\n    const int K_CANDIDATES = 30; // Increased number of closest sources/sinks to consider (from 20 to 30)\n\n    // Timer for execution time limit\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; // Use 1.9 seconds to be safe (total limit is 2.0 sec)\n\n    // Main loop: continues until all soil is leveled or operation/time limits are reached\n    while (soil_moved_to_level_sinks < total_initial_positive_soil) {\n        if (ops.size() >= 99000) { // Max 100000 turns, stop early to avoid exceeding\n            break;\n        }\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > TIME_LIMIT_MS) {\n            break;\n        }\n\n        std::vector<CandidateCell> all_sources; // List of all cells with H > 0\n        std::vector<CandidateCell> all_sinks;   // List of all cells with H < 0\n\n        // Populate sources and sinks lists\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (H[i][j] > 0) {\n                    // For sources, calculate distance from current truck position\n                    all_sources.push_back({i, j, manhattan_dist(current_r, current_c, i, j)});\n                } else if (H[i][j] < 0) {\n                    all_sinks.push_back({i, j, 0}); // Distance for sinks will be calculated later from a potential source\n                }\n            }\n        }\n\n        // If no sources or sinks remain, the leveling is complete (or stuck)\n        if (all_sources.empty() || all_sinks.empty()) {\n            break;\n        }\n\n        // Partially sort sources by their distance from the current truck position\n        int num_source_candidates_to_process = std::min((int)all_sources.size(), K_CANDIDATES);\n        if (num_source_candidates_to_process > 0) {\n            std::partial_sort(all_sources.begin(), all_sources.begin() + num_source_candidates_to_process, all_sources.end());\n        }\n\n        // Variables to track the best transfer based on MINIMUM ABSOLUTE TOTAL COST\n        long long min_total_cost = std::numeric_limits<long long>::max(); \n\n        int best_sr = -1, best_sc = -1, best_dr = -1, best_dc = -1; // Coordinates of the best source/sink\n        long long best_D_value = 0; // Amount of soil for the best transfer\n\n        // Iterate through a limited number of closest source candidates\n        for (int i = 0; i < num_source_candidates_to_process; ++i) {\n            int sr = all_sources[i].r;\n            int sc = all_sources[i].c;\n\n            // Create a temporary list of sinks, calculating their distance from the current source candidate\n            std::vector<CandidateCell> current_sink_candidates;\n            for (const auto& sink : all_sinks) {\n                current_sink_candidates.push_back({sink.r, sink.c, manhattan_dist(sr, sc, sink.r, sink.c)});\n            }\n            \n            // Partially sort these sinks by their distance from the current source candidate\n            int num_sink_candidates_to_process = std::min((int)current_sink_candidates.size(), K_CANDIDATES);\n            if (num_sink_candidates_to_process > 0) {\n                std::partial_sort(current_sink_candidates.begin(), current_sink_candidates.begin() + num_sink_candidates_to_process, current_sink_candidates.end());\n            }\n\n            // Iterate through a limited number of closest sink candidates for this source\n            for (int j = 0; j < num_sink_candidates_to_process; ++j) {\n                int dr = current_sink_candidates[j].r;\n                int dc = current_sink_candidates[j].c;\n\n                // Calculate the amount of soil to transfer: min of available at source and needed at sink\n                long long D = std::min((long long)H[sr][sc], -(long long)H[dr][dc]);\n                if (D <= 0) continue; // No actual transfer possible\n\n                // Calculate the total cost for this specific (source, sink, amount) transfer\n                long long cost_to_source = manhattan_dist(current_r, current_c, sr, sc) * 100LL;\n                long long cost_source_to_sink = manhattan_dist(sr, sc, dr, dc) * (100LL + D);\n                long long current_total_cost = cost_to_source + cost_source_to_sink + 2LL * D;\n\n                // Update if this transfer is cheaper based on MINIMUM ABSOLUTE TOTAL COST\n                if (current_total_cost < min_total_cost) {\n                    min_total_cost = current_total_cost;\n                    best_sr = sr; best_sc = sc;\n                    best_dr = dr; best_dc = dc;\n                    best_D_value = D;\n                }\n            }\n        }\n\n        // If no valid transfer was found in this iteration (min_total_cost is still its initial max value), break the loop\n        if (min_total_cost == std::numeric_limits<long long>::max()) {\n            break;\n        }\n\n        // Execute the operations for the chosen best transfer\n        \n        // 1. Move truck to the best source\n        move_truck_to(best_sr, best_sc);\n        \n        // 2. Load soil\n        ops.push_back(\"+\" + std::to_string(best_D_value));\n        truck_load += best_D_value;\n        H[best_sr][best_sc] -= best_D_value; // Update source cell's height\n        \n        // 3. Move truck to the best sink\n        move_truck_to(best_dr, best_dc);\n        \n        // 4. Unload soil\n        ops.push_back(\"-\" + std::to_string(best_D_value));\n        truck_load -= best_D_value;\n        H[best_dr][best_dc] += best_D_value; // Update sink cell's height\n        soil_moved_to_level_sinks += best_D_value; // Increment total soil leveled\n    }\n\n    // Output all recorded operations\n    for (const std::string& op : ops) {\n        std::cout << op << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip> // For std::fixed and std::setprecision\n#include <cmath>   // For std::exp\n\n// --- Global variables for N, M, T and X_seeds ---\nint N_global, M_global, T_global;\nstd::vector<std::vector<int>> X_seeds_global; // Current seeds available for planting\nstd::vector<int> initial_X_max_global;       // Max value for each criterion from initial seeds\n\n// --- RNG ---\n// Use std::mt19937_64 for potentially better randomness and larger range.\nstd::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// --- Helper function to calculate potential for a pair ---\n// Returns the sum of max values for each criterion between two seeds.\n// seed_idx1 and seed_idx2 are indices into X_seeds_global.\nlong long calculate_pair_potential(int seed_idx1, int seed_idx2) {\n    long long potential = 0;\n    for (int l = 0; l < M_global; ++l) {\n        potential += std::max(X_seeds_global[seed_idx1][l], X_seeds_global[seed_idx2][l]);\n    }\n    return potential;\n}\n\n// --- Helper function to get adjacent coordinates ---\n// Returns a vector of {row, col} pairs for direct neighbors of (r, c).\n// For N=6, this will return at most 4 pairs.\nstd::vector<std::pair<int, int>> get_adjacent_coords(int r, int c) {\n    std::vector<std::pair<int, int>> adj;\n    adj.reserve(4); // Reserve capacity to avoid reallocations, N is small and fixed\n    int dr[] = {-1, 1, 0, 0}; // Up, Down, Left, Right\n    int dc[] = {0, 0, -1, 1};\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_global && nc >= 0 && nc < N_global) {\n            adj.push_back({nr, nc});\n        }\n    }\n    return adj;\n}\n\n// --- Function to calculate total score for a grid configuration ---\n// Sum of potential values for all adjacent pairs in the grid.\nlong long calculate_grid_score(const std::vector<std::vector<int>>& A) {\n    long long total_score = 0;\n    // Horizontal adjacencies\n    for (int i = 0; i < N_global; ++i) {\n        for (int j = 0; j < N_global - 1; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i][j+1]);\n        }\n    }\n    // Vertical adjacencies\n    for (int i = 0; i < N_global - 1; ++i) {\n        for (int j = 0; j < N_global; ++j) {\n            total_score += calculate_pair_potential(A[i][j], A[i+1][j]);\n        }\n    }\n    return total_score;\n}\n\nvoid solve() {\n    std::cin >> N_global >> M_global >> T_global;\n\n    int seed_count = 2 * N_global * (N_global - 1); // For N=6, this is 2*6*5 = 60 seeds\n    X_seeds_global.resize(seed_count, std::vector<int>(M_global));\n    initial_X_max_global.resize(M_global, 0);\n\n    // Read initial seeds and compute initial_X_max_global\n    for (int i = 0; i < seed_count; ++i) {\n        for (int j = 0; j < M_global; ++j) {\n            std::cin >> X_seeds_global[i][j];\n            initial_X_max_global[j] = std::max(initial_X_max_global[j], X_seeds_global[i][j]);\n        }\n    }\n\n    // Main simulation loop for T turns\n    for (int turn = 0; turn < T_global; ++turn) {\n        // TUNING: Reverted alpha_value back to 300LL, as it previously yielded the highest total score.\n        // This value seems to strike the best balance for seed selection.\n        long long alpha_value = 300LL; \n        \n        // 1. Select seeds for planting:\n        // Calculate a combined score for all current seeds and pick the top N*N.\n        // The combined score considers V_k + a bonus for carrying initial global max traits.\n        std::vector<std::pair<long long, int>> seed_scores(seed_count); // {combined_score, seed_idx}\n        for (int i = 0; i < seed_count; ++i) {\n            long long current_Vk = 0;\n            int trait_count = 0;\n            for (int l = 0; l < M_global; ++l) {\n                current_Vk += X_seeds_global[i][l];\n                if (X_seeds_global[i][l] == initial_X_max_global[l]) {\n                    trait_count++;\n                }\n            }\n            long long combined_score = current_Vk + alpha_value * trait_count; \n            seed_scores[i] = {combined_score, i};\n        }\n        std::sort(seed_scores.rbegin(), seed_scores.rend()); // Sort descending by combined_score\n\n        std::vector<int> selected_seeds_indices(N_global * N_global); // N*N = 36 seeds\n        for (int i = 0; i < N_global * N_global; ++i) {\n            selected_seeds_indices[i] = seed_scores[i].second;\n        }\n\n        // 2. Determine placement using Simulated Annealing\n        std::vector<std::vector<int>> current_A(N_global, std::vector<int>(N_global));\n        \n        // Initial placement for SA: random permutation of selected seeds\n        std::shuffle(selected_seeds_indices.begin(), selected_seeds_indices.end(), rng);\n        int k_idx = 0;\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                current_A[i][j] = selected_seeds_indices[k_idx++];\n            }\n        }\n\n        long long current_score = calculate_grid_score(current_A);\n        std::vector<std::vector<int>> best_A = current_A;\n        long long best_score = current_score;\n\n        // SA parameters (tuned for AHC035 constraints)\n        double start_temp = 30000.0; \n        double end_temp = 50.0;    \n        long long max_iterations = 250000; // Safety upper bound, time budget is primary control\n        \n        // TUNING: Maintained time_budget at 190ms to allow more SA iterations per turn,\n        // which helps in exploring the search space more thoroughly.\n        auto start_time = std::chrono::high_resolution_clock::now();\n        std::chrono::milliseconds time_budget(190); \n\n        std::uniform_real_distribution<double> dist_prob(0.0, 1.0);\n        std::uniform_int_distribution<int> dist_rc(0, N_global - 1); // For random row/col\n\n        for (long long iter = 0; iter < max_iterations; ++iter) {\n            // Check time budget\n            auto current_time = std::chrono::high_resolution_clock::now();\n            if (std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time) > time_budget) {\n                break; \n            }\n\n            // Calculate current temperature with exponential decay\n            double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / max_iterations);\n\n            // Pick two random distinct cells to swap\n            int r1 = dist_rc(rng);\n            int c1 = dist_rc(rng);\n            int r2 = dist_rc(rng);\n            int c2 = dist_rc(rng);\n            while (r1 == r2 && c1 == c2) { // Ensure distinct cells\n                r2 = dist_rc(rng);\n                c2 = dist_rc(rng);\n            }\n\n            int seed1_idx = current_A[r1][c1]; // Original seed at (r1,c1)\n            int seed2_idx = current_A[r2][c2]; // Original seed at (r2,c2)\n\n            // Calculate change in score (delta_score) efficiently\n            long long old_adj_contrib = 0;\n            std::vector<std::pair<int, int>> neighbors_r1c1 = get_adjacent_coords(r1, c1);\n            std::vector<std::pair<int, int>> neighbors_r2c2 = get_adjacent_coords(r2, c2);\n\n            for (auto p : neighbors_r1c1) {\n                // If the other swapped cell is a neighbor, exclude it.\n                // The direct edge contribution (P(seed1, seed2)) is symmetric and\n                // does not change when the seeds are swapped, so it's not part of delta_score calculation.\n                if (!(p.first == r2 && p.second == c2)) { \n                    old_adj_contrib += calculate_pair_potential(seed1_idx, current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    old_adj_contrib += calculate_pair_potential(seed2_idx, current_A[p.first][p.second]);\n                }\n            }\n\n            // Temporarily perform the swap\n            current_A[r1][c1] = seed2_idx;\n            current_A[r2][c2] = seed1_idx;\n\n            long long new_adj_contrib = 0;\n            for (auto p : neighbors_r1c1) {\n                if (!(p.first == r2 && p.second == c2)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r1][c1], current_A[p.first][p.second]);\n                }\n            }\n            for (auto p : neighbors_r2c2) {\n                if (!(p.first == r1 && p.second == c1)) { \n                    new_adj_contrib += calculate_pair_potential(current_A[r2][c2], current_A[p.first][p.second]);\n                }\n            }\n            \n            long long delta_score = new_adj_contrib - old_adj_contrib;\n            long long new_score = current_score + delta_score;\n\n            // Metropolis criterion for acceptance\n            if (new_score > current_score || dist_prob(rng) < std::exp(static_cast<double>(new_score - current_score) / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_A = current_A;\n                }\n            } else {\n                // Revert the swap if not accepted\n                current_A[r1][c1] = seed1_idx;\n                current_A[r2][c2] = seed2_idx;\n            }\n        }\n        \n        // Output the best placement found for this turn\n        for (int i = 0; i < N_global; ++i) {\n            for (int j = 0; j < N_global; ++j) {\n                std::cout << best_A[i][j];\n                if (j < N_global - 1) {\n                    std::cout << \" \";\n                } else {\n                    std::cout << std::endl;\n                }\n            }\n        }\n        std::cout.flush(); // Flush output to interactive judge\n\n        // 3. Read the new seeds for the next turn\n        for (int i = 0; i < seed_count; ++i) {\n            for (int j = 0; j < M_global; ++j) {\n                std::cin >> X_seeds_global[i][j];\n            }\n        }\n    }\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n    \n    solve();\n    \n    return 0;\n}\n","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set> // No longer used for main data, but keeping for possible local use if needed\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n// #include <map> // Not used\n\nusing namespace std;\n\n// Global variables for grid and problem parameters\nint N, M, V_MAX;\n\n// Optimized grid representation for O(1) lookups\nvector<vector<bool>> grid_has_takoyaki; // true if takoyaki at (i,j)\nvector<vector<bool>> grid_is_target_empty; // true if (i,j) is a target and needs takoyaki\n\n// Global sums and counts for O(1) centroid calculation\nlong long s_sum_x = 0, s_sum_y = 0;\nint s_count = 0;\nlong long t_sum_x = 0, t_sum_y = 0;\nint t_count = 0;\n\n// Robotic arm state\nstruct Vec2 {\n    int x, y; // x for row, y for col\n    Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }\n    Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }\n    long long dist_sq(const Vec2& other) const { return 1LL * (x - other.x) * (x - other.x) + 1LL * (y - other.y) * (y - other.y); }\n    bool operator==(const Vec2& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator<(const Vec2& other) const { // For use in sets/maps if needed, though pair<int,int> is typical\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n};\n\nVec2 root_pos;\nvector<Vec2> rel_vecs; // relative position of vertex u to its parent p_u\nvector<int> orient_idx; // 0:right, 1:down, 2:left, 3:up (problem's definition)\n\n// For positions calculation\nvector<Vec2> abs_pos;\nvector<bool> is_fingertip;\nvector<int> parent_map; // parent_map[u] gives parent of u\nvector<int> L_map; // L_map[u] gives length of (parent[u], u)\n\nvector<bool> fingertip_holding; // Whether each fingertip is holding a takoyaki\n\n// PROBLEM_REL_DX, PROBLEM_REL_DY for cardinal directions (0:R, 1:D, 2:L, 3:U)\n// These define the (row_diff, col_diff) for a segment pointing in that direction.\n// R: (0,1)\n// D: (1,0)\n// L: (0,-1)\n// U: (-1,0)\nconst int PROBLEM_REL_DX[] = {0, 1, 0, -1}; \nconst int PROBLEM_REL_DY[] = {1, 0, -1, 0};\n\n// Rotate a vector (dr, dc) 90 degrees clockwise (dr -> dc, dc -> -dr)\nVec2 rotate_cw_problem(const Vec2& v) { return {v.y, -v.x}; }\n// Rotate a vector (dr, dc) 90 degrees counter-clockwise (dr -> -dc, dc -> dr)\nVec2 rotate_ccw_problem(const Vec2& v) { return {-v.y, v.x}; }\n\n// Check if a coordinate is within grid boundaries\nbool is_valid_coord(const Vec2& p) {\n    return p.x >= 0 && p.x < N && p.y >= 0 && p.y < N;\n}\n\n// Update absolute positions of all vertices\nvoid update_abs_pos_global() {\n    abs_pos[0] = root_pos;\n    for (size_t i = 1; i < abs_pos.size(); ++i) {\n        abs_pos[i] = abs_pos[parent_map[i]] + rel_vecs[i];\n    }\n}\n\n// Calculate centroid from global sums and counts (O(1) operation)\nVec2 calculate_centroid_fast(long long sum_x_val, long long sum_y_val, int count_val) {\n    if (count_val == 0) {\n        return {-1, -1}; // Invalid centroid\n    }\n    return {(int)round((double)sum_x_val / count_val), (int)round((double)sum_y_val / count_val)};\n}\n\n// Struct to represent a potential action for a fingertip\nstruct Action {\n    int fingertip_id;\n    int direction; // Direction the fingertip would point in\n    Vec2 cell_coord; // The actual cell (source or target) it would interact with\n    bool is_place; // True if placing, false if picking\n    int score_gain; // The score value this action provides\n};\n\n// Evaluates a potential root position based on immediate picks/places\n// Returns a score: higher is better.\nint evaluate_root_move(int V_prime, const Vec2& test_root_pos) {\n    int score = 0;\n    \n    vector<Action> possible_actions;\n\n    // Identify all possible individual actions for all fingertips\n    for (int u = 1; u < V_prime; ++u) { // Iterate fingertips (vertices 1 to V_prime-1)\n        if (fingertip_holding[u]) { // If holding, look for places\n            for (int d = 0; d < 4; ++d) {\n                Vec2 target_cell = test_root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                if (is_valid_coord(target_cell) && grid_is_target_empty[target_cell.x][target_cell.y]) {\n                    possible_actions.push_back({u, d, target_cell, true, 2}); // Weight 2 for placing\n                }\n            }\n        } else { // If not holding, look for picks\n            for (int d = 0; d < 4; ++d) {\n                Vec2 source_cell = test_root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                if (is_valid_coord(source_cell) && grid_has_takoyaki[source_cell.x][source_cell.y]) {\n                    possible_actions.push_back({u, d, source_cell, false, 1}); // Weight 1 for picking\n                }\n            }\n        }\n    }\n\n    // Sort actions by score_gain (descending) to prioritize higher value actions (placing over picking)\n    // For actions with same score_gain, secondary sorting by fingertip_id ensures deterministic tie-breaking.\n    sort(possible_actions.begin(), possible_actions.end(), [](const Action& a, const Action& b) {\n        if (a.score_gain != b.score_gain) return a.score_gain > b.score_gain;\n        return a.fingertip_id < b.fingertip_id; \n    });\n\n    vector<bool> fingertip_assigned(V_prime, false); // Tracks if a fingertip is assigned an action\n    vector<vector<bool>> occupied_cells_map(N, vector<bool>(N, false)); // Tracks cells that are claimed by an action to prevent double-targeting\n\n    // Greedily apply actions from the sorted list\n    for (const auto& action : possible_actions) {\n        // If the fingertip is not yet assigned AND the target cell is not yet claimed\n        if (!fingertip_assigned[action.fingertip_id] && \n            !occupied_cells_map[action.cell_coord.x][action.cell_coord.y]) {\n            \n            score += action.score_gain;\n            fingertip_assigned[action.fingertip_id] = true;\n            occupied_cells_map[action.cell_coord.x][action.cell_coord.y] = true;\n        }\n    }\n\n    return score;\n}\n\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> M >> V_MAX;\n\n    grid_has_takoyaki.assign(N, vector<bool>(N, false));\n    grid_is_target_empty.assign(N, vector<bool>(N, false));\n\n    // Read initial takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                grid_has_takoyaki[i][j] = true;\n                s_sum_x += i;\n                s_sum_y += j;\n                s_count++;\n            }\n        }\n    }\n\n    // Read target takoyaki positions\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            if (row[j] == '1') {\n                grid_is_target_empty[i][j] = true; // Initially all target squares are empty, assuming no takoyaki is there\n                t_sum_x += i;\n                t_sum_y += j;\n                t_count++;\n            }\n        }\n    }\n\n    // Adjust grid_has_takoyaki and grid_is_target_empty by removing already satisfied takoyaki\n    // If a target square (i,j) initially has a takoyaki, then it's satisfied.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid_has_takoyaki[i][j] && grid_is_target_empty[i][j]) {\n                grid_has_takoyaki[i][j] = false; // Takoyaki removed from source\n                s_sum_x -= i; s_sum_y -= j; s_count--;\n\n                grid_is_target_empty[i][j] = false; // Target filled\n                t_sum_x -= i; t_sum_y -= j; t_count--;\n            }\n        }\n    }\n\n    // Design the robotic arm (V' = V_MAX, star graph with varied edge lengths)\n    int V_prime = V_MAX; // Number of vertices in the arm\n    cout << V_prime << endl;\n\n    parent_map.resize(V_prime);\n    L_map.resize(V_prime);\n    is_fingertip.resize(V_prime, false);\n    \n    // Root is 0. Children 1 to V_prime-1 are fingertips.\n    for (int u = 1; u < V_prime; ++u) {\n        // Parent of u is 0. Varied length (u-1)/2 + 1\n        int length = (u - 1) / 2 + 1;\n        // Clamp length to N-1 (max 29) to be safe, although for V_MAX=15, max length is 7.\n        if (length > N - 1) length = N - 1; \n        cout << 0 << \" \" << length << endl;\n        parent_map[u] = 0;\n        L_map[u] = length; \n        is_fingertip[u] = true;\n    }\n\n    // Initial root position (center of the grid)\n    root_pos = {N / 2, N / 2};\n    cout << root_pos.x << \" \" << root_pos.y << endl;\n\n    // Initialize arm state\n    abs_pos.resize(V_prime);\n    rel_vecs.resize(V_prime);\n    orient_idx.resize(V_prime, 0); // All edges initially point right (direction 0)\n\n    for (int u = 1; u < V_prime; ++u) {\n        rel_vecs[u] = {L_map[u] * PROBLEM_REL_DX[0], L_map[u] * PROBLEM_REL_DY[0]}; // (L,0) for parent-child edge\n    }\n\n    fingertip_holding.resize(V_prime, false); // No fingertip holds takoyaki initially\n\n    // Operation loop\n    for (int turn = 0; turn < 100000; ++turn) {\n        if (t_count == 0) { // Check count of remaining target spots\n            break; // All takoyaki delivered\n        }\n\n        // 1. Determine root movement\n        char best_root_move_char = '.';\n        Vec2 next_root_pos_candidate = root_pos;\n        int max_eval_score = -1; \n\n        // Options for root movement (., U, D, L, R)\n        vector<pair<char, Vec2>> move_options;\n        move_options.push_back({'.', root_pos}); // No move\n        if (root_pos.x - 1 >= 0) move_options.push_back({'U', {root_pos.x - 1, root_pos.y}});\n        if (root_pos.x + 1 < N) move_options.push_back({'D', {root_pos.x + 1, root_pos.y}});\n        if (root_pos.y - 1 >= 0) move_options.push_back({'L', {root_pos.x, root_pos.y - 1}});\n        if (root_pos.y + 1 < N) move_options.push_back({'R', {root_pos.x, root_pos.y + 1}});\n\n        // Calculate a general centroid for tie-breaking in root movement (O(1) now)\n        Vec2 overall_centroid = {-1, -1};\n        int holding_takoyaki_fingertips_count = 0;\n        for(int u = 0; u < V_prime; ++u) {\n            if (is_fingertip[u] && fingertip_holding[u]) holding_takoyaki_fingertips_count++;\n        }\n        \n        if (holding_takoyaki_fingertips_count > 0) {\n            overall_centroid = calculate_centroid_fast(t_sum_x, t_sum_y, t_count);\n        } else {\n            overall_centroid = calculate_centroid_fast(s_sum_x, s_sum_y, s_count);\n        }\n\n        // Evaluate each move option\n        for (const auto& option : move_options) {\n            char move_char = option.first;\n            Vec2 test_pos = option.second;\n            int current_eval_score = evaluate_root_move(V_prime, test_pos);\n\n            // Tie-breaking:\n            // 1. Higher immediate score is always better.\n            // 2. If scores are equal, prefer no movement ('.').\n            // 3. If scores are equal and neither is '.', prefer closer to overall centroid.\n            if (current_eval_score > max_eval_score) {\n                max_eval_score = current_eval_score;\n                best_root_move_char = move_char;\n                next_root_pos_candidate = test_pos;\n            } else if (current_eval_score == max_eval_score) {\n                if (best_root_move_char != '.' && move_char == '.') {\n                    // This case should be handled by `max_eval_score` already being the max,\n                    // but we explicitly pick '.' if available and score is equal.\n                    best_root_move_char = move_char;\n                    next_root_pos_candidate = test_pos;\n                } else if (overall_centroid.x != -1 && move_char != '.') { // If centroid is valid and not moving\n                    // Prefer move that gets closer to the centroid\n                    if (test_pos.dist_sq(overall_centroid) < next_root_pos_candidate.dist_sq(overall_centroid)) {\n                         best_root_move_char = move_char;\n                         next_root_pos_candidate = test_pos;\n                    }\n                }\n            }\n        }\n        \n        root_pos = next_root_pos_candidate; // Apply chosen root movement\n        string command_root_move_str(1, best_root_move_char);\n        \n        // Update positions after root move (needed for rotation logic)\n        update_abs_pos_global();\n\n        // 2. Determine rotations\n        string command_rotations_str(V_prime - 1, '.'); // For non-root vertices (1 to V_prime-1)\n        \n        // This time, we re-evaluate and apply rotations based on the *actual* new root_pos\n        // and current global state. This makes sure the decisions are up-to-date.\n        vector<int> desired_orient_idx(V_prime, -1); \n\n        // Use a 2D bool array to track cells claimed by a fingertip's desired rotation for this turn\n        vector<vector<bool>> cells_claimed_by_rotation(N, vector<bool>(N, false)); \n\n        // Prioritize placing takoyaki\n        // Loop through fingertips (in increasing ID order for determinism)\n        for (int u = 1; u < V_prime; ++u) { \n            if (is_fingertip[u] && fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                for (int d = 0; d < 4; ++d) { \n                    Vec2 target_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                    if (is_valid_coord(target_cell) && grid_is_target_empty[target_cell.x][target_cell.y] && \n                        !cells_claimed_by_rotation[target_cell.x][target_cell.y]) {\n                        desired_orient_idx[u] = d;\n                        cells_claimed_by_rotation[target_cell.x][target_cell.y] = true;\n                        break; // Found a target for this fingertip\n                    }\n                }\n            }\n        }\n\n        // Then assign empty fingertips to source squares\n        // Loop through fingertips (in increasing ID order for determinism)\n        for (int u = 1; u < V_prime; ++u) { \n            if (is_fingertip[u] && !fingertip_holding[u] && desired_orient_idx[u] == -1) {\n                for (int d = 0; d < 4; ++d) { \n                    Vec2 source_cell = root_pos + Vec2{PROBLEM_REL_DX[d] * L_map[u], PROBLEM_REL_DY[d] * L_map[u]};\n                    if (is_valid_coord(source_cell) && grid_has_takoyaki[source_cell.x][source_cell.y] &&\n                        !cells_claimed_by_rotation[source_cell.x][source_cell.y]) {\n                        desired_orient_idx[u] = d;\n                        cells_claimed_by_rotation[source_cell.x][source_cell.y] = true;\n                        break; // Found a source for this fingertip\n                    }\n                }\n            }\n        }\n        \n        // Apply rotations based on desired_orient_idx\n        for (int u = 1; u < V_prime; ++u) { // Only non-root vertices can rotate (fingertips in this design)\n            if (desired_orient_idx[u] != -1) {\n                int current_d = orient_idx[u];\n                int target_d = desired_orient_idx[u];\n\n                if (current_d == target_d) {\n                    command_rotations_str[u - 1] = '.'; \n                } else {\n                    int cw_diff = (target_d - current_d + 4) % 4; // Number of CW 90-deg turns\n                    int ccw_diff = (current_d - target_d + 4) % 4; // Number of CCW 90-deg turns\n\n                    if (cw_diff == 1) { // 90 deg CW\n                        command_rotations_str[u - 1] = 'R';\n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    } else if (ccw_diff == 1) { // 90 deg CCW\n                        command_rotations_str[u - 1] = 'L';\n                        orient_idx[u] = (orient_idx[u] + 3) % 4;\n                        rel_vecs[u] = rotate_ccw_problem(rel_vecs[u]);\n                    } else { // 180 deg (cw_diff == 2), takes 2 turns. Take one step (arbitrarily CW).\n                        command_rotations_str[u - 1] = 'R'; \n                        orient_idx[u] = (orient_idx[u] + 1) % 4;\n                        rel_vecs[u] = rotate_cw_problem(rel_vecs[u]);\n                    }\n                }\n            } else {\n                command_rotations_str[u - 1] = '.'; // No specific target, no rotation\n            }\n        }\n        \n        // Update positions after rotations\n        update_abs_pos_global();\n\n        // 3. Determine grab/release actions\n        string command_P_actions_part(V_prime, '.'); \n        \n        // A 2D array to track cells where takoyaki are placed/picked up in this turn,\n        // to prevent multiple fingertips from targeting the same cell.\n        vector<vector<bool>> cells_acted_on_this_turn(N, vector<bool>(N, false)); \n\n        // Process fingertips in order of ID (1 to V_prime-1) as problem states vertex order.\n        // Vertex 0 (root) is not a fingertip, so command_P_actions_part[0] remains '.'\n        for (int u = 1; u < V_prime; ++u) { \n            Vec2 current_tip_pos = abs_pos[u];\n\n            // Check if fingertip is within grid boundaries\n            if (!is_valid_coord(current_tip_pos)) {\n                continue; \n            }\n\n            if (fingertip_holding[u]) { // If currently holding a takoyaki\n                if (grid_is_target_empty[current_tip_pos.x][current_tip_pos.y] && \n                    !cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y]) {\n                    // Place takoyaki on target square\n                    command_P_actions_part[u] = 'P'; \n                    grid_is_target_empty[current_tip_pos.x][current_tip_pos.y] = false; // Target filled\n                    t_sum_x -= current_tip_pos.x; t_sum_y -= current_tip_pos.y; t_count--;\n                    fingertip_holding[u] = false;\n                    cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y] = true;\n                }\n            } else { // If not holding a takoyaki\n                if (grid_has_takoyaki[current_tip_pos.x][current_tip_pos.y] &&\n                    !cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y]) {\n                    // Pick up takoyaki from source square\n                    command_P_actions_part[u] = 'P';\n                    grid_has_takoyaki[current_tip_pos.x][current_tip_pos.y] = false; // Takoyaki picked\n                    s_sum_x -= current_tip_pos.x; s_sum_y -= current_tip_pos.y; s_count--;\n                    fingertip_holding[u] = true;\n                    cells_acted_on_this_turn[current_tip_pos.x][current_tip_pos.y] = true;\n                }\n            }\n        }\n        \n        // Output combined command string\n        // Format: [root_move_char][V_prime-1 rotation_chars][V_prime P_chars]\n        cout << command_root_move_str << command_rotations_str << command_P_actions_part << endl;\n    }\n\n    return 0;\n}\n","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <set>\n#include <optional> // Still useful for initial (optional) hole logic in old designs, but now just for outer rect.\n\nusing namespace std;\n\n// Timer utility\nstruct Timer {\n    chrono::high_resolution_clock::time_point start_time;\n    double time_limit_ms;\n\n    Timer(double limit_ms) : time_limit_ms(limit_ms) {\n        start_time = chrono::high_resolution_clock::now();\n    }\n\n    bool is_time_up() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() >= time_limit_ms;\n    }\n\n    double get_elapsed_time_ms() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count();\n    }\n};\n\n// Point structure\nstruct Point {\n    int x, y;\n};\n\n// Rectangle structure\nstruct Rect {\n    int x_min, y_min, x_max, y_max;\n    long long length() const {\n        if (x_min >= x_max || y_min >= y_max) return 0; \n        return 2LL * (x_max - x_min) + 2LL * (y_max - y_min); \n    }\n};\n\n// Fenwick Tree (BIT) for 2D range sum queries\ntemplate <typename T>\nstruct FenwickTree2D {\n    int max_x_idx, max_y_idx;\n    vector<vector<T>> bit;\n\n    FenwickTree2D(int mx_idx, int my_idx) : max_x_idx(mx_idx), max_y_idx(my_idx) {\n        bit.assign(max_x_idx + 1, vector<T>(my_idx + 1, 0));\n    }\n\n    void update(int x, int y, T delta) { // x, y are 0-based compressed indices\n        for (int i = x + 1; i <= max_x_idx; i += i & -i) {\n            for (int j = y + 1; j <= max_y_idx; j += j & -j) {\n                bit[i][j] += delta;\n            }\n        }\n    }\n\n    T query(int x, int y) { // query sum from (0,0) to (x,y) inclusive (0-based compressed indices)\n        T sum = 0;\n        for (int i = x + 1; i > 0; i -= i & -i) {\n            for (int j = y + 1; j > 0; j -= j & -j) {\n                sum += bit[i][j];\n            }\n        }\n        return sum;\n    }\n\n    // query sum for rectangle [x1, x2] x [y1, y2] (0-based compressed indices)\n    T query_rect_sum(int x1, int y1, int x2, int y2) { \n        if (x1 > x2 || y1 > y2) return 0; \n        T sum = query(x2, y2);\n        if (x1 > 0) sum -= query(x1 - 1, y2);\n        if (y1 > 0) sum -= query(x2, y1 - 1);\n        if (x1 > 0 && y1 > 0) sum += query(x1 - 1, y1 - 1);\n        return sum;\n    }\n};\n\n// Global data\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nvector<int> unique_xs, unique_ys;\nmap<int, int> x_to_idx, y_to_idx;\nFenwickTree2D<int>* ft_ptr = nullptr; // Pointer to FenwickTree2D\n\n// Score calculation wrapper for real coordinates using compressed FT\nlong long calculate_rect_score(const Rect& rect) {\n    if (rect.x_min >= rect.x_max || rect.y_min >= rect.y_max) return 0; \n\n    // Find compressed indices for the given real coordinate rectangle\n    auto it_x1 = lower_bound(unique_xs.begin(), unique_xs.end(), rect.x_min);\n    if (it_x1 == unique_xs.end()) return 0; \n    int x1_idx = distance(unique_xs.begin(), it_x1);\n\n    auto it_x2 = upper_bound(unique_xs.begin(), unique_xs.end(), rect.x_max);\n    if (it_x2 == unique_xs.begin()) return 0; \n    int x2_idx = distance(unique_xs.begin(), it_x2) - 1;\n\n    auto it_y1 = lower_bound(unique_ys.begin(), unique_ys.end(), rect.y_min);\n    if (it_y1 == unique_ys.end()) return 0; \n    int y1_idx = distance(unique_ys.begin(), it_y1);\n\n    auto it_y2 = upper_bound(unique_ys.begin(), unique_ys.end(), rect.y_max);\n    if (it_y2 == unique_ys.begin()) return 0; \n    int y2_idx = distance(unique_ys.begin(), it_y2) - 1;\n\n    if (x1_idx > x2_idx || y1_idx > y2_idx) return 0; \n\n    return ft_ptr->query_rect_sum(x1_idx, y1_idx, x2_idx, y2_idx);\n}\n\n// Polygon state: now ONLY a single rectangle\nstruct PolygonState {\n    Rect outer;\n    // Removed notch\n    \n    long long value; \n    long long total_len; \n    vector<Point> vertices; \n\n    PolygonState() : value(0), total_len(0), outer({0,0,0,0}) {} \n\n    void calculate_polygon_data() {\n        if (outer.x_min >= outer.x_max || outer.y_min >= outer.y_max) { \n            value = -1; \n            total_len = 0;\n            vertices.clear();\n            return;\n        }\n        \n        value = calculate_rect_score(outer);\n        total_len = outer.length();\n\n        vertices.clear();\n        if (value >= 0) { \n            vertices.push_back({outer.x_min, outer.y_min});\n            vertices.push_back({outer.x_max, outer.y_min});\n            vertices.push_back({outer.x_max, outer.y_max});\n            vertices.push_back({outer.x_min, outer.y_max});\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    Timer global_timer(1950); // Total time for all restarts\n\n    cin >> N;\n    mackerels.resize(N);\n    sardines.resize(N);\n\n    set<int> x_coords_set, y_coords_set;\n    int min_m_x = 100001, max_m_x = -1, min_m_y = 100001, max_m_y = -1; \n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        x_coords_set.insert(mackerels[i].x);\n        y_coords_set.insert(mackerels[i].y);\n        min_m_x = min(min_m_x, mackerels[i].x);\n        max_m_x = max(max_m_x, mackerels[i].x);\n        min_m_y = min(min_m_y, mackerels[i].y);\n        max_m_y = max(max_m_y, mackerels[i].y);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        x_coords_set.insert(sardines[i].x);\n        y_coords_set.insert(sardines[i].y);\n    }\n\n    unique_xs.assign(x_coords_set.begin(), x_coords_set.end());\n    unique_ys.assign(y_coords_set.begin(), y_coords_set.end());\n\n    if (unique_xs.empty() || unique_xs.front() != 0) unique_xs.insert(unique_xs.begin(), 0);\n    if (unique_xs.back() != 100000) unique_xs.push_back(100000);\n    if (unique_ys.empty() || unique_ys.front() != 0) unique_ys.insert(unique_ys.begin(), 0);\n    if (unique_ys.back() != 100000) unique_ys.push_back(100000);\n    \n    sort(unique_xs.begin(), unique_xs.end());\n    sort(unique_ys.begin(), unique_ys.end());\n\n    for (int i = 0; i < unique_xs.size(); ++i) x_to_idx[unique_xs[i]] = i;\n    for (int i = 0; i < unique_ys.size(); ++i) y_to_idx[unique_ys[i]] = i;\n\n    FenwickTree2D<int> ft(unique_xs.size(), unique_ys.size());\n    ft_ptr = &ft;\n\n    for (int i = 0; i < N; ++i) { \n        ft.update(x_to_idx[mackerels[i].x], y_to_idx[mackerels[i].y], 1);\n    }\n    for (int i = 0; i < N; ++i) { \n        ft.update(x_to_idx[sardines[i].x], y_to_idx[sardines[i].y], -1);\n    }\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> rand_prob(0.0, 1.0);\n    \n    PolygonState overall_best_polygon;\n    overall_best_polygon.value = -1; // Initialize with a value that ensures any valid solution is better\n\n    int num_restarts = 3;\n    double time_per_restart = global_timer.time_limit_ms / num_restarts;\n\n    for (int restart_idx = 0; restart_idx < num_restarts; ++restart_idx) {\n        if (global_timer.is_time_up()) break;\n\n        PolygonState current_polygon;\n        // Different initialization strategies for restarts\n        if (restart_idx == 0) { // Bounding box of mackerels\n            current_polygon.outer = {max(0, min_m_x - 1), max(0, min_m_y - 1), min(100000, max_m_x + 1), min(100000, max_m_y + 1)};\n        } else if (restart_idx == 1) { // Random rectangle\n            int x1 = unique_xs[uniform_int_distribution<int>(0, unique_xs.size() - 1)(rng)];\n            int y1 = unique_ys[uniform_int_distribution<int>(0, unique_ys.size() - 1)(rng)];\n            int x2 = unique_xs[uniform_int_distribution<int>(0, unique_xs.size() - 1)(rng)];\n            int y2 = unique_ys[uniform_int_distribution<int>(0, unique_ys.size() - 1)(rng)];\n            current_polygon.outer = {min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2)};\n        } else { // Another random rectangle (or full map default)\n            current_polygon.outer = {0,0,100000,100000};\n        }\n        \n        // Ensure initial box is not degenerate\n        if (current_polygon.outer.x_min >= current_polygon.outer.x_max) current_polygon.outer.x_max = current_polygon.outer.x_min + 1;\n        if (current_polygon.outer.y_min >= current_polygon.outer.y_max) current_polygon.outer.y_max = current_polygon.outer.y_min + 1;\n        \n        current_polygon.calculate_polygon_data();\n        if (current_polygon.value < 0 || current_polygon.total_len > 400000) {\n            current_polygon.outer = {0,0,1,1};\n            current_polygon.calculate_polygon_data();\n        }\n\n        double T_start = 10000.0; \n        double T_end = 1.0;      \n        \n        chrono::high_resolution_clock::time_point restart_start_time = chrono::high_resolution_clock::now();\n\n        while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - restart_start_time).count() < time_per_restart && !global_timer.is_time_up()) { \n            PolygonState next_polygon = current_polygon;\n\n            // Modify outer rectangle (only move type now)\n            int dim_to_change = uniform_int_distribution<int>(0, 3)(rng); \n            \n            int current_x_min_idx = x_to_idx[next_polygon.outer.x_min];\n            int current_x_max_idx = x_to_idx[next_polygon.outer.x_max];\n            int current_y_min_idx = y_to_idx[next_polygon.outer.y_min];\n            int current_y_max_idx = y_to_idx[next_polygon.outer.y_max];\n\n            int new_idx;\n            int lower_bound_idx, upper_bound_idx;\n\n            if (dim_to_change == 0) { lower_bound_idx = 0; upper_bound_idx = current_x_max_idx; } \n            else if (dim_to_change == 1) { lower_bound_idx = 0; upper_bound_idx = current_y_max_idx; }\n            else if (dim_to_change == 2) { lower_bound_idx = current_x_min_idx; upper_bound_idx = unique_xs.size() - 1; } \n            else { lower_bound_idx = current_y_min_idx; upper_bound_idx = unique_ys.size() - 1; }\n\n            if (lower_bound_idx > upper_bound_idx) continue;\n\n            if (rand_prob(rng) < 0.2) { // 20% chance for a large jump (random index)\n                new_idx = uniform_int_distribution<int>(lower_bound_idx, upper_bound_idx)(rng);\n            } else { // 80% chance for a small step, adaptive range\n                int current_dim_range = upper_bound_idx - lower_bound_idx;\n                int step_max = max(1, current_dim_range / 100); \n                uniform_int_distribution<int> adaptive_step_dist(1, step_max);\n                int step = adaptive_step_dist(rng);\n                bool move_positive = uniform_int_distribution<int>(0, 1)(rng); \n\n                int current_idx;\n                if (dim_to_change == 0) current_idx = current_x_min_idx;\n                else if (dim_to_change == 1) current_idx = current_y_min_idx;\n                else if (dim_to_change == 2) current_idx = current_x_max_idx;\n                else current_idx = current_y_max_idx;\n\n                new_idx = current_idx + (move_positive ? step : -step);\n                new_idx = clamp(new_idx, lower_bound_idx, upper_bound_idx); \n            }\n\n            if (dim_to_change == 0) next_polygon.outer.x_min = unique_xs[new_idx];\n            else if (dim_to_change == 1) next_polygon.outer.y_min = unique_ys[new_idx];\n            else if (dim_to_change == 2) next_polygon.outer.x_max = unique_xs[new_idx];\n            else next_polygon.outer.y_max = unique_ys[new_idx];\n        \n            next_polygon.calculate_polygon_data();\n            \n            if (next_polygon.value < 0 || next_polygon.total_len > 400000) {\n                continue; \n            }\n\n            double elapsed_in_restart = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - restart_start_time).count();\n            double current_temp = T_start * pow(T_end / T_start, elapsed_in_restart / time_per_restart);\n            double acceptance_prob = 1.0;\n            if (next_polygon.value < current_polygon.value) {\n                acceptance_prob = exp((double)(next_polygon.value - current_polygon.value) / current_temp);\n            }\n\n            if (rand_prob(rng) < acceptance_prob) {\n                current_polygon = next_polygon;\n                if (current_polygon.value > overall_best_polygon.value) {\n                    overall_best_polygon = current_polygon;\n                }\n            }\n        }\n        // After SA for this restart, do a quick hill climbing to maximize from current_polygon\n        // No separate loop, just ensure overall_best_polygon is updated.\n        if (current_polygon.value > overall_best_polygon.value) {\n            overall_best_polygon = current_polygon;\n        }\n    }\n\n    if (overall_best_polygon.value < 0) { \n        cout << 4 << endl;\n        cout << \"0 0\" << endl;\n        cout << \"1 0\" << endl;\n        cout << \"1 1\" << endl;\n        cout << \"0 1\" << endl;\n    } else {\n        cout << overall_best_polygon.vertices.size() << endl;\n        for (const auto& v : overall_best_polygon.vertices) {\n            cout << v.x << \" \" << v.y << endl;\n        }\n    }\n\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <iomanip> // For std::fixed, std::setprecision\n#include <chrono> // For timing\n#include <cmath> // For std::exp, std::pow, std::sqrt\n\n// Random number generator\nstd::mt19937 rng;\n\n// Global parameters from input\nint N_GLOBAL;\nint T_TOTAL_GLOBAL;\nlong long SIGMA_GLOBAL;\nstd::vector<long long> W_PRIME_GLOBAL, H_PRIME_GLOBAL; // Initial observed dimensions\n\n// Current estimates for true widths and heights, using double for precision\nstd::vector<double> current_estimated_w, current_estimated_h;\n\n// Struct to represent a single placement operation\nstruct Operation {\n    int p;     // Rectangle index (0 to N-1)\n    int r;     // Rotation (0: no, 1: 90-deg)\n    char d;    // Direction ('U' or 'L')\n    int b;     // Reference rectangle index (-1 for origin or 0 to p-1)\n};\n\n// Struct to store details of a rectangle after it's been placed\nstruct PlacedRectInfo {\n    long long x, y, w, h; // Coordinates and dimensions\n    int p_idx;             // Original index of the rectangle\n    bool rotated;          // True if rotated\n};\n\n// Helper function for random integer generation\nint random_int(int min, int max) {\n    std::uniform_int_distribution<int> dist(min, max);\n    return dist(rng);\n}\n\n// Helper function for random char selection\nchar random_char(char c1, char c2) {\n    return (random_int(0, 1) == 0) ? c1 : c2;\n}\n\n// Helper for random double in range [0, 1)\ndouble random_double_01() {\n    std::uniform_real_distribution<double> dist(0.0, 1.0);\n    return dist(rng);\n}\n\n// Simulates the placement of rectangles given a set of operations and current dimension estimates.\n// Returns the predicted bounding box (W, H).\nstd::pair<long long, long long>\nsimulate_placement(const std::vector<Operation>& ops,\n                   const std::vector<double>& est_w,\n                   const std::vector<double>& est_h) {\n    \n    // Using a vector indexed by original rectangle index for O(1) access\n    // This is valid because rectangle indices `p` are placed in ascending order.\n    std::vector<PlacedRectInfo> p_idx_to_info_vec(N_GLOBAL); \n    \n    long long max_X = 0;\n    long long max_Y = 0;\n\n    // A list of already placed rectangle indices to iterate over.\n    // This is more efficient than iterating through the entire `p_idx_to_info_vec` if `N` is large\n    // and only a few items are placed so far.\n    std::vector<int> current_placed_indices;\n    current_placed_indices.reserve(N_GLOBAL);\n\n    for (const auto& op : ops) {\n        // Get estimated dimensions and apply rotation\n        long long current_w = static_cast<long long>(est_w[op.p]);\n        long long current_h = static_cast<long long>(est_h[op.p]);\n        \n        if (op.r == 1) { // Rotate 90 degrees\n            std::swap(current_w, current_h);\n        }\n\n        // Clamp dimensions to problem constraints [1, 10^9]\n        current_w = std::max(1LL, std::min(1000000000LL, current_w));\n        current_h = std::max(1LL, std::min(1000000000LL, current_h));\n\n        long long new_x = 0;\n        long long new_y = 0;\n\n        if (op.d == 'U') {\n            // Determine the x-coordinate of the left edge\n            long long target_x_left = 0;\n            if (op.b != -1) {\n                // op.b must be a previously placed rectangle's index, so it will be in p_idx_to_info_vec\n                target_x_left = p_idx_to_info_vec[op.b].x + p_idx_to_info_vec[op.b].w;\n            }\n            new_x = target_x_left;\n\n            // Find the highest point (max y + h) that the new rectangle would sit on\n            long long y_stop_level = 0;\n            for (int p_idx : current_placed_indices) { // Iterate only through actually placed rectangles\n                const auto& placed_r = p_idx_to_info_vec[p_idx];\n                // Check for horizontal overlap with placed_r\n                if (placed_r.x < new_x + current_w && placed_r.x + placed_r.w > new_x) {\n                    y_stop_level = std::max(y_stop_level, placed_r.y + placed_r.h);\n                }\n            }\n            new_y = y_stop_level;\n\n        } else { // op.d == 'L'\n            // Determine the y-coordinate of the top edge\n            long long target_y_top = 0;\n            if (op.b != -1) {\n                // op.b must be a previously placed rectangle's index\n                target_y_top = p_idx_to_info_vec[op.b].y + p_idx_to_info_vec[op.b].h;\n            }\n            new_y = target_y_top;\n\n            // Find the rightmost point (max x + w) that the new rectangle would push against\n            long long x_stop_level = 0;\n            for (int p_idx : current_placed_indices) { // Iterate only through actually placed rectangles\n                const auto& placed_r = p_idx_to_info_vec[p_idx];\n                // Check for vertical overlap with placed_r\n                if (placed_r.y < new_y + current_h && placed_r.y + placed_r.h > new_y) {\n                    x_stop_level = std::max(x_stop_level, placed_r.x + placed_r.w);\n                }\n            }\n            new_x = x_stop_level;\n        }\n\n        // Store info for the newly placed rectangle\n        PlacedRectInfo info = {new_x, new_y, current_w, current_h, op.p, (op.r == 1)};\n        p_idx_to_info_vec[op.p] = info;      // For quick lookup by original index\n        current_placed_indices.push_back(op.p); // Add to list of placed indices\n\n        // Update overall bounding box dimensions\n        max_X = std::max(max_X, new_x + current_w);\n        max_Y = std::max(max_Y, new_y + current_h);\n    }\n\n    return {max_X, max_Y};\n}\n\n// Generates an initial random placement strategy\nstd::vector<Operation> generate_random_strategy(int N) {\n    std::vector<Operation> ops(N);\n    for (int i = 0; i < N; ++i) {\n        ops[i].p = i; // Always place rectangles in ascending order of their original indices\n        ops[i].r = random_int(0, 1);\n        ops[i].d = random_char('U', 'L');\n        ops[i].b = random_int(-1, i - 1); // Reference rectangle must be -1 or a previously placed index\n    }\n    return ops;\n}\n\n// Main solution function\nvoid solve() {\n    // Read initial N, T, sigma and rectangle measurements\n    std::cin >> N_GLOBAL >> T_TOTAL_GLOBAL >> SIGMA_GLOBAL;\n\n    W_PRIME_GLOBAL.resize(N_GLOBAL);\n    H_PRIME_GLOBAL.resize(N_GLOBAL);\n    current_estimated_w.resize(N_GLOBAL);\n    current_estimated_h.resize(N_GLOBAL);\n\n    for (int i = 0; i < N_GLOBAL; ++i) {\n        std::cin >> W_PRIME_GLOBAL[i] >> H_PRIME_GLOBAL[i];\n        current_estimated_w[i] = static_cast<double>(W_PRIME_GLOBAL[i]);\n        current_estimated_h[i] = static_cast<double>(H_PRIME_GLOBAL[i]);\n    }\n\n    // Initialize the best strategy found so far across all turns\n    std::vector<Operation> overall_best_ops = generate_random_strategy(N_GLOBAL);\n    auto initial_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n    long long overall_best_score_predicted = initial_sim_result.first + initial_sim_result.second;\n\n    // Time management for local search\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_SECONDS = 2.9; // Allow some buffer for I/O and final calculations\n\n    // Simulated Annealing temperature parameters (reverted to best performing config)\n    double T_GLOBAL_START = 0;\n    for(int i=0; i<N_GLOBAL; ++i) T_GLOBAL_START += (current_estimated_w[i] + current_estimated_h[i]);\n    T_GLOBAL_START /= N_GLOBAL; // Average side length sum per rectangle\n    T_GLOBAL_START *= 15.0;     // Multiplier from best performing config\n    T_GLOBAL_START = std::max(T_GLOBAL_START, 100000.0); // Minimum temp to ensure it's not too small.\n\n    const double T_GLOBAL_END_RATIO = 0.01; // Global temp decay from best performing config\n    const double T_INNER_END_RATIO = 0.01;  // Inner temp decay from best performing config\n    \n    // Dynamic adjustment of NUM_LOCAL_SEARCH_ATTEMPTS\n    const int BASE_LOCAL_SEARCH_ATTEMPTS = 50;\n    int actual_local_search_attempts = std::max(BASE_LOCAL_SEARCH_ATTEMPTS, (int)(BASE_LOCAL_SEARCH_ATTEMPTS * (100.0 / N_GLOBAL)));\n\n    for (int turn = 0; turn < T_TOTAL_GLOBAL; ++turn) {\n        // Calculate the current global temperature for this turn.\n        double turn_progress = (double)turn / T_TOTAL_GLOBAL;\n        double T_turn_start = T_GLOBAL_START * std::pow(T_GLOBAL_END_RATIO, turn_progress);\n\n        std::vector<Operation> current_ops_SA = overall_best_ops; \n        long long current_score_SA = overall_best_score_predicted;\n        \n        std::vector<Operation> best_ops_in_SA = overall_best_ops;\n        long long best_score_in_SA = overall_best_score_predicted;\n\n        for (int iter = 0; iter < actual_local_search_attempts; ++iter) { // Use dynamically adjusted attempts\n            std::vector<Operation> candidate_ops = current_ops_SA; \n            int p_idx_to_change = random_int(0, N_GLOBAL - 1); \n\n            int mutate_type = random_int(0, 2); \n\n            if (mutate_type == 0) { // Mutate rotation\n                candidate_ops[p_idx_to_change].r = 1 - candidate_ops[p_idx_to_change].r;\n            } else if (mutate_type == 1) { // Mutate direction\n                candidate_ops[p_idx_to_change].d = (candidate_ops[p_idx_to_change].d == 'U' ? 'L' : 'U');\n            } else { // Mutate reference rectangle (b_i)\n                candidate_ops[p_idx_to_change].b = random_int(-1, p_idx_to_change - 1);\n            }\n\n            auto sim_result = simulate_placement(candidate_ops, current_estimated_w, current_estimated_h);\n            long long candidate_score = sim_result.first + sim_result.second;\n\n            double inner_iter_progress = (double)iter / actual_local_search_attempts; // Use actual_local_search_attempts\n            double temp_for_this_iter = T_turn_start * std::pow(T_INNER_END_RATIO, inner_iter_progress);\n            \n            if (temp_for_this_iter < 1.0) temp_for_this_iter = 1.0; \n\n            if (candidate_score < current_score_SA) {\n                current_ops_SA = candidate_ops;\n                current_score_SA = candidate_score;\n                if (current_score_SA < best_score_in_SA) {\n                    best_ops_in_SA = current_ops_SA;\n                    best_score_in_SA = current_score_SA;\n                }\n            } else {\n                double acceptance_prob = std::exp(-(double)(candidate_score - current_score_SA) / temp_for_this_iter);\n                if (random_double_01() < acceptance_prob) {\n                    current_ops_SA = candidate_ops;\n                    current_score_SA = candidate_score;\n                }\n            }\n        } \n\n        if (best_score_in_SA < overall_best_score_predicted) {\n            overall_best_ops = best_ops_in_SA;\n            overall_best_score_predicted = best_score_in_SA;\n        }\n\n        std::cout << N_GLOBAL << std::endl;\n        for (const auto& op : overall_best_ops) {\n            std::cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << std::endl;\n        }\n        std::cout << std::flush;\n\n        long long W_observed, H_observed;\n        std::cin >> W_observed >> H_observed;\n\n        // One call to simulate_placement to update dimension estimates\n        auto sim_result_for_update = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        long long W_predicted = sim_result_for_update.first;\n        long long H_predicted = sim_result_for_update.second;\n\n        double W_ratio = static_cast<double>(W_observed) / W_predicted;\n        double H_ratio = static_cast<double>(H_observed) / H_predicted;\n\n        double learn_rate = 0.07 / std::sqrt(turn + 1.0); // Learn rate base from best performing config\n        double initial_reversion_rate = 0.01 / std::sqrt(turn + 1.0); // Reversion rate base from best performing config\n\n        for (int i = 0; i < N_GLOBAL; ++i) {\n            current_estimated_w[i] = current_estimated_w[i] * (1.0 + learn_rate * (W_ratio - 1.0));\n            current_estimated_h[i] = current_estimated_h[i] * (1.0 + learn_rate * (H_ratio - 1.0));\n\n            current_estimated_w[i] = (1.0 - initial_reversion_rate) * current_estimated_w[i] + initial_reversion_rate * W_PRIME_GLOBAL[i];\n            current_estimated_h[i] = (1.0 - initial_reversion_rate) * current_estimated_h[i] + initial_reversion_rate * H_PRIME_GLOBAL[i];\n\n            current_estimated_w[i] = std::max(1.0, std::min(1000000000.0, current_estimated_w[i]));\n            current_estimated_h[i] = std::max(1.0, std::min(1000000000.0, current_estimated_h[i]));\n        }\n\n        // Re-calculate the overall best predicted score with the new estimates\n        auto new_overall_best_sim_result = simulate_placement(overall_best_ops, current_estimated_w, current_estimated_h);\n        overall_best_score_predicted = new_overall_best_sim_result.first + new_overall_best_sim_result.second;\n\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_time = std::chrono::duration<double>(current_time - start_time).count();\n        if (elapsed_time > TIME_LIMIT_SECONDS) {\n            break; \n        }\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    rng.seed(std::chrono::system_clock::now().time_since_epoch().count());\n\n    solve();\n\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <queue>\n#include <chrono>\n#include <random>\n#include <cmath> // For std::exp\n\n// Global random number generator\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Structure to hold graph and problem data\nstruct ProblemData {\n    int N, M, H_limit;\n    std::vector<int> A;\n    std::vector<std::vector<int>> adj; // Adjacency list for the original graph\n};\n\n// Structure to hold a solution candidate (parent array, score, heights)\nstruct Solution {\n    std::vector<int> parent;\n    long long score;\n    std::vector<int> heights; // Heights for current parent configuration\n\n    Solution(int N_val) : parent(N_val, -1), score(0), heights(N_val, -1) {}\n};\n\n// Function to evaluate a given parent array and compute heights\n// Returns score, and populates heights_out. Returns -1 for invalid states.\n// Invalid states include cycles or height constraint violations.\nlong long eval_score(const ProblemData& pd, const std::vector<int>& p, std::vector<int>& heights_out) {\n    int N = pd.N;\n    int H_limit = pd.H_limit;\n    const std::vector<int>& A = pd.A;\n\n    std::vector<std::vector<int>> children_lists(N);\n    std::vector<char> is_root(N, 1); // Using char for boolean (1 for true, 0 for false)\n\n    for (int v = 0; v < N; ++v) {\n        if (p[v] != -1) {\n            if (p[v] < 0 || p[v] >= N || p[v] == v) { \n                return -1; // Invalid parent reference\n            }\n            children_lists[p[v]].push_back(v);\n            is_root[v] = 0; // Node v is not a root\n        }\n    }\n\n    std::fill(heights_out.begin(), heights_out.end(), -1); // Initialize heights to -1 (unvisited)\n    long long current_total_score = 0;\n    \n    std::queue<int> q; // Queue for BFS\n\n    for (int r = 0; r < N; ++r) {\n        if (is_root[r] == 1 && heights_out[r] == -1) { // If 'r' is a root and has not been visited yet\n            q.push(r);\n            heights_out[r] = 0; // Root has height 0\n            current_total_score += (1LL * (heights_out[r] + 1) * A[r]);\n\n            while (!q.empty()) {\n                int u = q.front();\n                q.pop();\n\n                if (heights_out[u] > H_limit) { \n                    return -1; \n                }\n\n                for (int v_child : children_lists[u]) {\n                    if (heights_out[v_child] == -1) { // If v_child has not yet been visited in this tree\n                        heights_out[v_child] = heights_out[u] + 1;\n                        if (heights_out[v_child] > H_limit) { // Height constraint violation for v_child\n                            return -1;\n                        }\n                        current_total_score += (1LL * (heights_out[v_child] + 1) * A[v_child]);\n                        q.push(v_child);\n                    } else {\n                        // Cycle or structural inconsistency detected (e.g., v_child visited in same tree via different path)\n                        return -1; \n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure all nodes have been assigned a height.\n    for(int v = 0; v < N; ++v){\n        if(heights_out[v] == -1){\n            return -1; // Indicates a disjoint node/subgraph not correctly rooted or parented\n        }\n    }\n\n    return current_total_score;\n}\n\n// Function to check for cycles efficiently during a proposed parent change.\nbool forms_cycle(int v, int new_p, const std::vector<int>& current_p, const ProblemData& pd) {\n    if (new_p == -1) return false; \n\n    int curr = new_p;\n    for(int i = 0; i < pd.H_limit + 2 && curr != -1; ++i) { \n        if (curr == v) {\n            return true; \n        }\n        curr = current_p[curr];\n    }\n    return false; \n}\n\nvoid solve() {\n    ProblemData pd;\n    std::cin >> pd.N >> pd.M >> pd.H_limit;\n    pd.A.resize(pd.N);\n    for (int i = 0; i < pd.N; ++i) std::cin >> pd.A[i];\n    \n    pd.adj.resize(pd.N);\n    for (int i = 0; i < pd.M; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        pd.adj[u].push_back(v);\n        pd.adj[v].push_back(u);\n    }\n    // Coordinates are not used.\n    for (int i = 0; i < pd.N; ++i) {\n        int x, y; \n        std::cin >> x >> y;\n    }\n\n    Solution current_sol(pd.N);\n    current_sol.score = eval_score(pd, current_sol.parent, current_sol.heights);\n\n    Solution best_sol = current_sol; \n\n    auto start_time = std::chrono::high_resolution_clock::now();\n    const double TIME_LIMIT_MS = 1900.0; \n    \n    double start_temp = 500.0;           \n    double end_temp = 0.1;               \n\n    std::uniform_real_distribution<double> dist_0_1(0.0, 1.0);\n    std::uniform_int_distribution<int> node_dist_uniform(0, pd.N - 1); \n\n    // Dynamic probability for biased selection - using the best-performing range\n    const double PROB_BIAS_DYNAMIC_START = 0.3; \n    const double PROB_BIAS_DYNAMIC_END = 0.9;   \n\n    // Vectors for dynamic priority calculation\n    std::vector<long long> dynamic_priorities(pd.N);\n    std::vector<long long> dynamic_priority_prefix_sum(pd.N);\n    \n    // Buffer for new heights when evaluating a candidate solution\n    std::vector<int> new_heights_buffer(pd.N);\n\n    // Main Simulated Annealing loop\n    while (true) {\n        auto current_time = std::chrono::high_resolution_clock::now();\n        double elapsed_ms = std::chrono::duration<double, std::milli>(current_time - start_time).count();\n        if (elapsed_ms >= TIME_LIMIT_MS) {\n            break; \n        }\n\n        double progress = elapsed_ms / TIME_LIMIT_MS;\n        // Linear cooling schedule\n        double temp = start_temp * (1.0 - progress) + end_temp * progress; \n        \n        double prob_bias_dynamic = PROB_BIAS_DYNAMIC_START * (1.0 - progress) + PROB_BIAS_DYNAMIC_END * progress;\n\n        int v;\n        if (dist_0_1(rng) < prob_bias_dynamic) {\n            // Biased selection: pick node proportional to its A_v * (H_limit - h_v + 1)\n            long long total_dynamic_priority_sum = 0;\n            for(int i = 0; i < pd.N; ++i) {\n                // Prioritize nodes with high beauty and more \"room\" to increase depth (low current height)\n                dynamic_priorities[i] = 1LL * pd.A[i] * (pd.H_limit - current_sol.heights[i] + 1);\n            }\n            \n            dynamic_priority_prefix_sum[0] = dynamic_priorities[0];\n            for(int i = 1; i < pd.N; ++i) {\n                dynamic_priority_prefix_sum[i] = dynamic_priority_prefix_sum[i-1] + dynamic_priorities[i];\n            }\n            total_dynamic_priority_sum = dynamic_priority_prefix_sum[pd.N - 1];\n\n            if (total_dynamic_priority_sum <= 0) { // Safety check: if sum is zero, fall back to uniform\n                v = node_dist_uniform(rng);\n            } else {\n                std::uniform_int_distribution<long long> dist_sum_priority(0, total_dynamic_priority_sum - 1);\n                long long target_sum = dist_sum_priority(rng);\n                v = std::upper_bound(dynamic_priority_prefix_sum.begin(), dynamic_priority_prefix_sum.end(), target_sum) - dynamic_priority_prefix_sum.begin();\n            }\n\n        } else {\n            // Uniform selection: pick any node with equal probability\n            v = node_dist_uniform(rng); \n        }\n\n        // --- SA acceptance logic ---\n        // Create a candidate parent array by copying current_sol's parent.\n        std::vector<int> candidate_parent_array = current_sol.parent;\n        \n        // Determine candidate parents for 'v'\n        std::vector<int> candidate_parents_for_v;\n        candidate_parents_for_v.push_back(-1); // Option to make v a root\n        for (int neighbor : pd.adj[v]) {\n            if (neighbor != v) { \n                candidate_parents_for_v.push_back(neighbor);\n            }\n        }\n        \n        if (candidate_parents_for_v.empty()) { \n            continue; // No valid parents for v (should be rare/impossible in connected N>1 graph), skip this iteration\n        }\n        std::uniform_int_distribution<int> parent_dist(0, candidate_parents_for_v.size() - 1);\n        int new_p = candidate_parents_for_v[parent_dist(rng)];\n        \n        // Apply the proposed change to the candidate array\n        candidate_parent_array[v] = new_p;\n\n        // Perform a quick cycle check\n        if (forms_cycle(v, new_p, candidate_parent_array, pd)) {\n             continue; // Invalid move due to cycle, try next iteration\n        }\n        \n        // Evaluate the new state and its score\n        long long new_score = eval_score(pd, candidate_parent_array, new_heights_buffer);\n\n        if (new_score != -1) { // If the new state is valid\n            // Update the global best solution if the new score is higher\n            if (new_score > best_sol.score) {\n                best_sol.score = new_score;\n                best_sol.parent = candidate_parent_array;\n                best_sol.heights = new_heights_buffer; // Also update heights for best_sol\n            }\n\n            // Simulated Annealing acceptance condition:\n            // Always accept if the new score is better.\n            // Accept with a certain probability if the new score is worse, allowing escape from local optima.\n            if (new_score > current_sol.score || \n                dist_0_1(rng) < std::exp((double)(new_score - current_sol.score) / temp)) {\n                \n                // Accept the move: update current_sol with the new state\n                current_sol.score = new_score;\n                current_sol.parent = candidate_parent_array;\n                current_sol.heights = new_heights_buffer; // Also update heights for current_sol\n            } \n            // Else (move rejected): current_sol remains unchanged, as candidate_parent_array was temporary.\n        } \n        // Else (new_score == -1, invalid state): candidate_parent_array is simply discarded. current_sol remains unchanged.\n    }\n\n    // Output the parent array of the best solution found\n    for (int i = 0; i < pd.N; ++i) {\n        std::cout << best_sol.parent[i] << (i == pd.N - 1 ? \"\" : \" \");\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}\n","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <set>\n#include <algorithm>\n#include <utility> // For std::pair\n#include <limits>  // For std::numeric_limits\n\n// Structure to store an operation\nstruct Operation {\n    char direction;\n    int index;\n\n    Operation(char d, int i) : direction(d), index(i) {}\n};\n\n// Structure to encapsulate the best choice found in an iteration\nstruct BestChoice {\n    double cost_per_oni; // Primary metric: moves / num_oni_removed (minimize)\n    int num_oni_removed; // Secondary metric: maximize\n    int moves_count;     // Tertiary metric: minimize\n    std::pair<int, int> target_oni_pos; // The specific Oni this action was calculated for\n    char direction;\n    int index;\n\n    // Default constructor for initialization to \"worst possible\" values\n    BestChoice() : cost_per_oni(std::numeric_limits<double>::max()),\n                   num_oni_removed(0), // Maximize this, so start low\n                   moves_count(std::numeric_limits<int>::max()),\n                   target_oni_pos({-1, -1}), direction(' '), index(-1) {}\n\n    // Method to check if 'this' choice is strictly better than 'other'\n    bool is_strictly_better_than(const BestChoice& other) const {\n        // 1. Compare cost_per_oni (less is better)\n        if (cost_per_oni < other.cost_per_oni) return true;\n        if (cost_per_oni > other.cost_per_oni) return false;\n\n        // 2. cost_per_oni is equal, compare num_oni_removed (more is better)\n        if (num_oni_removed > other.num_oni_removed) return true;\n        if (num_oni_removed < other.num_oni_removed) return false;\n\n        // 3. num_oni_removed is equal, compare moves_count (less is better)\n        if (moves_count < other.moves_count) return true;\n\n        return false; // Not strictly better\n    }\n};\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N;\n    std::cin >> N;\n\n    // Store initial Fukunokami positions for constant lookup, as they never move\n    std::set<std::pair<int, int>> fuku_positions_set;\n    // Store current Oni positions. This set will be modified as Oni are removed.\n    std::set<std::pair<int, int>> current_oni_positions_set;\n\n    for (int i = 0; i < N; ++i) {\n        std::string row_str;\n        std::cin >> row_str;\n        for (int j = 0; j < N; ++j) {\n            if (row_str[j] == 'x') {\n                current_oni_positions_set.insert({i, j});\n            } else if (row_str[j] == 'o') {\n                fuku_positions_set.insert({i, j});\n            }\n        }\n    }\n\n    std::vector<Operation> operations;\n\n    // Continue as long as there are Oni on the board\n    while (!current_oni_positions_set.empty()) {\n        BestChoice best_overall_choice;\n\n        // Iterate through all currently present Oni to find the best action.\n        // The iteration order of std::set provides a stable tie-breaking for target_oni_pos\n        for (const auto& oni_pos : current_oni_positions_set) {\n            int r = oni_pos.first;\n            int c = oni_pos.second;\n\n            // --- Check Upward path ---\n            bool up_clear = true;\n            int oni_in_up_path_count = 0;\n            // Iterate from row 0 up to and including 'r' in column 'c'\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    up_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_up_path_count++;\n                }\n            }\n\n            if (up_clear) {\n                int moves = 2 * (r + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_up_path_count;\n                // 'num_oni_removed' is guaranteed to be at least 1 (the target Oni itself)\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_up_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'U';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Downward path ---\n            bool down_clear = true;\n            int oni_in_down_path_count = 0;\n            // Iterate from row 'r' down to and including 'N-1' in column 'c'\n            for (int k_row = r; k_row < N; ++k_row) {\n                if (fuku_positions_set.count({k_row, c})) {\n                    down_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({k_row, c})) {\n                    oni_in_down_path_count++;\n                }\n            }\n\n            if (down_clear) {\n                int moves = 2 * (N - r);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_down_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_down_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'D';\n                current_choice.index = c;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Leftward path ---\n            bool left_clear = true;\n            int oni_in_left_path_count = 0;\n            // Iterate from column 0 up to and including 'c' in row 'r'\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    left_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_left_path_count++;\n                }\n            }\n\n            if (left_clear) {\n                int moves = 2 * (c + 1);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_left_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_left_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'L';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n\n            // --- Check Rightward path ---\n            bool right_clear = true;\n            int oni_in_right_path_count = 0;\n            // Iterate from column 'c' down to and including 'N-1' in row 'r'\n            for (int k_col = c; k_col < N; ++k_col) {\n                if (fuku_positions_set.count({r, k_col})) {\n                    right_clear = false;\n                    break;\n                }\n                if (current_oni_positions_set.count({r, k_col})) {\n                    oni_in_right_path_count++;\n                }\n            }\n\n            if (right_clear) {\n                int moves = 2 * (N - c);\n                BestChoice current_choice;\n                current_choice.moves_count = moves;\n                current_choice.num_oni_removed = oni_in_right_path_count;\n                current_choice.cost_per_oni = static_cast<double>(moves) / oni_in_right_path_count;\n                current_choice.target_oni_pos = oni_pos;\n                current_choice.direction = 'R';\n                current_choice.index = r;\n\n                if (current_choice.is_strictly_better_than(best_overall_choice)) {\n                    best_overall_choice = current_choice;\n                }\n            }\n        } // End loop over current_oni_positions_set\n\n        // Apply the best found operations and update the set of Oni\n        int r = best_overall_choice.target_oni_pos.first;\n        int c = best_overall_choice.target_oni_pos.second;\n        char chosen_direction = best_overall_choice.direction;\n        int chosen_index = best_overall_choice.index;\n\n        // The problem guarantee ensures that a valid choice is always found.\n        // If it weren't, chosen_index would be -1, indicating an error or no more Oni.\n        // For robustness, could add: if (chosen_index == -1) break;\n\n        if (chosen_direction == 'U') {\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('U', chosen_index);\n            for (int k = 0; k < r + 1; ++k) operations.emplace_back('D', chosen_index);\n            for (int k_row = 0; k_row <= r; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'D') {\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('D', chosen_index);\n            for (int k = 0; k < N - r; ++k) operations.emplace_back('U', chosen_index);\n            for (int k_row = r; k_row < N; ++k_row) {\n                current_oni_positions_set.erase({k_row, chosen_index});\n            }\n        } else if (chosen_direction == 'L') {\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('L', chosen_index);\n            for (int k = 0; k < c + 1; ++k) operations.emplace_back('R', chosen_index);\n            for (int k_col = 0; k_col <= c; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        } else if (chosen_direction == 'R') {\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('R', chosen_index);\n            for (int k = 0; k < N - c; ++k) operations.emplace_back('L', chosen_index);\n            for (int k_col = c; k_col < N; ++k_col) {\n                current_oni_positions_set.erase({chosen_index, k_col});\n            }\n        }\n    }\n\n    // Output operations\n    for (const auto& op : operations) {\n        std::cout << op.direction << \" \" << op.index << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric> // For std::accumulate\n#include <cmath>   // For std::abs, std::pow, std::exp\n#include <random>  // For std::mt19937, std::uniform_int_distribution, std::uniform_real_distribution, std::discrete_distribution\n#include <chrono>  // For high_resolution_clock\n#include <algorithm> // For std::min, std::max\n\n// Use a global random number generator for convenience and efficiency\n// Seeded with current time to ensure different runs produce different results\nstd::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());\n\n// Function to calculate the error for a given assignment\n// N: Number of employees\n// L: Total number of weeks\n// T: Target cleaning counts for each employee\n// assignments: Vector of pairs (a_i, b_i) for each employee i\nlong long calculate_error(\n    int N, int L, \n    const std::vector<int>& T, \n    const std::vector<std::pair<int, int>>& assignments\n) {\n    std::vector<long long> actual_final_counts(N, 0); // Stores the final cleaning counts for each employee\n\n    int current_cleaner = 0; // The employee who cleans in the current week (starts with employee 0)\n    // counts_in_sim tracks cleaning counts *during this specific simulation run* for cycle detection\n    std::vector<int> counts_in_sim(N, 0); \n    \n    // For cycle detection:\n    // path_cleaners stores the sequence of employees who cleaned, week by week (0-indexed)\n    // It will store at most 2N elements before a cycle is guaranteed to be detected.\n    std::vector<int> path_cleaners; \n    path_cleaners.reserve(N * 2 + 1); // Reserve space to avoid reallocations\n\n    // visited_states stores the week_idx when a state (cleaner_id * 2 + count_parity) was first observed.\n    // Initialize with -1 to indicate not visited. Max state key is (N-1)*2+1 = 2N-1. Size 2N is sufficient.\n    std::vector<int> visited_states(N * 2, -1); \n\n    // Simulate week by week until L weeks are covered or a cycle is detected\n    for (int week_idx = 0; week_idx < L; ++week_idx) {\n        int cleaner_for_this_week = current_cleaner;\n        counts_in_sim[cleaner_for_this_week]++; // Increment count for the current cleaner\n        path_cleaners.push_back(cleaner_for_this_week); // Record this week's cleaner\n\n        // A state is defined by (employee who just finished cleaning, their total cleaning count parity)\n        // Map (cleaner_id, count_parity) to a single integer key for vector lookup (O(1) access)\n        int state_key = cleaner_for_this_week * 2 + (counts_in_sim[cleaner_for_this_week] % 2);\n\n        // Check if this state has been visited before, indicating a cycle\n        if (visited_states[state_key] != -1) { // If this state_key was visited before\n            int cycle_start_idx = visited_states[state_key]; // Week index where this state first occurred\n            int cycle_length = week_idx - cycle_start_idx + 1; // Length of the detected cycle (from cycle_start_idx to current week_idx, inclusive)\n\n            // Step 1: Accumulate counts for the pre-cycle part (weeks 0 to cycle_start_idx-1)\n            for (int i = 0; i < cycle_start_idx; ++i) {\n                actual_final_counts[path_cleaners[i]]++;\n            }\n\n            // Step 2: Calculate cleaning counts within one full cycle period\n            std::vector<long long> cycle_counts_one_period(N, 0);\n            for (int i = cycle_start_idx; i <= week_idx; ++i) {\n                cycle_counts_one_period[path_cleaners[i]]++;\n            }\n\n            // Step 3: Distribute remaining weeks using the cycle counts\n            // Total weeks that need to be covered by the cycle from cycle_start_idx until L\n            long long remaining_weeks_to_fill = L - cycle_start_idx;\n            \n            if (cycle_length > 0) { // Safety check to prevent division by zero\n                long long num_full_cycles = remaining_weeks_to_fill / cycle_length;\n                for (int i = 0; i < N; ++i) {\n                    actual_final_counts[i] += num_full_cycles * cycle_counts_one_period[i];\n                }\n                // Add remaining part of a partial cycle at the very end\n                long long remaining_in_partial_cycle = remaining_weeks_to_fill % cycle_length;\n                for (int i = 0; i < remaining_in_partial_cycle; ++i) {\n                    actual_final_counts[path_cleaners[cycle_start_idx + i]]++;\n                }\n            }\n            \n            // All L weeks have been accounted for, so we can exit the simulation early\n            goto end_simulation; \n        }\n        \n        // If no cycle detected yet, record the current state and its week index\n        visited_states[state_key] = week_idx;\n\n        // Determine the next cleaner based on current cleaner's count parity and assignments\n        if (counts_in_sim[cleaner_for_this_week] % 2 != 0) { // If total count for 'cleaner_for_this_week' is odd\n            current_cleaner = assignments[cleaner_for_this_week].first;\n        } else { // If total count for 'cleaner_for_this_week' is even\n            current_cleaner = assignments[cleaner_for_this_week].second;\n        }\n    }\n\n    // This block is reached if the loop completes without finding a cycle.\n    // This happens if L is small enough that no state repeats, or if L happens to be exactly the pre-cycle length.\n    // In this case, 'path_cleaners' contains the cleaners for all L weeks, and their counts\n    // haven't been added to 'actual_final_counts' yet.\n    for (int i = 0; i < L; ++i) {\n        actual_final_counts[path_cleaners[i]]++;\n    }\n\nend_simulation:; // Label for goto\n\n    // Calculate the total absolute error\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += std::abs(actual_final_counts[i] - T[i]);\n    }\n    return error;\n}\n\nint main() {\n    // Optimize C++ standard streams for faster input/output\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    int N_val, L_val; \n    std::cin >> N_val >> L_val;\n\n    std::vector<int> T(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        std::cin >> T[i];\n    }\n\n    // Prepare a discrete distribution for selecting employees based on target counts\n    // Used *only* for initial assignment.\n    std::vector<double> T_weights(N_val);\n    for (int i = 0; i < N_val; ++i) {\n        T_weights[i] = static_cast<double>(T[i] + 1); // Add 1 to ensure positive weights\n    }\n    std::discrete_distribution<int> weighted_dist_by_T(T_weights.begin(), T_weights.end());\n\n    // Uniform distribution for picking any employee ID [0, N-1]\n    // This will be used for SA mutations.\n    std::uniform_int_distribution<int> dist_N(0, N_val - 1); \n\n    std::vector<std::pair<int, int>> best_assignments(N_val);\n    std::vector<std::pair<int, int>> current_assignments(N_val);\n\n    // Initial random assignments for a_i and b_i using the weighted distribution\n    // This provides a potentially better starting point for SA.\n    for (int i = 0; i < N_val; ++i) {\n        current_assignments[i] = {weighted_dist_by_T(rng), weighted_dist_by_T(rng)};\n    }\n\n    // Calculate initial state error\n    long long current_error = calculate_error(N_val, L_val, T, current_assignments);\n    long long best_error = current_error;\n    best_assignments = current_assignments; // Deep copy the initial best state\n\n    // Simulated Annealing parameters\n    double start_temp = 3000.0; \n    double end_temp = 0.01;     \n    // This iteration_limit determines the shape of the temperature curve.\n    // It should be roughly the number of iterations expected to run in total.\n    long long iteration_limit = 10000000; \n    \n    auto start_time = std::chrono::high_resolution_clock::now();\n    // Reverted time_limit_ms to the value that previously yielded the highest score.\n    long long time_limit_ms = 1980; // Allot 1.98 seconds for computation\n\n    // Main Simulated Annealing loop\n    for (long long iter = 0; iter < iteration_limit; ++iter) {\n        // Check elapsed time to ensure compliance with the time limit\n        auto current_time = std::chrono::high_resolution_clock::now();\n        long long elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();\n        if (elapsed_ms > time_limit_ms) {\n            break; // Exit SA loop if time limit approached\n        }\n\n        // Geometric cooling schedule for temperature\n        double temp = start_temp * std::pow(end_temp / start_temp, static_cast<double>(iter) / iteration_limit);\n        \n        // Generate a neighbor state by modifying one a_i or b_i\n        int employee_to_change = dist_N(rng); // Randomly pick an employee whose rule (a_i, b_i) to change\n        bool change_first_val = (rng() % 2 == 0); // Randomly decide whether to change a_i (true) or b_i (false)\n        \n        // Store the original value to allow reverting if the move is not accepted\n        int original_val_to_revert;\n        if (change_first_val) {\n            original_val_to_revert = current_assignments[employee_to_change].first;\n            // Propose a new value for a_i using uniform distribution (for SA mutations)\n            current_assignments[employee_to_change].first = dist_N(rng); \n        } else {\n            original_val_to_revert = current_assignments[employee_to_change].second;\n            // Propose a new value for b_i using uniform distribution (for SA mutations)\n            current_assignments[employee_to_change].second = dist_N(rng); \n        }\n\n        // Calculate the error for the new (modified) assignments\n        long long next_error = calculate_error(N_val, L_val, T, current_assignments);\n\n        if (next_error < current_error) {\n            // If the new solution is better, always accept it\n            current_error = next_error;\n            if (next_error < best_error) {\n                // If it's the best solution found so far, update best_assignments\n                best_error = next_error;\n                best_assignments = current_assignments; // Deep copy\n            }\n        } else {\n            // If the new solution is worse, accept it with a certain probability\n            double probability = std::exp(-(static_cast<double>(next_error - current_error)) / temp);\n            std::uniform_real_distribution<double> dist_real(0.0, 1.0); // For generating a random probability [0.0, 1.0)\n            if (dist_real(rng) < probability) {\n                current_error = next_error; // Accept the worse solution\n            } else {\n                // If the worse solution is not accepted, revert the change to the original value\n                if (change_first_val) {\n                    current_assignments[employee_to_change].first = original_val_to_revert;\n                } else {\n                    current_assignments[employee_to_change].second = original_val_to_revert;\n                }\n            }\n        }\n    }\n\n    // Output the best assignments found after the SA process\n    for (int i = 0; i < N_val; ++i) {\n        std::cout << best_assignments[i].first << \" \" << best_assignments[i].second << \"\\n\";\n    }\n\n    return 0;\n}\n","ahc045":"#include <iostream>\n#include <vector>\n#include <string>\n#include <numeric>\n#include <algorithm>\n#include <set>\n#include <cmath> // For std::sqrt, std::floor, std::ceil, std::max\n\n// Structure to hold city bounding box\nstruct Rect {\n    int lx, rx, ly, ry;\n};\n\n// Structure to hold city data\nstruct City {\n    int id;\n    int cx, cy; // Center coordinates, using integer division for consistency with sample\n    unsigned int z_order_val; // Z-order curve value for sorting\n    Rect bounds;\n};\n\n// Disjoint Set Union structure for Kruskal's algorithm\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) return i;\n        return parent[i] = find(parent[i]);\n    }\n    bool 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            return true;\n        }\n        return false;\n    }\n};\n\n// Edge structure for Kruskal's\nstruct Edge {\n    int u, v;\n    std::pair<int, long long> weight; // rank (0=queried, 1=estimated), estimated_dist_sq\n};\n\n// Helper for Z-order curve: bit interleaving (Morton code)\n// Optimized for 16-bit inputs (max value 65535) resulting in 32-bit output.\n// Coordinates up to 10000 fit into 14 bits.\n// For example, an input of 10000 will have its 14 bits interleaved into a 32-bit output.\nunsigned int morton_encode(unsigned int x, unsigned int y) {\n    x = (x | (x << 8)) & 0x00FF00FF;\n    x = (x | (x << 4)) & 0x0F0F0F0F;\n    x = (x | (x << 2)) & 0x33333333;\n    x = (x | (x << 1)) & 0x55555555;\n    y = (y | (y << 8)) & 0x00FF00FF;\n    y = (y | (y << 4)) & 0x0F0F0F0F;\n    y = (y | (y << 2)) & 0x33333333;\n    y = (y | (y << 1)) & 0x55555555;\n    return x | (y << 1);\n}\n\n// Functions to calculate min/max squared distance components along one axis\nlong long calc_min_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff;\n    if (r1_max < r2_min) { // Rect 1 is entirely before Rect 2 on this axis\n        diff = r2_min - r1_max;\n    } else if (r2_max < r1_min) { // Rect 2 is entirely before Rect 1 on this axis\n        diff = r1_min - r2_max;\n    } else { // Rectangles overlap on this axis\n        diff = 0;\n    }\n    return diff * diff;\n}\n\nlong long calc_max_dist_component_sq(int r1_min, int r1_max, int r2_min, int r2_max) {\n    long long diff1 = (long long)r1_max - r2_min;\n    long long diff2 = (long long)r2_max - r1_min;\n    return std::max(diff1 * diff1, diff2 * diff2);\n}\n\n// Function to calculate estimated squared distance using min/max bounds range midpoint\nlong long estimated_dist_mid_range_sq(int u_id, int v_id, const std::vector<City>& cities_data) {\n    const Rect& r_u = cities_data[u_id].bounds;\n    const Rect& r_v = cities_data[v_id].bounds;\n\n    long long min_dx_sq = calc_min_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long min_dy_sq = calc_min_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_min_sq = min_dx_sq + min_dy_sq;\n\n    long long max_dx_sq = calc_max_dist_component_sq(r_u.lx, r_u.rx, r_v.lx, r_v.rx);\n    long long max_dy_sq = calc_max_dist_component_sq(r_u.ly, r_u.ry, r_v.ly, r_v.ry);\n    long long d_max_sq = max_dx_sq + max_dy_sq;\n\n    // Use the midpoint of the possible squared distance range\n    return (d_min_sq + d_max_sq) / 2;\n}\n\n\n// Function to make a query to the judge\nstd::vector<std::pair<int, int>> make_query(const std::vector<int>& c_subset) {\n    std::cout << \"? \" << c_subset.size();\n    for (int city_id : c_subset) {\n        std::cout << \" \" << city_id;\n    }\n    std::cout << std::endl; // Flush!\n\n    std::vector<std::pair<int, int>> result;\n    result.reserve(c_subset.size() - 1);\n    for (size_t i = 0; i < c_subset.size() - 1; ++i) {\n        int u, v;\n        std::cin >> u >> v;\n        if (u > v) std::swap(u, v); // Ensure canonical form (u < v)\n        result.push_back({u, v});\n    }\n    return result;\n}\n\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL); // Untie cin and cout for faster I/O, though flushing is still needed for queries\n\n    int N, M, Q, L_actual, W;\n    std::cin >> N >> M >> Q >> L_actual >> 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_data(N);\n    for (int i = 0; i < N; ++i) {\n        cities_data[i].id = i;\n        std::cin >> cities_data[i].bounds.lx >> cities_data[i].bounds.rx >> cities_data[i].bounds.ly >> cities_data[i].bounds.ry;\n        \n        // Use center for Z-order calculation as well\n        cities_data[i].cx = (cities_data[i].bounds.lx + cities_data[i].bounds.rx) / 2;\n        cities_data[i].cy = (cities_data[i].bounds.ly + cities_data[i].bounds.ry) / 2;\n        cities_data[i].z_order_val = morton_encode(cities_data[i].cx, cities_data[i].cy);\n    }\n\n    // 1. Initial Grouping: Sort by Z-order curve value\n    std::vector<int> p(N); // p stores sorted city IDs\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return cities_data[i].z_order_val < cities_data[j].z_order_val;\n    });\n\n    std::vector<std::vector<int>> tentative_groups(M);\n    int current_city_idx_p = 0;\n    for (int k = 0; k < M; ++k) {\n        tentative_groups[k].reserve(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            tentative_groups[k].push_back(p[current_city_idx_p++]);\n        }\n    }\n\n    // 2. Query Phase\n    std::set<std::pair<int, int>> queried_edges;\n    int Q_rem = Q;\n\n    // Phase 1: Query small groups entirely\n    for (int k = 0; k < M; ++k) {\n        if (G[k] >= 2 && G[k] <= L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k]; // Use const ref\n            std::vector<std::pair<int, int>> res_edges = make_query(current_group);\n            for (auto edge : res_edges) {\n                queried_edges.insert(edge);\n            }\n            Q_rem--;\n        }\n    }\n\n    // Phase 2: Query large groups with adaptive step_size\n    long long num_chunks_to_query_if_step1 = 0; // Total count of (G_k - L_actual + 1) for large groups\n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual) { // This condition ensures G[k] >= L_actual + 1, so G[k] - L_actual >= 1\n            num_chunks_to_query_if_step1 += (G[k] - L_actual + 1);\n        }\n    }\n\n    int step_size = 1;\n    if (Q_rem > 0 && num_chunks_to_query_if_step1 > 0) {\n        // Calculate step_size to distribute Q_rem queries among the total chunks\n        step_size = static_cast<int>(std::ceil(static_cast<double>(num_chunks_to_query_if_step1) / Q_rem));\n        step_size = std::max(1, step_size); // Ensure step_size is at least 1\n    } else {\n        step_size = N + 1; // Effectively skip this phase if no queries left or no large groups to query\n    }\n    \n    for (int k = 0; k < M; ++k) {\n        if (G[k] > L_actual && Q_rem > 0) {\n            const std::vector<int>& current_group = tentative_groups[k];\n            int last_queried_start = -1; // To track the starting index of the last query made\n            \n            for (int i = 0; i <= (int)current_group.size() - L_actual; i += step_size) {\n                if (Q_rem <= 0) break;\n                \n                std::vector<int> c_subset;\n                c_subset.reserve(L_actual);\n                for (int j = 0; j < L_actual; ++j) {\n                    c_subset.push_back(current_group[i+j]);\n                }\n                \n                std::vector<std::pair<int, int>> res_edges = make_query(c_subset);\n                for (auto edge : res_edges) {\n                    queried_edges.insert(edge);\n                }\n                Q_rem--;\n                last_queried_start = i;\n            }\n\n            // Handle cities at the end of the group that might not have been fully covered\n            // Query the last L_actual cities if the last possible window was not queried\n            // and we still have queries left.\n            if (Q_rem > 0) { // Check Q_rem again\n                int ideal_last_start_idx = (int)current_group.size() - L_actual;\n                if (ideal_last_start_idx >= 0 && last_queried_start != ideal_last_start_idx) { // Ensure ideal_last_start_idx is valid\n                    std::vector<int> c_subset_end;\n                    c_subset_end.reserve(L_actual);\n                    for(int j = ideal_last_start_idx; j < current_group.size(); ++j) {\n                        c_subset_end.push_back(current_group[j]);\n                    }\n                    if (c_subset_end.size() >= 2) { // Ensure minimum size for query\n                        std::vector<std::pair<int, int>> res_edges = make_query(c_subset_end);\n                        for (auto edge : res_edges) {\n                            queried_edges.insert(edge);\n                        }\n                        Q_rem--;\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Output Phase\n    std::cout << \"!\" << std::endl;\n\n    for (int k = 0; k < M; ++k) {\n        // Output cities in group k\n        for (int i = 0; i < G[k]; ++i) {\n            std::cout << tentative_groups[k][i] << (i == G[k] - 1 ? \"\" : \" \");\n        }\n        std::cout << std::endl;\n\n        if (G[k] == 1) { // A single city group needs no roads\n            continue;\n        }\n\n        // Prepare edges for MST\n        std::vector<Edge> edges_for_mst;\n        const std::vector<int>& current_group = tentative_groups[k];\n        \n        // Create all possible edges within the group\n        for (size_t i = 0; i < current_group.size(); ++i) {\n            for (size_t j = i + 1; j < current_group.size(); ++j) {\n                int u = current_group[i];\n                int v = current_group[j];\n                \n                // Ensure u < v for canonical form (matches queried_edges)\n                if (u > v) std::swap(u, v); \n                \n                int rank = 1; // 1 for estimated, 0 for queried\n                if (queried_edges.count({u, v})) {\n                    rank = 0;\n                }\n                \n                long long dist_sq = estimated_dist_mid_range_sq(u, v, cities_data); // Use new estimation\n                edges_for_mst.push_back({u, v, {rank, dist_sq}});\n            }\n        }\n\n        // Sort edges\n        std::sort(edges_for_mst.begin(), edges_for_mst.end(), [](const Edge& a, const Edge& b) {\n            if (a.weight.first != b.weight.first) {\n                return a.weight.first < b.weight.first;\n            }\n            // Tie-break with estimated squared distance\n            if (a.weight.second != b.weight.second) {\n                return a.weight.second < b.weight.second;\n            }\n            // Final tie-break with lexicographical order of cities\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Run Kruskal's\n        DSU dsu(N); // Initialize DSU for all N cities for simplicity\n        std::vector<std::pair<int, int>> mst_output_edges;\n        int edges_count = 0;\n        for (const auto& edge : edges_for_mst) {\n            if (edges_count == G[k] - 1) break; // Found enough edges\n            \n            if (dsu.unite(edge.u, edge.v)) {\n                mst_output_edges.push_back({edge.u, edge.v});\n                edges_count++;\n            }\n        }\n\n        // Output MST edges (lexicographically within group, as required by problem)\n        std::sort(mst_output_edges.begin(), mst_output_edges.end());\n        for (const auto& edge : mst_output_edges) {\n            std::cout << edge.first << \" \" << edge.second << std::endl;\n        }\n    }\n\n    return 0;\n}\n","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <map>\n#include <set>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int N_SIZE = 20;\n\n// Directions for movement and alter actions\n// Corresponding to U, D, L, R\nint DR[] = {-1, 1, 0, 0}; \nint DC[] = {0, 0, -1, 1}; \nchar DIR_CHARS[] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int r, c;\n    int cost;\n\n    // Custom comparator for priority queue (min-heap)\n    bool operator>(const State& other) const {\n        return cost > other.cost;\n    }\n};\n\n// Enum to categorize the type of action that led to a state\nenum ActionType {\n    MOVE,\n    MOVE_REMOVE_BLOCK,    // Move into a square that was blocked, removing the block first\n    SLIDE_WALL,           // Slide, stopping because of an N x N boundary wall\n    SLIDE_EXISTING_BLOCK  // Slide, stopping because of an existing block\n};\n\n// Information to reconstruct the path\nstruct ParentInfo {\n    int pr, pc; // previous row, previous column\n    ActionType type;\n    char dir_char; // direction character for the action (U, D, L, R)\n    int br, bc;   // block row, block column (relevant for SLIDE_EXISTING_BLOCK or MOVE_REMOVE_BLOCK)\n                  // For SLIDE_WALL, it's (-1,-1).\n};\n\n// Global board state, tracks currently existing blocks\nset<pair<int, int>> current_blocks;\n\n// Helper function to check if coordinates are within grid bounds\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_SIZE && c >= 0 && c < N_SIZE;\n}\n\nint main() {\n    // Optimize C++ standard streams for competitive programming\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M; // N will be 20, M will be 40 as per problem statement\n    cin >> N >> M;\n\n    vector<pair<int, int>> targets(M);\n    for (int k = 0; k < M; ++k) {\n        cin >> targets[k].first >> targets[k].second;\n    }\n\n    vector<pair<char, char>> all_actions; // Stores the final sequence of actions to output\n\n    int current_r = targets[0].first;\n    int current_c = targets[0].second;\n\n    // Iterate through each target segment (from current_pos to next target)\n    for (int k = 0; k < M - 1; ++k) {\n        int start_r = current_r;\n        int start_c = current_c;\n        int target_r = targets[k+1].first;\n        int target_c = targets[k+1].second;\n\n        // Dijkstra's algorithm for shortest path in terms of turns\n        vector<vector<int>> dist(N, vector<int>(N, INF));\n        vector<vector<ParentInfo>> parent(N, vector<ParentInfo>(N)); \n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[start_r][start_c] = 0;\n        pq.push({start_r, start_c, 0});\n\n        while (!pq.empty()) {\n            State current = pq.top();\n            pq.pop();\n\n            int r = current.r;\n            int c = current.c;\n            int d = current.cost;\n\n            // If we found a shorter path previously, skip this one\n            if (d > dist[r][c]) {\n                continue;\n            }\n            // If we reached the target, we found the shortest path for this segment\n            if (r == target_r && c == target_c) {\n                break; \n            }\n\n            // --- Explore possible Move actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int nr = r + DR[i];\n                int nc = c + DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                if (!is_valid(nr, nc)) continue; // Check bounds\n\n                int cost = 0;\n                ActionType type;\n                if (current_blocks.count({nr, nc})) {\n                    // Moving onto a square that currently has a block.\n                    // This costs 1 for Alter (to remove the block) + 1 for Move. Total 2 turns.\n                    cost = 2;\n                    type = MOVE_REMOVE_BLOCK;\n                } else {\n                    // Moving onto an empty square. Costs 1 for Move.\n                    cost = 1;\n                    type = MOVE;\n                }\n\n                if (d + cost < dist[nr][nc]) {\n                    dist[nr][nc] = d + cost;\n                    parent[nr][nc] = {r, c, type, dir_char, nr, nc}; // br, bc store coord of block removed for MOVE_REMOVE_BLOCK\n                    pq.push({nr, nc, d + cost});\n                }\n            }\n\n            // --- Explore possible Slide actions ---\n            for (int i = 0; i < 4; ++i) { // For each of 4 cardinal directions\n                int dr = DR[i];\n                int dc = DC[i];\n                char dir_char = DIR_CHARS[i];\n\n                int current_slide_r = r;\n                int current_slide_c = c;\n                \n                // This loop finds all possible valid stopping points for a slide in a given direction.\n                while (true) {\n                    // Tentatively advance one step to find the next square the slide *could* reach.\n                    int next_r = current_slide_r + dr;\n                    int next_c = current_slide_c + dc;\n\n                    // If the next square is out of bounds or blocked by an existing block,\n                    // we cannot slide *into* it. Thus, current_slide_r,c is a potential stopping point.\n                    if (!is_valid(next_r, next_c) || current_blocks.count({next_r, next_c})) {\n                        // We can only stop at current_slide_r,c if we've actually moved.\n                        // If current_slide_r,c is still (r,c), it means we can't even slide one square.\n                        if (current_slide_r == r && current_slide_c == c) {\n                             break; // Cannot slide even one square, no valid stops in this direction.\n                        }\n\n                        // current_slide_r,c is a valid stopping square.\n                        int stop_r = current_slide_r;\n                        int stop_c = current_slide_c;\n                        \n                        // The \"stopper\" is either the boundary or the existing block at (next_r, next_c)\n                        int stopper_block_r = next_r;\n                        int stopper_block_c = next_c;\n\n                        int slide_cost = 1; // All valid slides cost 1 turn\n                        ActionType type;\n\n                        if (!is_valid(stopper_block_r, stopper_block_c)) {\n                            type = SLIDE_WALL;\n                            stopper_block_r = -1; stopper_block_c = -1; // Sentinel\n                        } else { // It must be an existing block at (stopper_block_r, stopper_block_c)\n                            type = SLIDE_EXISTING_BLOCK;\n                        }\n\n                        if (d + slide_cost < dist[stop_r][stop_c]) {\n                            dist[stop_r][stop_c] = d + slide_cost;\n                            parent[stop_r][stop_c] = {r, c, type, dir_char, stopper_block_r, stopper_block_c};\n                            pq.push({stop_r, stop_c, d + slide_cost});\n                        }\n                        break; // This slide path ends here, either at boundary or existing block\n                    }\n\n                    // If next_r,c is valid and not blocked, we slide past current_slide_r,c.\n                    // So, current_slide_r,c itself cannot be a stopping point (because nothing stops us there).\n                    // Update current_slide_r,c to next_r,c and continue to find further stops.\n                    current_slide_r = next_r;\n                    current_slide_c = next_c;\n                }\n            }\n        }\n\n        // --- Path reconstruction and action recording ---\n        vector<tuple<int,int,ActionType,char,int,int>> path_segments_info;\n        int curr_r = target_r;\n        int curr_c = target_c;\n\n        // Traverse parent pointers backwards from target to start, storing segment info.\n        // This gives actions in reverse order of execution.\n        while (curr_r != start_r || curr_c != start_c) {\n            ParentInfo p = parent[curr_r][curr_c];\n            path_segments_info.emplace_back(p.pr, p.pc, p.type, p.dir_char, p.br, p.bc);\n            curr_r = p.pr;\n            curr_c = p.pc;\n        }\n        // Reverse to get actions in the correct execution order.\n        reverse(path_segments_info.begin(), path_segments_info.end()); \n\n        // Process each action segment in forward order and update global blocks and the action list\n        for (const auto& info : path_segments_info) {\n            int pr, pc, br, bc;\n            ActionType type;\n            char dir_char;\n            tie(pr, pc, type, dir_char, br, bc) = info;\n\n            if (type == MOVE) {\n                all_actions.emplace_back('M', dir_char);\n            } else if (type == MOVE_REMOVE_BLOCK) {\n                all_actions.emplace_back('A', dir_char); // First Alter to remove block at (br,bc)\n                current_blocks.erase({br, bc});           // Update global block state (remove it)\n                all_actions.emplace_back('M', dir_char); // Then Move\n            } else if (type == SLIDE_WALL || type == SLIDE_EXISTING_BLOCK) {\n                // No Alter action needed for these slide types, just the Slide itself.\n                // The block for SLIDE_EXISTING_BLOCK is already there and isn't toggled by us.\n                all_actions.emplace_back('S', dir_char);\n            }\n        }\n\n        // Update current player position for the next segment\n        current_r = target_r;\n        current_c = target_c;\n    }\n    \n    // Output all recorded actions\n    for (const auto& action : all_actions) {\n        cout << action.first << \" \" << action.second << endl;\n    }\n\n    return 0;\n}"}}}