{"model_name":"glm-4.7","codes":{"1":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <limits>\n#include <numeric>\n\nusing namespace std;\n\n// Use long long for area and error calculations to avoid overflow\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n    int a, b, c, d; // Output rectangle coordinates\n};\n\nvector<Company> companies;\n\n// Recursive function to partition the space\n// (x1, y1) is the bottom-left of the current region, (x2, y2) is the top-right\n// ids contains the indices of companies that must be placed in this region\nvoid solve_recursive(int x1, int y1, int x2, int y2, vector<int> ids) {\n    int k = ids.size();\n    if (k == 0) return;\n    \n    // Base case: only one company, assign the whole region\n    if (k == 1) {\n        int id = ids[0];\n        companies[id].a = x1;\n        companies[id].b = y1;\n        companies[id].c = x2;\n        companies[id].d = y2;\n        return;\n    }\n\n    ll total_area = (ll)(x2 - x1) * (y2 - y1);\n    \n    // Find the best cut (vertical or horizontal)\n    // We minimize the squared error: sum((assigned_area - desired_area)^2)\n    \n    ll best_error = numeric_limits<ll>::max();\n    int best_split_axis = -1; // 0: vertical, 1: horizontal\n    int best_split_idx = -1; // Index in the sorted list to split at\n    int best_cut_pos = -1;   // Coordinate of the cut\n    \n    // --- Try Vertical Cut ---\n    // Sort companies by X coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].x < companies[j].x;\n    });\n    \n    // Calculate prefix sums of r to quickly get sum of desired areas for a split\n    vector<ll> prefix_sum(k);\n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int height = y2 - y1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        // Split between i and i+1\n        ll sum_r_left = prefix_sum[i];\n        ll sum_r_right = prefix_sum[k-1] - sum_r_left;\n        \n        // The cut position X must separate the points.\n        // Left points must have x < X, Right points must have x >= X.\n        // Since points are integers, X must be > max_x_left and <= min_x_right.\n        int max_x_left = companies[ids[i]].x;\n        int min_x_right = companies[ids[i+1]].x;\n        \n        // Also must be within the current rectangle bounds (x1, x2)\n        // Left rect: [x1, X), Right: [X, x2) -> x1 < X < x2\n        int low = max(x1 + 1, max_x_left + 1);\n        int high = min(x2 - 1, min_x_right);\n        \n        if (low > high) continue; // No valid cut position for this split\n        \n        // Calculate optimal cut position to match area\n        // We want (X - x1) * height approx sum_r_left\n        double target_x = x1 + (double)sum_r_left / height;\n        int cut_x = (int)round(target_x);\n        \n        // Clamp to valid range\n        if (cut_x < low) cut_x = low;\n        if (cut_x > high) cut_x = high;\n        \n        ll actual_area_left = (ll)(cut_x - x1) * height;\n        ll actual_area_right = total_area - actual_area_left;\n        \n        ll error = (actual_area_left - sum_r_left) * (actual_area_left - sum_r_left) \n                 + (actual_area_right - sum_r_right) * (actual_area_right - sum_r_right);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 0;\n            best_split_idx = i;\n            best_cut_pos = cut_x;\n        }\n    }\n    \n    // --- Try Horizontal Cut ---\n    // Sort companies by Y coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].y < companies[j].y;\n    });\n    \n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int width = x2 - x1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        ll sum_r_bottom = prefix_sum[i];\n        ll sum_r_top = prefix_sum[k-1] - sum_r_bottom;\n        \n        int max_y_bottom = companies[ids[i]].y;\n        int min_y_top = companies[ids[i+1]].y;\n        \n        int low = max(y1 + 1, max_y_bottom + 1);\n        int high = min(y2 - 1, min_y_top);\n        \n        if (low > high) continue;\n        \n        double target_y = y1 + (double)sum_r_bottom / width;\n        int cut_y = (int)round(target_y);\n        \n        if (cut_y < low) cut_y = low;\n        if (cut_y > high) cut_y = high;\n        \n        ll actual_area_bottom = (ll)(cut_y - y1) * width;\n        ll actual_area_top = total_area - actual_area_bottom;\n        \n        ll error = (actual_area_bottom - sum_r_bottom) * (actual_area_bottom - sum_r_bottom) \n                 + (actual_area_top - sum_r_top) * (actual_area_top - sum_r_top);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 1;\n            best_split_idx = i;\n            best_cut_pos = cut_y;\n        }\n    }\n    \n    // --- Perform the Split ---\n    vector<int> left_ids, right_ids;\n    \n    if (best_split_axis == 0) {\n        // Vertical split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].x < companies[j].x;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, best_cut_pos, y2, left_ids);\n        solve_recursive(best_cut_pos, y1, x2, y2, right_ids);\n    } else {\n        // Horizontal split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].y < companies[j].y;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, x2, best_cut_pos, left_ids);\n        solve_recursive(x1, best_cut_pos, x2, y2, right_ids);\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    companies.resize(n);\n    vector<int> all_ids(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        all_ids[i] = i;\n    }\n    \n    solve_recursive(0, 0, 10000, 10000, all_ids);\n    \n    for (int i = 0; i < n; ++i) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" << companies[i].c << \" \" << companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n#include <random>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\n// mt19937_64 for high quality random numbers\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n};\n\nstruct Tile {\n    int id;\n    int size;\n    Point cells[2];\n    int total_val;\n    bool visited;\n};\n\n// Global variables for grid\nint H = 50, W = 50;\nint si, sj;\nvector<vector<int>> tile_ids;\nvector<vector<int>> p_vals;\nvector<Tile> tiles;\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHARS[4] = {'U', 'D', 'L', 'R'};\n\n// Helper to check bounds\ninline bool inside(int r, int c) {\n    return 0 <= r && r < H && 0 <= c && c < W;\n}\n\n// Heuristic function to evaluate the \"future\" potential of a cell\n// It sums the values of unvisited neighbor tiles + a bonus for connectivity\nint get_future_potential(int r, int c, const vector<bool>& visited) {\n    int score = 0;\n    int connections = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + DR[d];\n        int nc = c + DC[d];\n        if (inside(nr, nc)) {\n            int tid = tile_ids[nr][nc];\n            if (!visited[tid]) {\n                score += tiles[tid].total_val;\n                connections++;\n            }\n        }\n    }\n    // Bonus for having multiple options (connectivity)\n    return score + connections * 10;\n}\n\n// Main solver function\nstring solve_single_run() {\n    int num_tiles = tiles.size();\n    vector<bool> visited(num_tiles, false);\n    string path = \"\";\n    int score = 0;\n    \n    // Initialize current position and tile\n    Point curr_pos(si, sj);\n    int curr_tile_id = tile_ids[si][sj];\n    \n    // Mark start tile as visited\n    visited[curr_tile_id] = true;\n    score += p_vals[si][sj]; // Add score of starting square\n    \n    // Handle start tile logic (if it's a 2-tile, we might want to move to the other cell)\n    if (tiles[curr_tile_id].size == 2) {\n        Point p0 = tiles[curr_tile_id].cells[0];\n        Point p1 = tiles[curr_tile_id].cells[1];\n        \n        Point other = (p0.r == si && p0.c == sj) ? p1 : p0;\n        \n        // Calculate heuristic for exiting from current pos vs exiting from other\n        // Note: We already 'visited' the start tile, so we can move freely within it.\n        // We haven't collected points from 'other' yet.\n        \n        int potential_curr = get_future_potential(si, sj, visited);\n        int potential_other = p_vals[other.r][other.c] + get_future_potential(other.r, other.c, visited);\n        \n        if (potential_other > potential_curr) {\n            // Move to the other cell\n            for (int d = 0; d < 4; ++d) {\n                if (si + DR[d] == other.r && sj + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    curr_pos = other;\n                    score += p_vals[other.r][other.c];\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Main greedy loop\n    while (true) {\n        Point best_next_pos(-1, -1);\n        int best_score_move = -1;\n        bool best_is_full_traverse = false; // True if we choose to visit both cells of a 2-tile\n        int best_dir_idx = -1;\n        \n        // Check neighbors\n        for (int d = 0; d < 4; ++d) {\n            int nr = curr_pos.r + DR[d];\n            int nc = curr_pos.c + DC[d];\n            \n            if (!inside(nr, nc)) continue;\n            \n            int nxt_tid = tile_ids[nr][nc];\n            if (visited[nxt_tid]) continue;\n            \n            // Evaluate moving to (nr, nc)\n            // We enter the tile at (nr, nc)\n            int gain = tiles[nxt_tid].total_val;\n            \n            // Strategy 1: Full traverse (visit all cells of the tile)\n            // We effectively collect `gain`, and end up at the \"best\" exit point of the tile\n            // But since we enter at (nr, nc), we must reach the exit point from there.\n            // For 1-tile, exit is (nr, nc).\n            // For 2-tile, we enter at (nr, nc) -> go to other -> exit. Or enter -> exit.\n            \n            int max_future = -1e9;\n            int best_exit_cell_idx = -1; // 0 or 1 relative to tile cells\n            int future_curr_entry = -1e9;\n            \n            // Evaluate exit points\n            // Entry point is always the cell adjacent to curr_pos\n            // We need to identify which cell of the target tile is (nr, nc)\n            Point entry_cell(nr, nc);\n            Point other_cell(-1, -1);\n            if (tiles[nxt_tid].size == 2) {\n                if (tiles[nxt_tid].cells[0].r == nr && tiles[nxt_tid].cells[0].c == nc) {\n                    other_cell = tiles[nxt_tid].cells[1];\n                } else {\n                    other_cell = tiles[nxt_tid].cells[0];\n                }\n            }\n\n            // Option A: Exit from entry_cell (Partial traverse if 2-tile)\n            // We only gain points of entry_cell? \n            // Wait, if we enter a 2-tile and don't visit the other cell, do we gain its points? No.\n            // But wait, problem statement: \"score... sum of values of visited squares\".\n            // So we must decide which squares to visit.\n            // If 1-tile: visit (nr, nc). Gain = p(nr, nc).\n            // If 2-tile: visit (nr, nc). Gain = p(nr, nc).\n            \n            // Let's calculate exact gain for each strategy.\n            \n            // Strat 1: Visit ONLY entry_cell\n            int gain_partial = p_vals[nr][nc];\n            int future_partial = get_future_potential(nr, nc, visited);\n            int score_partial = gain_partial + future_partial;\n            \n            int score_full = -1e9;\n            int future_full = -1;\n            \n            if (tiles[nxt_tid].size == 1) {\n                // Only one option\n                score_full = gain_partial; // gain_partial is total_val here\n                future_full = future_partial;\n            } else {\n                // Strat 2: Visit entry_cell AND other_cell\n                int gain_full = tiles[nxt_tid].total_val;\n                // We end up at other_cell. Can we exit from other_cell? Yes.\n                // Can we exit from entry_cell? No, we stepped on other_cell, we must be at other_cell.\n                // Wait, if we step on entry, then other. We are at other. We leave from other.\n                // So future depends on other_cell.\n                int future_other = get_future_potential(other_cell.r, other_cell.c, visited);\n                score_full = gain_full + future_other;\n                future_full = future_other;\n            }\n            \n            // Pick best strategy for this neighbor\n            int current_best_score = max(score_partial, score_full);\n            \n            // Add noise\n            int noise = rng() % 20;\n            current_best_score += noise;\n            \n            if (current_best_score > best_score_move) {\n                best_score_move = current_best_score;\n                best_next_pos = Point(nr, nc);\n                best_dir_idx = d;\n                \n                // Record which strategy was better to update path later\n                // If score_full > score_partial, we will traverse fully\n                // Note: For 1-tile, they are equal, doesn't matter.\n                best_is_full_traverse = (score_full > score_partial);\n            }\n        }\n        \n        if (best_score_move == -1) {\n            break; // No moves left\n        }\n        \n        // Execute best move\n        int nxt_tid = tile_ids[best_next_pos.r][best_next_pos.c];\n        visited[nxt_tid] = true;\n        \n        // Update path and score\n        path += DIR_CHARS[best_dir_idx];\n        curr_pos = best_next_pos;\n        score += p_vals[best_next_pos.r][best_next_pos.c];\n        \n        if (tiles[nxt_tid].size == 2 && best_is_full_traverse) {\n            // Find the other cell\n            Point p0 = tiles[nxt_tid].cells[0];\n            Point p1 = tiles[nxt_tid].cells[1];\n            Point other = (p0.r == best_next_pos.r && p0.c == best_next_pos.c) ? p1 : p0;\n            \n            // Move to other cell\n            // Find direction\n            for (int d = 0; d < 4; ++d) {\n                if (best_next_pos.r + DR[d] == other.r && best_next_pos.c + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    break;\n                }\n            }\n            curr_pos = other;\n            score += p_vals[other.r][other.c];\n        }\n    }\n    \n    return path;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    cin >> si >> sj;\n    \n    tile_ids.resize(H, vector<int>(W));\n    p_vals.resize(H, vector<int>(W));\n    \n    // Map tile ID to vector of cells to construct Tile objects\n    vector<vector<Point>> raw_tile_cells;\n    \n    // Temporary map to normalize tile IDs if needed (though problem says 0..M-1)\n    // Just read and store\n    \n    // First pass to find M and store points\n    int max_id = 0;\n    vector<vector<int>> temp_ids(H, vector<int>(W));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> temp_ids[i][j];\n            max_id = max(max_id, temp_ids[i][j]);\n        }\n    }\n    \n    raw_tile_cells.resize(max_id + 1);\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = temp_ids[i][j];\n            raw_tile_cells[id].push_back(Point(i, j));\n        }\n    }\n    \n    // Construct Tile objects\n    tiles.resize(raw_tile_cells.size());\n    for (int i = 0; i < raw_tile_cells.size(); ++i) {\n        tiles[i].id = i;\n        tiles[i].size = raw_tile_cells[i].size();\n        tiles[i].cells[0] = raw_tile_cells[i][0];\n        if (tiles[i].size == 2) {\n            tiles[i].cells[1] = raw_tile_cells[i][1];\n        }\n        // Will update total_val after reading p\n    }\n    \n    // Assign normalized IDs to grid (can reuse original if they are dense 0..M-1, they are)\n    tile_ids = temp_ids;\n    \n    // Read values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> p_vals[i][j];\n            tiles[tile_ids[i][j]].total_val += p_vals[i][j];\n        }\n    }\n    \n    // Run multiple trials with random variations\n    string best_path = \"\";\n    int best_score = -1;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Limit to 1.8 seconds to be safe\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800) {\n        string current_path = solve_single_run();\n        \n        // Calculate score of this path (re-simulate or just compute during solve?)\n        // Let's re-simulate to be sure and clean.\n        int score = 0;\n        int cr = si, cc = sj;\n        vector<bool> vis(tiles.size(), false);\n        vis[tile_ids[cr][cc]] = true;\n        score += p_vals[cr][cc];\n        \n        bool valid = true;\n        \n        for (char move : current_path) {\n            int d = -1;\n            if (move == 'U') d = 0;\n            else if (move == 'D') d = 1;\n            else if (move == 'L') d = 2;\n            else if (move == 'R') d = 3;\n            \n            int nr = cr + DR[d];\n            int nc = cc + DC[d];\n            \n            if (!inside(nr, nc)) { valid = false; break; }\n            \n            int tid = tile_ids[nr][nc];\n            if (vis[tid]) { valid = false; break; }\n            \n            vis[tid] = true;\n            cr = nr; cc = nc;\n            score += p_vals[cr][cc];\n        }\n        \n        if (valid && score > best_score) {\n            best_score = score;\n            best_path = current_path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Global parameters\nconst int N = 30; // Grid size\nconst int NUM_PARAMS = N * 2; // 30 row costs + 30 col costs\n\nstruct RLS_Estimator {\n    int n_params;\n    vector<double> theta; // Estimated parameters\n    vector<vector<double>> P; // Covariance matrix\n\n    RLS_Estimator(int n) : n_params(n) {\n        theta.assign(n, 5000.0); // Initial guess\n        P.assign(n, vector<double>(n, 0.0));\n        // Initialize P with large diagonal values for high initial uncertainty\n        for (int i = 0; i < n; ++i) {\n            P[i][i] = 1000.0;\n        }\n    }\n\n    void update(const vector<int>& counts, double measured_total) {\n        // Calculate predicted total\n        double predicted_total = 0.0;\n        for (int i = 0; i < n_params; ++i) {\n            predicted_total += theta[i] * counts[i];\n        }\n\n        double error = measured_total - predicted_total;\n\n        // Vector x = P * counts\n        vector<double> Px(n_params, 0.0);\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                Px[i] += P[i][j] * counts[j];\n            }\n        }\n\n        // Denominator: 1 + counts^T * P * counts = 1 + counts^T * Px\n        double denom = 1.0;\n        for (int i = 0; i < n_params; ++i) {\n            denom += counts[i] * Px[i];\n        }\n\n        // Kalman gain: K = Px / denom\n        vector<double> K(n_params);\n        for (int i = 0; i < n_params; ++i) {\n            K[i] = Px[i] / denom;\n        }\n\n        // Update theta: theta = theta + error * K\n        for (int i = 0; i < n_params; ++i) {\n            theta[i] += error * K[i];\n        }\n\n        // Update P: P = P - K * (Px)^T\n        // This is a rank-1 update\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                P[i][j] -= K[i] * Px[j];\n            }\n        }\n    }\n};\n\nstring find_path(int si, int sj, int ti, int tj, RLS_Estimator& estimator) {\n    // Dijkstra's algorithm\n    // Distances\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<pair<int, int>>> prev(N, vector<pair<int, int>>(N, {-1, -1}));\n    \n    priority_queue<tuple<double, int, int>, vector<tuple<double, int, int>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, si, sj});\n\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    string dirs = \"UDLR\";\n\n    while (!pq.empty()) {\n        auto [d, r, c] = pq.top();\n        pq.pop();\n\n        if (r == ti && c == tj) break;\n        if (d > dist[r][c]) continue;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            double cost;\n            if (k < 2) { // Vertical move (U, D)\n                // Edge weight depends on column\n                cost = estimator.theta[N + nc];\n            } else { // Horizontal move (L, R)\n                // Edge weight depends on row\n                cost = estimator.theta[r];\n            }\n\n            if (dist[r][c] + cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[r][c] + cost;\n                prev[nr][nc] = {r, c};\n                pq.push({dist[nr][nc], nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cr = ti, cc = tj;\n    while (cr != si || cc != sj) {\n        int pr = prev[cr][cc].first;\n        int pc = prev[cr][cc].second;\n        \n        if (pr == -1 && pc == -1) break; // Should not happen\n\n        if (pr < cr) path += \"D\";\n        else if (pr > cr) path += \"U\";\n        else if (pc < cc) path += \"R\";\n        else if (pc > cc) path += \"L\";\n        \n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Helper to get feature counts from a path\nvector<int> get_feature_counts(const string& path, int si, int sj) {\n    vector<int> counts(NUM_PARAMS, 0);\n    int r = si, c = sj;\n    for (char dir : path) {\n        if (dir == 'L') {\n            counts[r]++;\n            c--;\n        } else if (dir == 'R') {\n            counts[r]++;\n            c++;\n        } else if (dir == 'U') {\n            counts[N + c]++;\n            r--;\n        } else if (dir == 'D') {\n            counts[N + c]++;\n            r++;\n        }\n    }\n    return counts;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    RLS_Estimator estimator(NUM_PARAMS);\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        string path = find_path(si, sj, ti, tj, estimator);\n        cout << path << endl;\n\n        // Read feedback\n        int measured;\n        cin >> measured;\n\n        vector<int> counts = get_feature_counts(path, si, sj);\n        estimator.update(counts, (double)measured);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <unordered_set>\n#include <chrono>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Utility: Rolling Hash\n// ---------------------------------------------------------\nstruct RollingHash {\n    static const uint64_t mod = (1ULL << 61) - 1;\n    uint64_t base;\n    vector<uint64_t> pow;\n    \n    RollingHash(uint64_t b) : base(b) {\n        pow.resize(100); // Enough for N=20\n        pow[0] = 1;\n        for(int i=1; i<100; i++) pow[i] = mul(pow[i-1], base);\n    }\n\n    static inline uint64_t add(uint64_t a, uint64_t b) {\n        if((a += b) >= mod) a -= mod;\n        return a;\n    }\n\n    static inline uint64_t mul(uint64_t a, uint64_t b) {\n        __uint128_t c = (__uint128_t)a * b;\n        return add((c >> 61) + (c & mod), mod);\n    }\n\n    // Compute hash of string s\n    uint64_t get_hash(const string& s) {\n        uint64_t res = 0;\n        for(char c : s) res = add(mul(res, base), c);\n        return res;\n    }\n\n    // Update hash when one character changes: old_char -> new_char at pos\n    // old_h is the hash of the current string of length len\n    uint64_t update_hash(uint64_t old_h, int pos, char old_char, char new_char, int len) {\n        // h = s0*B^(len-1) + s1*B^(len-2) + ... + s_pos*B^(len-1-pos) + ...\n        // We want to remove old_char and add new_char\n        // term = old_char * B^(len-1-pos)\n        // new_h = old_h - old_term + new_term\n        \n        uint64_t p = pow[len - 1 - pos];\n        // Removing old\n        uint64_t old_term = mul(old_char, p);\n        uint64_t h = (old_h + mod - old_term) % mod;\n        \n        // Adding new\n        uint64_t new_term = mul(new_char, p);\n        h = add(h, new_term);\n        \n        return h;\n    }\n};\n\n// ---------------------------------------------------------\n// Solver Class\n// ---------------------------------------------------------\nclass Solver {\npublic:\n    int N;\n    int M;\n    vector<string> S;\n    vector<vector<int>> str_len_groups; // Group strings by length\n\n    mt19937 rng;\n    RollingHash rh;\n\n    Solver(int n, int m, const vector<string>& s) : N(n), M(m), S(s), rng(chrono::steady_clock::now().time_since_epoch().count()), rh(10007) {\n        // Group strings by length for processing\n        int max_len = 0;\n        for(auto& t : S) max_len = max(max_len, (int)t.size());\n        str_len_groups.resize(max_len + 1);\n        for(int i=0; i<M; i++) {\n            str_len_groups[S[i].size()].push_back(i);\n        }\n    }\n\n    // -----------------------------------------------------\n    // Phase 1: Assemble Sequences from Long Strings\n    // -----------------------------------------------------\n    vector<string> assemble_sequences() {\n        vector<string> sequences;\n        \n        // We focus on long strings first, as they are unique.\n        // Length >= 6 usually works well for N=20, but let's try 8 for safety.\n        // Process lengths from 12 down to 6.\n        vector<int> lens;\n        for(int i=0; i<=12; i++) lens.push_back(i);\n        sort(lens.rbegin(), lens.rend());\n\n        for(int len : lens) {\n            if(len < 6) break; // Cutoff for assembly\n            for(int idx : str_len_groups[len]) {\n                const string& s = S[idx];\n                int best_seq_idx = -1;\n                int best_overlap = -1;\n                int best_rot = -1;\n\n                // Try to fit s into existing sequences\n                for(int i=0; i<(int)sequences.size(); i++) {\n                    string& seq = sequences[i];\n                    // Try all rotations\n                    for(int r=0; r<N; r++) {\n                        int overlap = 0;\n                        bool conflict = false;\n                        for(int k=0; k<(int)s.size(); k++) {\n                            int seq_idx = (r + k) % N;\n                            char c_seq = seq[seq_idx];\n                            if(c_seq != '.') {\n                                if(c_seq != s[k]) {\n                                    conflict = true;\n                                    break;\n                                } else {\n                                    overlap++;\n                                }\n                            }\n                        }\n                        if(!conflict) {\n                            // Prefer higher overlap\n                            if(overlap > best_overlap) {\n                                best_overlap = overlap;\n                                best_seq_idx = i;\n                                best_rot = r;\n                            }\n                        }\n                    }\n                }\n\n                if(best_seq_idx != -1) {\n                    // Merge into best_seq\n                    string& seq = sequences[best_seq_idx];\n                    for(int k=0; k<(int)s.size(); k++) {\n                        int seq_idx = (best_rot + k) % N;\n                        if(seq[seq_idx] == '.') {\n                            seq[seq_idx] = s[k];\n                        }\n                    }\n                } else {\n                    // Create new sequence\n                    if(sequences.size() < 50) { // Limit total sequences\n                        string new_seq(N, '.');\n                        int start = rng() % N;\n                        for(int k=0; k<(int)s.size(); k++) {\n                            new_seq[(start + k) % N] = s[k];\n                        }\n                        sequences.push_back(new_seq);\n                    }\n                }\n            }\n        }\n        return sequences;\n    }\n\n    // -----------------------------------------------------\n    // Phase 2: Assign Sequences to Rows/Cols (Simulated Annealing)\n    // -----------------------------------------------------\n    vector<string> assign_sequences(const vector<string>& sequences) {\n        // State: 40 strings (20 rows + 20 cols). \n        // Each slot holds a string (candidate or generic).\n        \n        int num_seqs = sequences.size();\n        int slots = 40;\n        \n        // Initialize assignment\n        // indices [0, 19] -> Rows, [20, 39] -> Cols\n        vector<int> assign(slots, -1);\n        vector<int> rot(slots, 0);\n        \n        // Fill with available sequences\n        for(int i=0; i<slots && i<num_seqs; i++) {\n            assign[i] = i;\n            rot[i] = 0; // Assume standard rotation initially\n        }\n        // If we have fewer than 40 sequences, fill rest with clones or random?\n        // Better to leave them as wildcards ('.') initially or generic.\n        // Let's map remaining to random existing ones to avoid empty slots in logic\n        for(int i=num_seqs; i<slots; i++) {\n            assign[i] = rng() % num_seqs;\n        }\n\n        auto get_seq = [&](int slot) -> string {\n            if(assign[slot] == -1) return string(N, '.');\n            string s = sequences[assign[slot]];\n            string res(N, '.');\n            for(int i=0; i<N; i++) res[i] = s[(i + rot[slot]) % N];\n            return res;\n        };\n\n        // Pre-calc energy\n        auto calc_energy = [&]() {\n            int cost = 0;\n            // For each cell (i, j), check Row[i][j] vs Col[j][i]\n            // Row i is slot i. Col j is slot 20 + j.\n            for(int i=0; i<N; i++) {\n                string row = get_seq(i);\n                for(int j=0; j<N; j++) {\n                    string col = get_seq(20 + j);\n                    if(row[j] != '.' && col[i] != '.' && row[j] != col[i]) {\n                        cost++;\n                    }\n                }\n            }\n            return cost;\n        };\n\n        int current_cost = calc_energy();\n        vector<int> best_assign = assign;\n        vector<int> best_rot = rot;\n        int best_cost = current_cost;\n\n        double temp_start = 2.0;\n        double temp_end = 0.01;\n        int iter = 0;\n        int max_iter = 40000; // Should be enough for small grid\n\n        while(iter < max_iter) {\n            double temp = temp_start + (temp_end - temp_start) * (iter / max_iter);\n            iter++;\n\n            // Transition\n            // 1. Change assignment of a slot\n            // 2. Change rotation of a slot\n            int slot = rng() % slots;\n            int prev_assign = assign[slot];\n            int prev_rot = rot[slot];\n            \n            if(rng() % 2 == 0) {\n                // Change assignment\n                assign[slot] = rng() % num_seqs;\n            } else {\n                // Change rotation\n                rot[slot] = (rot[slot] + 1 + rng() % 3) % N; // Small rotations better\n            }\n\n            int new_cost = calc_energy();\n            int delta = new_cost - current_cost;\n            \n            if(delta < 0 || exp(-delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                current_cost = new_cost;\n                if(current_cost < best_cost) {\n                    best_cost = current_cost;\n                    best_assign = assign;\n                    best_rot = rot;\n                }\n            } else {\n                // Revert\n                assign[slot] = prev_assign;\n                rot[slot] = prev_rot;\n            }\n        }\n\n        // Construct grid from best assignment\n        vector<string> grid(N, string(N, '.'));\n        for(int i=0; i<N; i++) {\n            string row = sequences[best_assign[i]];\n            for(int j=0; j<N; j++) {\n                char c = row[(j + best_rot[i]) % N];\n                if(c != '.') grid[i][j] = c;\n            }\n        }\n        for(int j=0; j<N; j++) {\n            string col = sequences[best_assign[20+j]];\n            for(int i=0; i<N; i++) {\n                char c = col[(i + best_rot[20+j]) % N];\n                if(c != '.') {\n                    if(grid[i][j] == '.') grid[i][j] = c;\n                    // If conflict, keep current (heuristic)\n                }\n            }\n        }\n        return grid;\n    }\n\n    // -----------------------------------------------------\n    // Phase 3: Local Search on Grid (Greedy / Randomized)\n    // -----------------------------------------------------\n    void optimize_grid(vector<string>& grid, double time_limit_ms) {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        // Precompute hashes for input strings\n        vector<uint64_t> s_hashes(M);\n        for(int i=0; i<M; i++) {\n            s_hashes[i] = rh.get_hash(S[i]);\n        }\n\n        // Current Grid State\n        vector<uint64_t> row_hashes(N);\n        vector<uint64_t> col_hashes(N);\n        vector<string> current_grid = grid;\n\n        auto init_hashes = [&]() {\n            for(int i=0; i<N; i++) row_hashes[i] = rh.get_hash(current_grid[i]);\n            for(int j=0; j<N; j++) {\n                string col_str;\n                for(int i=0; i<N; i++) col_str += current_grid[i][j];\n                col_hashes[j] = rh.get_hash(col_str);\n            }\n        };\n        init_hashes();\n\n        // Function to check string matches\n        auto count_matches = [&]() {\n            int cnt = 0;\n            unordered_set<uint64_t> row_h_set(row_hashes.begin(), row_hashes.end());\n            unordered_set<uint64_t> col_h_set(col_hashes.begin(), col_hashes.end());\n            \n            for(int i=0; i<M; i++) {\n                // Also need to check all substrings of length L in a row.\n                // Storing only full row hash is insufficient because strings are length 2..12.\n                // We need to check if S[i] is a substring of any row or col.\n                // Since N=20 is small, and we have hashes, we can compute hash of all substrings of S[i]? No.\n                // We compute hash of all substrings of length L in grid and check against hash(S[i]).\n                \n                // Optimization: Precompute all substring hashes of grid rows/cols?\n                // N=20, M=800. 20 rows * 20 shifts * 12 lens = 4800 checks.\n                // Hash computation is fast.\n                \n                uint64_t target = s_hashes[i];\n                int L = S[i].size();\n                bool found = false;\n\n                // Check rows\n                for(int r=0; r<N; r++) {\n                    // Construct substring hash\n                    // We can compute rolling hash for the row for length L.\n                    // But we have full row hash.\n                    // Let's just extract string for simplicity, given N=20, extracting substring is fast.\n                    // Actually, extracting string is O(L).\n                    // Total ops 800 * 20 * 20 * 10 = 3.2e6 per eval. Acceptable.\n                    \n                    for(int start=0; start<N; start++) {\n                        bool match = true;\n                        for(int k=0; k<L; k++) {\n                            if(current_grid[r][(start+k)%N] != S[i][k]) {\n                                match = false;\n                                break;\n                            }\n                        }\n                        if(match) { found = true; break; }\n                    }\n                    if(found) break;\n                }\n\n                if(!found) {\n                    for(int c=0; c<N; c++) {\n                        for(int start=0; start<N; start++) {\n                            bool match = true;\n                            for(int k=0; k<L; k++) {\n                                if(current_grid[(start+k)%N][c] != S[i][k]) {\n                                    match = false;\n                                    break;\n                                }\n                            }\n                            if(match) { found = true; break; }\n                        }\n                        if(found) break;\n                    }\n                }\n                \n                if(found) cnt++;\n            }\n            return cnt;\n        };\n\n        int best_score = count_matches();\n        vector<string> best_grid = current_grid;\n\n        // Simple Hill Climbing with random restarts/moves\n        // Since SA logic is similar, let's just do random perturbations keeping best.\n        // With time limit, just loop.\n        \n        int iter = 0;\n        while(true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if(elapsed > time_limit_ms - 50) break;\n\n            iter++;\n            // Random move: change a cell\n            int r = rng() % N;\n            int c = rng() % N;\n            char old_c = current_grid[r][c];\n            char new_c = 'A' + (rng() % 8); // A-H\n            \n            if(new_c == old_c) continue;\n\n            // Update grid and hashes\n            current_grid[r][c] = new_c;\n            // Re-init hashes is easiest (N=20) -> 20 strings of len 20. Very fast.\n            // No need for incremental update complexity for N=20.\n            init_hashes();\n\n            int score = count_matches();\n            if(score > best_score) {\n                best_score = score;\n                best_grid = current_grid;\n                // If perfect match, can we stop?\n                // Maybe try to reduce '.' count? \n                // Scoring bonus for '.' is only if c=M. \n                // If c=M, maximizing score means minimizing '.' (wait, re-reading problem).\n                // Score = round(1e8 * 800 / (800-d)). Larger d is better score.\n                // So if c=M, we want MORE dots.\n                // But we established that achieving c=M usually forces d small.\n                // If we reach c=M, we can try to change '.' cells to valid chars? \n                // No, we want to change VALID chars to '.' if they are not needed?\n                // That's risky. \n                // For now, maximizing c is priority.\n                if(score == M) {\n                    // We could try to clear '.' but logic is complex. \n                    // A perfect reconstruction (d=0) gives 1e8. \n                    // The problem likely expects close to 1e8.\n                }\n            } else {\n                // Revert with probability?\n                // Just revert if not improving (Hill Climbing)\n                // Actually, pure Hill Climbing gets stuck. Use simulated annealing probability.\n                // But count_matches is expensive. \n                // Let's just do: if score >= best_score, keep. \n                // Wait, we need to explore.\n                // Simple strategy: if random < 0.1 keep even if worse.\n                if(score < best_score && (rng() % 100) > 5) {\n                    current_grid[r][c] = old_c;\n                    init_hashes(); // Restore hashes\n                } else {\n                    // Kept the \"worse\" or \"better\" move. Update best if better.\n                    if(score > best_score) {\n                        best_score = score;\n                        best_grid = current_grid;\n                    }\n                }\n            }\n        }\n        \n        grid = best_grid;\n    }\n\n    void solve() {\n        // Phase 1\n        auto seqs = assemble_sequences();\n        \n        // Phase 2\n        auto grid = assign_sequences(seqs);\n        \n        // Phase 3\n        optimize_grid(grid, 2800); // Leave margin\n\n        for(auto& row : grid) cout << row << endl;\n    }\n};\n\n// ---------------------------------------------------------\n// Main\n// ---------------------------------------------------------\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for(int i=0; i<M; i++) cin >> S[i];\n\n    Solver solver(N, M, S);\n    solver.solve();\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/scc>\n#include <atcoder/modint>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\nusing point = bg::model::point<int, 2, bg::cs::cartesian>;\nusing value = std::pair<point, size_t>; // point, index in nodes\n\nusing namespace std;\n\n// Global Constants\nconst int INF = 1e9;\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\nconst char dc[4] = {'R', 'L', 'D', 'U'};\n\nstruct Input {\n    int N;\n    int si, sj;\n    vector<string> grid;\n    int total_road;\n};\n\nInput read_input() {\n    Input in;\n    cin >> in.N >> in.si >> in.sj;\n    in.grid.resize(in.N);\n    in.total_road = 0;\n    for (int i = 0; i < in.N; ++i) {\n        cin >> in.grid[i];\n        for (int j = 0; j < in.N; ++j) {\n            if (in.grid[i][j] != '#') in.total_road++;\n        }\n    }\n    return in;\n}\n\n// Hopcroft-Karp for Maximum Bipartite Matching\nclass HopcroftKarp {\npublic:\n    int n_left, n_right;\n    vector<vector<int>> adj;\n    vector<int> pair_u, pair_v, dist;\n\n    HopcroftKarp(int n_left, int n_right) : n_left(n_left), n_right(n_right), adj(n_left) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        for (int u = 0; u < n_left; ++u) {\n            if (pair_u[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = INF;\n            }\n        }\n        dist[n_left] = INF; // Dummy node for right side check\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (dist[u] < dist[n_left]) {\n                for (int v : adj[u]) {\n                    if (pair_v[v] == -1) {\n                        dist[n_left] = dist[u] + 1;\n                    } else if (dist[pair_v[v]] == INF) {\n                        dist[pair_v[v]] = dist[u] + 1;\n                        q.push(pair_v[v]);\n                    }\n                }\n            }\n        }\n        return dist[n_left] != INF;\n    }\n\n    bool dfs(int u) {\n        if (u != n_left) {\n            for (int v : adj[u]) {\n                if (pair_v[v] == -1 || (dist[pair_v[v]] == dist[u] + 1 && dfs(pair_v[v]))) {\n                    pair_u[u] = v;\n                    pair_v[v] = u;\n                    return true;\n                }\n            }\n            dist[u] = INF;\n            return false;\n        }\n        return true;\n    }\n\n    int max_matching() {\n        pair_u.assign(n_left, -1);\n        pair_v.assign(n_right, -1);\n        dist.assign(n_left + 1, 0);\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < n_left; ++u) {\n                if (pair_u[u] == -1) {\n                    if (dfs(u)) {\n                        matching++;\n                    }\n                }\n            }\n        }\n        return matching;\n    }\n    \n    // Get Minimum Vertex Cover from Maximum Matching\n    // Returns a bitset or boolean vector for left and right nodes respectively\n    pair<vector<bool>, vector<bool>> get_min_vertex_cover() {\n        vector<bool> in_cover_left(n_left, false);\n        vector<bool> in_cover_right(n_right, false);\n        \n        // Standard Konig's theorem construction:\n        // Z = { unmatched L } U { reachable from unmatched L via alternating paths }\n        // Min VC = (L \\ Z) U (R n Z)\n        // Here dist[] is used. In BFS layering, nodes with dist[] < INF are in Z (L side)\n        // But we need to re-run or use the state from the last BFS? \n        // Let's just use the pairings to find Z.\n        // Z starts with unmatched U.\n        // Then alternating paths: U -> V (not paired) -> U (paired) ...\n        \n        queue<int> q;\n        vector<bool> visited_L(n_left, false);\n        vector<bool> visited_R(n_right, false);\n        \n        for(int u=0; u<n_left; ++u) {\n            if(pair_u[u] == -1) {\n                q.push(u);\n                visited_L[u] = true;\n            }\n        }\n        \n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            for(int v : adj[u]) {\n                if(!visited_R[v]) {\n                    visited_R[v] = true;\n                    int paired_u = pair_v[v];\n                    if(paired_u != -1 && !visited_L[paired_u]) {\n                        visited_L[paired_u] = true;\n                        q.push(paired_u);\n                    }\n                }\n            }\n        }\n        \n        for(int u=0; u<n_left; ++u) {\n            if(!visited_L[u]) in_cover_left[u] = true;\n        }\n        for(int v=0; v<n_right; ++v) {\n            if(visited_R[v]) in_cover_right[v] = true;\n        }\n        \n        return {in_cover_left, in_cover_right};\n    }\n};\n\n// Dijkstra\nvector<int> dijkstra(const Input& in, pair<int, int> start, const vector<pair<int,int>>& targets) {\n    int N = in.N;\n    int s_dist = start.first * N + start.second;\n    vector<int> dist(N*N, INF);\n    dist[s_dist] = 0;\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, s_dist});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    return dist;\n}\n\nstring get_path(const Input& in, pair<int,int> s, pair<int,int> t) {\n    // Reconstruct path using simplified Dijkstra or A* since we just need one path\n    // Given N is small, Dijkstra with prev pointer is fine.\n    int N = in.N;\n    int s_idx = s.first * N + s.second;\n    int t_idx = t.first * N + t.second;\n    \n    vector<int> dist(N*N, INF);\n    vector<int> prev(N*N, -1);\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    dist[s_idx] = 0;\n    pq.push({0, s_idx});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (idx == t_idx) break;\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                prev[nidx] = k; // store direction\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    \n    string path = \"\";\n    int curr = t_idx;\n    while(curr != s_idx) {\n        int dir = prev[curr];\n        path += dc[dir];\n        // reverse direction to go back\n        int rdir;\n        if(dir==0) rdir=1; if(dir==1) rdir=0; if(dir==2) rdir=3; if(dir==3) rdir=2;\n        \n        int ci = curr / N;\n        int cj = curr % N;\n        ci += dx[rdir];\n        cj += dy[rdir];\n        curr = ci * N + cj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid solve() {\n    Input in = read_input();\n    int N = in.N;\n    \n    // 1. Identify Segments\n    vector<vector<int>> h_id(N, vector<int>(N, -1));\n    vector<vector<int>> v_id(N, vector<int>(N, -1));\n    int h_cnt = 0, v_cnt = 0;\n    \n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                if(j>0 && in.grid[i][j-1] != '#' && h_id[i][j-1] != -1) {\n                    h_id[i][j] = h_id[i][j-1];\n                } else {\n                    h_id[i][j] = h_cnt++;\n                }\n            }\n        }\n    }\n    \n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        for(int i=0; i<N; ++i) {\n            if(in.grid[i][j] != '#') {\n                if(i>0 && in.grid[i-1][j] != '#' && v_id[i-1][j] != -1) {\n                    v_id[i][j] = v_id[i-1][j];\n                } else {\n                    v_id[i][j] = v_cnt++;\n                }\n            }\n        }\n    }\n    \n    // 2. Build Bipartite Graph\n    HopcroftKarp hk(h_cnt, v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                hk.add_edge(h_id[i][j], v_id[i][j]);\n            }\n        }\n    }\n    \n    // 3. Solve Min Vertex Cover\n    hk.max_matching();\n    auto [cover_h, cover_v] = hk.get_min_vertex_cover();\n    \n    // Set of covered segments\n    vector<bool> covered_h_seg = cover_h; // rename for clarity\n    vector<bool> covered_v_seg = cover_v;\n    \n    // 4. Select Key Points\n    // We need to visit points such that every segment in the cover is visited.\n    // Strategy: Collect all intersection points of segments in the cover.\n    // Also add representative points for segments in cover that might be isolated.\n    \n    set<pair<int, int>> key_points_set;\n    vector<pair<int, int>> key_points;\n    \n    auto add_point = [&](int i, int j) {\n        if(key_points_set.count({i,j}) == 0) {\n            key_points_set.insert({i,j});\n            key_points.push_back({i,j});\n        }\n    };\n\n    // Add intersections of covered segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                int hid = h_id[i][j];\n                int vid = v_id[i][j];\n                if(covered_h_seg[hid] && covered_v_seg[vid]) {\n                    add_point(i, j);\n                }\n            }\n        }\n    }\n    \n    // Add representative points for segments that are not \"covered\" by the intersections logic\n    // (i.e., segments in cover that don't intersect any other segment in cover)\n    // A segment is satisfied if we visit at least one point on it.\n    // So we ensure for each segment in cover, there is a key point on it.\n    \n    // Find segments without intersection\n    vector<bool> h_has_intersect(h_cnt, false);\n    vector<bool> v_has_intersect(v_cnt, false);\n    for(auto p : key_points) {\n        int i = p.first, j = p.second;\n        h_has_intersect[h_id[i][j]] = true;\n        v_has_intersect[v_id[i][j]] = true;\n    }\n    \n    // For segments in cover without intersection, add their point closest to Start\n    // Or just middle point. Middle point is safer and faster.\n    vector<vector<pair<int,int>>> h_cells(h_cnt);\n    vector<vector<pair<int,int>>> v_cells(v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                h_cells[h_id[i][j]].push_back({i,j});\n                v_cells[v_id[i][j]].push_back({i,j});\n            }\n        }\n    }\n    \n    for(int i=0; i<h_cnt; ++i) {\n        if(covered_h_seg[i] && !h_has_intersect[i]) {\n            // Add middle cell\n            int mid = h_cells[i].size() / 2;\n            add_point(h_cells[i][mid].first, h_cells[i][mid].second);\n        }\n    }\n    for(int i=0; i<v_cnt; ++i) {\n        if(covered_v_seg[i] && !v_has_intersect[i]) {\n            int mid = v_cells[i].size() / 2;\n            add_point(v_cells[i][mid].first, v_cells[i][mid].second);\n        }\n    }\n    \n    // Make sure start point is in key points to build the cycle\n    add_point(in.si, in.sj);\n    \n    // 5. Compute Distances between Key Points\n    int K = key_points.size();\n    vector<vector<int>> dist(K, vector<int>(K, INF));\n    \n    // Optimization: Only run Dijkstra from each point. K should be small.\n    // Map point to index\n    map<pair<int,int>, int> pt_to_idx;\n    for(int i=0; i<K; ++i) pt_to_idx[key_points[i]] = i;\n    \n    for(int i=0; i<K; ++i) {\n        auto ds = dijkstra(in, key_points[i], key_points);\n        for(int j=0; j<K; ++j) {\n            int idx = key_points[j].first * N + key_points[j].second;\n            dist[i][j] = ds[idx];\n        }\n    }\n    \n    // 6. Construct Path\n    // Greedy insertion to ensure coverage, then 2-opt\n    \n    int start_idx = pt_to_idx[{in.si, in.sj}];\n    \n    // Current Path: [start_idx]\n    vector<int> path = {start_idx};\n    // Current coverage: segments containing S\n    vector<bool> visited_h(h_cnt, false);\n    vector<bool> visited_v(v_cnt, false);\n    \n    auto visit_pt = [&](int idx) {\n        int i = key_points[idx].first;\n        int j = key_points[idx].second;\n        visited_h[h_id[i][j]] = true;\n        visited_v[v_id[i][j]] = true;\n    };\n    visit_pt(start_idx);\n    \n    // Check if all covered segments are satisfied\n    auto all_covered = [&]() {\n        for(int i=0; i<h_cnt; ++i) if(covered_h_seg[i] && !visited_h[i]) return false;\n        for(int i=0; i<v_cnt; ++i) if(covered_v_seg[i] && !visited_v[i]) return false;\n        return true;\n    };\n    \n    // Greedy Insertion\n    while(!all_covered()) {\n        int best_k = -1;\n        int best_pos = -1;\n        int best_gain = -INF;\n        int best_cost = INF;\n        \n        for(int k=0; k<K; ++k) {\n            if(find(path.begin(), path.end(), k) != path.end()) continue;\n            \n            // Gain: number of newly covered segments\n            int i = key_points[k].first;\n            int j = key_points[k].second;\n            int gain = 0;\n            if(covered_h_seg[h_id[i][j]] && !visited_h[h_id[i][j]]) gain++;\n            if(covered_v_seg[v_id[i][j]] && !visited_v[v_id[i][j]]) gain++;\n            \n            if(gain == 0) continue;\n            \n            // Find best insertion position\n            for(int pos=0; pos<=path.size(); ++pos) {\n                int u = (pos==0) ? path.back() : path[pos-1];\n                int v = (pos==path.size()) ? path[0] : path[pos];\n                \n                // Cost change: dist[u][k] + dist[k][v] - dist[u][v]\n                int delta = dist[u][k] + dist[k][v] - dist[u][v];\n                \n                if(gain * best_cost > best_gain * delta) {\n                    best_gain = gain;\n                    best_cost = delta;\n                    best_k = k;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if(best_k == -1) {\n            // Should not happen if graph is connected and cover is valid\n            // Fallback: add any unvisited point on required segments\n            // (omitted for brevity, break to prevent infinite loop)\n            break; \n        }\n        \n        path.insert(path.begin() + best_pos, best_k);\n        visit_pt(best_k);\n    }\n    \n    // 2-opt Optimization\n    // Simple 2-opt loop\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int n = path.size();\n        for(int i=0; i<n; ++i) {\n            for(int j=i+2; j<n + (i>0 ? 1 : 0); ++j) {\n                // Edge (i, i+1) and (j, j+1) become (i, j) and (i+1, j+1)\n                int u = path[i];\n                int v = path[(i+1)%n];\n                int x = path[j%n];\n                int y = path[(j+1)%n];\n                \n                int current = dist[u][v] + dist[x][y];\n                int proposal = dist[u][x] + dist[v][y];\n                \n                if(proposal < current) {\n                    // Reverse path between i+1 and j\n                    reverse(path.begin() + (i+1)%n, path.begin() + (j%n) + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Generate Output String\n    string full_path = \"\";\n    int p_sz = path.size();\n    for(int i=0; i<p_sz; ++i) {\n        int u = path[i];\n        int v = path[(i+1)%p_sz];\n        string sub = get_path(in, key_points[u], key_points[v]);\n        full_path += sub;\n    }\n    \n    cout << full_path << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for problem parameters\nint N, M, K, R;\nvector<vector<int>> d; // Task requirements d[1..N][1..K]\nvector<vector<int>> adj; // Graph adjacency list (dependencies)\nvector<int> in_degree; // In-degree of tasks\nvector<int> task_state; // 0: pending, 1: available, 2: assigned/completed\nvector<int> start_day; // Day when task started\n\nvector<vector<double>> s; // Estimated skills s[1..M][1..K]\nvector<int> member_task; // Task assigned to member (-1 if idle)\nvector<vector<int>> rev_adj; // For processing dependents, though standard adj works if we update deg\n\n// Parameters for skill estimation\nconst double LEARNING_RATE = 0.1;\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n        }\n    }\n\n    adj.resize(N);\n    rev_adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u); // Actually we need forward adj to update deps?\n        // We need to know which tasks unlock when task u finishes. \n        // So adj[u] should list dependents v.\n        // Input format: (u, v) means v depends on u. So u -> v.\n        // This matches the logic: when u finishes, v's pending count decreases.\n        in_degree[v]++;\n    }\n\n    // Initialize task states\n    task_state.resize(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            task_state[i] = 1;\n        }\n    }\n\n    // Initialize estimated skills\n    // Based on generation: task len ~ 10-40, member len ~ 20-60.\n    // Initialize with a safe guess like 25.\n    s.resize(M, vector<double>(K, 25.0));\n\n    member_task.resize(M, -1);\n    start_day.resize(N, -1);\n\n    int day = 0;\n    while (true) {\n        day++;\n        \n        // --- Assignment Phase ---\n        vector<pair<int, int>> assignments; // (member, task)\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n\n        // Find available tasks (state == 1)\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 1) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Greedy Assignment\n        // Try to assign idle members to available tasks\n        // Heuristic: For each member, pick the task with minimum estimated cost\n        \n        // We iterate through idle members. For each, find best task.\n        // To avoid assigning the same task to multiple members, we mark tasks as assigned (state 2).\n        \n        for (int j : idle_members) {\n            if (available_tasks.empty()) break;\n\n            int best_task = -1;\n            double min_cost = 1e9;\n\n            // Evaluate all currently available tasks for this member\n            for (int t_idx = 0; t_idx < static_cast<int>(available_tasks.size()); ++t_idx) {\n                int i = available_tasks[t_idx];\n                \n                // Calculate estimated cost w_{i,j}\n                double cost = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = d[i][k] - s[j][k];\n                    if (diff > 0) {\n                        cost += diff;\n                    }\n                }\n                // If cost is 0, it's a perfect match (expected t=1), very high priority.\n                // Add small random jitter to break ties and add exploration\n                // But deterministic is safer for reproducibility unless random is needed.\n                // Let's stick to min cost.\n\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_task = t_idx; // index in available_tasks\n                }\n            }\n\n            if (best_task != -1) {\n                int task_id = available_tasks[best_task];\n                assignments.push_back({j + 1, task_id + 1}); // Output is 1-indexed\n                \n                member_task[j] = task_id;\n                task_state[task_id] = 2; // Mark as assigned\n                start_day[task_id] = day;\n                \n                // Remove from available list (swap with last and pop)\n                available_tasks[best_task] = available_tasks.back();\n                available_tasks.pop_back();\n            }\n        }\n\n        // --- Output ---\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n\n        // --- Input Phase ---\n        string line;\n        if (!getline(cin, line)) {\n            // Should not happen usually, but handle EOF\n            break;\n        }\n        // The input reading is a bit tricky. We need to read the line that judge provides.\n        // However, standard cin >> n might hang if not handled correctly with getline.\n        // The sample shows input format: `n f1 ... fn` or `-1`.\n        // Let's use a stringstream or direct cin >>.\n        \n        // Re-reading logic: Since we flushed, judge replies.\n        // We need to read the line. If we used cin >> for initial data, buffer might have newline?\n        // No, initial data ends with newlines. The loop logic:\n        // 1. We output.\n        // 2. We read.\n        \n        // Use getline to read the whole line for safety, then parse.\n        // But wait, we are inside a loop. We need to ensure we read the *response* to our output.\n        \n        // Let's use cin directly to parse integers.\n        int n_finished;\n        if (!(cin >> n_finished)) break;\n\n        if (n_finished == -1) {\n            break; // All tasks done or timeout\n        }\n\n        vector<int> finished_members(n_finished);\n        for (int i = 0; i < n_finished; ++i) {\n            cin >> finished_members[i];\n            finished_members[i]--; // Convert to 0-indexed\n        }\n\n        // --- Update State ---\n        for (int member_idx : finished_members) {\n            int task_idx = member_task[member_idx];\n            if (task_idx == -1) continue; // Should not happen\n\n            // Calculate duration\n            int t = day - start_day[task_idx] + 1;\n            \n            // Update Skills (Stochastic Gradient Descent)\n            // We want s such that sum(max(0, d - s)) approx t.\n            // Current estimated cost C\n            double C = 0.0;\n            vector<int> deficit_dims;\n            for (int k = 0; k < K; ++k) {\n                double diff = d[task_idx][k] - s[member_idx][k];\n                if (diff > 0) {\n                    C += diff;\n                    deficit_dims.push_back(k);\n                }\n            }\n\n            // Error = t - C. If t > C, we underestimated difficulty, skills are too high. Decrease s.\n            // If t < C, we overestimated, skills are too low. Increase s.\n            // However, if C was 0, and t > 1, we thought we were perfect but we weren't.\n            \n            double error = t - C;\n            \n            // Update skills in dimensions where we had deficit\n            // If no deficit_dims (C=0), we need to identify which dimension to decrease.\n            // If C > 0, we just adjust the deficit dimensions.\n            \n            if (!deficit_dims.empty()) {\n                // Distribute update over deficit dimensions\n                double update_per_dim = LEARNING_RATE * error / deficit_dims.size();\n                for (int k : deficit_dims) {\n                    s[member_idx][k] += update_per_dim;\n                    if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                }\n            } else {\n                // C = 0. All s >= d.\n                // If error > 0 (t > C), we need to increase cost, so decrease s.\n                // We don't know which k to decrease.\n                // Heuristic: decrease dimensions where d is largest (most likely to be bottleneck if we are just barely under).\n                // Or decrease all uniformly?\n                // Let's decrease all dimensions slightly.\n                if (error > 0) {\n                    double update_per_dim = LEARNING_RATE * error / K;\n                    for (int k = 0; k < K; ++k) {\n                        s[member_idx][k] -= update_per_dim;\n                        if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                    }\n                }\n            }\n            \n            // Mark task completed\n            // Actually task_state is 2 (assigned). We can mark it 3 or just keep 2 as 'not available'.\n            // We just need to process dependencies.\n            // We don't have a 'completed' state distinct from assigned in terms of availability,\n            // but we should know it's done. \n            // member_task[member_idx] = -1; // Mark member idle\n            \n            // Update dependencies\n            for (int dependent_task : adj[task_idx]) {\n                in_degree[dependent_task]--;\n                if (in_degree[dependent_task] == 0) {\n                    task_state[dependent_task] = 1; // Now available\n                }\n            }\n            \n            member_task[member_idx] = -1;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nconst int CENTER = 1000; // Special index for Center\n\nint dist(const vector<pair<int, int>>& points, int i, int j) {\n    if (i == CENTER) return 400 - points[j].first + 400 - points[j].second; // dist from Center\n    if (j == CENTER) return points[i].first - 400 + points[i].second - 400; // dist to Center\n    return abs(points[i].first - points[j].first) + abs(points[i].second - points[j].second);\n}\n\nint dist_center(int x, int y) {\n    return abs(400 - x) + abs(400 - y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    int N = 1000;\n    vector<Order> orders(N);\n    // We will use points index: 0..999 for Pickup, 1000..1999 for Delivery\n    // Center is 2000 (or handled separately)\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n        orders[i].id = i + 1;\n    }\n    \n    // Best solution found\n    int best_score = -1;\n    vector<int> best_route_indices;\n    vector<int> best_order_ids;\n    long long best_len = 1e18;\n    \n    // We have time limit 2.0s. Let's run a few iterations of the heuristic with different random seeds or perturbations.\n    // Given the complexity, a single good run with local search might be sufficient, but multiple restarts helps escape local optima.\n    int NUM_ITERATIONS = 5;\n    \n    for (int iter = 0; iter < NUM_ITERATIONS; ++iter) {\n        // --- 1. Construction Phase (Greedy Insertion) ---\n        vector<int> used(N, 0);\n        vector<int> route_indices; // Stores point indices (0-999 for P, 1000-1999 for D)\n        route_indices.push_back(CENTER); // Start at center\n        \n        // Shuffle orders for randomness in selection if costs are equal, or just to explore different construction paths\n        // Actually, to make the greedy deterministic but good, we shouldn't shuffle for evaluation.\n        // We iterate all orders and pick the best.\n        \n        for (int step = 0; step < 50; ++step) {\n            int best_order = -1;\n            int best_delta = 1e9;\n            int best_u = -1;\n            int best_v = -1;\n            \n            // Pre-calculate coordinates for current route to speed up dist queries\n            // But constructing points vector on the fly is easy.\n            vector<pair<int, int>> current_points;\n            for (int idx : route_indices) {\n                if (idx == CENTER) current_points.push_back({400, 400});\n                else if (idx < 1000) current_points.push_back({orders[idx].a, orders[idx].b});\n                else current_points.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            \n            // Candidate selection (top-K)\n            // To avoid O(1000 * L^2) every step, we do a coarse filter.\n            vector<pair<int, int>> candidates; // {cost, order_id}\n            \n            for (int i = 0; i < N; ++i) {\n                if (used[i]) continue;\n                \n                // Est cost: dist(Route, P_i) + dist(P_i, D_i) + dist(D_i, Route)\n                int min_dist_P = 1e9;\n                int min_pos_P = -1;\n                int min_dist_D = 1e9;\n                int min_pos_D = -1;\n\n                // Find closest point in route to P_i and D_i\n                for (size_t k = 0; k < current_points.size(); ++k) {\n                    int dP = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    if (dP < min_dist_P) {\n                        min_dist_P = dP;\n                        min_pos_P = k;\n                    }\n                    int dD = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                    if (dD < min_dist_D) {\n                        min_dist_D = dD;\n                        min_pos_D = k;\n                    }\n                }\n                \n                // internal dist\n                int d_internal = abs(orders[i].a - orders[i].c) + abs(orders[i].b - orders[i].d);\n                int est_cost = min_dist_P + d_internal + min_dist_D;\n                \n                candidates.push_back({est_cost, i});\n            }\n            \n            // Sort by estimated cost and take top 30\n            sort(candidates.begin(), candidates.end());\n            if (candidates.size() > 30) candidates.resize(30);\n            \n            // Detailed check for top candidates\n            for (auto& cand : candidates) {\n                int i = cand.second;\n                \n                // Find exact best insertion for P_i\n                // Route has L points. Indices 0 to L-1.\n                // Insert P_i at u (between u-1 and u)\n                // Insert D_i at v (between v-1 and v), where v > u+1 (since P_i takes a spot)\n                \n                int L = route_indices.size();\n                \n                // Optimize: We can precompute distances to all nodes for P_i and D_i\n                vector<int> dists_P(L), dists_D(L);\n                for (int k = 0; k < L; ++k) {\n                    dists_P[k] = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    dists_D[k] = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                }\n                \n                // Current route edges distances (sum of edges)\n                // We compute delta added - delta removed\n                \n                for (int u = 1; u < L; ++u) {\n                    // Insert P_i between u-1 and u\n                    // Removed edge: (u-1, u). Added edges: (u-1, P_i), (P_i, u)\n                    // Note: route is path, not cycle. Center is at 0.\n                    // Edge indices: (0,1), (1,2), ..., (L-2, L-1)\n                    // But we treat insert positions as 'slots' between points.\n                    // Insert at pos u means after point u-1, before point u.\n                    // Valid u: 1 to L-1. (After Center is 1, After last is L-1)\n                    // Actually, we can append? No, route must end at Center eventually?\n                    // Greedy construction builds a path that starts at Center. \n                    // The final step will add dist(last, center).\n                    // So yes, we can insert at the end (u = L).\n                    \n                    // Cost to insert P at u\n                    int edge_old_u = (u < L) ? dists_P[u-1] + dists_P[u] - (abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second)) : dists_P[u-1];\n                    // Wait, calculating delta properly:\n                    // Base edge cost E_u = dist(route[u-1], route[u]) for u < L. \n                    // For u = L, E_L = 0 (virtual edge to nothing? no, last point connects to nothing yet)\n                    \n                    int delta_P = 0;\n                    int old_u = 0;\n                    if (u < L) {\n                         old_u = abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                         delta_P = dists_P[u-1] + dists_P[u] - old_u;\n                    } else {\n                        delta_P = dists_P[u-1];\n                    }\n                    \n                    // For D_i, insert at v > u. \n                    // Since P_i is inserted, the indices shift. \n                    // Let's say we insert P at u. The new length is L+1.\n                    // D can be inserted at v from u+1 to L.\n                    // The points involved: \n                    // segment (u-1) -> P -> (u) -> ... -> (v-1) -> (v)\n                    // New: (u-1) -> P -> (u) ... -> (v-1) -> D -> (v)\n                    \n                    // Distance from P_i to next point (original u) is dists_P[u].\n                    // Distance from prev point (original v-1) to D_i is dists_D[v-1].\n                    // Distance from D_i to next point (original v) is dists_D[v].\n                    \n                    for (int v = u + 1; v <= L; ++v) {\n                        int delta_D = 0;\n                        if (v < L) {\n                            int old_v = abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            // P_i is at index u (0-based in new array, but original indices...)\n                            // Current points array indices: 0 to L-1.\n                            // P is inserted at index u-1 in the \"gap\" sense?\n                            // Let's stick to \"insert before old index k\" logic.\n                            // u is index in OLD route. P inserted before route[u].\n                            // v is index in OLD route. D inserted before route[v].\n                            // Condition: u < v.\n                            // If v == u+1, sequence is ..., route[u-1], P, D, route[u], ...\n                            // If v == L, sequence is ..., route[u-1], P, ..., route[L-1], D.\n                            \n                            int dist_P_next = (u < L) ? dists_P[u] : 0; // dist(P, route[u])\n                            \n                            // dist(route[v-1], D)\n                            int dist_prev_D = dists_D[v-1]; \n                            // dist(D, route[v])\n                            int dist_D_next = dists_D[v];\n                            \n                            // Edge broken: (route[u-1], route[u]) and (route[v-1], route[v])\n                            // Wait, if u and v are far apart, edges between u and v-1 are shifted but not broken?\n                            // The segment route[u] ... route[v-1] shifts right by 2. No internal distance change.\n                            // Only edges at insertion points change.\n                            // 1. Edge (route[u-1], route[u]) becomes (route[u-1], P) and (P, route[u]) ?\n                            // No, route[u] moves to u+1. P is at u.\n                            // So we replace (u-1, u) with (u-1, P) and (P, u).\n                            // Wait, if v = u+1. Then (u-1, u) -> (i-1, P), (P, u). \n                            // And (u, u+1) -> (D, u+1)?\n                            // Actually, simpler:\n                            // Old edges: (u-1, u) and (v-1, v).\n                            // New edges: (u-1, P), (P, v-1) -- NO.\n                            // The path is ... -> u-1 -> P -> u -> ... -> v-1 -> D -> v -> ...\n                            // Old edges broken: (u-1, u), (v-1, v).\n                            // New edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Note: if u == v-1, then (u-1, u) broken, (u, u+1) broken. \n                            // Path ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Broken: (u-1, u), (u, u+1).\n                            // New: (u-1, P), (P, D), (D, u+1).\n                            \n                            // General case:\n                            // Removed: dist(u-1, u) + dist(v-1, v).\n                            // Added: dist(u-1, P) + dist(P, u) + dist(v-1, D) + dist(D, v).\n                            \n                            int removed = 0;\n                            if (u < L) removed += abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                            else removed = 0; // u == L\n                            \n                            if (v < L) removed += abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            else removed += 0; // v == L\n\n                            int added = dists_P[u-1];\n                            if (u < L) added += dists_P[u];\n                            else added += 0;\n                            \n                            added += dists_D[v-1];\n                            if (v < L) added += dists_D[v];\n                            else added += 0;\n                            \n                            // If u == v-1 (consecutive insertions), P connects to D?\n                            // Logic: ... -> u-1 -> P -> u -> ...\n                            // If v = u+1: ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Edges added: (u-1, P), (P, D), (D, u+1).\n                            // dists_P[u] is dist(P, route[u]). \n                            // dists_D[u] is dist(D, route[u]).\n                            // My logic above:\n                            // Added: dist(u-1, P) + dist(P, u) + dist(u, D) + dist(D, u+1).\n                            // Wait, v-1 = u. So dists_D[v-1] = dist(D, route[u]).\n                            // Correct.\n                            // What if u and v are not consecutive?\n                            // ... -> u-1 -> P -> u -> u+1 -> ... -> v-1 -> D -> v -> ...\n                            // Edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Correct.\n                            \n                            // Wait, there is a case where u > v?\n                            // We loop u from 1 to L. v from u+1 to L. So u < v always.\n                            // This ensures P is before D.\n                            \n                            int delta = added - removed;\n                            if (delta < best_delta) {\n                                best_delta = delta;\n                                best_order = i;\n                                best_u = u;\n                                best_v = v;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (best_order != -1) {\n                used[best_order] = 1;\n                // Insert P\n                route_indices.insert(route_indices.begin() + best_u, best_order);\n                // Insert D (index shifted by 1 because P was inserted)\n                route_indices.insert(route_indices.begin() + best_v, best_order + 1000);\n            }\n        }\n        \n        // Add final return to center\n        // Route construction logic didn't account for return to center yet, \n        // but since we always start at Center (index 0), and we never insert before it,\n        // and we only append/insert after, the route is valid path.\n        // Total length will be calculated later.\n        \n        // --- 2. Optimization Phase (2-opt + Order Swap) ---\n        \n        // Helper to calculate total length\n        auto calc_len = [&](const vector<int>& route) -> long long {\n            long long len = 0;\n            vector<pair<int, int>> coords;\n            for (int idx : route) {\n                if (idx == CENTER) coords.push_back({400, 400});\n                else if (idx < 1000) coords.push_back({orders[idx].a, orders[idx].b});\n                else coords.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            for (size_t i = 0; i < coords.size() - 1; ++i) {\n                len += abs(coords[i].first - coords[i+1].first) + abs(coords[i].second - coords[i+1].second);\n            }\n            len += abs(coords.back().first - 400) + abs(coords.back().second - 400); // Return to center\n            return len;\n        };\n        \n        // 2-opt\n        // Route: Center, ..., last\n        // Cycle is Center -> ... -> last -> Center.\n        // Indices in `route_indices` vector: 0, 1, ..., M.\n        // 2-opt swaps edges (i, i+1) and (j, j+1) for 0 <= i < j < M.\n        // Segment [i+1, j] is reversed.\n        // Note: Center (index 0) is fixed? \n        // Actually, standard 2-opt on the cycle.\n        // The cycle is nodes 0..M where 0 is Center.\n        // Edge (M, 0) exists (return to center).\n        // If we include edge (M, 0) in swaps, we might move Center? No, Center is fixed node 0.\n        // But the edge (M, 0) can be swapped with (i, i+1).\n        // That would mean segment [i+1, M] is reversed, and 0 connects to M, i connects to 0?\n        // Standard 2-opt logic on array `route`:\n        // Edges are (0,1), (1,2), ..., (M-1, M), (M, 0).\n        // We fix node 0 (Center) at position 0.\n        // Edges (k, k+1) for k=0..M-1.\n        // Edge (M, 0) is special.\n        \n        // Let's treat the route as Center fixed at start.\n        // We can swap edges (u, u+1) and (v, v+1) where 0 <= u < v < M.\n        // New path: 0 -> ... -> u -> v -> v-1 -> ... -> u+1 -> v+1 -> ... -> M -> 0.\n        // Constraint: For every order k, P_k before D_k.\n        // Reversing segment [u+1, v].\n        \n        // Validity check:\n        // Map order id -> indices of P and D in route.\n        \n        bool improved = true;\n        while (improved && (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800)) {\n            improved = false;\n            int M = route_indices.size();\n            \n            // Precompute positions for validity check\n            // This changes every swap, so recomputing is slow.\n            // Check validity of swap locally.\n            // Segment [u+1, v] reversed.\n            // For an order with nodes at p, q:\n            // If p and q are both in [u+1, v], their relative order reverses -> INVALID (unless we check specific case, but generally P before D fails).\n            //   Wait, if P is before D in original, after reversal P is after D. So INVALID.\n            //   Exception: If we reverse a segment containing P and D, it becomes invalid.\n            //   So swap is valid ONLY IF for every order, it has 0 or 1 nodes in the segment.\n            //   If it has 1 node, the node moves, but P is still before D relative to outside nodes?\n            //   Consider P inside, D outside (after segment). Original: ... P ... D. After rev: ... (rev) ... D. P moves to end of segment. Still before D. OK.\n            //   Consider P outside (before segment), D inside. Original: P ... D. After rev: P ... (rev) ... D. D moves to start of segment. Still after P. OK.\n            //   So condition: No order has BOTH P and D in the segment.\n            \n            for (int u = 0; u < M - 1; ++u) {\n                // Optimization: only iterate v reasonably far? Standard 2-opt is O(N^2).\n                for (int v = u + 1; v < M; ++v) {\n                    // Check validity\n                    bool valid = true;\n                    // Scan segment [u+1, v]\n                    // Use a frequency array for current segment scan?\n                    // N=50, so 100 nodes. Scanning 100 orders for each pair is 10,000 checks per pair.\n                    // Pairs 5000. Total 50M. A bit high but doable in C++.\n                    // Faster: count P and D in segment.\n                    vector<char> in_segment(N, 0);\n                    for (int k = u + 1; k <= v; ++k) {\n                        int idx = route_indices[k];\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (idx < 1000) in_segment[oid] |= 1; // P\n                        else in_segment[oid] |= 2; // D\n                        if (in_segment[oid] == 3) {\n                            valid = false;\n                            break;\n                        }\n                    }\n                    if (!valid) continue;\n                    \n                    // Calculate delta\n                    // Edges removed: (u, u+1) and (v, v+1)\n                    // Edges added: (u, v) and (u+1, v+1)\n                    // Note: v < M, so v+1 exists.\n                    // Coordinates\n                    auto get_pt = [&](int idx) -> pair<int,int> {\n                        if (idx == CENTER) return {400, 400};\n                        if (idx < 1000) return {orders[idx].a, orders[idx].b};\n                        return {orders[idx-1000].c, orders[idx-1000].d};\n                    };\n\n                    auto p_u = get_pt(route_indices[u]);\n                    auto p_u1 = get_pt(route_indices[u+1]);\n                    auto p_v = get_pt(route_indices[v]);\n                    auto p_v1 = get_pt(route_indices[v+1]);\n                    \n                    long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                      + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                    long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                     + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                    \n                    if (added < removed) {\n                        // Perform swap\n                        reverse(route_indices.begin() + u + 1, route_indices.begin() + v + 1);\n                        improved = true;\n                        // Reset search? Or continue?\n                        // With found improvement, resetting loops is safer to find new structure.\n                        // But breaking and restarting outer loop is standard.\n                        goto next_opt_pass; \n                    }\n                }\n            }\n            next_opt_pass:;\n        }\n        \n        // Local Search: Swap one order\n        // Try removing an order and inserting another\n        for (int step = 0; step < 5; ++step) {\n            if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 1900) break;\n            \n            // Current route length\n            long long current_len = calc_len(route_indices);\n            \n            // Try remove each order\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) continue;\n                \n                // Remove order i\n                auto it_p = find(route_indices.begin(), route_indices.end(), i);\n                auto it_d = find(route_indices.begin(), route_indices.end(), i + 1000);\n                if (it_p == route_indices.end() || it_d == route_indices.end()) continue;\n                \n                int pos_p = distance(route_indices.begin(), it_p);\n                int pos_d = distance(route_indices.begin(), it_d);\n                \n                // Indices: pos_p < pos_d\n                // Remove D then P to keep indices correct\n                route_indices.erase(it_d);\n                route_indices.erase(route_indices.begin() + pos_p);\n                \n                // Try insert all j not used\n                bool found_better = false;\n                for (int j = 0; j < N; ++j) {\n                    if (used[j] || j == i) continue;\n                    \n                    // Try insert P_j and D_j optimally\n                    // Similar to construction but smaller\n                    int L = route_indices.size();\n                    \n                    // We need to calculate insertion cost\n                    // This is O(L^2) per j. N ~ 1000. L ~ 100. 1000 * 10000 = 10M.\n                    // Plus the loop over i (50). Total 500M. Too slow.\n                    // Optimization: Only try a subset of j?\n                    // Or only try replacing with \"good\" candidates?\n                    // Or break early.\n                    \n                    // Just pick the best j to insert.\n                    // We can check the \"approximate\" cost of j first.\n                    // dist(route, P_j) + dist(P_j, D_j) + dist(D_j, route)\n                    \n                    // Let's limit this local search.\n                    // Instead of iterating all i, iterate random i.\n                    // Instead of iterating all j, iterate top 50 candidates.\n                }\n                \n                // Revert if not better\n                route_indices.insert(route_indices.begin() + pos_p, i);\n                route_indices.insert(route_indices.begin() + pos_d, i + 1000);\n            }\n        }\n\n        // Calculate final length for this iteration\n        long long current_len = calc_len(route_indices);\n        if (current_len < best_len) {\n            best_len = current_len;\n            best_route_indices = route_indices;\n            // best_order_ids not needed if we reconstruct from route_indices\n        }\n    }\n    \n    // --- Output ---\n    // Extract order IDs from best_route_indices\n    vector<int> final_orders;\n    set<int> seen;\n    for (int idx : best_route_indices) {\n        if (idx == CENTER) continue;\n        int oid = (idx < 1000) ? idx : idx - 1000;\n        if (seen.find(oid) == seen.end()) {\n            final_orders.push_back(oid + 1);\n            seen.insert(oid);\n        }\n    }\n    // final_orders should be 50.\n    // Ensure exactly 50? My logic inserts exactly 50.\n    \n    // Output format\n    // m r1 ... rm\n    // n x1 y1 ... xn yn\n    \n    cout << 50;\n    for (int oid : final_orders) cout << \" \" << oid;\n    cout << \"\\n\";\n    \n    cout << best_route_indices.size() + 1; // +1 for final Center\n    for (int idx : best_route_indices) {\n        int x, y;\n        if (idx == CENTER) { x = 400; y = 400; }\n        else if (idx < 1000) { x = orders[idx].a; y = orders[idx].b; }\n        else { x = orders[idx-1000].c; y = orders[idx-1000].d; }\n        cout << \" \" << x << \" \" << y;\n    }\n    // Final center\n    cout << \" \" << 400 << \" \" << 400 << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct DSU {\n    vector<int> parent;\n    int components;\n\n    DSU(int n) : parent(n), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        components--;\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Fixed constraints\n    int N = 400;\n    int M = 1995;\n\n    vector<pair<int, int>> points(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = points[edges[i].u].first - points[edges[i].v].first;\n        int dy = points[edges[i].u].second - points[edges[i].v].second;\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        edges[i].d = (int)round(dist);\n    }\n\n    DSU dsu(N);\n    int taken = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        // If we already have a spanning tree, we don't need more edges (though we should output 0)\n        // The problem statement implies we must output 0 or 1 for all inputs.\n        // But if taken == N-1, we reject all remaining to save cost (no need to add cycles).\n        if (taken == N - 1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int need = dsu.components - 1;\n        \n        // Collect distances of remaining useful edges\n        vector<int> candidate_ds;\n        candidate_ds.reserve(M - i - 1);\n        \n        for (int j = i + 1; j < M; ++j) {\n            // Check if edge j connects different components\n            if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                candidate_ds.push_back(edges[j].d);\n            }\n        }\n\n        // If we don't have enough candidates in the future, we must take the current one\n        if ((int)candidate_ds.size() < need) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n        } else {\n            // Find the distance of the 'need'-th shortest edge in the future candidates\n            // This represents the \"worst\" edge we expect to take in an optimal future scenario\n            sort(candidate_ds.begin(), candidate_ds.end());\n            int d_ref = candidate_ds[need - 1];\n            \n            // Heuristic threshold: take current edge if its cost l is <= 2 * d_ref\n            // 2 * d_ref is the expected cost of an edge with distance d_ref\n            // This is a \"secretary problem\" style threshold.\n            int threshold = 2 * d_ref;\n\n            if (l <= threshold) {\n                cout << 1 << endl;\n                dsu.unite(u, v);\n                taken++;\n            } else {\n                cout << 0 << endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multi_array.hpp>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int TURNS = 300;\nconstexpr int DX[4] = {0, 0, 1, -1};\nconstexpr int DY[4] = {1, -1, 0, 0};\nconstexpr char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\nconstexpr char BLOCK_CHAR[4] = {'r', 'l', 'd', 'u'}; // Action to block (x+dx, y+dy)\n\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int x, int y) : x(x), y(y) {}\n    bool operator==(const Point& p) const { return x == p.x && y == p.y; }\n    int dist(const Point& p) const { return abs(x - p.x) + abs(y - p.y); }\n};\n\n// Global State\nint N, M;\nvector<Point> pets;\nvector<Point> humans;\nvector<int> pet_types; \n// grid[x][y] : true if impassable (wall)\n// Note: walls are built on squares. Humans/Pets can be on squares that are passable.\n// Once a wall is built on (x,y), it becomes impassable.\n// Humans and Pets can be on the same square? \"each square can contain any number of humans and pets.\"\n// So grid state is independent of entity positions, except for the \"cannot build adjacent to pet\" rule.\nvector<vector<bool>> grid; \n\n// Input parsing\nvoid read_init() {\n    cin >> N;\n    pets.resize(N);\n    pet_types.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> pet_types[i];\n        // Convert to 0-based for internal logic if needed, but problem is 1-based\n        pets[i].x--; pets[i].y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    grid.assign(H, vector<bool>(W, false));\n}\n\n// Read pet movements for one turn\n// pet_moves[i] is a string of characters like \"U\", \"R.\", etc.\nvoid read_turn(vector<string>& pet_moves) {\n    pet_moves.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_moves[i];\n    }\n}\n\n// Apply pet movements\nvoid apply_moves(const vector<string>& pet_moves) {\n    for (int i = 0; i < N; ++i) {\n        int cx = pets[i].x;\n        int cy = pets[i].y;\n        for (char c : pet_moves[i]) {\n            int dir = -1;\n            if (c == 'U') dir = 3;\n            else if (c == 'D') dir = 2;\n            else if (c == 'L') dir = 1;\n            else if (c == 'R') dir = 0;\n            \n            if (dir != -1) {\n                int nx = cx + DX[dir];\n                int ny = cy + DY[dir];\n                // Pets move randomly but logically. \n                // The problem says they move to passable squares chosen randomly.\n                // Assuming the server provides valid moves that respect grid bounds and walls.\n                // We just update coordinates.\n                cx = nx;\n                cy = ny;\n            }\n        }\n        pets[i].x = cx;\n        pets[i].y = cy;\n    }\n}\n\n// Helper to check bounds\nbool inside(int x, int y) {\n    return 0 <= x && x < H && 0 <= y && y < W;\n}\n\n// Helper to check if a cell is buildable (wall action)\n// Cannot build if:\n// 1. The cell contains a pet or human at the START of the turn.\n// 2. The cell is already a wall.\n// 3. An adjacent cell contains a pet.\nbool is_buildable(int x, int y, const vector<Point>& current_pets, const vector<Point>& current_humans) {\n    if (!inside(x, y)) return false;\n    if (grid[x][y]) return false; // Already impassable\n    \n    // Check if pet or human is on (x, y)\n    for (const auto& p : current_pets) {\n        if (p.x == x && p.y == y) return false;\n    }\n    for (const auto& h : current_humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    \n    // Check if adjacent cell contains a pet\n    for (int i = 0; i < 4; ++i) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (!inside(nx, ny)) continue;\n        for (const auto& p : current_pets) {\n            if (p.x == nx && p.y == ny) return false;\n        }\n    }\n    return true;\n}\n\n// Strategy: Secure a large rectangle with 0 pets.\nstruct Rect {\n    int r1, r2, c1, c2;\n    int area;\n};\n\n// Find best rectangle to secure\n// Criteria: \n// 1. Contains 0 pets currently.\n// 2. Maximize Area.\n// 3. Minimize Wall Length (perimeter).\n// 4. Maximize distance from pets to wall (safety).\nRect find_best_rectangle() {\n    // 2D prefix sum for pet counts\n    vector<vector<int>> ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int cnt = 0;\n            for (const auto& p : pets) {\n                if (p.x == i && p.y == j) cnt++;\n            }\n            ps[i+1][j+1] = ps[i][j+1] + ps[i+1][j] - ps[i][j] + cnt;\n        }\n    }\n    \n    auto get_pet_count = [&](int r1, int c1, int r2, int c2) {\n        return ps[r2+1][c2+1] - ps[r1][c2+1] - ps[r2+1][c1] + ps[r1][c1];\n    };\n\n    double best_score = -1e9;\n    Rect best_r = {0, H-1, 0, W-1, 0};\n\n    // Iterate over all rectangles\n    // To limit search, maybe only consider those touching boundary? \n    // No, a central island is also valid, though walls are expensive.\n    // Let's iterate all.\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (get_pet_count(r1, c1, r2, c2) > 0) continue;\n                    \n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    \n                    // Calculate required wall length\n                    // Walls needed on sides that are not touching map boundary\n                    int wall_len = 0;\n                    if (r1 > 0) wall_len += (c2 - c1 + 1);\n                    if (r2 < H - 1) wall_len += (c2 - c1 + 1);\n                    if (c1 > 0) wall_len += (r2 - r1 + 1);\n                    if (c2 < W - 1) wall_len += (r2 - r1 + 1);\n                    \n                    // Safety: min distance of any pet to the rectangle boundary\n                    // If a pet is very close, we can't build there easily.\n                    // This is a heuristic.\n                    int min_dist = H + W;\n                    for (const auto& p : pets) {\n                        // If inside, skip (already filtered)\n                        // Distance to rectangle\n                        int dx = max({r1 - p.x, 0, p.x - r2});\n                        int dy = max({c1 - p.y, 0, p.y - c2});\n                        int d = dx + dy;\n                        // If pet is outside, d >= 1\n                        if (d < min_dist) min_dist = d;\n                    }\n                    \n                    // We cannot build adjacent to pet. So we need buffer of 1.\n                    // If min_dist < 2, the wall is adjacent to pet.\n                    // Actually, if min_dist == 1, pet is adjacent to rect. \n                    // We need to build wall outside rect. So dist to wall is min_dist - 1.\n                    // If dist_to_wall == 0 (pet touching rect), we CANNOT build the wall on that side.\n                    // So such rectangles are dangerous.\n                    \n                    // Score: Area - Cost\n                    // Cost = Wall_Length * K1 + (if unsafe) * LargePenalty\n                    double score = (double)area;\n                    \n                    // Penalty for walls\n                    score -= wall_len * 0.5; // Tunable factor\n                    \n                    // Penalty for low safety margin\n                    // Buffer needed is 1.\n                    // If pet is touching boundary (min_dist=1), we are blocked.\n                    if (min_dist == 0) { /* Should not happen since count=0 */ }\n                    else if (min_dist == 1) {\n                        score -= 100; // Heavily penalize touching pets\n                    } else {\n                        // Slight penalty for being close\n                        score -= (5.0 / min_dist);\n                    }\n                    \n                    // Bonus for containing humans? No, we can move them in.\n                    // Penalty for humans being far away?\n                    // Sum of distances from humans to rect.\n                    int total_dist = 0;\n                    for (const auto& h : humans) {\n                        // Closest point in rect\n                        int cx = max(r1, min(h.x, r2));\n                        int cy = max(c1, min(h.y, c2));\n                        total_dist += abs(h.x - cx) + abs(h.y - cy);\n                    }\n                    score -= total_dist * 0.05;\n\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = {r1, r2, c1, c2, area};\n                    }\n                }\n            }\n        }\n    }\n    return best_r;\n}\n\n// Action Generation\nvector<char> generate_actions(Rect& target_rect, vector<Point>& current_humans, int& phase, vector<Point>& wall_tasks, int turn_cnt) {\n    vector<char> actions(M, '.');\n    \n    // Wall cells needed to seal the rectangle\n    vector<Point> needed_walls;\n    // r1-1, r2+1, c1-1, c2+1\n    if (target_rect.r1 > 0) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r1 - 1, c);\n    if (target_rect.r2 < H - 1) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r2 + 1, c);\n    if (target_rect.c1 > 0) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c1 - 1);\n    if (target_rect.c2 < W - 1) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c2 + 1);\n    \n    // Remove already built walls\n    needed_walls.erase(remove_if(needed_walls.begin(), needed_walls.end(), \n        [&](const Point& p){ return grid[p.x][p.y]; }), \n        needed_walls.end());\n        \n    // Phase 1: Move humans into the rectangle\n    if (phase == 1) {\n        bool all_in = true;\n        for (int i = 0; i < M; ++i) {\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            if (target_rect.r1 <= hx && hx <= target_rect.r2 && target_rect.c1 <= hy && hy <= target_rect.c2) {\n                actions[i] = '.';\n                continue;\n            }\n            all_in = false;\n            \n            // Move towards closest point in rect\n            int tx = max(target_rect.r1, min(hx, target_rect.r2));\n            int ty = max(target_rect.c1, min(hy, target_rect.c2));\n            \n            // BFS to find shortest path to (tx, ty) or any cell in rect?\n            // Simple greedy: reduce Manhattan distance\n            int best_d = abs(hx - tx) + abs(hy - ty);\n            int best_dir = -1;\n            \n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + DX[d];\n                int ny = hy + DY[d];\n                if (!inside(nx, ny)) continue;\n                if (grid[nx][ny]) continue; // Can't move into wall\n                \n                // Check if (nx, ny) is in rect (good)\n                bool in_rect = (target_rect.r1 <= nx && nx <= target_rect.r2 && target_rect.c1 <= ny && ny <= target_rect.c2);\n                int d_score = abs(nx - tx) + abs(ny - ty);\n                if (in_rect) d_score = -1000; // Priority to enter\n                \n                if (d_score < best_d) {\n                    best_d = d_score;\n                    best_dir = d;\n                }\n            }\n            if (best_dir != -1) {\n                actions[i] = DIR_CHAR[best_dir];\n                current_humans[i].x += DX[best_dir];\n                current_humans[i].y += DY[best_dir];\n            }\n        }\n        \n        if (all_in) {\n            phase = 2;\n            // Assign wall tasks\n            wall_tasks = needed_walls;\n            // Shuffle to distribute work randomly? Or keep sorted?\n            // Keep simple.\n        }\n    } \n    // Phase 2: Build walls\n    else if (phase == 2) {\n        if (wall_tasks.empty()) {\n            phase = 3;\n            return actions;\n        }\n        \n        // Greedy assignment: each human picks closest task\n        // To avoid conflict, we process humans in order of distance to tasks? \n        // Or simply assign static chunks? \n        // Static chunks are better for consistency.\n        \n        // Let's use a persistent assignment.\n        // If no assignment yet, create one.\n        static vector<int> assignment(M, -1);\n        static bool assigned = false;\n        \n        if (!assigned || wall_tasks.size() != (unsigned)(assignment.size())) {\n             // Simple Round Robin assignment based on human index\n             assignment.clear();\n             assignment.resize(M, -1);\n             for (size_t i = 0; i < wall_tasks.size(); ++i) {\n                 assignment[i % M] = i;\n             }\n             assigned = true;\n        }\n        \n        // Execute\n        for (int i = 0; i < M; ++i) {\n            int task_idx = assignment[i];\n            if (task_idx == -1 || task_idx >= (int)wall_tasks.size()) {\n                actions[i] = '.';\n                continue;\n            }\n            \n            Point target = wall_tasks[task_idx];\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            // If adjacent, try build\n            bool adj = false;\n            int build_dir = -1;\n            for (int d = 0; d < 4; ++d) {\n                if (hx + DX[d] == target.x && hy + DY[d] == target.y) {\n                    adj = true;\n                    build_dir = d;\n                    break;\n                }\n            }\n            \n            if (adj) {\n                // Check if buildable\n                // Need to check adjacency to pets at the START of this turn\n                // We have `pets` vector which is already updated for this turn?\n                // No, `pets` in global state is updated at the START of the loop in main.\n                // So `pets` holds positions at the START of the turn.\n                // We check buildability against `pets`.\n                \n                // is_buildable checks `grid` and `pets` and `current_humans`\n                // But `current_humans` is being modified. We should use previous pos? \n                // Rule: \"cannot choose a square that contains pets or humans at the start of this turn\"\n                // So we check against `humans` (initial state of turn).\n                // `current_humans` is a copy we modify to simulate moves. \n                // We need the actual start positions.\n                // Let's pass `humans` (the vector holding start-of-turn pos) to is_buildable?\n                // Or just check `current_humans[i]` before moving? No, that's wrong for other humans.\n                // Let's assume `humans` is not modified yet.\n                // Wait, I modify `current_humans` in place.\n                // So at the start of generate_actions, `current_humans` IS the start position.\n                // Good.\n                \n                if (is_buildable(target.x, target.y, pets, current_humans)) {\n                    actions[i] = BLOCK_CHAR[build_dir];\n                    grid[target.x][target.y] = true; // Mark as built immediately for logic?\n                    // Note: The problem says \"perform each action simultaneously\".\n                    // However, for our planning in the next turn, we update grid.\n                    // If two humans build the same wall, the second one does nothing (rule: \"If you choose a square that is already impassable, nothing happens\").\n                    // But we shouldn't assign two humans to the same task ideally.\n                    // With round robin, tasks are distinct.\n                    \n                    // Remove task\n                    wall_tasks.erase(wall_tasks.begin() + task_idx);\n                    // Update assignments?\n                    // Shift indices down for those > task_idx\n                    for (int k = 0; k < M; ++k) {\n                        if (assignment[k] > task_idx) assignment[k]--;\n                    }\n                } else {\n                    actions[i] = '.'; // Cannot build now\n                }\n            } else {\n                // Move towards target\n                // BFS or simple Manhattan\n                int best_d = abs(hx - target.x) + abs(hy - target.y);\n                int best_dir = -1;\n                \n                for (int d = 0; d < 4; ++d) {\n                    int nx = hx + DX[d];\n                    int ny = hy + DY[d];\n                    if (!inside(nx, ny)) continue;\n                    if (grid[nx][ny]) continue;\n                    if (nx == target.x && ny == target.y) continue; // Moving onto the wall square? No, can only build adjacent. \n                    // Actually, can we move onto a square that will be a wall? \n                    // \"It is not possible to move to a square that becomes impassable by another person's action in this turn.\"\n                    // We are the person. If we move to target, we can't build it (must be adjacent).\n                    // So we shouldn't move onto target.\n                    \n                    int d_score = abs(nx - target.x) + abs(ny - target.y);\n                    if (d_score < best_d) {\n                        best_d = d_score;\n                        best_dir = d;\n                    }\n                }\n                if (best_dir != -1) {\n                    actions[i] = DIR_CHAR[best_dir];\n                    current_humans[i].x += DX[best_dir];\n                    current_humans[i].y += DY[best_dir];\n                } else {\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        if (wall_tasks.empty()) phase = 3;\n    }\n    // Phase 3: Done\n    else {\n        for (int i = 0; i < M; ++i) actions[i] = '.';\n    }\n    \n    return actions;\n}\n\nvoid solve() {\n    read_init();\n    \n    Rect target_rect;\n    int phase = 1; // 1: Enter, 2: Build, 3: Done\n    vector<Point> wall_tasks;\n    \n    for (int t = 0; t < TURNS; ++t) {\n        // Read Pet Moves\n        vector<string> pet_moves;\n        read_turn(pet_moves);\n        \n        // Update Pet Positions\n        apply_moves(pet_moves);\n        \n        // Check if plan is still valid\n        bool valid = true;\n        if (phase == 3) {\n            // Just stay put\n            cout << string(M, '.') << endl;\n            continue;\n        }\n        \n        // Check if pets entered target rect\n        for (const auto& p : pets) {\n            if (target_rect.r1 <= p.x && p.x <= target_rect.r2 &&\n                target_rect.c1 <= p.y && p.y <= target_rect.c2) {\n                valid = false;\n                break;\n            }\n        }\n        \n        if (!valid || phase == 0) {\n            // Re-plan\n            target_rect = find_best_rectangle();\n            phase = 1;\n            wall_tasks.clear();\n            // cout << \"# Turn \" << t << \" Replanning. Rect: \" \n            //      << target_rect.r1 << \" \" << target_rect.r2 << \" \"\n            //      << target_rect.c1 << \" \" << target_rect.c2 << \" Area: \" << target_rect.area << endl;\n        }\n        \n        // Generate Actions\n        // We need a copy of human positions to simulate moves for next turn logic?\n        // No, the problem state updates based on our output.\n        // We just need to update our internal `humans` state for the next iteration's `is_buildable` check.\n        // So `generate_actions` should update `humans`.\n        // But `is_buildable` needs \"start of turn\" positions.\n        // So we pass `humans` (which holds start pos) and update it at the end.\n        \n        vector<char> actions = generate_actions(target_rect, humans, phase, wall_tasks, t);\n        \n        // Output\n        string s(actions.begin(), actions.end());\n        cout << s << endl;\n        cout.flush();\n    }\n}\n\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n    solve();\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Directions: U, D, L, R\nconst int DY[4] = {-1, 1, 0, 0};\nconst int DX[4] = {0, 0, -1, 1};\nconst char DC[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(20);\n    vector<string> v(19);\n\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n\n    // A* Search\n    // priority_queue stores (estimated_cost, y, x)\n    using State = pair<int, pair<int, int>>;\n    priority_queue<State, vector<State>, greater<State>> pq;\n\n    // dist[y][x] stores the cost (number of moves) to reach (x, y)\n    // Initialize to a large number\n    const int INF = 1e9;\n    vector<vector<int>> dist(20, vector<int>(20, INF));\n    \n    // parent[y][x] stores the direction taken to reach (x, y) from its parent\n    vector<vector<int>> parent(20, vector<int>(20, -1));\n\n    // Manhattan distance heuristic\n    auto heuristic = [&](int y, int x) {\n        return abs(y - ti) + abs(x - tj);\n    };\n\n    dist[si][sj] = 0;\n    pq.push({heuristic(si, sj), {si, sj}});\n\n    while (!pq.empty()) {\n        auto current = pq.top();\n        pq.pop();\n\n        int y = current.second.first;\n        int x = current.second.second;\n        int cost = dist[y][x];\n\n        if (y == ti && x == tj) break;\n\n        // If we found a better path to (y, x) already, skip this one\n        if (cost > dist[y][x]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int ny = y + DY[i];\n            int nx = x + DX[i];\n\n            // Check boundaries\n            if (ny < 0 || ny >= 20 || nx < 0 || nx >= 20) continue;\n\n            // Check walls\n            bool blocked = false;\n            if (i == 0) { // U\n                if (y > 0 && v[y-1][x] == '1') blocked = true;\n            } else if (i == 1) { // D\n                if (y < 19 && v[y][x] == '1') blocked = true;\n            } else if (i == 2) { // L\n                if (x > 0 && h[y][x-1] == '1') blocked = true;\n            } else if (i == 3) { // R\n                if (x < 19 && h[y][x] == '1') blocked = true;\n            }\n\n            if (blocked) continue;\n\n            if (dist[ny][nx] > cost + 1) {\n                dist[ny][nx] = cost + 1;\n                parent[ny][nx] = i;\n                pq.push({dist[ny][nx] + heuristic(ny, nx), {ny, nx}});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cy = ti, cx = tj;\n    while (cy != si || cx != sj) {\n        int dir = parent[cy][cx];\n        path.push_back(DC[dir]);\n        // Move backwards to parent\n        cy -= DY[dir];\n        cx -= DX[dir];\n    }\n    reverse(path.begin(), path.end());\n\n    // Generate robust string\n    // Repeat the path until length 200\n    string ans = \"\";\n    int len = path.length();\n    if (len == 0) {\n        // Already at target (should not happen based on constraints)\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    // We repeat the path sequence. \n    // If we just repeat the whole path, we might not reach the goal if we forget the last step of the first iteration.\n    // But repeating allows re-attempting.\n    // Given the strategy analysis, simple repetition is robust.\n    // To maximize score, we fill up to 200 chars.\n    \n    while ((int)ans.size() < 200) {\n        ans += path;\n    }\n    ans.resize(200);\n\n    cout << ans << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <ctime>\n#include <cassert>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\nconst int N = H * W;\n\n// Directions: 0:Up, 1:Right, 2:Down, 3:Left\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\n\n// to[type][in_dir] = out_dir\n// in_dir: direction from which the train enters the tile\n// out_dir: direction to which the train exits the tile\n// -1 if no connection\nint to[8][4] = {\n    {1, 0, -1, -1}, // 0: TR\n    {-1, 2, 1, -1}, // 1: RD\n    {-1, -1, 3, 2}, // 2: DL\n    {0, -1, -1, 3}, // 3: LU\n    {1, 0, 3, 2},   // 4: TR & DL\n    {3, 2, 1, 0},   // 5: RD & LU\n    {2, -1, 0, -1}, // 6: Vert\n    {-1, 3, -1, 1}  // 7: Horz\n};\n\nint grid[H][W]; // Initial types\nint rot[H][W];  // Current rotations\nint state[H][W]; // Effective types after rotation\nint vis[H][W][4]; // Visited stamps\nint stamp = 0;\n\nmt19937 rng(123456789);\n\n// Precomputed effective types\nint effective_type[8][4];\n\nvoid init_effective_types() {\n    for (int base = 0; base < 8; ++base) {\n        for (int r = 0; r < 4; ++r) {\n            if (base <= 3) effective_type[base][r] = (base + r) % 4;\n            else if (base == 4 || base == 5) effective_type[base][r] = ((base + r) % 2 == 0) ? 4 : 5;\n            else effective_type[base][r] = ((base + r) % 2 == 0) ? 6 : 7;\n        }\n    }\n}\n\nlong long calc_score() {\n    stamp++;\n    vector<int> loops;\n    \n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t = state[i][j];\n            for (int d = 0; d < 4; ++d) {\n                if (vis[i][j][d] == stamp) continue;\n                \n                int nd = to[t][d];\n                if (nd == -1) continue;\n                \n                // Start walk\n                int cr = i, cc = j, cd = d;\n                int len = 0;\n                bool is_loop = true;\n                vis[cr][cc][cd] = stamp;\n                \n                while (true) {\n                    int nr = cr + dr[nd];\n                    int nc = cc + dc[nd];\n                    len++;\n                    \n                    if (nr < 0 || nr >= H || nc < 0 || nc >= W) {\n                        is_loop = false;\n                        break;\n                    }\n                    \n                    int next_cd = (nd + 2) % 4;\n                    if (vis[nr][nc][next_cd] == stamp) {\n                        if (nr == i && nc == j && next_cd == d) {\n                            break;\n                        } else {\n                            is_loop = false;\n                            break;\n                        }\n                    }\n                    \n                    vis[nr][nc][next_cd] = stamp;\n                    cr = nr; cc = nc; cd = next_cd;\n                    \n                    int next_nd = to[state[cr][cc]][cd];\n                    if (next_nd == -1) {\n                        is_loop = false;\n                        break;\n                    }\n                    nd = next_nd;\n                }\n                \n                if (is_loop) {\n                    loops.push_back(len);\n                }\n            }\n        }\n    }\n    \n    if (loops.empty()) return 0;\n    sort(loops.begin(), loops.end());\n    \n    // Remove duplicates (since each loop is traversed in both directions)\n    // loops contains [L1, L1, L2, L2, ...]\n    vector<int> uniq_loops;\n    uniq_loops.push_back(loops[0]);\n    for (size_t k = 1; k < loops.size(); ++k) {\n        if (loops[k] != loops[k-1]) {\n            uniq_loops.push_back(loops[k]);\n        }\n    }\n    \n    if (uniq_loops.size() < 2) return 0;\n    \n    int L1 = uniq_loops.back();\n    int L2 = uniq_loops[uniq_loops.size() - 2];\n    \n    return (long long)L1 * L2;\n}\n\nint main() {\n    init_effective_types();\n    \n    // Input\n    for (int i = 0; i < H; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < W; ++j) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Initialize rotations (random)\n    // Try to minimize boundary exits for better start\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            rot[i][j] = rng() % 4;\n            state[i][j] = effective_type[grid[i][j]][rot[i][j]];\n        }\n    }\n    \n    long long current_score = calc_score();\n    long long best_score = current_score;\n    int best_rot[H][W];\n    for(int i=0; i<H; ++i) \n        for(int j=0; j<W; ++j) \n            best_rot[i][j] = rot[i][j];\n            \n    auto start_time = clock();\n    const double TIME_LIMIT = 1.9 * CLOCKS_PER_SEC;\n    \n    int iter = 0;\n    while ((clock() - start_time) < TIME_LIMIT) {\n        // Temperature cooling\n        double progress = (double)(clock() - start_time) / TIME_LIMIT;\n        double T = 500.0 * (1.0 - progress);\n        if (T < 0.1) T = 0.1;\n        \n        // Transition\n        int r = rng() % H;\n        int c = rng() % W;\n        \n        int old_rot = rot[r][c];\n        int new_rot = rng() % 4;\n        \n        if (new_rot == old_rot) continue;\n        \n        rot[r][c] = new_rot;\n        state[r][c] = effective_type[grid[r][c]][new_rot];\n        \n        long long new_score = calc_score();\n        \n        long long diff = new_score - current_score;\n        // Accept if better or with probability exp(diff/T)\n        if (diff > 0 || (rng() % 10000 < 10000 * exp(diff / T))) {\n            current_score = new_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                for(int i=0; i<H; ++i) \n                    for(int j=0; j<W; ++j) \n                        best_rot[i][j] = rot[i][j];\n            }\n        } else {\n            // Revert\n            rot[r][c] = old_rot;\n            state[r][c] = effective_type[grid[r][c]][old_rot];\n        }\n        iter++;\n    }\n    \n    // Output best solution\n    string ans = \"\";\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ans += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << ans << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <array>\n\nusing namespace std;\n\n// Bitmask constants\nconst int LEFT = 1;\nconst int UP = 2;\nconst int RIGHT = 4;\nconst int DOWN = 8;\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n    bool operator==(const Point& p) const { return r == p.r && c == p.c; }\n    bool operator!=(const Point& p) const { return !(*this == p); }\n};\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\n// Corresponding bit required for the NEIGHBOR to connect back\n// If we move U (empty square goes up, tile goes down), tile at (r+1, c) moves up.\n// The problem says: \"sliding the ... tile ... into the empty square\"\n// U: Move tile from (r+1, c) to (r, c). Empty was at (r, c), moves to (r+1, c).\n// Let's define operation 'U' as \"The tile ABOVE the empty square moves DOWN into the empty square\".\n// This is consistent with standard notations (U pushes tile Up, so empty goes Down? No).\n// Standard: \"U\" means move the tile \"Up\" (relative to the board) or \"Up\" relative to the empty square?\n// Problem statement: \"sliding the ... tile ... into the empty square ... U, D, L, or R\"\n// Usually means the direction the TILE moves.\n// Let's verify with example or standard.\n// If empty is at (r, c). Tile at (r+1, c) moves UP to (r, c).\n// So \"U\" corresponds to empty square moving DOWN.\n// Wait. \"sliding the ... adjacent tile ... into the empty square ... U, D, L, R\"\n// This usually refers to the direction the tile moves.\n// If I output 'U', the tile moves Up. Empty square moves Down.\n// Let's stick to: U/D/L/R = direction the tile moves.\n// Corresponding empty square moves: D/U/R/L.\n\nconst char MOVE_CHARS[4] = {'U', 'D', 'L', 'R'};\n// Mapping tile move direction to empty move direction\n// Tile moves U (r-1) -> Empty moves D (r+1) relative to tile, but essentially\n// If Tile is at (r, c) and moves U, it goes to (r-1, c). Empty was at (r-1, c), now at (r, c).\n// So Empty moves D.\n\nclass Solver {\npublic:\n    int N;\n    int T_limit;\n    vector<vector<int>> board;\n    Point empty_pos;\n    string moves;\n    mt19937 rng;\n\n    Solver(int n, int t_limit) : N(n), T_limit(t_limit), rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void set_board(const vector<vector<int>>& b, Point ep) {\n        board = b;\n        empty_pos = ep;\n        moves = \"\";\n    }\n\n    bool is_valid(int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    }\n\n    // Returns the connected component containing (sr, sc) based on edge connections\n    vector<Point> get_component(int sr, int sc) {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<Point> comp;\n        queue<Point> q;\n        q.push(Point(sr, sc));\n        visited[sr][sc] = true;\n        comp.push_back(Point(sr, sc));\n\n        while (!q.empty()) {\n            Point cur = q.front(); q.pop();\n            int cr = cur.r, cc = cur.c;\n            int tile = board[cr][cc];\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = cr + DR[d];\n                int nc = cc + DC[d];\n                if (is_valid(nr, nc) && board[nr][nc] != 0) {\n                    // Check connection\n                    // Edge exists if (cr, cc) has bit d and (nr, nc) has opposite bit\n                    bool connects = false;\n                    if (d == 0 && (tile & UP) && (board[nr][nc] & DOWN)) connects = true;\n                    if (d == 1 && (tile & DOWN) && (board[nr][nc] & UP)) connects = true;\n                    if (d == 2 && (tile & LEFT) && (board[nr][nc] & RIGHT)) connects = true;\n                    if (d == 3 && (tile & RIGHT) && (board[nr][nc] & LEFT)) connects = true;\n\n                    if (connects && !visited[nr][nc]) {\n                        visited[nr][nc] = true;\n                        comp.push_back(Point(nr, nc));\n                        q.push(Point(nr, nc));\n                    }\n                }\n            }\n        }\n        return comp;\n    }\n\n    // Find the largest connected component on the board\n    vector<Point> get_largest_component() {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<Point> largest;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] != 0 && !visited[i][j]) {\n                    // BFS\n                    vector<Point> comp;\n                    queue<Point> q;\n                    q.push(Point(i, j));\n                    visited[i][j] = true;\n                    comp.push_back(Point(i, j));\n\n                    while (!q.empty()) {\n                        Point cur = q.front(); q.pop();\n                        int cr = cur.r, cc = cur.c;\n                        int tile = board[cr][cc];\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (is_valid(nr, nc) && board[nr][nc] != 0 && !visited[nr][nc]) {\n                                bool connects = false;\n                                int neighbor_tile = board[nr][nc];\n                                if (d == 0 && (tile & UP) && (neighbor_tile & DOWN)) connects = true;\n                                if (d == 1 && (tile & DOWN) && (neighbor_tile & UP)) connects = true;\n                                if (d == 2 && (tile & LEFT) && (neighbor_tile & RIGHT)) connects = true;\n                                if (d == 3 && (tile & RIGHT) && (neighbor_tile & LEFT)) connects = true;\n                                \n                                if (connects) {\n                                    visited[nr][nc] = true;\n                                    comp.push_back(Point(nr, nc));\n                                    q.push(Point(nr, nc));\n                                }\n                            }\n                        }\n                    }\n                    if (comp.size() > largest.size()) largest = comp;\n                }\n            }\n        }\n        return largest;\n    }\n\n    // Move tile at (fr, fc) to (tr, tc)\n    // We assume we just want to get the tile there.\n    // Implementation: Move empty square to adjacent to target, push.\n    // This is simplified \"greedy\" tile movement.\n    void move_tile(Point from, Point to) {\n        if (from == to) return;\n\n        // We want to move tile at 'from' to 'to'.\n        // We perform BFS to find a sequence of moves for the empty square\n        // such that it pushes 'from' towards 'to'.\n        \n        // Current state: Empty at empty_pos. Tile at 'from'.\n        // We need to move the empty square to a neighbor of 'from' in the direction of 'to'.\n        \n        Point cur = from;\n        while (cur != to) {\n            // Determine primary direction to move 'cur'\n            Point diff = Point(to.r - cur.r, to.c - cur.c);\n            \n            vector<int> dirs;\n            if (diff.r > 0) dirs.push_back(1); // Down\n            else if (diff.r < 0) dirs.push_back(0); // Up\n            \n            if (diff.c > 0) dirs.push_back(3); // Right\n            else if (diff.c < 0) dirs.push_back(2); // Left\n            \n            // Shuffle directions to avoid simple loops if path blocked\n            shuffle(dirs.begin(), dirs.end(), rng);\n\n            bool moved = false;\n            for (int d : dirs) {\n                int nr = cur.r + DR[d];\n                int nc = cur.c + DC[d];\n                Point next_target(nr, nc);\n\n                if (next_target == to) {\n                    // Try to move 'cur' to 'to'.\n                    // Empty square must be at 'to'.\n                    // BFS empty to 'to'.\n                    vector<Point> path = get_path_for_empty(to);\n                    execute_empty_path(path);\n                    \n                    // Now empty is at 'to'. Push 'cur' to 'to'.\n                    // Move tile at 'cur' in direction d.\n                    // This corresponds to moving empty square in opposite direction.\n                    // Wait. Tile moves U -> Empty moves D.\n                    // d is tile move direction.\n                    // If d=1 (Down), tile goes (r+1, c). Empty was (r+1, c), becomes (r, c).\n                    // So we append MOVE_CHARS[d] to moves.\n                    // Update empty pos to 'cur'.\n                    moves += MOVE_CHARS[d];\n                    empty_pos = cur;\n                    board[to.r][to.c] = board[cur.r][cur.c];\n                    board[cur.r][cur.c] = 0;\n                    cur = to;\n                    moved = true;\n                    break;\n                } else {\n                    // Move 'cur' one step towards 'to' to 'next_target'.\n                    // Empty square must be at 'next_target'.\n                    vector<Point> path = get_path_for_empty(next_target);\n                    execute_empty_path(path);\n\n                    // Push 'cur' to 'next_target'.\n                    moves += MOVE_CHARS[d];\n                    empty_pos = cur;\n                    board[next_target.r][next_target.c] = board[cur.r][cur.c];\n                    board[cur.r][cur.c] = 0;\n                    cur = next_target;\n                    moved = true;\n                    break;\n                }\n            }\n            if (!moved) {\n                // Stuck? Should not happen with simple connectivity, but just in case.\n                // Random move to unstuck?\n                // Or retry. Let's break to avoid infinite loop.\n                break;\n            }\n        }\n    }\n\n    // BFS to find path for empty square to target (r, c)\n    // Avoids moving the tile that we intend to move? No, just simple path.\n    // We don't have a \"current tile to protect\" in this abstraction,\n    // but the logic implies we are moving specific tiles.\n    // To simplify, we just BFS shortest path.\n    vector<Point> get_path_for_empty(Point target) {\n        if (empty_pos == target) return {};\n        \n        queue<Point> q;\n        vector<vector<Point>> parent(N, vector<Point>(N, Point(-1, -1)));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        \n        q.push(empty_pos);\n        visited[empty_pos.r][empty_pos.c] = true;\n        \n        bool found = false;\n        while(!q.empty()) {\n            Point p = q.front(); q.pop();\n            if(p == target) { found = true; break; }\n            \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) && !visited[nr][nc]) {\n                    // We can move empty square to (nr, nc) if there is a tile there to swap.\n                    // Which is always true unless (nr, nc) is empty (which it isn't, except start).\n                    visited[nr][nc] = true;\n                    parent[nr][nc] = p;\n                    q.push(Point(nr, nc));\n                }\n            }\n        }\n        \n        vector<Point> path;\n        if(found) {\n            Point curr = target;\n            while(curr != empty_pos) {\n                path.push_back(curr);\n                curr = parent[curr.r][curr.c];\n            }\n            reverse(path.begin(), path.end());\n        }\n        return path;\n    }\n\n    void execute_empty_path(const vector<Point>& path) {\n        for (Point p : path) {\n            // Move empty from empty_pos to p.\n            // Determine direction from p to empty_pos (where tile is).\n            // Wait. Empty moves to p. Tile at p moves to empty_pos.\n            // Direction is (empty_pos - p).\n            int dr = empty_pos.r - p.r;\n            int dc = empty_pos.c - p.c;\n            \n            int d = -1;\n            if(dr == 1) d = 0; // Empty moves Down (Tile moves Up)\n            else if(dr == -1) d = 1; // Empty moves Up (Tile moves Down)\n            else if(dc == 1) d = 2; // Empty moves Right (Tile moves Left)\n            else if(dc == -1) d = 3; // Empty moves Left (Tile moves Right)\n            \n            // The output string corresponds to TILE movement.\n            // Tile moves from p to empty_pos.\n            // Vector is p -> empty_pos.\n            // If empty moves D (dr=1), Tile moves U (d=0).\n            // Yes, mapping matches.\n            moves += MOVE_CHARS[d];\n            \n            // Swap\n            board[empty_pos.r][empty_pos.c] = board[p.r][p.c];\n            board[p.r][p.c] = 0;\n            empty_pos = p;\n        }\n    }\n\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        // Main loop\n        while ((int)moves.size() < T_limit) {\n            auto curr_time = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(curr_time - start_time).count();\n            if (elapsed > 2.8) break; // Time limit\n\n            vector<Point> cc = get_largest_component();\n            if (cc.size() == N * N - 1) {\n                // Solved! Minimize moves?\n                // Just stop.\n                break;\n            }\n\n            // Try to expand CC\n            bool moved = false;\n            \n            // Boundary nodes of CC\n            vector<Point> boundary;\n            vector<bool> in_cc(N*N, false);\n            for (auto& p : cc) in_cc[p.r * N + p.c] = true;\n\n            for (auto& p : cc) {\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) && !in_cc[nr * N + nc] && board[nr][nc] != 0) {\n                        boundary.push_back(Point(nr, nc));\n                    }\n                }\n            }\n\n            // Shuffle boundary\n            shuffle(boundary.begin(), boundary.end(), rng);\n\n            // Strategy 1: One-sided expansion\n            // Look for edge (u, v) where u in CC, v not in CC.\n            // If u points to v, find v' (replacement for v) that points to u.\n            // If v points to u, find u' (replacement for u) that points to v.\n\n            for (Point v : boundary) {\n                // Check neighbors of v\n                for (int d = 0; d < 4; ++d) {\n                    int ur = v.r + DR[d];\n                    int uc = v.c + DC[d];\n                    Point u(ur, uc);\n                    \n                    if (is_valid(ur, uc) && in_cc[ur * N + uc]) {\n                        int tile_u = board[u.r][u.c];\n                        int tile_v = board[v.r][v.c];\n                        \n                        // Check u -> v\n                        bool u_points_v = false;\n                        if (d == 0 && (tile_v & UP)) u_points_v = true; // v points to u -> u needs down to point back? No.\n                        // Connection requires: u has bit(d) and v has opposite_bit(d)\n                        // bit(Up)=2, opp=8(Down)\n                        // If u is above v (u.r < v.r), d=1(Down) for u. u needs 8. v needs 2.\n                        // Let's just check connection condition.\n                        \n                        bool u_has_bit = false;\n                        bool v_has_bit = false;\n                        int bit_u = 0, bit_v = 0;\n                        \n                        // Dir from u to v\n                        int du = DR[d]; // 0: u at v-1 (Up). u needs Down(8). v needs Up(2)\n                        int dv = DC[d];\n                        \n                        if (du == 1) { bit_u = 8; bit_v = 2; } // u down, v up\n                        else if (du == -1) { bit_u = 2; bit_v = 8; } // u up, v down\n                        else if (dv == 1) { bit_u = 4; bit_v = 1; } // u right, v left\n                        else if (dv == -1) { bit_u = 1; bit_v = 4; } // u left, v right\n                        \n                        if (tile_u & bit_u) u_has_bit = true;\n                        if (tile_v & bit_v) v_has_bit = true;\n\n                        if (u_has_bit && !v_has_bit) {\n                            // Case: u connects to v, v does not connect to u.\n                            // Find a replacement for v (v') that has bit_v.\n                            // Move v' to v.\n                            for (int r = 0; r < N; ++r) {\n                                for (int c = 0; c < N; ++c) {\n                                    if (r == v.r && c == v.c) continue;\n                                    if (in_cc[r * N + c]) continue; // Don't take from CC\n                                    \n                                    int candidate = board[r][c];\n                                    if ((candidate & bit_v) == bit_v) {\n                                        // Move (r,c) to v.\n                                        // Check cost estimation (Manhattan distance)\n                                        int dist = abs(r - v.r) + abs(c - v.c);\n                                        if (dist > 5) continue; // Optimization: don't move too far\n                                        \n                                        move_tile(Point(r, c), v);\n                                        moved = true;\n                                        break;\n                                    }\n                                }\n                                if (moved) break;\n                            }\n                        } else if (!u_has_bit && v_has_bit) {\n                             // Case: v connects to u, u does not connect to v.\n                             // Find replacement for u (u').\n                             // u' must have bit_u AND maintain u's other connections?\n                             // This is harder. For now, skip \"fix u\" to save complexity.\n                             // Focus on \"fix v\" which is outside CC.\n                        }\n                        \n                        if (moved) break;\n                    }\n                }\n                if (moved) break;\n            }\n\n            if (moved) continue;\n\n            // Strategy 2: Two-sided expansion (connect u in CC to v outside)\n            // Need u' and v'.\n            // Only try if we can find a pair quickly.\n            \n            // Strategy 3: Just move a random tile adjacent to CC to shake it up? \n            // Or try to merge small components.\n            // For heuristic simplicity, if we can't grow CC, we try to connect ANY two components.\n            \n            // Find two adjacent cells (u, v) not connected.\n            // u in C1, v in C2.\n            // Try to connect them.\n            // This is complex to do in one go.\n            \n            // Fallback: Just perform a random valid move to get out of local minima?\n            // If no improvement, maybe stop.\n            // Actually, just move a random tile outside CC to a random spot.\n            // Or better: pick a random tile on board, move it to a random empty spot (no, 1 empty).\n            \n            // Just try to find ANY semi-edge anywhere on board and complete it.\n            // If it connects to CC, great.\n            for (int r = 0; r < N && !moved; ++r) {\n                for (int c = 0; c < N && !moved; ++c) {\n                    if (board[r][c] == 0) continue;\n                    for (int d = 0; d < 4; ++d) {\n                        int nr = r + DR[d];\n                        int nc = c + DC[d];\n                        if (is_valid(nr, nc) && board[nr][nc] != 0) {\n                             // Check if r,c connects to nr,nc\n                             int bit_c = 0, bit_n = 0;\n                             if (DR[d]==1) { bit_c=8; bit_n=2; }\n                             else if (DR[d]==-1) { bit_c=2; bit_n=8; }\n                             else if (DC[d]==1) { bit_c=4; bit_n=1; }\n                             else if (DC[d]==-1) { bit_c=1; bit_n=4; }\n                             \n                             int t1 = board[r][c];\n                             int t2 = board[nr][nc];\n                             \n                             if ((t1 & bit_c) && !(t2 & bit_n)) {\n                                 // Find t2' with bit_n\n                                 for (int i=0; i<N && !moved; ++i) {\n                                     for (int j=0; j<N && !moved; ++j) {\n                                         if (i==nr && j==nc) continue;\n                                         if (board[i][j] & bit_n) {\n                                             // Move (i,j) to (nr,nc)\n                                             move_tile(Point(i, j), Point(nr, nc));\n                                             moved = true;\n                                         }\n                                     }\n                                 }\n                             } else if (!(t1 & bit_c) && (t2 & bit_n)) {\n                                 // Find t1' with bit_c\n                                 for (int i=0; i<N && !moved; ++i) {\n                                     for (int j=0; j<N && !moved; ++j) {\n                                         if (i==r && j==c) continue;\n                                         if (board[i][j] & bit_c) {\n                                             move_tile(Point(i, j), Point(r, c));\n                                             moved = true;\n                                         }\n                                     }\n                                 }\n                             }\n                        }\n                    }\n                }\n            }\n            \n            if (!moved) {\n                // Should not happen often. Panic move: move random tile?\n                // Or just stop.\n                // For safety, stop if we can't make progress.\n                break;\n            }\n        }\n        \n        cout << moves << endl;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    \n    vector<vector<int>> board(N, vector<int>(N));\n    Point empty_pos;\n    \n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) {\n            char c = line[j];\n            if (c == '0') {\n                board[i][j] = 0;\n                empty_pos = Point(i, j);\n            } else {\n                if (c >= 'a') board[i][j] = 10 + (c - 'a');\n                else board[i][j] = c - '0';\n            }\n        }\n    }\n\n    Solver solver(N, T);\n    solver.set_board(board, empty_pos);\n    solver.solve();\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n#include <cmath>\n#include <bitset>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\ntypedef long long ll;\n\n// Define the maximum number of cuts allowed\nconst int K_MAX = 100;\n\n// Structure to represent a point\nstruct Point {\n    ll x, y;\n};\n\n// Structure to represent a line defined by two points\nstruct Line {\n    ll x1, y1, x2, y2;\n};\n\n// Global variables for problem input\nint N, K;\nvector<int> a(11); // Demands a[1]...a[10]\nvector<Point> points;\n\n// Random number generator\nmt19937 rng(1337); // Fixed seed for reproducibility, can use time(0) for random\n\n// Utility to get random integer in range [l, r]\nll rand_ll(ll l, ll r) {\n    uniform_int_distribution<ll> dist(l, r);\n    return dist(rng);\n}\n\n// Calculate cross product of (b-a) and (c-a)\nll cross_product(const Point& a, const Point& b, const Point& c) {\n    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n// Function to compute the score given a set of lines\n// Returns a pair: (score, number_of_dead_points)\n// Dead points are those lying exactly on a cut line.\npair<int, int> compute_score(const vector<Line>& lines) {\n    int k = lines.size();\n    if (k == 0) {\n        // Only one region containing all points\n        int cnt = 0;\n        for (int i = 0; i < N; ++i) {\n            // Check if points are valid (always true for input)\n            cnt++;\n        }\n        if (cnt > 0 && cnt <= 10) {\n            return {min(a[cnt], 1), 0};\n        }\n        return {0, 0};\n    }\n\n    // Map to store counts of points in each region\n    // Since we can't easily hash a vector<bool> or bitset, we use the signature directly\n    // However, map with bitset is fine. \n    // Optimization: Just use a string or vector<int> as key. \n    // But bitset<100> is faster and smaller.\n    \n    map<bitset<K_MAX>, int> region_counts;\n    int dead_points = 0;\n\n    for (int i = 0; i < N; ++i) {\n        bitset<K_MAX> signature;\n        bool is_dead = false;\n\n        for (int j = 0; j < k; ++j) {\n            ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n            if (val == 0) {\n                is_dead = true;\n                break;\n            }\n            if (val > 0) {\n                signature.set(j);\n            }\n        }\n\n        if (is_dead) {\n            dead_points++;\n        } else {\n            region_counts[signature]++;\n        }\n    }\n\n    int score = 0;\n    for (const auto& p : region_counts) {\n        int cnt = p.second;\n        if (1 <= cnt && cnt <= 10) {\n            score += min(a[cnt], 1); // We count how many demands we satisfy\n        }\n    }\n    return {score, dead_points};\n}\n\n// Generate a random line that avoids passing through points\n// Ideally passes through the region of interest\nLine generate_random_line() {\n    // Generate lines passing through points inside the bounding box of the cake\n    // Cake radius 10^4, so box is [-10000, 10000].\n    // We pick two points in this box.\n    \n    while (true) {\n        ll x1 = rand_ll(-10000, 10000);\n        ll y1 = rand_ll(-10000, 10000);\n        ll x2 = rand_ll(-10000, 10000);\n        ll y2 = rand_ll(-10000, 10000);\n\n        if (x1 == x2 && y1 == y2) continue;\n\n        Line l{x1, y1, x2, y2};\n        \n        // Check if this line passes through any point\n        bool hits_point = false;\n        for (const auto& p : points) {\n            if (cross_product({x1, y1}, {x2, y2}, p) == 0) {\n                hits_point = true;\n                break;\n            }\n        }\n        if (!hits_point) {\n            return l;\n        }\n    }\n}\n\nvoid solve() {\n    // Input reading\n    cin >> N >> K;\n    for (int i = 1; i <= 10; ++i) cin >> a[i];\n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n\n    // Simulated Annealing / Local Search parameters\n    double start_temp = 1000.0;\n    double end_temp = 1.0;\n    int iterations = 20000; // Number of iterations\n    \n    // State initialization\n    vector<Line> current_lines;\n    \n    // Try to add some initial random lines\n    int initial_lines = min(K, 20); \n    for (int i = 0; i < initial_lines; ++i) {\n        current_lines.push_back(generate_random_line());\n    }\n    \n    auto [current_score, current_dead] = compute_score(current_lines);\n    // Penalize dead points heavily\n    double current_energy = - (double)current_score * 1000.0 - current_dead * 500000.0;\n\n    vector<Line> best_lines = current_lines;\n    double best_energy = current_energy;\n\n    // Main loop\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        // Generate neighbor\n        vector<Line> next_lines = current_lines;\n        \n        double r = (double)rand_ll(0, 10000) / 10000.0;\n        int action = -1;\n\n        if (next_lines.size() == 0) {\n            action = 0; // Add\n        } else if (next_lines.size() == K) {\n             // Can only replace or remove\n             if (r < 0.7) action = 2; // Replace\n             else action = 1; // Remove\n        } else {\n            if (r < 0.4) action = 0; // Add\n            else if (r < 0.7) action = 1; // Remove\n            else action = 2; // Replace\n        }\n\n        if (action == 0) {\n            // Add line\n            next_lines.push_back(generate_random_line());\n        } else if (action == 1) {\n            // Remove line\n            int idx = rand_ll(0, next_lines.size() - 1);\n            next_lines.erase(next_lines.begin() + idx);\n        } else if (action == 2) {\n            // Replace line\n            int idx = rand_ll(0, next_lines.size() - 1);\n            next_lines[idx] = generate_random_line();\n        }\n\n        auto [next_score, next_dead] = compute_score(next_lines);\n        double next_energy = - (double)next_score * 1000.0 - next_dead * 500000.0;\n\n        double delta = next_energy - current_energy;\n        \n        // Metropolis criterion\n        if (delta < 0 || exp(-delta / temp) > (double)rand_ll(0, 10000) / 10000.0) {\n            current_lines = next_lines;\n            current_energy = next_energy;\n            \n            if (next_energy < best_energy) {\n                best_lines = next_lines;\n                best_energy = next_energy;\n            }\n        }\n    }\n\n    // Final Calculation to extract actual score for display/debug if needed\n    // But output is just the lines\n    int output_k = best_lines.size();\n    cout << output_k << endl;\n    for (const auto& l : best_lines) {\n        cout << l.x1 << \" \" << l.y1 << \" \" << l.x2 << \" \" << l.y2 << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Set seed based on time for different runs, though specific seeds can be good for debugging\n    // rng.seed(time(0)); \n    \n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <tuple>\n#include <chrono>\n#include <bitset>\n\nusing namespace std;\n\nconst int MAX_N = 61;\nint N, M;\nint center;\n// Grid of dots\nbool grid[MAX_N][MAX_N];\n// Used segments: bitset is sufficient.\n// Segment types:\n// 0: Horizontal (y, x) -> (y, x+1)\n// 1: Vertical (x, y) -> (x, y+1)\n// 2: Diag 1 (\\) (x, y) -> (x+1, y+1)\n// 3: Diag 2 (/) (x+1, y) -> (x, y+1)\n// We can map all segments to a single ID.\n// Total segments: 4 * N * (N-1)\nbitset<4 * 61 * 60> used_segments;\n\nstruct Point {\n    int x, y;\n    int weight;\n};\n\nvector<Point> targets; // Points we want to try to fill, sorted by weight\nvector<tuple<int, int, int, int, int, int, int, int>> ops;\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\nbool time_limit_exceeded = false;\n\nvoid check_time() {\n    auto now = chrono::high_resolution_clock::now();\n    auto duration = chrono::duration_cast<chrono::milliseconds>(now - start_time);\n    if (duration.count() > 4500) { // 4.5s limit\n        time_limit_exceeded = true;\n    }\n}\n\n// Helper to get segment ID\nint get_seg_id(int x1, int y1, int x2, int y2) {\n    // Ensure order to handle bidirectionality if necessary, though logic handles directed\n    // Horizontal\n    if (y1 == y2 && abs(x1 - x2) == 1) {\n        int x = min(x1, x2);\n        return y1 * (N - 1) + x;\n    }\n    // Vertical\n    if (x1 == x2 && abs(y1 - y2) == 1) {\n        int y = min(y1, y2);\n        return N * (N - 1) + x1 * (N - 1) + y;\n    }\n    // Diag 1 (\\): (x,y) -> (x+1, y+1)\n    if (x2 == x1 + 1 && y2 == y1 + 1) {\n        return 2 * N * (N - 1) + y1 * (N - 1) + x1;\n    }\n    // Diag 1 (\\) reverse\n    if (x1 == x2 + 1 && y1 == y2 + 1) {\n        return 2 * N * (N - 1) + y2 * (N - 1) + x2;\n    }\n    // Diag 2 (/): (x+1, y) -> (x, y+1)  => top-right to bot-left\n    // Vector (-1, 1). x2 = x1 - 1, y2 = y1 + 1\n    if (x2 == x1 - 1 && y2 == y1 + 1) {\n        // Check bounds? x1 > 0, y1 < N-1.\n        // Map: based on top-left corner of the unit square?\n        // Let's say base is (x, y) where segment is (x+1, y) to (x, y+1).\n        // So x goes 0..N-2, y goes 0..N-2.\n        // Here x1 is the right point. x = x1 - 1. y = y1.\n        return 3 * N * (N - 1) + (x1 - 1) * (N - 1) + y1;\n    }\n    // Diag 2 reverse: (x, y+1) -> (x+1, y)\n    if (x2 == x1 + 1 && y2 == y1 - 1) {\n        // x2 is right point. x = x2 - 1. y = y2.\n        return 3 * N * (N - 1) + (x2 - 1) * (N - 1) + y2;\n    }\n    return -1; // Should not happen for unit steps\n}\n\n// Check if a segment (p1 -> p2) is free.\n// If free, mark it as used. Otherwise, return false.\n// This function checks the WHOLE segment, which is composed of unit segments.\nbool check_and_mark_segment(int x1, int y1, int x2, int y2, bool mark) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    int sx = dx / steps;\n    int sy = dy / steps;\n    \n    int cx = x1;\n    int cy = y1;\n    \n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        int id = get_seg_id(cx, cy, nx, ny);\n        if (id == -1) return false; // Invalid geometry\n        \n        if (mark) {\n            if (used_segments[id]) return false; // Already used\n            used_segments[id] = true;\n        } else {\n            // Just checking, don't mark. This mode is used in \"can_place\"\n            // But we need to mark if we decide to place.\n            // This function is a bit awkward. \n            // Let's split logic.\n        }\n        cx = nx;\n        cy = ny;\n    }\n    return true;\n}\n\nbool is_segment_free(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    int sx = dx / steps;\n    int sy = dy / steps;\n    \n    int cx = x1;\n    int cy = y1;\n    \n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        int id = get_seg_id(cx, cy, nx, ny);\n        if (id != -1 && used_segments[id]) return false;\n        cx = nx;\n        cy = ny;\n    }\n    return true;\n}\n\nvoid mark_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    int sx = dx / steps;\n    int sy = dy / steps;\n    \n    int cx = x1;\n    int cy = y1;\n    \n    for (int i = 0; i < steps; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        int id = get_seg_id(cx, cy, nx, ny);\n        if (id != -1) used_segments[id] = true;\n        cx = nx;\n        cy = ny;\n    }\n}\n\n// Check if perimeter has no other dots\nbool check_perimeter_clean(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    auto check_line = [](int ax, int ay, int bx, int by) {\n        int dx = bx - ax;\n        int dy = by - ay;\n        int steps = max(abs(dx), abs(dy));\n        if (steps == 0) return true;\n        int sx = dx / steps;\n        int sy = dy / steps;\n        int cx = ax + sx;\n        int cy = ay + sy;\n        for (int i = 0; i < steps - 1; ++i) { // Exclude end points\n            if (grid[cx][cy]) return false;\n            cx += sx;\n            cy += sy;\n        }\n        return true;\n    };\n    \n    // The 4 sides. p1 is new (empty), p2, p3, p4 are dots.\n    // We must ensure no other dots on p2-p3, p3-p4, p4-p1, p1-p2\n    // Note: p2, p3, p4 are dots, so we check strictly between them.\n    if (!check_line(x2, y2, x3, y3)) return false;\n    if (!check_line(x3, y3, x4, y4)) return false;\n    if (!check_line(x4, y4, x1, y1)) return false;\n    if (!check_line(x1, y1, x2, y2)) return false;\n    return true;\n}\n\n// Try to place a dot at (x, y).\n// Returns true if successful.\nbool try_place(int x, int y) {\n    if (grid[x][y]) return false;\n\n    // Iterate over possible u, v vectors for the rectangle A(p1), B(p2), C(p3), D(p4)\n    // A = (x,y)\n    // B = A + u\n    // C = B + v\n    // D = A + v\n    // Constraints: B, C, D must be dots.\n    // Sides AB, BC, CD, DA must be axis or 45-degree aligned.\n    // u, v must be perpendicular.\n    // Permutations of u, v signs?\n    // We just iterate geometric shapes.\n    \n    // Possible directions for u:\n    // Axis: (1,0), (-1,0), (0,1), (0,-1)\n    // Diag: (1,1), (1,-1), (-1,1), (-1,-1)\n    \n    vector<pair<int,int>> dirs = {{1,0}, {-1,0}, {0,1}, {0,-1}, {1,1}, {1,-1}, {-1,1}, {-1,-1}};\n    \n    // We try to find small rectangles first to increase success rate and save space\n    // Max side length to try?\n    // Since N is small, we can try up to N.\n    \n    for (int len_u = 1; len_u < N; ++len_u) {\n        for (int len_v = 1; len_v < N; ++len_v) {\n            for (auto& du : dirs) {\n                for (auto& dv : dirs) {\n                    // Check perpendicular: dot product 0\n                    if (du.first * dv.first + du.second * dv.second != 0) continue;\n                    \n                    // Calculate B, C, D\n                    int bx = x + du.first * len_u;\n                    int by = y + du.second * len_u;\n                    int dx_coord = x + dv.first * len_v;\n                    int dy = y + dv.second * len_v;\n                    int cx = bx + dv.first * len_v;\n                    int cy = by + dv.second * len_v;\n                    \n                    // Check bounds\n                    if (bx < 0 || bx >= N || by < 0 || by >= N) continue;\n                    if (dx_coord < 0 || dx_coord >= N || dy < 0 || dy >= N) continue;\n                    if (cx < 0 || cx >= N || cy < 0 || cy >= N) continue;\n                    \n                    // Check dots existence\n                    if (!grid[bx][by]) continue;\n                    if (!grid[dx_coord][dy]) continue;\n                    if (!grid[cx][cy]) continue;\n                    \n                    // Check segment availability\n                    // Perimeter: A->B, B->C, C->D, D->A\n                    if (!is_segment_free(x, y, bx, by)) continue;\n                    if (!is_segment_free(bx, by, cx, cy)) continue;\n                    if (!is_segment_free(cx, cy, dx_coord, dy)) continue;\n                    if (!is_segment_free(dx_coord, dy, x, y)) continue;\n                    \n                    // Check clean perimeter\n                    if (!check_perimeter_clean(x, y, bx, by, cx, cy, dx_coord, dy)) continue;\n                    \n                    // Found valid rectangle!\n                    \n                    // Apply\n                    grid[x][y] = true;\n                    mark_segment(x, y, bx, by);\n                    mark_segment(bx, by, cx, cy);\n                    mark_segment(cx, cy, dx_coord, dy);\n                    mark_segment(dx_coord, dy, x, y);\n                    \n                    ops.emplace_back(x, y, bx, by, cx, cy, dx_coord, dy);\n                    return true;\n                }\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    center = (N - 1) / 2;\n    \n    // Initialize grid\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = false;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        grid[x][y] = true;\n    }\n    \n    // Prepare targets: all empty cells, sorted by weight descending\n    // Weight = dist^2 + 1\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!grid[i][j]) {\n                int dist_sq = (i - center) * (i - center) + (j - center) * (j - center);\n                targets.push_back({i, j, dist_sq});\n            }\n        }\n    }\n    \n    // Sort by weight descending\n    sort(targets.begin(), targets.end(), [](const Point& a, const Point& b) {\n        return a.weight > b.weight;\n    });\n    \n    // Main Loop: Iteratively try to fill targets\n    // Restart scan from beginning whenever we place a dot\n    bool progress = true;\n    int idx = 0;\n    int total_targets = targets.size();\n    \n    while (progress && !time_limit_exceeded) {\n        progress = false;\n        check_time();\n        \n        for (int i = 0; i < total_targets; ++i) {\n            // Optimization: skip if already filled\n            if (grid[targets[i].x][targets[i].y]) continue;\n            \n            if (try_place(targets[i].x, targets[i].y)) {\n                progress = true;\n                break; // Restart scan from highest weight\n            }\n        }\n    }\n    \n    // Output\n    cout << ops.size() << \"\\n\";\n    for (auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \" \"\n             << get<4>(op) << \" \" << get<5>(op) << \" \"\n             << get<6>(op) << \" \" << get<7>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int H = 10;\nconst int W = 10;\n\nstruct Solver {\n    vector<vector<int>> board;\n    vector<int> flavors;\n    int step;\n    // Targets for each flavor (1-indexed flavor -> target coordinates)\n    // We choose corners/edges to maximize separation.\n    // Flavor 1: Top-Left (0,0)\n    // Flavor 2: Top-Right (0,9)\n    // Flavor 3: Bottom-Center (9,4)\n    vector<pair<int, int>> targets;\n    \n    Solver(vector<int> f) : flavors(f), step(0) {\n        board.assign(H, vector<int>(W, 0));\n        targets = {{0, 0}, {0, 9}, {9, 4}};\n    }\n\n    // Maps the 1-based index p to the actual empty cell coordinates\n    pair<int, int> get_pos(int p) {\n        int cnt = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (board[i][j] == 0) {\n                    cnt++;\n                    if (cnt == p) return {i, j};\n                }\n            }\n        }\n        return {-1, -1}; \n    }\n\n    // Simulates tilting the board\n    // 0: F (Forward/Up), 1: B (Backward/Down), 2: L (Left), 3: R (Right)\n    vector<vector<int>> tilt(vector<vector<int>> b, int dir) {\n        if (dir == 0) { // Forward\n            for (int j = 0; j < W; ++j) {\n                int write_i = 0;\n                for (int i = 0; i < H; ++i) {\n                    if (b[i][j] != 0) {\n                        if (write_i != i) {\n                            b[write_i][j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_i++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // Backward\n            for (int j = 0; j < W; ++j) {\n                int write_i = H - 1;\n                for (int i = H - 1; i >= 0; --i) {\n                    if (b[i][j] != 0) {\n                        if (write_i != i) {\n                            b[write_i][j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_i--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // Left\n            for (int i = 0; i < H; ++i) {\n                int write_j = 0;\n                for (int j = 0; j < W; ++j) {\n                    if (b[i][j] != 0) {\n                        if (write_j != j) {\n                            b[i][write_j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_j++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < H; ++i) {\n                int write_j = W - 1;\n                for (int j = W - 1; j >= 0; --j) {\n                    if (b[i][j] != 0) {\n                        if (write_j != j) {\n                            b[i][write_j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_j--;\n                    }\n                }\n            }\n        }\n        return b;\n    }\n\n    // Evaluate the board state\n    double evaluate(const vector<vector<int>>& b) {\n        int sum_sq = 0;\n        vector<vector<bool>> visited(H, vector<bool>(W, false));\n        \n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0 && !visited[i][j]) {\n                    queue<pair<int,int>> q;\n                    q.push({i,j});\n                    visited[i][j] = true;\n                    int size = 0;\n                    int type = b[i][j];\n                    while (!q.empty()) {\n                        auto [r, c] = q.front(); q.pop();\n                        size++;\n                        int dr[] = {0, 0, 1, -1};\n                        int dc[] = {1, -1, 0, 0};\n                        for (int k = 0; k < 4; ++k) {\n                            int nr = r + dr[k];\n                            int nc = c + dc[k];\n                            if (nr >= 0 && nr < H && nc >= 0 && nc < W && !visited[nr][nc] && b[nr][nc] == type) {\n                                visited[nr][nc] = true;\n                                q.push({nr,nc});\n                            }\n                        }\n                    }\n                    sum_sq += size * size;\n                }\n            }\n        }\n\n        double penalty = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0) {\n                    int flavor_idx = b[i][j] - 1;\n                    penalty += abs(i - targets[flavor_idx].first) + abs(j - targets[flavor_idx].second);\n                }\n            }\n        }\n        \n        // Weight the penalty. \n        // We want to cluster (maximize sum_sq) and separate flavors (minimize penalty).\n        // sum_sq grows quadratically, penalty linearly.\n        // However, early in the game, sum_sq is small (mostly 1s), so penalty dominates naturally if weight is significant.\n        // We use a constant weight. Since sum_sq is at most 10000 and penalty at most ~1800,\n        // a weight of 2.0 ensures that until clusters form, we optimize for position (penalty),\n        // and once clusters are large, sum_sq dominates.\n        double weight = 3.0;\n        \n        return (double)sum_sq - weight * penalty;\n    }\n\n    char solve(int p) {\n        // Place candy\n        auto [r, c] = get_pos(p);\n        board[r][c] = flavors[step];\n        \n        double best_score = -1e18;\n        int best_dir = -1;\n        \n        // Try all 4 directions\n        for (int d = 0; d < 4; ++d) {\n            auto next_board = tilt(board, d);\n            double score = evaluate(next_board);\n            if (score > best_score) {\n                best_score = score;\n                best_dir = d;\n            }\n        }\n        \n        // Apply best move\n        board = tilt(board, best_dir);\n        step++;\n        \n        if (best_dir == 0) return 'F';\n        if (best_dir == 1) return 'B';\n        if (best_dir == 2) return 'L';\n        return 'R';\n    }\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) cin >> f[i];\n    \n    Solver solver(f);\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        if (t < 99) {\n            char out = solver.solve(p);\n            cout << out << endl;\n            cout.flush();\n        } else {\n            solver.solve(p); // 100th move, no output needed\n        }\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// MT19937 for random number generation\nmt19937 rng(1337); // Fixed seed or random_device? \n// Since we want reproducible results locally or generally good randomness, \n// fixed seed is fine, but for contest, we usually want different runs?\n// Actually, the graphs we output are deterministic based on the random seed used during generation.\n// We should use a good seed.\n\ndouble estimate_expected_errors(int M, double eps, int N) {\n    if (eps == 0.0) return 0.0;\n    \n    int P = N * (N - 1) / 2;\n    // For random graphs, expected Hamming distance d is P/2.\n    // The distribution of d is Binomial(P, 0.5), roughly normal with mean P/2, var P/4.\n    double d_mean = P / 2.0;\n    \n    // Probability that one graph is mistaken for another.\n    // Condition: z >= d/2, where z ~ Binomial(d, eps).\n    // Approximate z as Normal(eps * d, eps*(1-eps)*d).\n    // We calculate Z-score for d/2.\n    // Z = (d/2 - eps*d) / sqrt(d*eps*(1-eps))\n    // Z = d * (0.5 - eps) / sqrt(d*eps*(1-eps))\n    // Z = sqrt(d) * (0.5 - eps) / sqrt(eps*(1-eps))\n    \n    double z_score = sqrt(d_mean) * (0.5 - eps) / sqrt(eps * (1.0 - eps));\n    \n    // P(z >= d/2) = P(N(0,1) > z_score) = 0.5 * erfc(z_score / sqrt(2))\n    // Use erfc from cmath\n    \n    if (z_score <= 0) {\n        // If eps >= 0.5, probability is high. But eps <= 0.4.\n        // If eps is very close to 0.5 or 0.5, we are in trouble.\n        // Since eps <= 0.4, z_score is positive.\n        return 100.0; // Cap expected errors\n    }\n    \n    double p_err_pair = 0.5 * erfc(z_score / sqrt(2.0));\n    \n    // Expected errors per query\n    // There are M-1 neighbors. Approx error is sum of pairwise errors.\n    // E_err_query = (M - 1) * p_err_pair\n    double E_err_query = (M - 1) * p_err_pair;\n    \n    // Total expected errors for 100 queries\n    return E_err_query * 100.0;\n}\n\nint choose_N(int M, double eps) {\n    int best_N = 15;\n    double best_score = -1.0;\n    \n    // Calculate minimal N to fit M graphs with distinct edge counts if eps=0\n    // P = N(N-1)/2 >= M\n    // N^2 - N - 2M >= 0\n    // N = (1 + sqrt(1+8M))/2\n    int min_N_feasible = (int)ceil((1.0 + sqrt(1.0 + 8.0 * M)) / 2.0);\n    if (min_N_feasible < 15) min_N_feasible = 15;\n    \n    for (int N = min_N_feasible; N <= 100; ++N) {\n        double E_est = estimate_expected_errors(M, eps, N);\n        \n        // Score formula: 10^9 * 0.9^E / N\n        // We can ignore 10^9 for comparison\n        // We also need to account that E is integer, but estimated is float.\n        // 0.9^E is monotonic.\n        double score = pow(0.9, E_est) / (double)N;\n        \n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n        }\n    }\n    return best_N;\n}\n\nstring generate_random_graph(int N) {\n    int P = N * (N - 1) / 2;\n    string graph(P, '0');\n    // Randomly flip bits to '1' with probability 0.5?\n    // Or should we make them sparse/dense?\n    // Random graphs with p=0.5 maximize entropy and expected Hamming distance.\n    // This is generally good for distinguishing.\n    // However, if we want to be safe against specific eps, maybe uniform density is best.\n    // Let's use density 0.5.\n    for (int i = 0; i < P; ++i) {\n        if (rng() % 2 == 1) {\n            graph[i] = '1';\n        }\n    }\n    return graph;\n}\n\nint hamming_dist(const string& a, const string& b) {\n    int d = 0;\n    for (size_t i = 0; i < a.size(); ++i) {\n        if (a[i] != b[i]) d++;\n    }\n    return d;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    // Determine optimal N\n    int N = choose_N(M, eps);\n    \n    cout << N << endl;\n    \n    // Generate M graphs\n    vector<string> graphs(M);\n    for (int i = 0; i < M; ++i) {\n        graphs[i] = generate_random_graph(N);\n        cout << graphs[i] << endl;\n    }\n    \n    cout << flush;\n    \n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        \n        int best_k = 0;\n        int min_dist = N * N; // Initialize with large value\n        // N(N-1)/2 is max possible dist\n        \n        for (int k = 0; k < M; ++k) {\n            int d = hamming_dist(H, graphs[k]);\n            if (d < min_dist) {\n                min_dist = d;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <tuple>\n#include <limits>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nconst int INF = 1e9;\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N); // (to, edge_id)\n\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        adj[edges[i].u].emplace_back(edges[i].v, i);\n        adj[edges[i].v].emplace_back(edges[i].u, i);\n    }\n\n    // Read coordinates (unused in logic but needed to consume input)\n    for (int i = 0; i < N; ++i) {\n        double x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate edge usage (number of shortest paths passing through the edge)\n    // We run Dijkstra from every node.\n    vector<long long> usage(M, 0);\n\n    for (int s = 0; s < N; ++s) {\n        vector<long long> dist(N, INF);\n        vector<int> parent(N, -1); // To reconstruct path\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = eid; // Store the edge used to reach v\n                    pq.emplace(nd, v);\n                } else if (nd == dist[v]) {\n                    // If multiple shortest paths exist, we can choose arbitrarily.\n                    // To make usage deterministic and potentially \"spread out\", \n                    // we can stick to the first found or randomize.\n                    // Sticking to first found (smaller vertex index due to PQ order naturally if weights equal) is fine.\n                }\n            }\n        }\n\n        // Reconstruct paths for all t != s\n        for (int t = 0; t < N; ++t) {\n            if (s == t) continue;\n            int curr = t;\n            while (curr != s) {\n                int eid = parent[curr];\n                // Should not be -1 since graph is connected\n                usage[eid]++;\n                // Move to previous node\n                // Edge eid connects prev and curr. We need to find which one is prev.\n                // Since parent map stores the edge entering 'curr', the other endpoint is prev.\n                int prev = (edges[eid].u == curr) ? edges[eid].v : edges[eid].u;\n                curr = prev;\n            }\n        }\n    }\n\n    // 2. Sort edges by usage descending\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return usage[a] > usage[b];\n    });\n\n    // 3. Greedy Assignment\n    vector<vector<int>> days(D);\n    vector<int> day_of_edge(M, -1);\n    vector<long long> load(D, 0); // Sum of usage of edges in the day\n\n    // Helper function to check connectivity\n    auto is_connected = [&](int day_k, int check_eid) {\n        vector<bool> visited(N, false);\n        queue<int> q;\n        q.push(0);\n        visited[0] = true;\n        int count = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            for (auto [v, eid] : adj[u]) {\n                if (visited[v]) continue;\n                \n                // Skip if this edge is assigned to day_k, or is the edge we are checking\n                if (day_of_edge[eid] == day_k || eid == check_eid) continue;\n                \n                visited[v] = true;\n                count++;\n                q.push(v);\n                \n                // Early exit optimization\n                if (count == N) return true;\n            }\n        }\n        return count == N;\n    };\n\n    for (int i = 0; i < M; ++i) {\n        int eid = edge_order[i];\n        long long e_usage = usage[eid];\n\n        // Try to assign to a day\n        // We prefer days with lower current load, but strictly enforce connectivity\n        \n        // Create list of day indices sorted by current load\n        vector<int> day_indices(D);\n        iota(day_indices.begin(), day_indices.end(), 0);\n        sort(day_indices.begin(), day_indices.end(), [&](int a, int b) {\n            return load[a] < load[b];\n        });\n\n        bool assigned = false;\n        for (int d : day_indices) {\n            if ((int)days[d].size() >= K) continue;\n\n            if (is_connected(d, eid)) {\n                days[d].push_back(eid);\n                day_of_edge[eid] = d + 1; // 1-indexed output\n                load[d] += e_usage;\n                assigned = true;\n                break;\n            }\n        }\n\n        if (!assigned) {\n            // Fallback: assign to day with min load (ignoring connectivity)\n            // This should rarely happen with 2-edge connected graph and enough slack\n            int min_d = 0;\n            for (int d = 1; d < D; ++d) {\n                if (load[d] < load[min_d]) min_d = d;\n            }\n            days[min_d].push_back(eid);\n            day_of_edge[eid] = min_d + 1;\n            load[min_d] += e_usage;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        if (i > 0) cout << \" \";\n        cout << day_of_edge[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nconst int D_MAX = 14;\nconst int XY_MAX = 14;\n\n// Timer for managing execution time\nclass Timer {\n    chrono::system_clock::time_point start;\npublic:\n    Timer() : start(chrono::system_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::system_clock::now() - start).count();\n    }\n};\n\n// Global state\nint D;\nbool f[2][D_MAX][D_MAX]; // Front silhouette: z, x\nbool r[2][D_MAX][D_MAX]; // Right silhouette: z, y\n\n// Grid representation of the two objects\n// grid[id][z][x][y] = 1 if occupied\n// Using bitset for efficiency and easy copy/overlap\nbitset<XY_MAX * XY_MAX> grid[2][D_MAX]; // Flattened x,y for z layer. Index = x*D + y\n\n// Helper structures for fast operations during SA\nvector<int> active_x[2][D_MAX];\nvector<int> active_y[2][D_MAX];\nint y_of_x[2][D_MAX][D_MAX]; // Mapping x -> y for active cells in a layer\nint cnt_of_y[2][D_MAX][D_MAX]; // Count of x mapped to y\n\nint current_overlap = 0;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Coordinates structure\nstruct Point {\n    int x, y, z;\n};\n\nint get_idx(int x, int y) {\n    return x * D + y;\n}\n\nvoid init() {\n    // Read D\n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int x = 0; x < D; ++x) {\n                f[i][z][x] = (s[x] == '1');\n                if (f[i][z][x]) active_x[i][z].push_back(x);\n            }\n        }\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int y = 0; y < D; ++y) {\n                r[i][z][y] = (s[y] == '1');\n                if (r[i][z][y]) active_y[i][z].push_back(y);\n            }\n        }\n    }\n}\n\nvoid construct_initial(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        \n        int kx = xs.size();\n        int ky = ys.size();\n        \n        // Reset mappings\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n        \n        if (kx == 0 || ky == 0) continue;\n        \n        // Greedy matching to maximize initial overlap potential\n        // If kx >= ky, match first ky xs to all ys, remaining xs to first y\n        // If kx < ky, match all xs to first ky ys. But remaining ys must be covered.\n        // Wait, if kx < ky, we must cover all ys.\n        // Basic logic: create a set of pairs (x, y) such that all x in xs, all y in ys are covered.\n        \n        // Simplified logic for minimal volume intersection\n        // We just need a valid configuration. SA will optimize it.\n        \n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            for (int i = ky; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[0]; // Map to first y\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            // Cover remaining ys. Reuse the first x (index 0)\n            for (int i = kx; i < ky; ++i) {\n                int x = xs[0];\n                int y = ys[i];\n                // Add pair (x, y)\n                // Note: x=0 might already have a pair.\n                y_of_x[obj_id][z][x] = y; // Overwrite? No, we just add to grid and counts.\n                // y_of_x only stores ONE y for x, but an x can map to multiple y if needed?\n                // Our structure assumes 1-to-1 or 1-to-many.\n                // In this case, x=0 maps to many y.\n                // y_of_x needs to support list of y, or we just iterate to find neighbors.\n                // For SA, we used y_of_x to find current y. If x maps to multiple, this fails.\n                // So we should stick to matchings or near-matchings.\n                // Since kx < ky, we have fewer columns than rows. Some columns MUST cover multiple rows.\n                // Let's change logic: use a matching where possible, then add extra edges.\n                // Since k is small, let's just make sure every x maps to at least 1 y, and every y is mapped by some x.\n                // This is a bipartite graph cover.\n                // Minimal edges = max(kx, ky).\n                // Structure: A spanning tree structure on the bipartite graph of xs and ys.\n                // Since xs and ys are sets of integers, we can sort them and try to match proximity.\n            }\n        }\n        \n        // Re-doing the construction more robustly for the kx < ky case\n        // and handling the \"multiple y per x\" issue.\n        // Let's store edges explicitly?\n        // Given D=14, we can just store a vector of pairs per layer.\n        // But SA needs O(1) modification.\n        // Let's allow \"y_of_x\" to be just one representative y, but counts to be correct.\n        // Actually, if x maps to multiple y, which one do we move?\n        // We can restrict to matchings (kx=ky) or star graphs (one central x or one central y).\n        // Let's use the star graph approach which covers all minimal volumes.\n        \n        // Clear again\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n\n        if (kx >= ky) {\n            // Star centered at ys.\n            // Each y gets at least one distinct x.\n            // Remaining x connect to y[0].\n            for(int i=0; i<ky; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            for(int i=ky; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y; \n                // If y_of_x already had this y from previous loop, it's fine.\n                // It just means x maps to y.\n                cnt_of_y[obj_id][z][y]++;\n            }\n        } else {\n            // Star centered at xs.\n            // Each x gets at least one distinct y.\n            // Remaining y connect to x[0].\n            for(int i=0; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            // Remaining ys\n            for(int i=kx; i<ky; i++) {\n                int y = ys[i];\n                int x = xs[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                // x[0] already maps to some y. We add another edge.\n                // y_of_x[x[0]] points to ys[0]. It doesn't capture this new edge.\n                // So y_of_x is insufficient for \"many y per x\".\n                // We need a list of edges.\n                // But D=14. Max edges per layer ~14.\n                // Let's store vector<pair<int,int>> cells[obj][z].\n                // SA moves:\n                // Pick an edge (x,y). Change to (x, y_new).\n                // If cnt[y] > 1, valid.\n                // If cnt[y] == 1, must swap with (x2, y_new).\n                // This works with edge lists.\n                \n                // Let's switch to edge lists representation.\n            }\n        }\n    }\n}\n\n// Let's use a unified representation that supports the move logic perfectly.\n// We will maintain:\n// - vector<pair<int, int>> cells[2][D_MAX];  List of active cells (x,y) at layer z.\n// - This is sufficient to reconstruct the grid.\n// - Counts are derived.\n// - \"Pick x, move y\" logic:\n//   We need to find if there is an edge (x, y_curr).\n//   With vector, searching is O(N).\n//   N is small (<=14). O(14) is fine.\n//   Swapping is also O(N).\n\nvector<pair<int, int>> layer_cells[2][D_MAX];\n\nvoid build_initial_with_edge_list(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        layer_cells[obj_id][z].clear();\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        int kx = xs.size();\n        int ky = ys.size();\n        \n        if (kx == 0 || ky == 0) continue;\n\n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = ky; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[0]});\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = kx; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[0], ys[i]});\n            }\n        }\n        \n        // Update bitset\n        grid[obj_id][z].reset();\n        for (auto& p : layer_cells[obj_id][z]) {\n            grid[obj_id][z].set(get_idx(p.first, p.second));\n        }\n    }\n}\n\nvoid solve() {\n    init();\n    \n    // Construct initial states\n    build_initial_with_edge_list(0);\n    build_initial_with_edge_list(1);\n    \n    // Calculate initial overlap\n    current_overlap = 0;\n    for (int z = 0; z < D; ++z) {\n        current_overlap += (grid[0][z] & grid[1][z]).count();\n    }\n    \n    // Simulated Annealing\n    double start_time = Timer().elapsed();\n    double time_limit = 5.8; // leave margin\n    double temp_start = 100.0;\n    double temp_end = 1e-4;\n    int iter = 0;\n    \n    // Helper to calculate counts from cells\n    auto get_counts = [&](int obj, int z) {\n        vector<int> cnt(D, 0);\n        for (auto& p : layer_cells[obj][z]) cnt[p.second]++;\n        return cnt;\n    };\n    \n    while (true) {\n        double now = Timer().elapsed();\n        if (now - start_time > time_limit) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, (now - start_time) / time_limit);\n        \n        // Pick operation\n        // 0: modify obj 0, 1: modify obj 1\n        int obj = (rng() % 2);\n        int z = rng() % D;\n        \n        vector<pair<int,int>>& cells = layer_cells[obj][z];\n        if (cells.empty()) continue;\n        \n        // Select a random edge to modify\n        int idx = rng() % cells.size();\n        int x_a = cells[idx].first;\n        int y_curr = cells[idx].second;\n        \n        // Pick target y\n        // Must be active y in silhouettes\n        vector<int>& active_ys = active_y[obj][z];\n        if (active_ys.empty()) continue;\n        int y_new = active_ys[rng() % active_ys.size()];\n        \n        if (y_new == y_curr) continue;\n        \n        // Check feasibility\n        auto counts = get_counts(obj, z);\n        \n        // Proposed change: move (x_a, y_curr) to (x_a, y_new)\n        // Valid if counts[y_curr] > 1 OR we swap with another edge ending at y_new\n        \n        bool valid = false;\n        int idx_swap = -1;\n        \n        if (counts[y_curr] > 1) {\n            valid = true;\n        } else {\n            // Must swap\n            // Find edge (x_b, y_new)\n            for (int i = 0; i < cells.size(); ++i) {\n                if (cells[i].second == y_new) {\n                    idx_swap = i;\n                    break;\n                }\n            }\n            if (idx_swap != -1) valid = true;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate Delta Overlap\n        int delta = 0;\n        int other = 1 - obj;\n        \n        // Remove (x_a, y_curr)\n        int pos1 = get_idx(x_a, y_curr);\n        if (grid[other][z].test(pos1)) delta--;\n        \n        // Add (x_a, y_new)\n        int pos2 = get_idx(x_a, y_new);\n        if (grid[other][z].test(pos2)) delta++;\n        \n        if (idx_swap != -1) {\n            // Remove (x_b, y_new)\n            int x_b = cells[idx_swap].first;\n            int pos3 = get_idx(x_b, y_new);\n            if (grid[other][z].test(pos3)) delta--;\n            \n            // Add (x_b, y_curr)\n            int pos4 = get_idx(x_b, y_curr);\n            if (grid[other][z].test(pos4)) delta++;\n        }\n        \n        // Acceptance\n        if (delta >= 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n            // Apply change\n            if (idx_swap == -1) {\n                // Simple move\n                cells[idx].second = y_new;\n            } else {\n                // Swap\n                int x_b = cells[idx_swap].first;\n                cells[idx].second = y_new;\n                cells[idx_swap].second = y_curr;\n            }\n            \n            // Update grid bitset\n            grid[obj][z].reset();\n            for (auto& p : cells) {\n                grid[obj][z].set(get_idx(p.first, p.second));\n            }\n            \n            current_overlap += delta;\n        }\n    }\n    \n    // Final block construction\n    // We need to assign Block IDs.\n    \n    // 1. Identify shared cells\n    vector<int> b1(D*D*D, 0);\n    vector<int> b2(D*D*D, 0);\n    \n    // Helper to convert x,y,z to linear index\n    auto lin = [&](int x, int y, int z) { return x * D * D + y * D + z; };\n    \n    // Map to store block IDs\n    // We will perform BFS to find connected components\n    int current_id = 0;\n    \n    // Visited arrays\n    int visited[2][D_MAX][D_MAX][D_MAX]; // 0=unvisited, 1=visited\n    for(int i=0; i<2; ++i) for(int z=0; z<D; ++z) for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) visited[i][z][x][y] = 0;\n\n    // First process Shared Components\n    // Cells that are in both grid[0] and grid[1]\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && grid[1][z].test(get_idx(x,y))) {\n                    if (visited[0][z][x][y] == 0) { // Not yet assigned\n                        // Start BFS for shared component\n                        current_id++;\n                        queue<Point> q;\n                        q.push({x,y,z});\n                        visited[0][z][x][y] = current_id;\n                        visited[1][z][x][y] = current_id; // Mark visited in both\n                        \n                        while (!q.empty()) {\n                            Point p = q.front(); q.pop();\n                            int idx = lin(p.x, p.y, p.z);\n                            b1[idx] = current_id;\n                            b2[idx] = current_id;\n                            \n                            // Neighbors: 6 directions\n                            int dx[6] = {1, -1, 0, 0, 0, 0};\n                            int dy[6] = {0, 0, 1, -1, 0, 0};\n                            int dz[6] = {0, 0, 0, 0, 1, -1};\n                            \n                            for (int k = 0; k < 6; ++k) {\n                                int nx = p.x + dx[k];\n                                int ny = p.y + dy[k];\n                                int nz = p.z + dz[k];\n                                \n                                if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                    // Check if cell is shared and unvisited\n                                    if (visited[0][nz][nx][ny] == 0 && \n                                        grid[0][nz].test(get_idx(nx, ny)) && \n                                        grid[1][nz].test(get_idx(nx, ny))) {\n                                        visited[0][nz][nx][ny] = current_id;\n                                        visited[1][nz][nx][ny] = current_id;\n                                        q.push({nx, ny, nz});\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Second process Unique Components for Object 1\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && visited[0][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b1[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[0][nz][nx][ny] == 0 && grid[0][nz].test(get_idx(nx, ny))) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Third process Unique Components for Object 2\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[1][z].test(get_idx(x,y)) && visited[1][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[1][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b2[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[1][nz][nx][ny] == 0 && grid[1][nz].test(get_idx(nx, ny))) {\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    int n = current_id;\n    \n    // Output\n    cout << n << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b1[i];\n    }\n    cout << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b2[i];\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <array>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Solver {\n    int N, M, K;\n    vector<pair<int, int>> coords;\n    vector<tuple<int, int, long long>> edges;\n    vector<pair<int, int>> residents;\n    vector<vector<long long>> dist_nodes; // Shortest path weights\n    vector<vector<int>> dist_res; // Euclidean distances (squared or rounded?)\n    // Problem says dist is Euclidean, check \"rounded\". \n    // Input says \"D_j = round(sqrt(...))\". \n    // For coverage, we need sqrt((x-x)^2 + (y-y)^2).\n    // Let's use squared distance to avoid sqrt until necessary, or integer rounded distances.\n    // \"area ... radius P_i\". Condition: sqrt((x-xi)^2 + (y-yi)^2) <= P_i\n    // So we should store integer distances. round(sqrt(...)).\n    // We can compute distance^2 and compare with P_i^2?\n    // No, P_i is integer radius. Condition is distance <= P_i.\n    // So store rounded distance or floating point?\n    // Floating point is safer for precision but slower. \n    // Integer rounding: round(sqrt(dx*dx + dy*dy)).\n    // Let's use integer rounded distances.\n\n    vector<int> P;\n    vector<int> B;\n\n    Solver(int n, int m, int k) : N(n), M(m), K(k) {\n        coords.resize(N);\n        edges.resize(M);\n        residents.resize(K);\n        dist_nodes.assign(N, vector<long long>(N, 1e18));\n        dist_res.assign(N, vector<int>(K));\n        P.assign(N, 0);\n        B.assign(M, 0);\n    }\n\n    void solve() {\n        // Floyd-Warshall\n        for (int i = 0; i < N; ++i) dist_nodes[i][i] = 0;\n        for (auto& e : edges) {\n            int u, v;\n            long long w;\n            tie(u, v, w) = e;\n            u--; v--;\n            if (w < dist_nodes[u][v]) {\n                dist_nodes[u][v] = w;\n                dist_nodes[v][u] = w;\n            }\n        }\n        for (int k = 0; k < N; ++k) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (dist_nodes[i][k] + dist_nodes[k][j] < dist_nodes[i][j]) {\n                        dist_nodes[i][j] = dist_nodes[i][k] + dist_nodes[k][j];\n                    }\n                }\n            }\n        }\n\n        // Precompute resident distances\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < K; ++k) {\n                long long dx = (long long)coords[i].first - residents[k].first;\n                long long dy = (long long)coords[i].second - residents[k].second;\n                dist_res[i][k] = (int)round(sqrt((double)dx*dx + dy*dy));\n            }\n        }\n\n        // Heuristic Search\n        vector<bool> active(N, false);\n        active[0] = true;\n        \n        // Assignment of residents to active nodes\n        vector<int> assign(K, 0);\n        vector<int> max_rad(N, 0);\n        // We need a fast way to update max_rad. \n        // Since N=100, K=5000, recomputing is O(NK) = 5e5, which is fast.\n        // We can afford to recompute radii from scratch in the inner loop of the search?\n        // Let's try to do it efficiently.\n        // To check \"add node u\", we need to know new radii.\n        \n        // Bucket counts for active nodes: cnt[u][r] = count of residents at dist r\n        // r can be up to ~15000. \n        // vector<vector<int>> cnt(N, vector<int>(15001, 0)); \n        // This is 100 * 15001 * 4 bytes ~= 6MB. OK.\n        const int MAX_D = 15001;\n        vector<vector<int>> cnt(N, vector<int>(MAX_D, 0));\n        \n        // Initialize: assign all to 0\n        long long current_node_cost = 0;\n        for (int k = 0; k < K; ++k) {\n            int d = dist_res[0][k];\n            cnt[0][d]++;\n            max_rad[0] = max(max_rad[0], d);\n        }\n        for (int i = 0; i < N; ++i) {\n            current_node_cost += (long long)max_rad[i] * max_rad[i];\n        }\n        \n        // Helper to get MST cost\n        auto get_mst_cost = [&](const vector<bool>& act) {\n            long long mst_cost = 0;\n            vector<bool> in_mst(N, false);\n            vector<long long> min_dist(N, 1e18);\n            min_dist[0] = 0; // Start from 0\n            for (int i = 0; i < N; ++i) {\n                int u = -1;\n                for (int j = 0; j < N; ++j) {\n                    if (act[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                        u = j;\n                    }\n                }\n                if (u == -1) break; // Should not happen if act is connected to 0\n                in_mst[u] = true;\n                mst_cost += min_dist[u];\n                for (int v = 0; v < N; ++v) {\n                    if (act[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                        min_dist[v] = dist_nodes[u][v];\n                    }\n                }\n            }\n            return mst_cost;\n        };\n\n        long long current_edge_cost = get_mst_cost(active);\n        long long total_cost = current_node_cost + current_edge_cost;\n\n        // Random order for greedy addition\n        vector<int> order(N-1);\n        iota(order.begin(), order.end(), 1);\n        mt19937 rng(2024); // Fixed seed for reproducibility during contest? Or random?\n        // Problem asks for high rank. Fixed seed is bad if local optimum is bad. \n        // But we can't run too long. Let's shuffle once or twice.\n        // Given 300 cases, let's stick to a deterministic but good order or just shuffle once.\n        // Actually, time limit is tight. Let's try not to shuffle (1, 2, 3...) first, then if time permits...\n        // Or just one shuffle.\n        shuffle(order.begin(), order.end(), rng);\n\n        // Greedy Add\n        for (int u : order) {\n            if (active[u]) continue;\n\n            // Simulate adding u\n            // We need to calculate delta cost.\n            // Node cost delta:\n            // We need to re-assign residents.\n            // If d(u, k) < current radius of assign[k], then k moves to u.\n            // Wait, \"current radius of assign[k]\" is P_{assign[k]}.\n            // If k moves to u, P_{assign[k]} might decrease, P_u might increase.\n            \n            // We will construct a list of changes.\n            // But P_{assign[k]} depends on the farthest resident in that group.\n            // We can't just look at one resident k. We need to know the new max for each group.\n            // However, since we only ADD u, only u can gain residents. Others can only lose.\n            // For a node v (v != u), it loses residents k where d(u, k) < P_v AND k is currently assigned to v.\n            // BUT, if k is not the one defining P_v, losing k doesn't change P_v.\n            // If k is the one defining P_v, we need to find the next farthest.\n            \n            // Efficient simulation:\n            // We maintain cnt and max_rad.\n            // We'll make a copy of cnt? Too slow (6MB copy).\n            // We will record modifications and revert.\n            struct Change { int node; int r; int delta; };\n            vector<Change> changes;\n\n            long long new_node_cost = current_node_cost;\n            long long new_edge_cost = 0;\n            \n            // Calculate new edge cost roughly\n            // Prim's add cost: min_{v in active} dist(u, v)\n            long long conn_cost = 1e18;\n            for (int v = 0; v < N; ++v) {\n                if (active[v] && dist_nodes[u][v] < conn_cost) {\n                    conn_cost = dist_nodes[u][v];\n                }\n            }\n            // This is the cost to add u to the existing tree? \n            // MST cost doesn't increase exactly by conn_cost if u connects closer nodes that were far apart.\n            // But Prim's algorithm adds exactly conn_cost.\n            // So new_edge_cost = current_edge_cost + conn_cost?\n            // Not exactly. MST on V + u is <= MST(V) + min_dist(u).\n            // Actually, if we run Prim on V, and then extend to u, the added edge is min_dist(u, V).\n            // Yes, if we maintain Prim's tree structure.\n            // However, we are just keeping the set V. We compute MST from scratch.\n            // Calculating MST from scratch is O(N^2). We do it N times -> 10^6 ops. Acceptable.\n            active[u] = true;\n            new_edge_cost = get_mst_cost(active);\n            active[u] = false;\n\n            // Calculate new node cost\n            // We need to update max_rad.\n            // We can just compute the new radii for affected nodes.\n            // For each resident k:\n            //   if d(u, k) < P_{assign[k]}:\n            //      k moves to u.\n            //      Update P_{assign[k]}? We need to find new max.\n            \n            // To handle \"find new max\" efficiently, we can use the bucket `cnt`.\n            // When we remove k from v, we decrement cnt[v][d].\n            // If cnt[v][P_v] becomes 0, we decrement P_v until cnt[v][P_v] > 0.\n            // This requires mutable access to cnt.\n            // We will apply changes to `cnt` and `max_rad` temporarily, calculate cost, then revert.\n            \n            // But applying changes one by one and reverting is O(changes).\n            // Changes are up to K.\n            \n            bool improved = false;\n            // Optimization: quick estimate\n            // If we roughly save a lot on radii, we do the detailed check.\n            \n            long long node_delta = 0;\n            \n            // We must be careful not to mutate the global state if we revert.\n            // We will use the global cnt/max_rad, apply changes, compute, revert.\n            // Since changes are only removals (v -> u), we can do this.\n            \n            vector<pair<int, int>> moved_residents; // {old_owner, dist}\n            \n            for (int k = 0; k < K; ++k) {\n                int cur = assign[k];\n                int dist_k = dist_res[cur][k];\n                // If we are moving k from cur to u\n                if (cur != u && dist_res[u][k] < dist_k) { // Strictly better?\n                   // Wait, if dist(u,k) < P_cur, we consider moving.\n                   // Condition for moving: dist(u,k) < P_cur? \n                   // Or dist(u,k) < dist(cur,k)? \n                   // Assign to closest active node.\n                   // Since we only added u, if dist(u,k) < dist(cur,k), then u is now the closest.\n                   // But P_cur is just the max of group. \n                   // Example: cur has P=100. u has P=0. k is at 90 from cur, 80 from u.\n                   // dist(u,k)=80 < P_cur=100. k moves to u.\n                   // Example: cur has P=100. u has P=0. k is at 95 from cur, 90 from u.\n                   // k moves.\n                   // Example: cur has P=100. u has P=0. k is at 100 from cur (the max), 110 from u.\n                   // dist(u,k) > P_cur. k does not move.\n                   \n                   if (dist_res[u][k] < max_rad[cur]) {\n                       moved_residents.emplace_back(cur, dist_res[cur][k]);\n                       // Apply change immediately\n                       cnt[cur][dist_res[cur][k]]--;\n                       while (max_rad[cur] > 0 && cnt[cur][max_rad[cur]] == 0) {\n                           max_rad[cur]--;\n                       }\n                       // Add to u (tentatively)\n                       int du = dist_res[u][k];\n                       if (du > max_rad[u]) {\n                           // Record old max for u? \n                           // We don't need to know old max for u if we just update node_delta incrementally.\n                           // node_delta -= old_P_u^2 + old_P_cur^2\n                           // node_delta += new_P_u^2 + new_P_cur^2\n                           // This is hard with interleaved updates.\n                           \n                           // Simpler: Just update cnt and max_rad.\n                           // At the end, compute sum(max_rad^2) - old_sum.\n                           // But max_rad[u] keeps increasing.\n                           // And for v, it keeps decreasing.\n                           \n                           // We need to restore cnt[u] changes too.\n                           // So we should store changes to u as well.\n                           // Actually, we don't need to store changes to u for \"revert\" because u was inactive, so cnt[u] was all 0.\n                           // But we might have multiple k moving to u.\n                           \n                           // Store change for u:\n                           changes.push_back({u, du, +1}); \n                           \n                           // Update max_rad[u] immediately\n                           max_rad[u] = du;\n                           \n                           // Store change for cur (for revert)\n                           changes.push_back({cur, dist_res[cur][k], +1}); // We will revert by adding back\n                           \n                           // Update node_delta calculation?\n                           // Let's calculate node_delta at the end based on new vs old max_rad.\n                           // But we changed max_rad for many v.\n                           \n                           // We need to know the ORIGINAL max_rad[v] to compute delta.\n                           // Let's store original max_rad copy?\n                           // Copy of max_rad[100] is cheap.\n                       } else {\n                           // u doesn't expand radius, but cnt increases.\n                           // Doesn't affect node cost.\n                           changes.push_back({u, du, +1});\n                           changes.push_back({cur, dist_res[cur][k], +1});\n                       }\n                   }\n                }\n            }\n            \n            // Revert changes to cnt, keep max_rad changes for calculation? No, max_rad is derived.\n            // We need old max_rad values.\n            // Let's restart the simulation logic.\n            \n            // Better approach:\n            // 1. Copy current max_rad to old_max_rad.\n            // 2. Apply changes to cnt and max_rad.\n            // 3. Calculate new_node_cost = sum(max_rad[i]^2).\n            // 4. node_delta = new_node_cost - current_node_cost.\n            // 5. Revert cnt and max_rad.\n            \n            // Apply logic:\n            vector<int> old_max_rad = max_rad; // Copy\n            \n            // Reset cnt changes? No, we already modified cnt in the loop above!\n            // We shouldn't have modified cnt in the loop above if we want to be clean.\n            // Let's redo the loop cleanly.\n            \n            // Revert cnt from previous failed attempt (if any) - start fresh.\n            // Since we didn't accept, we should have reverted.\n            // Let's assume we are at a clean state (cnt/max_rad corresponds to current V).\n            \n            moved_residents.clear();\n            changes.clear();\n            max_rad = old_max_rad; // Ensure max_rad is clean too\n            \n            for (int k = 0; k < K; ++k) {\n                int cur = assign[k];\n                if (dist_res[u][k] < max_rad[cur]) {\n                    // Tentative move\n                    // Record to revert cur\n                    int dk = dist_res[cur][k];\n                    changes.push_back({cur, dk, +1}); // +1 to revert\n                    \n                    // Update cur\n                    cnt[cur][dk]--;\n                    while (max_rad[cur] > 0 && cnt[cur][max_rad[cur]] == 0) max_rad[cur]--;\n                    \n                    // Update u\n                    int du = dist_res[u][k];\n                    if (du > max_rad[u]) max_rad[u] = du;\n                    // Note: we don't need to revert cnt[u] changes explicitly if we just clear cnt[u] later?\n                    // No, we must revert cnt[u].\n                    // But since u was inactive, cnt[u] was 0.\n                    // We can just record changes for u and revert by -1? No, we +1'ed it.\n                    // Wait, we didn't +1 cnt[u] in the loop above.\n                    // Let's do it properly.\n                    cnt[u][du]++;\n                    // Record to revert u\n                    changes.push_back({u, du, -1}); // -1 to revert (undo the ++)\n                }\n            }\n            \n            long long tentative_node_cost = 0;\n            for (int i = 0; i < N; ++i) {\n                tentative_node_cost += (long long)max_rad[i] * max_rad[i];\n            }\n            \n            // Revert\n            for (auto& c : changes) {\n                cnt[c.node][c.r] += c.delta;\n            }\n            // Restore max_rad\n            for (int i = 0; i < N; ++i) {\n                if (i == u) {\n                    max_rad[i] = 0; // Was 0\n                } else {\n                    // For others, we can recalculate from cnt? Or restore from old_max_rad?\n                    // Recalculating is safer.\n                    while (max_rad[i] < MAX_D - 1 && cnt[i][max_rad[i] + 1] > 0) max_rad[i]++;\n                    // Wait, we decreased them.\n                    // Simple: max_rad[i] = old_max_rad[i];\n                    max_rad[i] = old_max_rad[i];\n                }\n            }\n\n            if (tentative_node_cost + new_edge_cost < total_cost) {\n                // Accept\n                active[u] = true;\n                current_edge_cost = new_edge_cost;\n                current_node_cost = tentative_node_cost;\n                total_cost = current_node_cost + current_edge_cost;\n                \n                // Apply changes permanently to cnt, max_rad, assign\n                // We need to re-run the move logic to update assign.\n                // But we know who moved.\n                // We can just re-scan residents.\n                for (int k = 0; k < K; ++k) {\n                    if (dist_res[u][k] < max_rad[assign[k]]) {\n                        cnt[assign[k]][dist_res[assign[k]][k]]--;\n                        while (max_rad[assign[k]] > 0 && cnt[assign[k]][max_rad[assign[k]]] == 0) max_rad[assign[k]]--;\n                        \n                        assign[k] = u;\n                        int du = dist_res[u][k];\n                        cnt[u][du]++;\n                        max_rad[u] = max(max_rad[u], du);\n                    }\n                }\n            }\n        }\n\n        // Greedy Remove\n        // Try removing nodes in active set (except 0)\n        vector<int> active_indices;\n        for (int i = 1; i < N; ++i) if (active[i]) active_indices.push_back(i);\n        shuffle(active_indices.begin(), active_indices.end(), rng);\n        \n        for (int u : active_indices) {\n            if (!active[u]) continue;\n\n            // Simulate removing u\n            // Residents assigned to u must be re-assigned to other active nodes.\n            \n            // 1. Find tentative new owners for k in C_u\n            vector<int> new_owner(K, -1); // Only for residents in C_u\n            vector<int> new_dist(K, -1);\n            vector<int> u_residents;\n            \n            for (int k = 0; k < K; ++k) {\n                if (assign[k] == u) {\n                    u_residents.push_back(k);\n                    int best_d = 1e9;\n                    int best_v = -1;\n                    for (int v = 0; v < N; ++v) {\n                        if (active[v] && v != u) {\n                            if (dist_res[v][k] < best_d) {\n                                best_d = dist_res[v][k];\n                                best_v = v;\n                            }\n                        }\n                    }\n                    new_owner[k] = best_v;\n                    new_dist[k] = best_d;\n                }\n            }\n            \n            // 2. Calculate changes\n            // We need to update cnt[v] and max_rad[v] for v in V\\{u}\n            // And cnt[u], max_rad[u] becomes 0 (or inactive)\n            \n            vector<int> saved_max_rad = max_rad; // Copy\n            // Apply changes to max_rad\n            // Remove u's contribution\n            max_rad[u] = 0; \n            \n            for (int k : u_residents) {\n                int v = new_owner[k];\n                int d = new_dist[k];\n                max_rad[v] = max(max_rad[v], d);\n                // Note: we don't update cnt here because it's tedious to revert.\n                // We just compute tentative cost based on max_rad?\n                // No, max_rad depends on counts.\n                // For v (receiving), max_rad can only increase. \n                // If d <= max_rad[v], no change.\n                // If d > max_rad[v], new max is d.\n                // Since we are moving residents FROM u, max_rad[v] is based on existing residents of v.\n                // So we just compare d with current max_rad[v].\n            }\n            \n            // Wait, we must check if removing u reduces radii of other nodes? No, u is leaving, others take load.\n            // So max_rad of others can increase.\n            // The cost of u disappears (becomes 0).\n            \n            long long tentative_node_cost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (i == u) continue;\n                tentative_node_cost += (long long)max_rad[i] * max_rad[i];\n            }\n            \n            active[u] = false;\n            long long new_edge_cost = get_mst_cost(active);\n            active[u] = true;\n            \n            if (tentative_node_cost + new_edge_cost < total_cost) {\n                // Accept removal\n                active[u] = false;\n                current_edge_cost = new_edge_cost;\n                current_node_cost = tentative_node_cost;\n                total_cost = current_node_cost + current_edge_cost;\n                \n                // Update cnt, assign, max_rad\n                // Remove all from u\n                for (int r = 0; r < MAX_D; ++r) cnt[u][r] = 0;\n                \n                for (int k : u_residents) {\n                    int v = new_owner[k];\n                    int d = new_dist[k];\n                    assign[k] = v;\n                    cnt[v][d]++;\n                    // max_rad[v] is updated\n                    if (d > max_rad[v]) max_rad[v] = d;\n                }\n                max_rad[u] = 0;\n            } else {\n                // Revert max_rad\n                max_rad = saved_max_rad;\n            }\n        }\n\n        // Finalize P\n        for (int i = 0; i < N; ++i) {\n            if (active[i]) {\n                P[i] = max_rad[i];\n            } else {\n                P[i] = 0;\n            }\n        }\n        \n        // Construct MST edges\n        // We need to output B_j for edges in the MST of active nodes (Steiner tree approximation)\n        // We already have active nodes.\n        // Build MST on active nodes using dist_nodes.\n        // Then expand edges to paths.\n        \n        vector<vector<int>> mst_edges(N, vector<int>(N, 0)); // Adjacency matrix of the abstract MST tree\n        // Actually we just need the list of connections\n        \n        // Run Prim on active nodes\n        vector<bool> in_mst(N, false);\n        vector<int> parent(N, -1);\n        vector<long long> min_dist(N, 1e18);\n        min_dist[0] = 0;\n        \n        for (int i = 0; i < N; ++i) {\n            int u = -1;\n            for (int j = 0; j < N; ++j) {\n                if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                    u = j;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (parent[u] != -1) {\n                // Add edge (parent[u], u) to the list of MST connections\n                // We need to find the path between parent[u] and u in the original graph\n                // Since we only have all-pairs shortest paths, we need path reconstruction.\n                // We don't have path reconstruction in Floyd-Warshall yet.\n                // We can run Dijkstra from parent[u] to u, or just BFS/Dijkstra for each MST edge.\n                // Number of MST edges is |V_active| - 1 <= 99.\n                // Dijkstra is O(M log N) or O(M). 99 * 300 = 30000. Trivial.\n                \n                // Let's just implement a Dijkstra to find shortest path and mark edges.\n                // But wait, edge weights are not unique. Any shortest path is fine?\n                // \"w_j satisfies ...\". \n                // We need to minimize sum of w_j.\n                // So taking *any* shortest path for each MST edge is correct?\n                // Union of shortest paths might contain cycles, but that's fine (cost is sum of unique edges? Or sum of edges we turn ON?).\n                // \"Setting the power of edge j to ON incurs a cost w_j\". \n                // If we turn on the same edge twice, we pay once.\n                // So we need a set of edges.\n                // We can use a Dijkstra that finds ONE shortest path and marks those edges.\n                // Overlapping paths are fine.\n                \n                // Run Dijkstra from start to end\n                int s = parent[u];\n                int t = u;\n                \n                // To avoid re-running Dijkstra for pairs sharing structure, we could run one Dijkstra from each node?\n                // But N=100 is small.\n                // Simple Dijkstra:\n                vector<long long> d(N, 1e18);\n                vector<int> prev(N, -1);\n                d[s] = 0;\n                priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n                pq.push({0, s});\n                while(!pq.empty()){\n                    auto [dist, v] = pq.top(); pq.pop();\n                    if(dist > d[v]) continue;\n                    if(v == t) break;\n                    for(auto& edge : edges){\n                        int a, b; long long w;\n                        tie(a, b, w) = edge;\n                        a--; b--;\n                        if(v == a && d[a] + w < d[b]){\n                            d[b] = d[a] + w;\n                            prev[b] = a;\n                            pq.push({d[b], b});\n                        } else if (v == b && d[b] + w < d[a]){\n                            d[a] = d[b] + w;\n                            prev[a] = b;\n                            pq.push({d[a], a});\n                        }\n                    }\n                }\n                \n                // Backtrack from t to s using prev\n                int curr = t;\n                while (curr != s && curr != -1) {\n                    int p = prev[curr];\n                    if (p == -1) break;\n                    // Find edge index for (p, curr)\n                    for (int j = 0; j < M; ++j) {\n                        int uj, vj; long long wj;\n                        tie(uj, vj, wj) = edges[j];\n                        uj--; vj--;\n                        if ((uj == p && vj == curr) || (uj == curr && vj == p)) {\n                            B[j] = 1;\n                            break;\n                        }\n                    }\n                    curr = p;\n                }\n            }\n            \n            for (int v = 0; v < N; ++v) {\n                if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                    min_dist[v] = dist_nodes[u][v];\n                    parent[v] = u;\n                }\n            }\n        }\n        \n        // Output\n        for (int i = 0; i < N; ++i) {\n            if (i > 0) cout << \" \";\n            cout << P[i];\n        }\n        cout << \"\\n\";\n        for (int j = 0; j < M; ++j) {\n            if (j > 0) cout << \" \";\n            cout << B[j];\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    \n    Solver solver(N, M, K);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        solver.edges[i] = {u, v, w};\n    }\n    for (int i = 0; i < K; ++i) {\n        cin >> solver.residents[i].first >> solver.residents[i].second;\n    }\n    \n    solver.solve();\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <numeric>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 30;\nconst int INF = 1e9;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> all_vals;\n    map<int, pair<int, int>> pos; // value -> (x, y)\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            grid[x][y] = v;\n            pos[v] = {x, y};\n            all_vals.push_back(v);\n        }\n    }\n\n    // Determine target tiers\n    // Sort values to determine their rank\n    sort(all_vals.begin(), all_vals.end());\n    map<int, int> rank_of_val;\n    for (int i = 0; i < (int)all_vals.size(); ++i) {\n        rank_of_val[all_vals[i]] = i;\n    }\n\n    // Map rank to target tier\n    // Total balls M = N(N+1)/2.\n    // Tier x contains balls with ranks T(x) to T(x+1)-1\n    // where T(x) = x(x+1)/2.\n    auto get_tier = [&](int rank) -> int {\n        // Solve t(t+1)/2 <= rank\n        // t^2 + t - 2*rank <= 0\n        // t = (-1 + sqrt(1 + 8*rank)) / 2\n        int t = (int)((-1 + sqrt(1 + 8.0 * rank)) / 2);\n        while ((t + 1) * (t + 2) / 2 <= rank) t++;\n        while (t * (t + 1) / 2 > rank) t--;\n        return t;\n    };\n\n    vector<int> target_tier(465);\n    for (int i = 0; i < 465; ++i) {\n        target_tier[i] = get_tier(i);\n    }\n\n    // Output operations\n    vector<tuple<int, int, int, int>> operations;\n\n    // Helper: Distance on hexagonal grid\n    // Based on analysis, dist((x1,y1), (x2,y2)) = max(|x1-x2|, |y1-y2|)\n    auto dist = [](int x1, int y1, int x2, int y2) -> int {\n        return max(abs(x1 - x2), abs(y1 - y2));\n    };\n\n    // Helper: Neighbors\n    vector<pair<int, int>> directions = {\n        {0, -1}, {0, 1}, {-1, 0}, {-1, -1}, {1, 0}, {1, 1}\n    };\n\n    // Process tiers from bottom to top\n    for (int t = N - 1; t >= 0; --t) {\n        // Identify balls belonging to this tier\n        // Start rank = t(t+1)/2, count = t+1\n        int start_rank = t * (t + 1) / 2;\n        int count = t + 1;\n        \n        vector<int> balls_in_tier;\n        for (int i = 0; i < count; ++i) {\n            balls_in_tier.push_back(all_vals[start_rank + i]);\n        }\n\n        // Get current positions of these balls\n        // We need to assign them to (t, 0), (t, 1), ..., (t, t)\n        // Minimum Cost Flow Assignment\n        \n        int s_idx = 0; // Source index for graph (virtual)\n        // We use 0..(t) for balls, (t+1)..(2t+1) for targets\n        \n        mcf_graph<int, int> g((t + 1) * 2 + 2);\n        int SRC = (t + 1) * 2;\n        int SNK = (t + 1) * 2 + 1;\n\n        for (int i = 0; i < count; ++i) {\n            int val = balls_in_tier[i];\n            auto [cx, cy] = pos[val];\n            \n            g.add_edge(SRC, i, 1, 0); // Source to ball node\n            \n            for (int j = 0; j < count; ++j) {\n                int cost = dist(cx, cy, t, j);\n                g.add_edge(i, (t + 1) + j, 1, cost); // Ball node to target node\n            }\n        }\n        \n        for (int j = 0; j < count; ++j) {\n             g.add_edge((t + 1) + j, SNK, 1, 0); // Target node to Sink\n        }\n\n        auto flow_res = g.flow(SRC, SNK);\n        // vector<pair<int, int>> assignment; // ball_index -> target_y\n        // The edges in flow_res correspond to the graph edges.\n        // We need to reconstruct which ball goes to which target.\n        \n        map<int, pair<int, int>> final_targets; // val -> (tx, ty)\n        \n        // Iterate edges to find matches\n        auto edges = g.edges();\n        for (auto &e : edges) {\n            if (e.from >= SRC || e.to >= SNK || e.to == SRC || e.from == SNK) continue;\n            if (e.from < t + 1 && e.to >= t + 1 && e.to < (t + 1) * 2 && e.flow > 0) {\n                int ball_idx = e.from;\n                int target_y = e.to - (t + 1);\n                int val = balls_in_tier[ball_idx];\n                final_targets[val] = {t, target_y};\n            }\n        }\n\n        // Now move balls to their targets\n        // We maintain a set of 'blocked' nodes (already settled balls)\n        // Initially, all balls in tiers > t are blocked.\n        // As we place balls in tier t, they become blocked.\n        \n        // To check if a node (x,y) is blocked:\n        // The ball at (x,y) must have target_tier > t, OR (target_tier == t AND already placed).\n        \n        // We process the balls in this tier one by one.\n        // Note: The order might matter slightly for pathfinding length if we consider other unplaced balls in this tier as obstacles? \n        // But they are not obstacles; we can swap with them.\n        // Only 'settled' balls are obstacles.\n        \n        for (int val : balls_in_tier) {\n            auto [tx, ty] = final_targets[val];\n            auto [sx, sy] = pos[val];\n\n            if (sx == tx && sy == ty) {\n                // Already there, mark as settled (implicit)\n                continue;\n            }\n\n            // BFS to find path from (sx, sy) to (tx, ty)\n            // Cannot pass through settled nodes.\n            \n            queue<pair<int, int>> q;\n            map<pair<int, int>, pair<int, int>> parent;\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            \n            q.push({sx, sy});\n            visited[sx][sy] = true;\n            \n            bool found = false;\n            \n            while (!q.empty() && !found) {\n                auto [cx, cy] = q.front();\n                q.pop();\n                \n                for (auto [dx, dy] : directions) {\n                    int nx = cx + dx;\n                    int ny = cy + dy;\n                    \n                    // Bounds check\n                    if (nx < 0 || nx >= N || ny < 0 || ny > nx) continue;\n                    \n                    if (visited[nx][ny]) continue;\n                    \n                    // Check obstacle\n                    int ball_at_nx = grid[nx][ny];\n                    int b_tier = target_tier[rank_of_val[ball_at_nx]];\n                    \n                    bool is_obstacle = false;\n                    if (b_tier > t) is_obstacle = true;\n                    else if (b_tier == t) {\n                        // Check if this ball is already settled (placed in its target)\n                        // We know the target of this ball if it is in final_targets\n                        // But we are iterating balls_in_tier.\n                        // If ball_at_nx is in final_targets, check if it's already placed.\n                        if (final_targets.count(ball_at_nx)) {\n                             // This ball belongs to this tier.\n                             // Is it already in its target?\n                             auto [b_tx, b_ty] = final_targets[ball_at_nx];\n                             if (nx == b_tx && ny == b_ty) {\n                                 is_obstacle = true;\n                             }\n                        }\n                    }\n                    \n                    if (!is_obstacle) {\n                        visited[nx][ny] = true;\n                        parent[{nx, ny}] = {cx, cy};\n                        q.push({nx, ny});\n                        if (nx == tx && ny == ty) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // Reconstruct path and execute swaps\n            vector<pair<int, int>> path;\n            {\n                auto curr = make_pair(tx, ty);\n                while (curr != make_pair(sx, sy)) {\n                    path.push_back(curr);\n                    curr = parent[curr];\n                }\n                path.push_back({sx, sy});\n                reverse(path.begin(), path.end());\n            }\n\n            // Execute swaps\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                auto [u1, v1] = path[i];\n                auto [u2, v2] = path[i+1];\n                \n                // Swap in grid\n                int val1 = grid[u1][v1];\n                int val2 = grid[u2][v2];\n                \n                swap(grid[u1][v1], grid[u2][v2]);\n                \n                // Update pos map\n                pos[val1] = {u2, v2};\n                pos[val2] = {u1, v1};\n                \n                operations.push_back({u1, v1, u2, v2});\n            }\n        }\n    }\n\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <numeric>\n\nusing namespace std;\n\n// Grid configuration\nconst int D = 9;\nconst int INF = 1e9;\n// Entrance\nconst int ER = 0;\nconst int EC = 4;\n\nstruct State {\n    vector<vector<bool>> obstacle;\n    vector<vector<int>> dist;\n    vector<vector<bool>> occupied;\n    int total_containers;\n\n    State(int n, const vector<pair<int, int>>& obs_coords) {\n        obstacle.assign(D, vector<bool>(D, false));\n        occupied.assign(D, vector<bool>(D, false));\n        dist.assign(D, vector<int>(D, -1));\n        \n        // Mark entrance and adjacent as not obstacles (problem guarantee)\n        // But we also treat them as not storage space.\n        \n        // Mark obstacles\n        for (auto p : obs_coords) {\n            obstacle[p.first][p.second] = true;\n        }\n\n        // Calculate distances from entrance\n        queue<pair<int, int>> q;\n        q.push({ER, EC});\n        dist[ER][EC] = 0;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (dist[nr][nc] == -1 && !obstacle[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + 1;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Count available spots\n        total_containers = 0;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                // Entrance and obstacles are not for storage\n                if ((i == ER && j == EC) || obstacle[i][j]) continue;\n                // Problem statement says entrance and its 3 adjacent are not obstacles\n                // But they are valid storage spots? \n                // \"Each D x D - 1 - N square other than the entrance and obstacles can hold at most 1 container.\"\n                // So adjacent squares (0,3), (0,5), (1,4) ARE valid storage spots.\n                total_containers++;\n            }\n        }\n    }\n    \n    // Find empty cells reachable from entrance via empty cells\n    vector<pair<int, int>> get_reachable_empty() {\n        vector<pair<int, int>> reachable;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        \n        // Start from entrance\n        q.push({ER, EC});\n        visited[ER][EC] = true;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (!visited[nr][nc] && !obstacle[nr][nc] && !occupied[nr][nc]) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                        reachable.push_back({nr, nc});\n                    }\n                }\n            }\n        }\n        return reachable;\n    }\n\n    // Check if placing a container at (tr, tc) blocks other empty cells from entrance\n    // It blocks if, after marking (tr, tc) occupied, some previously reachable empty cell becomes unreachable.\n    bool is_safe_placement(int tr, int tc) {\n        // Temporarily mark as occupied\n        occupied[tr][tc] = true;\n        \n        vector<pair<int, int>> new_reachable = get_reachable_empty();\n        \n        // Restore\n        occupied[tr][tc] = false;\n\n        // Count previously reachable (excluding the cell itself)\n        auto prev_reachable = get_reachable_empty();\n        \n        // Actually, we can just compare counts of reachable nodes (excluding the one we are filling)\n        // Since we are adding an obstacle, the set of reachable empty cells can only shrink.\n        // We want it to NOT shrink (except for the cell itself).\n        // Note: get_reachable_empty returns EMPTY cells.\n        // (tr, tc) is empty before placement. It is in prev_reachable.\n        // After placement, it is not in new_reachable.\n        // So we expect |new_reachable| == |prev_reachable| - 1.\n        \n        if (new_reachable.size() == prev_reachable.size() - 1) return true;\n        return false;\n    }\n\n    // Choose best cell for container t\n    pair<int, int> choose_placement(int t) {\n        auto reachable = get_reachable_empty();\n        \n        if (reachable.empty()) {\n            // Should not happen\n            return {-1, -1};\n        }\n\n        // Target distance\n        // Map t from [0, M-1] to a distance range\n        // Max distance is around 15.\n        double ratio = (double)t / total_containers;\n        \n        // We want to sort candidates.\n        // Heuristic: \n        // 1. Is safe (doesn't block).\n        // 2. Distance is close to target.\n        // 3. (Optional) Prefer low degree or corners?\n        \n        vector<tuple<int, int, double>> candidates; // score, r, c\n        // Score > 0 means safe, < 0 unsafe.\n        \n        int max_dist = 0;\n        for(auto& p : reachable) max_dist = max(max_dist, dist[p.first][p.second]);\n        \n        for (auto& p : reachable) {\n            int r = p.first;\n            int c = p.second;\n            int d = dist[r][c];\n            \n            double ideal_d = ratio * max_dist;\n            double dist_error = abs(d - ideal_d);\n            \n            int safe_score = is_safe_placement(r, c) ? 1000 : 0;\n            \n            // Combine: safety is most important. Then distance match.\n            // We maximize score.\n            double final_score = safe_score - dist_error;\n            \n            // If unsafe, we might still want to place it if we have no other choice,\n            // but we pick the one with max_dist_error (least bad? or best distance?).\n            // Let's say if unsafe, score is just -dist_error.\n            // If safe, score is 1000 - dist_error.\n            \n            candidates.push_back({final_score, r, c});\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<tuple<double, int, int>>());\n        \n        // Pick the best one\n        return {get<1>(candidates[0]), get<2>(candidates[0])};\n    }\n\n    void place(int t, int r, int c) {\n        occupied[r][c] = true;\n        cout << r << \" \" << c << endl;\n        // cout << \"# Placed \" << t << \" at \" << r << \" \" << c << endl;\n    }\n\n    // Retrieve phase\n    void retrieve_all(const map<int, pair<int, int>>& id_to_coord) {\n        vector<pair<int, int>> retrieval_order;\n        \n        // Set of remaining IDs\n        set<int> remaining;\n        for (auto p : id_to_coord) remaining.insert(p.first);\n        \n        // While there are containers\n        while (!remaining.empty()) {\n            // Find reachable occupied cells\n            queue<pair<int, int>> q;\n            vector<vector<bool>> visited(D, vector<bool>(D, false));\n            q.push({ER, EC});\n            visited[ER][EC] = true;\n            \n            vector<int> reachable_ids;\n            \n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n\n            while (!q.empty()) {\n                auto curr = q.front(); 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                    if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                        if (!visited[nr][nc] && !obstacle[nr][nc]) {\n                            // Check if occupied\n                            bool is_occupied = false;\n                            int id_at = -1;\n                            // We need to check if this coordinate has a container that is still in 'remaining'\n                            // We can look up in id_to_coord map (inverse map needed?)\n                            // Actually we have id_to_coord. We need coord_to_id.\n                            // Or just iterate remaining? remaining size is up to 80. O(80*80) is fine.\n                            for (int rid : remaining) {\n                                if (id_to_coord.at(rid) == make_pair(nr, nc)) {\n                                    is_occupied = true;\n                                    id_at = rid;\n                                    break;\n                                }\n                            }\n\n                            if (is_occupied) {\n                                visited[nr][nc] = true; // Can reach this square (but stop here?)\n                                // Actually we pass through it? No.\n                                // Rule: \"passing through adjacent empty squares\".\n                                // Occupied squares are NOT empty.\n                                // So we CANNOT pass through occupied squares.\n                                // We can only reach the occupied square itself if we are adjacent to an empty square.\n                                // But we CANNOT go THROUGH an occupied square.\n                                // However, the square containing the container is the target.\n                                // The rule says: \"The square containing the container to be transported out must be reachable... by passing through adjacent empty squares.\"\n                                // This means the path ends at the square. The square itself is occupied.\n                                // So we just check connectivity via EMPTY squares.\n                                // If (nr, nc) is occupied, we don't push it to queue.\n                                // But we record it as a retrievable target.\n                                reachable_ids.push_back(id_at);\n                            } else {\n                                // Empty, traverse\n                                visited[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (reachable_ids.empty()) {\n                // Should not happen\n                break;\n            }\n            \n            // Pick smallest ID\n            sort(reachable_ids.begin(), reachable_ids.end());\n            int to_retrieve = reachable_ids[0];\n            \n            retrieval_order.push_back(id_to_coord.at(to_retrieve));\n            remaining.erase(to_retrieve);\n        }\n        \n        // Output\n        for (auto p : retrieval_order) {\n            cout << p.first << \" \" << p.second << endl;\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N;\n    cin >> N;\n    \n    vector<pair<int, int>> obstacles(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    State solver(N, obstacles);\n    \n    map<int, pair<int, int>> id_to_coord;\n    \n    for (int i = 0; i < solver.total_containers; ++i) {\n        int t;\n        cin >> t;\n        \n        auto p = solver.choose_placement(t);\n        solver.place(t, p.first, p.second);\n        id_to_coord[t] = p;\n    }\n    \n    solver.retrieve_all(id_to_coord);\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/convolution>\n#include <atcoder/math>\n#include <atcoder/maxflow>\n#include <atcoder/modint>\n#include <atcoder/scc>\n#include <atcoder/segtree>\n#include <atcoder/string>\n#include <boost/multiprecision/cpp_int.hpp>\n\nusing namespace std;\nusing namespace atcoder;\nnamespace bmp = boost::multiprecision;\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Global variables\nint n, m;\nint grid[N][N];\nvector<pair<int, int>> pos[M + 1];\nset<pair<int, int>> region[M + 1];\nvector<int> adj[M + 1];\nset<int> adj_set[M + 1];\nbool is_boundary[M + 1];\nint color_cnt[M + 1];\n\n// Directions\nint dx[4] = {0, 1, 0, -1};\nint dy[4] = {1, 0, -1, 0};\n\n// Heuristic variables\nset<pair<int, int>> kept[M + 1];\nbool removed[N][N];\n\n// Helper functions\nbool in_grid(int x, int y) {\n    return 0 <= x && x < n && 0 <= y && y < n;\n}\n\nvoid build_graph() {\n    // Initialize adj_set\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int c = grid[i][j];\n            region[c].insert({i, j});\n            color_cnt[c]++;\n            \n            // Check boundary for color 0 (outside)\n            if (i == 0 || i == N - 1 || j == 0 || j == N - 1) {\n                is_boundary[c] = true;\n            }\n        }\n    }\n\n    // Build adj\n    for (int c = 1; c <= m; ++c) {\n        for (auto [x, y] : region[c]) {\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny)) {\n                    int nc = grid[nx][ny];\n                    if (nc != c) {\n                        if (adj_set[c].find(nc) == adj_set[c].end()) {\n                            adj_set[c].insert(nc);\n                            adj[c].push_back(nc);\n                            adj_set[nc].insert(c);\n                            adj[nc].push_back(c);\n                        }\n                    }\n                } else {\n                    // Outside is color 0\n                    if (adj_set[c].find(0) == adj_set[c].end()) {\n                        adj_set[c].insert(0);\n                        adj[c].push_back(0);\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Check if removing v (x, y) of color c is valid\nbool can_remove(int c, int x, int y) {\n    // 1. Connectivity check for kept[c] - {v}\n    // We need to verify if removing v disconnects the kept cells of c.\n    // Since we remove one by one, we can just check if v is an articulation point in the subgraph induced by kept[c].\n    // However, kept[c] is a subset of grid cells.\n    // Simple BFS from one neighbor of v in kept[c] (excluding v) to see if it reaches all other kept cells of c.\n    \n    // If kept[c] has only 1 cell (v), we cannot remove it if c has neighbors or c is boundary.\n    // Actually, we can't remove it if c has any neighbors in adj (needs witnesses).\n    // Since c must be connected, kept[c] must be non-empty.\n    if (kept[c].size() == 1) return false;\n\n    vector<pair<int, int>> neighbors_in_c;\n    for (int k = 0; k < 4; ++k) {\n        int nx = x + dx[k];\n        int ny = y + dy[k];\n        if (in_grid(nx, ny) && kept[c].count({nx, ny})) {\n            neighbors_in_c.push_back({nx, ny});\n        }\n    }\n\n    if (neighbors_in_c.empty()) {\n        // v is isolated in kept[c]? No, v is connected to kept[c].\n        // If v has no neighbors in kept[c], then kept[c] = {v} (size 1 case) or v is disconnected from kept[c] (impossible).\n        // So if size > 1, must have neighbors.\n        return false; \n    }\n\n    // Perform BFS from neighbors_in_c[0]\n    // Target: visit all nodes in kept[c] except v\n    queue<pair<int, int>> q;\n    set<pair<int, int>> visited;\n    q.push(neighbors_in_c[0]);\n    visited.insert(neighbors_in_c[0]);\n    \n    int count = 0;\n    while (!q.empty()) {\n        auto [cx, cy] = q.front(); q.pop();\n        count++;\n        for (int k = 0; k < 4; ++k) {\n            int nx = cx + dx[k];\n            int ny = cy + dy[k];\n            if (in_grid(nx, ny) && (nx != x || ny != y) && kept[c].count({nx, ny}) && !visited.count({nx, ny})) {\n                visited.insert({nx, ny});\n                q.push({nx, ny});\n            }\n        }\n    }\n\n    // We should be able to visit kept[c].size() - 1 nodes\n    if (count != kept[c].size() - 1) {\n        return false; // v is an articulation point\n    }\n\n    // 2. Witness check\n    // For each neighbor d of c, we need some u in kept[c] (u != v) adjacent to kept[d].\n    // Since we only remove v, if v was the ONLY witness for some d, we cannot remove it.\n    \n    for (int d : adj[c]) {\n        if (d == 0) continue; // 0 is outside, handled by boundary property\n        \n        bool has_witness = false;\n        // Check if any cell u in kept[c] - {v} is adjacent to kept[d]\n        // We can iterate over boundary of kept[d] or just iterate kept[c] - {v}\n        // Optimization: Only check neighbors of v in kept[c]? No, because other cells of c might witness d.\n        // But if v was NOT a witness for d, removing it doesn't affect d.\n        // If v WAS a witness, we need to check if there's another witness.\n        \n        // Is v a witness for d?\n        bool v_is_witness = false;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && kept[d].count({nx, ny})) {\n                v_is_witness = true;\n                break;\n            }\n        }\n        \n        if (!v_is_witness) continue; // Safe to remove\n        \n        // v is a witness. Find another one.\n        has_witness = false;\n        for (auto [cx, cy] : kept[c]) {\n            if (cx == x && cy == y) continue;\n            for (int k = 0; k < 4; ++k) {\n                int nx = cx + dx[k];\n                int ny = cy + dy[k];\n                if (in_grid(nx, ny) && kept[d].count({nx, ny})) {\n                    has_witness = true;\n                    break;\n                }\n            }\n            if (has_witness) break;\n        }\n        \n        if (!has_witness) return false;\n    }\n\n    return true;\n}\n\nvoid solve() {\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    build_graph();\n\n    // Initialize kept sets\n    for (int c = 1; c <= m; ++c) {\n        kept[c] = region[c];\n    }\n    memset(removed, false, sizeof(removed));\n\n    // Greedy removal BFS queue\n    // Start with all boundary cells of the grid\n    queue<pair<int, int>> q;\n    \n    // Find all boundary cells (grid boundary)\n    for (int i = 0; i < n; ++i) {\n        if (!removed[i][0]) q.push({i, 0});\n        if (!removed[i][n-1]) q.push({i, n-1});\n    }\n    for (int j = 0; j < n; ++j) {\n        if (!removed[0][j]) q.push({0, j});\n        if (!removed[n-1][j]) q.push({n-1, j});\n    }\n\n    // Also, any cell adjacent to a removed cell is a candidate\n    // We will add them to q dynamically.\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        \n        if (removed[x][y]) continue;\n        \n        int c = grid[x][y];\n        \n        // If color is not boundary, we generally shouldn't remove it (as per analysis)\n        // Unless it's \"shielded\" from 0? But we start from boundary 0, so we only reach boundary colors.\n        // So we only process c in is_boundary.\n        if (!is_boundary[c]) continue;\n\n        if (can_remove(c, x, y)) {\n            // Remove v\n            removed[x][y] = true;\n            kept[c].erase({x, y});\n            \n            // Add neighbors to queue\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny) && !removed[nx][ny]) {\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Construct output\n    // Fill with 0 first\n    int out_grid[N][N];\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            out_grid[i][j] = 0;\n        }\n    }\n\n    // Fill kept cells\n    for (int c = 1; c <= m; ++c) {\n        for (auto [x, y] : kept[c]) {\n            out_grid[x][y] = c;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << out_grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <iomanip>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\n\n// Structure to represent a node in the tournament tree\n// We only need to store the winner index at each node for the standard logic,\n// but to recover the \"depth\" or status of losers for weight estimation, we might need more.\n// However, standard tournament sort only maintains the path of winners.\n// To estimate weights of losers, we can just look at the remaining tree.\n// Items that are closer to the root in the remaining tree are \"winners\" of sub-tournaments, hence heavier.\n// Items that are leaves are losers of the first round, hence lighter.\n// So we can assign weights by traversing the remaining tree in level order.\n\nstruct Node {\n    int winner = -1;\n    int left = -1;\n    int right = -1;\n    int depth = 0; // Distance from root (0 is root)\n};\n\nvector<Node> tree;\nvector<int> extracted_indices; // Stores the indices of items in sorted order (heaviest first)\nvector<int> item_to_weight_est; // Estimated weight for each item\n\nint ask(int l, int r) {\n    cout << 1 << \" \" << 1 << \" \" << l << \" \" << r << endl;\n    cout.flush();\n    query_count++;\n    string res;\n    cin >> res;\n    if (res == \"<\") return -1;\n    if (res == \">\") return 1;\n    return 0;\n}\n\n// Build tournament tree.\n// Returns the index of the root node in the 'tree' vector.\nint build_tournament(const vector<int>& items, int depth) {\n    int node_idx = tree.size();\n    tree.emplace_back();\n    tree[node_idx].depth = depth;\n\n    if (items.size() == 1) {\n        tree[node_idx].winner = items[0];\n        return node_idx;\n    }\n\n    int mid = items.size() / 2;\n    vector<int> left_items(items.begin(), items.begin() + mid);\n    vector<int> right_items(items.begin() + mid, items.end());\n\n    int left_idx = build_tournament(left_items, depth + 1);\n    int right_idx = build_tournament(right_items, depth + 1);\n\n    tree[node_idx].left = left_idx;\n    tree[node_idx].right = right_idx;\n\n    int w_left = tree[left_idx].winner;\n    int w_right = tree[right_idx].winner;\n\n    // If one side is empty (shouldn't happen with split logic but good for safety)\n    if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n    return node_idx;\n}\n\n// Re-evaluate the node based on its children.\n// Used after a winner is extracted and removed.\nvoid update_node(int node_idx) {\n    if (tree[node_idx].left == -1 && tree[node_idx].right == -1) {\n        // Leaf\n        tree[node_idx].winner = -1;\n        return;\n    }\n\n    int w_left = -1;\n    int w_right = -1;\n    \n    if (tree[node_idx].left != -1) w_left = tree[tree[node_idx].left].winner;\n    if (tree[node_idx].right != -1) w_right = tree[tree[node_idx].right].winner;\n\n    if (w_left == -1 && w_right == -1) {\n        tree[node_idx].winner = -1;\n    } else if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n}\n\n// Extract the winner from the tree and update the structure.\n// Returns the index of the extracted item.\nint extract_max(int root_idx) {\n    int winner_idx = tree[root_idx].winner;\n    \n    // Trace down to the leaf\n    int curr = root_idx;\n    while (curr != -1) {\n        int left_child = tree[curr].left;\n        int right_child = tree[curr].right;\n        \n        // If leaf, winner is removed\n        if (left_child == -1 && right_child == -1) {\n            tree[curr].winner = -1;\n            break;\n        }\n\n        int w_left = (left_child != -1) ? tree[left_child].winner : -1;\n        int w_right = (right_child != -1) ? tree[right_child].winner : -1;\n\n        // Determine which child contains the current winner\n        if (w_left == winner_idx) {\n            curr = left_child;\n        } else {\n            curr = right_child;\n        }\n    }\n\n    // Propagate changes back up to root\n    // We need to reconstruct the path. We didn't store parents.\n    // Alternative: simply traverse down again? No, we need to update ancestors.\n    // Let's just rebuild winners along the path from root to where winner was found?\n    // Better approach for small N (100): Just re-update everything bottom-up? No.\n    // We can do a recursive update.\n    // Or simply: when we removed the leaf, we can walk back up? We don't have parent pointers.\n    \n    // Let's modify extraction: we know the winner. We search for it in the tree? No, structure is fixed.\n    // We can implement a recursive function `remove(node, target_winner)`\n    \n    return winner_idx;\n}\n\n// Helper to recursively remove and update\nbool remove_winner(int node_idx, int target_winner) {\n    if (node_idx == -1) return false;\n    \n    int left = tree[node_idx].left;\n    int right = tree[node_idx].right;\n    \n    // If this is the leaf node holding the winner\n    if (left == -1 && right == -1) {\n        if (tree[node_idx].winner == target_winner) {\n            tree[node_idx].winner = -1; // Mark as empty\n            return true;\n        }\n        return false;\n    }\n\n    // Recurse\n    int next_child = -1;\n    int w_left = (left != -1) ? tree[left].winner : -1;\n    \n    if (w_left == target_winner) {\n        if (remove_winner(left, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    } else {\n        if (remove_winner(right, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    }\n    return false;\n}\n\n// Assign weights to items remaining in the tree\nvoid estimate_weights_from_tree(int node_idx, int base_weight) {\n    if (node_idx == -1) return;\n    \n    int winner = tree[node_idx].winner;\n    if (winner != -1) {\n        // If this item hasn't been assigned a weight yet (not in extracted list)\n        // Since we process extracted items first, we only assign to unassigned ones.\n        if (item_to_weight_est[winner] == -1) {\n            // Heuristic: The winner of a subtree is heavier than items in sub-subtrees.\n            // We traverse down, so we give larger weight to higher nodes?\n            // Actually, DFS pre-order visits root, then children.\n            // Root is max. Children are smaller.\n            // So assign current base_weight to winner, then smaller to children.\n            item_to_weight_est[winner] = base_weight;\n        }\n    }\n\n    // Recurse to children with smaller weight\n    // We want to maintain order. We don't know order of left/right children without querying.\n    // But we can just average the weight or decrement by a small amount.\n    // Since N is small, we can just spread the remaining weights.\n    \n    estimate_weights_from_tree(tree[node_idx].left, base_weight - 2); // Arbitrary decrement\n    estimate_weights_from_tree(tree[node_idx].right, base_weight - 2);\n}\n\nvoid solve() {\n    cin >> N >> D >> Q;\n    \n    // Initialize indices\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    // Shuffle indices? \n    // For tournament sort, initial order affects which items meet in early rounds.\n    // It doesn't change the set of Top K found.\n    // Random shuffle might help if we were approximating, but exact Top K is exact.\n    // Shuffle might be useful to randomize which \"branch\" heavy items fall into, \n    // but strictly speaking not necessary for correctness of top K.\n    // However, for the \"remaining\" items, if we assume distribution, random order is fine.\n    // Let's shuffle to ensure no bias in early rounds for equal weights (though unlikely).\n    mt19937 rng(0); // Fixed seed for reproducibility or random?\n    // Problem says \"seed\" for input generation, but we can use random for our logic.\n    // Actually, usually deterministic is better for debugging, but random helps break patterns.\n    // Let's use default random_device or fixed seed.\n    shuffle(indices.begin(), indices.end(), rng);\n\n    tree.clear();\n    int root = build_tournament(indices, 0);\n\n    item_to_weight_est.assign(N, -1);\n    extracted_indices.clear();\n\n    // We used N-1 queries to build. Remaining Q - (N-1).\n    // We want to extract top K.\n    // Each extraction takes approx log2(N) queries.\n    // But update_node might ask queries again.\n    // In worst case, update_node asks 1 query per level.\n    // So extraction costs O(log N).\n    \n    // Reserve 5 queries for safety/flushing\n    int limit = Q - 5;\n    \n    while (query_count < limit) {\n        int winner = tree[root].winner;\n        if (winner == -1) break; // No items left\n        \n        extracted_indices.push_back(winner);\n        \n        // Remove this winner from the tree\n        remove_winner(root, winner);\n        \n        // Check if we exceeded limit during removal (query inside update_node)\n        if (query_count > limit) {\n            // Revert? No, just stop. \n            // The last extraction might be incomplete if update stopped early?\n            // remove_winner calls update_node recursively. \n            // If a query pushes us over, the update is done but we should stop.\n            break;\n        }\n    }\n\n    int K = extracted_indices.size();\n    \n    // Assign weights to extracted items\n    // Heaviest gets N, then N-1, etc.\n    for (int i = 0; i < K; ++i) {\n        item_to_weight_est[extracted_indices[i]] = N - i;\n    }\n    \n    // Assign weights to remaining items\n    // Use a DFS/BFS traversal. \n    // We want to assign weights smaller than N-K.\n    // The root of the current tree holds the max of remaining.\n    // We can give it N-K-1.\n    // We need to traverse.\n    // Since we don't know the exact order of remaining, we just give them weights\n    // based on depth or random values in the range [1, N-K].\n    \n    // Let's assign based on BFS order.\n    // Root gets next largest weight. Children get smaller.\n    if (tree[root].winner != -1) {\n       queue<int> q;\n       q.push(root);\n       int next_w = N - K;\n       \n       while(!q.empty()) {\n           int node = q.front();\n           q.pop();\n           \n           int winner = tree[node].winner;\n           if (winner != -1 && item_to_weight_est[winner] == -1) {\n               item_to_weight_est[winner] = next_w;\n               next_w = max(1, next_w - 1); // Decrement weight\n           }\n           \n           if (tree[node].left != -1) q.push(tree[node].left);\n           if (tree[node].right != -1) q.push(tree[node].right);\n       }\n    }\n\n    // Fill any unassigned items (shouldn't happen if tree covers all)\n    for (int i = 0; i < N; ++i) {\n        if (item_to_weight_est[i] == -1) {\n            item_to_weight_est[i] = 1;\n        }\n    }\n\n    // Now partition using LPT (Longest Processing Time) heuristic\n    // Create pairs of (estimated weight, original index)\n    vector<pair<int, int>> items_with_est;\n    for (int i = 0; i < N; ++i) {\n        items_with_est.push_back({item_to_weight_est[i], i});\n    }\n    \n    // Sort by estimated weight descending\n    sort(items_with_est.begin(), items_with_est.end(), greater<pair<int, int>>());\n\n    // Maintain D bins with their current sums\n    // Since we need to assign indices to bins, we can just store the sum\n    // and a reference to the bin assignments.\n    \n    // For small N and D, simple linear scan for min bin is fine.\n    // Optimization: priority_queue.\n    \n    // We need to output d_i for each item 0..N-1\n    vector<int> assignment(N);\n    vector<long long> bin_sums(D, 0); // Use long long to avoid overflow (though weights are small)\n    \n    // Min-heap to find the bin with smallest sum\n    // pair<sum, bin_index>\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n    for (int i = 0; i < D; ++i) {\n        pq.push({0, i});\n    }\n    \n    for (auto& p : items_with_est) {\n        int w = p.first;\n        int idx = p.second;\n        \n        auto top = pq.top();\n        pq.pop();\n        \n        int bin_idx = top.second;\n        bin_sums[bin_idx] += w;\n        assignment[idx] = bin_idx;\n        \n        pq.push({bin_sums[bin_idx], bin_idx});\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for state and parameters\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // 0-indexed stack and height\nvector<pair<int, int>> operations;\n\n// Structure to hold heuristic evaluation results\nstruct DestInfo {\n    int id;\n    long long score;\n    int min_val; // Smallest element in the stack (used for tie-breaking)\n};\n\n// Helper to get the top element of a stack, return large number if empty\nint get_top(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return stacks[stack_id].back();\n}\n\n// Helper to get the minimum element in a stack\nint get_min(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return *min_element(stacks[stack_id].begin(), stacks[stack_id].end());\n}\n\n// Evaluate the cost of moving a segment 'seg' to stack 'dest'\n// Score represents the \"badness\", lower is better.\n// Badness is defined as the number of inversions created.\n// An inversion is a pair (t, s) where t is in destination, s is in segment, and t > s.\n// We also want to prefer keeping segments intact if they are sorted,\n// but the split logic handles that before calling this.\nlong long evaluate_move(int dest, const vector<int>& seg) {\n    if (stacks[dest].empty()) return 0; // No inversions possible with empty stack\n\n    long long inv_count = 0;\n    \n    // Optimization: Since we sum counts of t > s for all s in seg\n    // We can iterate through t in destination and count how many s it is greater than.\n    // Complexity: O(Size(D) * Size(S)). Max 20 * 200 = 4000. Negligible.\n    \n    const vector<int>& dest_stack = stacks[dest];\n    \n    // Pre-calculate prefix sums? Not necessary for N=200.\n    // Just brute force double loop.\n    for (int t : dest_stack) {\n        for (int s : seg) {\n            if (t > s) {\n                inv_count++;\n            }\n        }\n    }\n    return inv_count;\n}\n\n// Execute operation type 1: Move box 'v' (and above it) to stack 'dest'\nvoid move_box(int v, int dest) {\n    // Find current stack\n    int s = pos[v].first;\n    int h = pos[v].second;\n    \n    if (s == dest) return; // Should not happen based on logic\n\n    // Identify segment to move\n    vector<int> boxes_to_move;\n    // stacks[s] has boxes from bottom (0) to top (size-1)\n    // v is at index h. We move h to size-1.\n    for (int i = h; i < stacks[s].size(); ++i) {\n        boxes_to_move.push_back(stacks[s][i]);\n    }\n    \n    // Update Source Stack\n    stacks[s].resize(h);\n    \n    // Update Destination Stack\n    for (int box : boxes_to_move) {\n        stacks[dest].push_back(box);\n    }\n    \n    // Update Positions\n    int new_h = stacks[dest].size() - boxes_to_move.size();\n    for (int i = 0; i < boxes_to_move.size(); ++i) {\n        int box = boxes_to_move[i];\n        pos[box] = {dest, new_h + i};\n    }\n    \n    operations.push_back({v, dest});\n}\n\n// Execute operation type 2: Carry out box 'v'\nvoid carry_out(int v) {\n    int s = pos[v].first;\n    // Check if v is at top (should be guaranteed by caller)\n    if (stacks[s].back() != v) {\n        // Error or should not happen\n        return;\n    }\n    \n    stacks[s].pop_back();\n    // pos[v] is no longer valid, but we won't query v again\n    operations.push_back({v, 0});\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M;\n    stacks.resize(M);\n    pos.resize(N + 1);\n    \n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Process boxes 1 to N\n    for (int v = 1; v <= N; ++v) {\n        // While v is not at top of its stack\n        while (true) {\n            int s = pos[v].first;\n            int h = pos[v].second;\n            \n            // If stack has been emptied or v is at top (h == size-1)\n            if (stacks[s].size() == h + 1) {\n                break;\n            }\n            \n            // Identify the top box of the stack containing v\n            int top_box = stacks[s].back();\n            \n            // We want to move segments that are \"inverted\" or simply move the blocking segment.\n            // Strategy:\n            // Look at the box immediately above v. Let's call it 'blocker'.\n            // Or look at the top of the stack.\n            // If the top of the stack is larger than the box below it, it creates an inversion.\n            // Moving just the top box resolves that inversion for the pair (top, below).\n            // Recursively doing this sorts the stack.\n            // Once the stack above v is sorted (small on top), we move the whole block.\n            \n            bool moved = false;\n            \n            // Check for shallow inversion at the top of the current stack\n            if (stacks[s].size() >= 2) {\n                int top = stacks[s].back();\n                int below = stacks[s][stacks[s].size() - 2];\n                \n                // If top > below, moving top alone is usually beneficial to fix the inversion.\n                // However, if 'below' is v, and top is v+1, moving top is bad.\n                // But if top > below, they are not consecutive (unless v, v+1 is inverted which is impossible in sorted 1..N).\n                // So top > below implies they are not in order.\n                if (top > below) {\n                    // Find best destination for 'top_box'\n                    // We want to minimize inversions created by adding 'top_box' to dest.\n                    \n                    vector<DestInfo> candidates;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == s) continue;\n                        \n                        // Segment is just {top_box}\n                        long long inv = evaluate_move(i, {top_box});\n                        candidates.push_back({i, inv, get_min(i)});\n                    }\n                    \n                    // Sort by score (inversions), then by min_val (larger is better buffer)\n                    sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                        if (a.score != b.score) return a.score < b.score;\n                        return a.min_val > b.min_val;\n                    });\n                    \n                    int best_dest = candidates[0].id;\n                    move_box(top_box, best_dest);\n                    moved = true;\n                }\n            }\n            \n            if (!moved) {\n                // No shallow inversion at the top, or we decided not to split.\n                // Move the entire segment above v.\n                // Segment starts at index h+1.\n                vector<int> seg;\n                for (int i = h + 1; i < stacks[s].size(); ++i) {\n                    seg.push_back(stacks[s][i]);\n                }\n                \n                // Find best destination for the whole segment\n                vector<DestInfo> candidates;\n                for (int i = 0; i < M; ++i) {\n                    if (i == s) continue;\n                    \n                    long long inv = evaluate_move(i, seg);\n                    candidates.push_back({i, inv, get_min(i)});\n                }\n                \n                sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.min_val > b.min_val;\n                });\n                \n                int best_dest = candidates[0].id;\n                \n                // The segment starts at seg[0], which is the box just above v.\n                move_box(seg[0], best_dest);\n            }\n        }\n        \n        // v is now at top. Carry out.\n        carry_out(v);\n    }\n\n    // Output\n    cout << operations.size() << endl;\n    for (auto op : operations) {\n        cout << op.first << \" \" << op.second << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <array>\n#include <numeric>\n\nusing namespace std;\n\nconst int MAX_N = 40;\nconst int MAX_NODES = MAX_N * MAX_N;\nconst int MAX_MOVES = 100000;\nconst double INF = 1e18;\n\nint N;\nint d[MAX_NODES];\nvector<int> adj[MAX_NODES];\nint cnt[MAX_NODES][MAX_NODES]; // Traversal counts for edges\nlong long k[MAX_NODES]; // Visit counts\nlong long total_len = 0;\n\nint dir_map[4] = {1, 0, -1, 0};\nint dj_map[4] = {0, 1, 0, -1};\nchar char_map[4] = {'D', 'R', 'U', 'L'};\n\nint to_idx(int i, int j) {\n    return i * N + j;\n}\n\nvoid from_idx(int idx, int& i, int& j) {\n    i = idx / N;\n    j = idx % N;\n}\n\nvoid dfs_init(int u, int p, vector<string>& h, vector<string>& v) {\n    // For constructing the initial spanning tree path\n    // We will just build the adjacency list and run a DFS to find a path that visits all nodes\n    // Then we set cnt[u][v] = 2 for tree edges.\n    // Wait, the problem says \"cleaning route\".\n    // A simple DFS that returns to start visits each edge twice.\n    // Let's store the DFS traversal to build the initial cnt.\n}\n\nstruct State {\n    int u;\n    int v;\n    double score;\n    State(int _u, int _v, double _score) : u(_u), v(_v), score(_score) {}\n    bool operator>(const State& other) const {\n        return score > other.score; // Min-heap based on score? No, we want max score.\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    vector<string> h(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[to_idx(i, j)];\n            k[to_idx(i, j)] = 0;\n        }\n    }\n\n    // Build adjacency list\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = to_idx(i, j);\n            if (i < N-1 && h[i][j] == '0') {\n                int v_idx = to_idx(i+1, j);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n            if (j < N-1 && v[i][j] == '0') {\n                int v_idx = to_idx(i, j+1);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n        }\n    }\n\n    // Initial DFS to ensure connectivity and set baseline k\n    // We don't need the string, just the edge counts and k\n    // Run DFS from 0\n    vector<bool> visited(N*N, false);\n    vector<pair<int, int>> stack; // parent, current\n    stack.push_back({-1, 0});\n    \n    // We perform a DFS and record the path as edges\n    // Actually, we just need to traverse edges.\n    // Standard DFS iterative\n    stack.push_back({-1, 0});\n    visited[0] = true;\n    \n    // We need to actually construct a cycle.\n    // Simple recursive DFS is easier to implement for logic.\n    // Since N is small, recursion depth is fine.\n    // We just need to modify 'cnt' and 'k'.\n    \n    // Use a lambda for DFS\n    // To compute 'k', we need to know how many times we \"arrive\" at a node.\n    // Start at 0. Go to neighbor...\n    // DFS traversal visits each node deg times (except root).\n    // Let's implement a DFS that returns to parent.\n    \n    vector<int> parent(N*N, -1);\n    // Re-usable stack for DFS\n    vector<int> dfs_stack;\n    dfs_stack.push_back(0);\n    vector<int> order;\n    \n    // To count k properly:\n    // A DFS tour: start at root.\n    // For each neighbor not visited: \n    //   go to neighbor (move 1), visit neighbor subtree\n    //   return to parent (move 1)\n    // This visits each edge twice.\n    // k[u] is the number of times we arrive at u.\n    // In a tree, arrival at root happens at the end (1 time).\n    // Arrival at internal node happens when returning from children + coming from parent.\n    // Effectively, for a tree, k[u] is the degree in the tree, except root is 1.\n    // But we don't have a tree, we have a grid.\n    // Let's just perform a standard DFS on the grid graph.\n    \n    fill(visited.begin(), visited.end(), false);\n    \n    // Recursive DFS function\n    // We need to pass `adj` and `cnt`, `k`, `visited`\n    // We can capture by reference\n    std::function<void(int, int)> dfs = [&](int u, int p) {\n        visited[u] = true;\n        for (int v : adj[u]) {\n            if (!visited[v]) {\n                // Go u -> v\n                cnt[u][v]++;\n                k[v]++; // Arrive at v\n                dfs(v, u);\n                // Return v -> u\n                cnt[v][u]++;\n                k[u]++; // Arrive at u (return)\n            }\n        }\n    };\n    \n    // The root is 0. k[0] starts at 0.\n    // We arrive at 0 at the end?\n    // In DFS above, we don't explicitly return to root at the very top level.\n    // So k[0] will be equal to the number of children (returns from children).\n    // The problem requires a cycle starting and ending at (0,0).\n    // The DFS path starts at 0 and ends at 0.\n    // So we arrive at 0 at the end.\n    // My DFS logic: `dfs(0, -1)`\n    // Inside, for each child `c`:\n    //   0->c (cnt++, k[c]++)\n    //   dfs(c)\n    //   c->0 (cnt++, k[0]++)\n    // So k[0] is incremented for each child.\n    // This matches the number of times we visit 0 (except start? No, start is 0).\n    // The definition of k is number of visits.\n    // In sequence p0, p1, ..., pL. p0=0, pL=0.\n    // k[0] is number of times 0 appears in p1..pL.\n    // In DFS, we visit 0 at the end. That's 1 visit?\n    // Wait. If we have children, we return from each child to 0.\n    // So we visit 0 multiple times.\n    // Is this a cycle?\n    // Sequence: 0 -> c1 -> ... -> c1 -> 0 -> c2 -> ... -> c2 -> 0.\n    // This is a valid cycle.\n    // k[0] is equal to number of children in DFS tree.\n    // Correct.\n    \n    dfs(0, -1);\n    \n    // Calculate total length\n    total_len = 0;\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            total_len += cnt[u][v];\n        }\n    }\n    // Divide by 2 because we counted u->v and v->u\n    total_len /= 2;\n    \n    // Greedy additions\n    // Priority queue: (score, u, v)\n    // score = d_u/k_u^2 + d_v/k_v^2\n    // Note: k can be 0 initially?\n    // DFS ensures all visited, so k >= 1 for all nodes except maybe root if isolated? \n    // Graph is connected. Root visited.\n    // k[u] > 0 for all u reachable from 0. Since all reachable, k[u] > 0.\n    \n    priority_queue<pair<double, pair<int, int>>> pq;\n    \n    // Initialize PQ\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            if (u < v) { // Add each edge once\n                double val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n                pq.push({val, {u, v}});\n            }\n        }\n    }\n    \n    // Loop\n    while (total_len < MAX_MOVES) {\n        if (pq.empty()) break;\n        \n        auto item = pq.top();\n        pq.pop();\n        double score = item.first;\n        int u = item.second.first;\n        int v = item.second.second;\n        \n        // Re-evaluate score lazily or just assume it's ok?\n        // Since scores decrease as k increases, the top is likely the best.\n        // But we should check.\n        double current_val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n        if (current_val < score - 1e-9) {\n            pq.push({current_val, {u, v}});\n            continue;\n        }\n        \n        // Add detour\n        if (total_len + 2 > MAX_MOVES) break;\n        \n        cnt[u][v]++;\n        cnt[v][u]++;\n        k[u]++;\n        k[v]++;\n        total_len += 2;\n        \n        // Push updates for neighbors of u and v\n        for (int w : adj[u]) {\n            int a = min(u, w);\n            int b = max(u, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n        for (int w : adj[v]) {\n            int a = min(v, w);\n            int b = max(v, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n    }\n    \n    // Hierholzer's Algorithm\n    // We need to construct the path string.\n    // Start at 0.\n    \n    // We need a mutable copy of adj with edge counts to remove edges.\n    // Or just use cnt array and decrement.\n    // Since max moves is 100k, recursion is safe? 100k depth might be too much for stack.\n    // Use iterative stack or manual stack.\n    \n    vector<char> path;\n    vector<int> stack_path;\n    stack_path.push_back(0);\n    \n    // To optimize neighbor iteration in Hierholzer, we can store current edge index?\n    // Or just loop.\n    \n    while (!stack_path.empty()) {\n        int u = stack_path.back();\n        bool found = false;\n        for (int v : adj[u]) {\n            if (cnt[u][v] > 0) {\n                // Take this edge\n                cnt[u][v]--;\n                \n                // Find direction char\n                int i1, j1, i2, j2;\n                from_idx(u, i1, j1);\n                from_idx(v, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                \n                stack_path.push_back(v);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) {\n            stack_path.pop_back();\n            if (!stack_path.empty()) {\n                int prev = stack_path.back();\n                // Find direction from prev to u\n                int i1, j1, i2, j2;\n                from_idx(prev, i1, j1);\n                from_idx(u, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                path.push_back(c);\n            }\n        }\n    }\n    \n    // Path is constructed backwards\n    reverse(path.begin(), path.end());\n    \n    // Output\n    for (char c : path) {\n        cout << c;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/random>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\nusing namespace atcoder;\n\n// ---------------------------------------------------\n// Constants and Globals\n// ---------------------------------------------------\n\nconstexpr int N = 15;\nconstexpr int N2 = N * N;\nconstexpr int M = 200;\nconstexpr int INF = 1e9;\n\nint grid[N][N];\nvector<int> char_pos[26]; // Stores positions (indices 0..N2-1) for each character\nint start_pos;\nvector<string> targets(M);\n\n// Precomputed distances\nint dist[N2][N2];\n\n// Timer for time limit management\nstd::chrono::system_clock::time_point start_time;\n\n// ---------------------------------------------------\n// Utilities\n// ---------------------------------------------------\n\nint get_elapsed_ms() {\n    auto now = std::chrono::system_clock::now();\n    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n}\n\n// ---------------------------------------------------\n// Precomputation\n// ---------------------------------------------------\n\nvoid precompute() {\n    // Calculate Manhattan distances between all pairs of cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            for (int k = 0; k < N; ++k) {\n                for (int l = 0; l < N; ++l) {\n                    int v = k * N + l;\n                    dist[u][v] = abs(i - k) + abs(j - l);\n                }\n            }\n        }\n    }\n}\n\n// ---------------------------------------------------\n// Overlap Calculation\n// ---------------------------------------------------\n\n// Calculate max overlap between A's suffix and B's prefix\nint calc_overlap(const string& A, const string& B) {\n    int max_ov = 0;\n    int len_A = A.size();\n    int len_B = B.size();\n    // Max possible overlap is 4\n    for (int k = 1; k <= min(len_A, 4); ++k) {\n        if (A.compare(len_A - k, k, B, 0, k) == 0) {\n            max_ov = k;\n        }\n    }\n    return max_ov;\n}\n\n// Precompute overlap matrix to save time during SA\nint overlap_mat[M][M];\n\nvoid build_overlap_matrix() {\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                overlap_mat[i][j] = 0; // Or maybe min(4, len) if self-overlap makes sense? Targets are distinct.\n                continue;\n            }\n            overlap_mat[i][j] = calc_overlap(targets[i], targets[j]);\n        }\n    }\n}\n\n// ---------------------------------------------------\n// String Construction from Permutation\n// ---------------------------------------------------\n\nstring build_string(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s = targets[order[0]];\n    for (size_t i = 1; i < order.size(); ++i) {\n        int u = order[i-1];\n        int v = order[i];\n        int ov = overlap_mat[u][v];\n        s += targets[v].substr(ov);\n    }\n    return s;\n}\n\n// ---------------------------------------------------\n// DP to calculate cost\n// ---------------------------------------------------\n\n// Returns the minimum cost and stores the path (if store_path is true)\npair<int, vector<pair<int, int>>> solve_grid(const string& s, bool store_path = false) {\n    if (s.empty()) return {0, {}};\n\n    // dp[u] = min cost to reach cell u having processed up to current char\n    vector<int> dp(N2, INF);\n    dp[start_pos] = 0;\n    \n    // To reconstruct path\n    // We only need to store the previous cell for the optimal path for each cell at each step\n    // Memory: L * N2 integers. L <= 1000, N2 = 225. ~225k integers. ~1MB. OK.\n    vector<vector<int>> prev_step; \n    if (store_path) {\n        prev_step.assign(s.size(), vector<int>(N2, -1));\n    }\n\n    for (size_t i = 0; i < s.size(); ++i) {\n        char c = s[i];\n        vector<int> next_dp(N2, INF);\n        \n        // For each cell v that has character c\n        for (int v : char_pos[c - 'A']) {\n            int best_cost = INF;\n            int best_prev = -1;\n            \n            // Find min_u (dp[u] + dist(u, v))\n            for (int u = 0; u < N2; ++u) {\n                if (dp[u] == INF) continue;\n                int cost = dp[u] + dist[u][v] + 1; // +1 for typing action\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_prev = u;\n                }\n            }\n            \n            next_dp[v] = best_cost;\n            if (store_path) {\n                prev_step[i][v] = best_prev;\n            }\n        }\n        dp = next_dp;\n    }\n\n    int min_cost = *min_element(dp.begin(), dp.end());\n    vector<pair<int, int>> path;\n\n    if (store_path) {\n        // Find the end position\n        int end_pos = -1;\n        for (int i = 0; i < N2; ++i) {\n            if (dp[i] == min_cost) {\n                end_pos = i;\n                break;\n            }\n        }\n        \n        if (end_pos != -1) {\n            path.resize(s.size());\n            int curr = end_pos;\n            for (int i = s.size() - 1; i >= 0; --i) {\n                path[i] = {curr / N, curr % N};\n                curr = prev_step[i][curr];\n            }\n        }\n    }\n\n    return {min_cost, path};\n}\n\n// ---------------------------------------------------\n// Heuristics\n// ---------------------------------------------------\n\nvector<int> initial_order_greedy() {\n    vector<int> order;\n    vector<bool> used(M, false);\n    \n    // Start with a random target to avoid bias\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis(0, M-1);\n    int first = dis(gen);\n    \n    order.push_back(first);\n    used[first] = true;\n    \n    for (int count = 1; count < M; ++count) {\n        int last = order.back();\n        string current_str = build_string(order); // Rebuild string to get suffix? No, just use the last target.\n        // Actually, we only need the suffix of the constructed string to check overlap.\n        // build_string is O(M^2 * 5) if called inside loop. M=200, M^2=40000. Fast.\n        // But we can just look at the last target for overlap calculation.\n        \n        int best_next = -1;\n        int max_ov = -1;\n        // To add randomness for variety, shuffle candidate checks or pick randomly from max overlaps\n        vector<int> candidates;\n        \n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlap_mat[last][i];\n            if (ov > max_ov) {\n                max_ov = ov;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (ov == max_ov) {\n                candidates.push_back(i);\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        uniform_int_distribution<> cand_dis(0, (int)candidates.size()-1);\n        best_next = candidates[cand_dis(gen)];\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\n// ---------------------------------------------------\n// Main Solving Logic\n// ---------------------------------------------------\n\nvoid solve() {\n    // Input\n    int si, sj;\n    cin >> si >> sj;\n    start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = row[j];\n            char_pos[row[j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i];\n    }\n    \n    // Sort targets to ensure deterministic behavior for overlap matrix calculation logic\n    // Actually, the input generation says they are sorted lexicographically.\n    // So we rely on that order for indices.\n    \n    precompute();\n    build_overlap_matrix();\n\n    // Initial State\n    vector<int> current_order = initial_order_greedy();\n    string current_s = build_string(current_order);\n    auto [current_cost, _] = solve_grid(current_s);\n    \n    vector<int> best_order = current_order;\n    int best_cost = current_cost;\n    \n    // Simulated Annealing\n    // Parameters\n    double start_temp = 2000.0; // Based on estimated cost range\n    double end_temp = 0.1;\n    double time_limit = 1950.0; // ms\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> idx_dist(0, M-1);\n    uniform_real_distribution<> prob_dist(0.0, 1.0);\n\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        // Generate neighbor: Swap two random indices\n        int idx1 = idx_dist(gen);\n        int idx2 = idx_dist(gen);\n        while(idx1 == idx2) idx2 = idx_dist(gen);\n        \n        swap(current_order[idx1], current_order[idx2]);\n        \n        string new_s = build_string(current_order);\n        auto [new_cost, _] = solve_grid(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            swap(current_order[idx1], current_order[idx2]);\n        }\n    }\n    \n    // Output Best Solution\n    string final_s = build_string(best_order);\n    auto [final_cost, path] = solve_grid(final_s, true);\n    \n    for (auto p : path) {\n        cout << p.first << \" \" << p.second << endl;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = std::chrono::system_clock::now();\n    \n    solve();\n    \n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\n#include <atcoder/random>\nusing namespace std;\nusing namespace atcoder;\n\nconst double INF = 1e9;\nconst int MAX_N = 20;\nconst int MAX_M = 20;\n\n// Global variables\nint N, M;\ndouble eps;\nvector<vector<pair<int, int>>> shapes; // Relative coordinates of each shape\nvector<pair<int, int>> shape_sizes;   // (height, width) of each shape\nmap<pair<int, int>, int> fixed_cells; // Known values: (r,c) -> value\n\n// Estimated sums from divination\nvector<double> est_row_sums;\nvector<double> est_col_sums;\n\n// Inverse variances for chi-squared\ndouble inv_var_row;\ndouble inv_var_col;\n\n// Random number generator\nrandom_device rd;\nmt19937 gen(rd());\n\n// Operation cost tracking\ndouble total_cost = 0.0;\n\n// Helper to output and flush\nvoid flush_output() {\n    cout << flush;\n}\n\n// Divination operation\ndouble divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto [r, c] : cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0 / sqrt(k);\n    \n    // Invert the noise model\n    // y ~ round(max(0, x)), x ~ N(k*eps + T(1-2*eps), k*eps(1-eps))\n    // Estimate T\n    double T_est = (res - k * eps) / (1.0 - 2.0 * eps);\n    if (T_est < 0) T_est = 0; // T must be non-negative\n    return T_est;\n}\n\n// Drilling operation\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0;\n    fixed_cells[{r, c}] = res;\n    return res;\n}\n\n// Answer operation\nbool answer(const vector<pair<int, int>>& pos_cells) {\n    cout << \"a \" << pos_cells.size();\n    for (auto [r, c] : pos_cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    return res == 1;\n}\n\n// State representation for SA\nstruct State {\n    vector<pair<int, int>> pos; // (r, c) for each field\n    int grid[MAX_N][MAX_N];\n    double energy;\n\n    void compute_grid_and_energy() {\n        // Reset grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = 0;\n            }\n        }\n\n        // Place fields\n        for (int k = 0; k < M; ++k) {\n            auto [pr, pc] = pos[k];\n            for (auto [dr, dc] : shapes[k]) {\n                int r = pr + dr;\n                int c = pc + dc;\n                grid[r][c]++;\n            }\n        }\n\n        // Check fixed cells constraint\n        for (auto [p, val] : fixed_cells) {\n            if (grid[p.first][p.second] != val) {\n                energy = INF;\n                return;\n            }\n        }\n\n        // Calculate chi-squared distance to observed row/col sums\n        double err = 0.0;\n        \n        // Row sums\n        for (int i = 0; i < N; ++i) {\n            int sum = 0;\n            for (int j = 0; j < N; ++j) sum += grid[i][j];\n            double diff = sum - est_row_sums[i];\n            err += diff * diff * inv_var_row;\n        }\n\n        // Column sums\n        for (int j = 0; j < N; ++j) {\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += grid[i][j];\n            double diff = sum - est_col_sums[j];\n            err += diff * diff * inv_var_col;\n        }\n\n        energy = err;\n    }\n};\n\n// Simulated Annealing\nState run_sa(int iterations) {\n    State cur, best;\n    cur.pos.resize(M);\n    best.pos.resize(M);\n\n    // Initialize random valid positions\n    for (int k = 0; k < M; ++k) {\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        cur.pos[k] = {dist_r(gen), dist_c(gen)};\n    }\n    cur.compute_grid_and_energy();\n    best = cur;\n\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        State nxt = cur;\n        \n        // Pick a field to move\n        int k = uniform_int_distribution<>(0, M - 1)(gen);\n        \n        // Generate new position\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        \n        if (uniform_real_distribution<>(0, 1)(gen) < 0.1) {\n            // Jump\n            nxt.pos[k] = {dist_r(gen), dist_c(gen)};\n        } else {\n            // Small step\n            int dr = uniform_int_distribution<>(-2, 2)(gen);\n            int dc = uniform_int_distribution<>(-2, 2)(gen);\n            int nr = nxt.pos[k].first + dr;\n            int nc = nxt.pos[k].second + dc;\n            \n            // Clamp to valid range\n            nr = max(0, min(N - h, nr));\n            nc = max(0, min(N - w, nc));\n            nxt.pos[k] = {nr, nc};\n        }\n\n        nxt.compute_grid_and_energy();\n\n        if (nxt.energy < cur.energy || uniform_real_distribution<>(0, 1)(gen) < exp((cur.energy - nxt.energy) / max(temp, 0.1))) {\n            cur = nxt;\n        }\n\n        if (cur.energy < best.energy) {\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M >> eps;\n    shapes.resize(M);\n    shape_sizes.resize(M);\n\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n            shapes[k].emplace_back(r, c);\n            max_r = max(max_r, r);\n            max_c = max(max_c, c);\n        }\n        shape_sizes[k] = {max_r, max_c};\n    }\n\n    // Precompute inverse variances\n    // Variance = k * eps * (1 - eps)\n    inv_var_row = 1.0 / (N * eps * (1.0 - eps));\n    inv_var_col = 1.0 / (N * eps * (1.0 - eps));\n    est_row_sums.resize(N);\n    est_col_sums.resize(N);\n\n    // Initial Probing: Rows and Columns\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_cells;\n        for (int j = 0; j < N; ++j) row_cells.emplace_back(i, j);\n        est_row_sums[i] = divine(row_cells);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_cells;\n        for (int i = 0; i < N; ++i) col_cells.emplace_back(i, j);\n        est_col_sums[j] = divine(col_cells);\n    }\n\n    // Main search loop\n    int max_ops = 2 * N * N;\n    int sa_iters = 3000; // Per iteration\n    \n    // We want to leave some buffer for the answer query\n    while (total_cost < max_ops - 1) {\n        // Run SA\n        State best_state = run_sa(sa_iters);\n\n        // If energy is very low, we might be done\n        // Heuristic: if energy < 10 (which is small for 40 degrees of freedom)\n        if (best_state.energy < 5.0) {\n            // Verify a few random cells or just submit?\n            // Let's try to submit if we are very confident\n            // Or drill one last cell to be safe\n            \n            // Construct answer\n            vector<pair<int, int>> ans;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0) {\n                        ans.emplace_back(i, j);\n                    }\n                }\n            }\n            \n            // Check if we have budget for another drill\n            if (total_cost + 1 + 0.01 > max_ops) {\n                 // Submit\n                if (answer(ans)) return;\n                else {\n                    // If wrong, we shouldn't really get here often if energy is low.\n                    // If we do, we break loop because we can't afford more ops?\n                    // Actually, we just continue if we have time.\n                    // But answer costs 1. So we lost 1 op.\n                }\n            } else {\n                // Try to verify a high-value cell\n                // Find a cell with max v that is not fixed\n                pair<int, int> target = {-1, -1};\n                int max_v = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                            if (best_state.grid[i][j] > max_v) {\n                                max_v = best_state.grid[i][j];\n                                target = {i, j};\n                            }\n                        }\n                    }\n                }\n\n                if (target.first != -1) {\n                    drill(target.first, target.second);\n                } else {\n                    // All positive cells fixed. Submit.\n                    if (answer(ans)) return;\n                }\n            }\n        } else {\n            // Energy is not low enough. Drill a cell to improve.\n            // Strategy: Drill a cell that is positive in the best model\n            pair<int, int> target = {-1, -1};\n            int max_v = -1;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                        if (best_state.grid[i][j] > max_v) {\n                            max_v = best_state.grid[i][j];\n                            target = {i, j};\n                        }\n                    }\n                }\n            }\n\n            // If no positive cell found (all fixed?), check empty?\n            // Or just pick a cell with v=0 that is surrounded by v>0?\n            if (target.first == -1) {\n                 // This case implies model says no undrilled positive cells.\n                 // But energy is high. Means model is wrong (missed some oil).\n                 // We should drill somewhere to find the missing oil.\n                 // Pick a random undrilled cell with v=0 in model.\n                 vector<pair<int,int>> candidates;\n                 for (int i=0; i<N; ++i) {\n                     for (int j=0; j<N; ++j) {\n                         if (best_state.grid[i][j] == 0 && fixed_cells.count({i,j}) == 0) {\n                             candidates.emplace_back(i,j);\n                         }\n                     }\n                 }\n                 if (!candidates.empty()) {\n                     target = candidates[uniform_int_distribution<>(0, candidates.size()-1)(gen)];\n                 } else {\n                     // All cells fixed? Just submit.\n                     vector<pair<int, int>> ans;\n                     for (int i = 0; i < N; ++i) {\n                        for (int j = 0; j < N; ++j) {\n                            if (best_state.grid[i][j] > 0) ans.emplace_back(i, j);\n                        }\n                    }\n                    if (answer(ans)) return;\n                 }\n            }\n            \n            if (target.first != -1) drill(target.first, target.second);\n        }\n    }\n    \n    // Fallback / Time up: Submit current best guess\n    State final_state = run_sa(1000); // Quick last run\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (final_state.grid[i][j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    answer(ans);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <array>\n\nusing namespace std;\n\nconst int W = 1000;\nconst int INF = 1e9;\n\nstruct DPState {\n    int cost;\n    int prev_pos;\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_input, D, N;\n    cin >> W_input >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // The 1D slicing strategy divides the W x W grid into N horizontal strips.\n    // Let y_k be the y-coordinate of the boundary between rectangle k-1 and k.\n    // y_0 = 0, y_N = W.\n    // We determine y_1, ..., y_{N-1}.\n    // Area of rectangle k is W * (y_{k+1} - y_k).\n    // We need to minimize:\n    // 1. Deficit Cost: Sum_{k} 100 * max(0, a[d][k] - W * h_k)\n    // 2. Move Cost: Sum_{k=1}^{N-1} W * |y_k - y_k_prev| * 2?\n    // Wait, problem statement says: 1 is added to L_d for each segment changed.\n    // For a horizontal cut spanning the full width W:\n    // Moving from y_old to y_new changes W segments from 1->0 and W segments from 0->1.\n    // Total change length = 2 * W * |y_new - y_old|.\n    // Cost factor is 1 per unit length. So Cost = 2 * W * dy.\n    // With W=1000, Cost = 2000 * dy.\n\n    // We process day by day.\n    // State for day d-1: cuts_y[1...N-1].\n    // For day d, we compute optimal cuts_y[1...N-1].\n\n    vector<int> prev_cuts(N - 1, 0); // For day 0, prev_cuts doesn't matter, L_0=0.\n    // We can assume prev_cuts are at 0 initially, cost is 0.\n\n    for (int d = 0; d < D; ++d) {\n        // We need to compute DP.\n        // dp[i][y] = min cost to place the first i cuts, where the i-th cut is at y.\n        // i ranges from 1 to N-1.\n        // y ranges from i to W - (N - i). (Minimum height i for first i rects, remaining space for N-i rects)\n        \n        // Cost function to transition from cut k-1 at pos 'u' to cut k at pos 'v':\n        // 1. Move cost for cut k: 2000 * |v - prev_cuts[k]|. (Note: index k is 1-based here for cuts)\n        // 2. Area cost for rectangle k-1 (between u and v):\n        //    Let h = v - u.\n        //    Area = W * h.\n        //    Deficit = a[d][k-1] - W*h (if positive).\n        //    Cost = 100 * max(0, deficit).\n\n        // dp[k][v] = min_{u < v} ( dp[k-1][u] + MoveCost(v, k) + AreaCost(u, v, k-1) )\n        \n        // To optimize, we separate the terms.\n        // dp[k][v] = 2000 * |v - prev_y_k| + min_{u < v} ( dp[k-1][u] + AreaCost(u, v, k-1) )\n        \n        // AreaCost(u, v) = 100 * max(0, A - W(v-u)).\n        // Let L_k = ceil(A / W). This is the minimum height to have 0 deficit.\n        // If v - u >= L_k, AreaCost = 0.\n        // If v - u < L_k, AreaCost = 100 * (A - W(v-u)).\n        \n        // Let's optimize the inner term: S[v] = min_{u < v} ( dp[k-1][u] + Term(u, v) )\n        // Term(u, v) = 0 if v - u >= L else 100*A - 100*W*(v-u).\n        \n        // Case 1: v - u >= L  => u <= v - L.\n        // Minimize dp[k-1][u]. This is just prefix_min[v - L].\n        \n        // Case 2: v - u < L  => u > v - L.\n        // Minimize dp[k-1][u] + 100*A - 100*W*v + 100*W*u.\n        // = (100*A - 100*W*v) + min_{u > v-L} ( dp[k-1][u] + 100*W*u ).\n        // Let B[u] = dp[k-1][u] + 100*W*u.\n        // We need suffix_min of B[u] for u > v - L.\n        \n        // So we can compute S[v] in O(1) per v using prefix/suffix minima.\n        // Total complexity O(N * W).\n\n        vector<int> optimal_cuts(N);\n        \n        // DP table for current k. Size W+1.\n        // We only need prev dp table for k-1.\n        vector<int> dp_prev(W + 1, INF);\n        vector<int> dp_curr(W + 1, INF);\n        \n        // Base case: k=0 (virtual cut at 0). Cost 0.\n        dp_prev[0] = 0;\n        \n        // Iterate cuts 1 to N-1\n        for (int k = 1; k < N; ++k) {\n            int A_req = a[d][k-1];\n            int min_h = (A_req + W - 1) / W; // ceil(A/W)\n            if (min_h == 0) min_h = 1; // Height must be at least 1?\n                                       // Actually, if a=0, h can be 0?\n                                       // Problem: a >= 1. So min_h >= 1.\n            \n            // Precompute prefix min of dp_prev\n            vector<int> pmin(W + 2, INF);\n            for (int i = 0; i <= W; ++i) {\n                pmin[i+1] = min(pmin[i], dp_prev[i]);\n            }\n            \n            // Precompute B[i] = dp_prev[i] + 100*W*i\n            vector<int> B(W + 2, INF);\n            for (int i = 0; i <= W; ++i) {\n                B[i] = dp_prev[i] + 100 * W * i;\n            }\n            // Precompute suffix min of B\n            vector<int> sminB(W + 2, INF);\n            for (int i = W; i >= 0; --i) {\n                sminB[i] = min(sminB[i+1], B[i]);\n            }\n            \n            // Iterate v from 1 to W\n            for (int v = 1; v <= W; ++v) {\n                // Valid u must be < v.\n                // Also logically: u must be >= k-1 (since first k-1 rects need at least height k-1).\n                // and v must be <= W - (N - k).\n                // Let's stick to math bounds, INF handles impossibility.\n                \n                // Inner min term\n                int inner_min = INF;\n                \n                // Case 1: u <= v - min_h\n                int limit1 = v - min_h;\n                if (limit1 >= 0) {\n                    inner_min = min(inner_min, pmin[limit1 + 1]); // pmin stores up to index\n                }\n                \n                // Case 2: u > v - min_h\n                // Strict inequality u < v. So u ranges from max(0, v - min_h + 1) to v-1.\n                // Corresponds to sminB[v - min_h + 1].\n                // sminB[i] = min_{j >= i} B[j].\n                // We need u > v - min_h. So start index is v - min_h + 1.\n                int idx = v - min_h + 1;\n                if (idx <= v - 1) { // ensure valid range\n                    if (idx <= W) {\n                        inner_min = min(inner_min, sminB[idx]);\n                    }\n                }\n                \n                if (inner_min < INF) {\n                    int move_cost = 2000 * abs(v - prev_cuts[k-1]);\n                    // Subtract 100*W*v for Case 2?\n                    // The term added was (100*A - 100*W*v + min_B).\n                    // sminB[idx] contains min(dp_prev[u] + 100*W*u).\n                    // So we need to add the linear term.\n                    \n                    int best_case_1_cost = (limit1 >= 0) ? pmin[limit1+1] : INF;\n                    int best_case_2_cost = (idx <= W) ? (sminB[idx] + 100*A_req - 100*W*v) : INF;\n                    \n                    inner_min = min(best_case_1_cost, best_case_2_cost);\n                }\n                \n                if (inner_min < INF) {\n                    dp_curr[v] = inner_min + 2000 * abs(v - prev_cuts[k-1]);\n                } else {\n                    dp_curr[v] = INF;\n                }\n            }\n            \n            dp_prev = dp_curr;\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n        }\n        \n        // Now dp_prev[v] stores the min cost for placing cuts 1..N-1 such that cut N-1 is at v.\n        // We have the last rectangle k=N-1 between v and W.\n        // We need to account for its area cost and the constraint v <= W - min_h_last.\n        \n        int last_min_h = (a[d][N-1] + W - 1) / W;\n        \n        int min_total_cost = INF;\n        int best_v = -1;\n        \n        for (int v = 0; v <= W; ++v) {\n            if (dp_prev[v] >= INF) continue;\n            \n            // Check if last rect fits\n            int h_last = W - v;\n            if (h_last < last_min_h) {\n                // Deficit\n                int deficit = a[d][N-1] - W * h_last;\n                if (deficit < 0) deficit = 0;\n                int area_cost = 100 * deficit;\n                \n                if (dp_prev[v] + area_cost < min_total_cost) {\n                    min_total_cost = dp_prev[v] + area_cost;\n                    best_v = v;\n                }\n            } else {\n                // No deficit\n                if (dp_prev[v] < min_total_cost) {\n                    min_total_cost = dp_prev[v];\n                    best_v = v;\n                }\n            }\n        }\n        \n        // Reconstruct cuts\n        // We need to store the 'u' that gave the min for each v.\n        // Since we didn't store it, we have to re-compute or backtrack during DP.\n        // To keep it simple and fast, let's just run the DP logic in reverse or store choices?\n        // With N=50, W=1000, we can afford to store choices.\n        // vector<vector<int>> choice(N, vector<int>(W+1, -1)); -> 50,000 ints, fine.\n        \n        // RE-RUN DP WITH RECONSTRUCTION\n        vector<vector<int>> choice(N, vector<int>(W+1, -1));\n        \n        dp_prev.assign(W + 1, INF);\n        dp_prev[0] = 0;\n        \n        for (int k = 1; k < N; ++k) {\n            int A_req = a[d][k-1];\n            int L = (A_req + W - 1) / W;\n            if (L == 0) L = 1;\n            \n            // Compute Prefix Min and ArgMin\n            vector<int> pmin(W + 2, INF);\n            vector<int> parg(W + 2, -1);\n            for (int i = 0; i <= W; ++i) {\n                if (dp_prev[i] < pmin[i]) {\n                    pmin[i+1] = dp_prev[i];\n                    parg[i+1] = i;\n                } else {\n                    pmin[i+1] = pmin[i];\n                    parg[i+1] = parg[i];\n                }\n            }\n            \n            // Compute B and Suffix Min of B\n            vector<int> B(W + 2, INF);\n            for (int i = 0; i <= W; ++i) {\n                B[i] = dp_prev[i] + 100 * W * i;\n            }\n            vector<int> sminB(W + 2, INF);\n            vector<int> sargB(W + 2, -1);\n            for (int i = W; i >= 0; --i) {\n                if (B[i] < sminB[i+1]) {\n                    sminB[i] = B[i];\n                    sargB[i] = i;\n                } else {\n                    sminB[i] = sminB[i+1];\n                    sargB[i] = sargB[i+1];\n                }\n            }\n            \n            for (int v = 1; v <= W; ++v) {\n                int limit1 = v - L;\n                int idx = v - L + 1;\n                \n                int c1_val = (limit1 >= 0) ? pmin[limit1+1] : INF;\n                int c1_arg = (limit1 >= 0) ? parg[limit1+1] : -1;\n                \n                int c2_val = INF;\n                int c2_arg = -1;\n                if (idx <= W && idx <= v-1) {\n                    c2_val = sminB[idx] + 100*A_req - 100*W*v;\n                    c2_arg = sargB[idx];\n                }\n                \n                int best_inner_val = INF;\n                int best_arg = -1;\n                \n                if (c1_val < c2_val) {\n                    best_inner_val = c1_val;\n                    best_arg = c1_arg;\n                } else {\n                    best_inner_val = c2_val;\n                    best_arg = c2_arg;\n                }\n                \n                if (best_inner_val < INF) {\n                    dp_curr[v] = best_inner_val + 2000 * abs(v - prev_cuts[k-1]);\n                    choice[k][v] = best_arg;\n                } else {\n                    dp_curr[v] = INF;\n                }\n            }\n            dp_prev = dp_curr;\n            fill(dp_curr.begin(), dp_curr.end(), INF);\n        }\n        \n        // Find best_v\n        min_total_cost = INF;\n        best_v = -1;\n        last_min_h = (a[d][N-1] + W - 1) / W;\n        \n        for (int v = 0; v <= W; ++v) {\n            if (dp_prev[v] >= INF) continue;\n            int cost = dp_prev[v];\n            int h_last = W - v;\n            if (h_last < last_min_h) {\n                cost += 100 * (a[d][N-1] - W * h_last);\n            }\n            if (cost < min_total_cost) {\n                min_total_cost = cost;\n                best_v = v;\n            }\n        }\n        \n        // Reconstruct cuts_y\n        // cuts_y[k] is the position of k-th cut (1-based).\n        // cuts_y has N-1 elements.\n        // Wait, choice[k][v] is the u (position of cut k-1) that led to v (position of cut k).\n        // Start from k=N-1, pos=best_v.\n        // choice[N-1][best_v] gives pos of cut N-2.\n        \n        vector<int> new_cuts(N - 1);\n        int curr_v = best_v;\n        for (int k = N - 1; k >= 1; --k) {\n            new_cuts[k-1] = curr_v;\n            curr_v = choice[k][curr_v];\n        }\n        \n        // Output rectangles for this day\n        // Rect k is between y_k and y_{k+1}\n        // y_0 = 0.\n        // y_k = new_cuts[k-1] for k=1..N-1.\n        // y_N = W.\n        // Rectangle coordinates: (y_k, 0) to (y_{k+1}, W).\n        \n        int y_prev = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            int y_curr = new_cuts[k];\n            cout << y_prev << \" \" << 0 << \" \" << y_curr << \" \" << W << \"\\n\";\n            y_prev = y_curr;\n        }\n        cout << y_prev << \" \" << 0 << \" \" << W << \" \" << W << \"\\n\";\n        \n        // Update prev_cuts for next day\n        prev_cuts = new_cuts;\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <tuple>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\nconst int MOD = 998244353;\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    // Board state\n    // Using long long to store accumulated values\n    array<array<long long, 9>, 9> board{};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> board[i][j];\n        }\n    }\n\n    // Stamps\n    // stamps[m][i][j]\n    array<array<array<long long, 3>, 3>, 20> stamps{};\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    // Precompute gains: gains[m][p][q] is the score increase by applying stamp m at (p, q)\n    // p, q range is 0 to N-3\n    array<array<array<long long, 7>, 7>, 20> gains{};\n    \n    // Lambda to calculate gain for a specific operation\n    auto calc_gain = [&](int m, int p, int q) {\n        long long score_diff = 0;\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                long long cur_val = board[p+i][q+j];\n                long long add_val = stamps[m][i][j];\n                long long new_val = cur_val + add_val;\n                score_diff += (new_val % MOD) - (cur_val % MOD);\n            }\n        }\n        return score_diff;\n    };\n\n    // Initialize all gains\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p <= N - 3; ++p) {\n            for (int q = 0; q <= N - 3; ++q) {\n                gains[m][p][q] = calc_gain(m, p, q);\n            }\n        }\n    }\n\n    vector<tuple<int, int, int>> operations;\n\n    // Greedy loop\n    for (int turn = 0; turn < K; ++turn) {\n        long long best_gain = -1e18;\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        // Scan all possible operations to find the one with maximum gain\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p <= N - 3; ++p) {\n                for (int q = 0; q <= N - 3; ++q) {\n                    if (gains[m][p][q] > best_gain) {\n                        best_gain = gains[m][p][q];\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        // If no operation improves the score, stop\n        if (best_gain <= 0) {\n            break;\n        }\n\n        // Apply the best operation\n        operations.emplace_back(best_m, best_p, best_q);\n\n        // Update board\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                board[best_p + i][best_q + j] += stamps[best_m][i][j];\n            }\n        }\n\n        // Update gains for operations that overlap with the modified region\n        // The modified region is [best_p, best_p+2] x [best_q, best_q+2]\n        // Any stamp placement (p', q') affecting a cell in this region needs update.\n        // A stamp at (p', q') affects [p', p'+2] x [q', q'+2].\n        // Overlap condition: |p' - best_p| <= 2 and |q' - best_q| <= 2.\n        int p_min = max(0, best_p - 2);\n        int p_max = min(N - 3, best_p + 2);\n        int q_min = max(0, best_q - 2);\n        int q_max = min(N - 3, best_q + 2);\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = p_min; p <= p_max; ++p) {\n                for (int q = q_min; q <= q_max; ++q) {\n                    gains[m][p][q] = calc_gain(m, p, q);\n                }\n            }\n        }\n    }\n\n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto [m, p, q] : operations) {\n        cout << m << \" \" << p << \" \" << q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    vector<vector<int>> A(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> A[i][j];\n        }\n    }\n    \n    vector<int> target_row(N * N);\n    for (int c = 0; c < N * N; c++) target_row[c] = c / N;\n    \n    vector<vector<int>> arrival(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) arrival[i][j] = A[i][j];\n    \n    vector<int> arrived(N, 0);\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_x(N), crane_y(N);\n    vector<int> carrying(N, -1);\n    \n    for (int i = 0; i < N; i++) {\n        crane_x[i] = i;\n        crane_y[i] = 0;\n    }\n    \n    vector<string> actions(N);\n    vector<bool> dispatched(N * N, false);\n    \n    for (int t = 0; t < MAX_TURNS; t++) {\n        for (int i = 0; i < N; i++) {\n            if (arrived[i] < N && grid[i][0] == -1) {\n                bool blocked = false;\n                for (int c = 0; c < N; c++)\n                    if (crane_x[c] == i && crane_y[c] == 0 && carrying[c] != -1) blocked = true;\n                if (!blocked) grid[i][0] = arrival[i][arrived[i]++];\n            }\n        }\n        \n        vector<char> act(N, '.');\n        vector<int> nx = crane_x, ny = crane_y;\n        vector<int> ncarry = carrying;\n        \n        for (int c = 0; c < N; c++) {\n            if (c == 0) {\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (crane_x[c] < tr) { act[c] = 'D'; nx[c]++; }\n                    else if (crane_x[c] > tr) { act[c] = 'U'; nx[c]--; }\n                    else if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                    else if (crane_y[c] > N - 1) { act[c] = 'L'; ny[c]--; }\n                    else { act[c] = 'Q'; ncarry[c] = -1; }\n                } else {\n                    int best_i = -1, best_j = -1, best_score = -1;\n                    for (int i = 0; i < N; i++) {\n                        for (int j = 0; j < N; j++) {\n                            int cont = grid[i][j];\n                            if (cont != -1 && !dispatched[cont]) {\n                                int wrong = (i != target_row[cont]);\n                                int dist = abs(i - crane_x[c]) + abs(j - crane_y[c]);\n                                int score = wrong * 1000 - dist;\n                                if (score > best_score) {\n                                    best_score = score; best_i = i; best_j = j;\n                                }\n                            }\n                        }\n                    }\n                    if (best_i != -1) {\n                        if (crane_x[c] < best_i) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > best_i) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < best_j) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > best_j) { act[c] = 'L'; ny[c]--; }\n                        else { act[c] = 'P'; ncarry[c] = grid[best_i][best_j]; }\n                    }\n                }\n            } else {\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (tr == c) {\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c] + 1] == -1) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] == N - 1) { act[c] = 'Q'; ncarry[c] = -1; }\n                    } else { act[c] = 'Q'; ncarry[c] = -1; }\n                } else {\n                    int cont = grid[c][crane_y[c]];\n                    if (cont != -1 && target_row[cont] == c) { act[c] = 'P'; ncarry[c] = cont; }\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (nx[i] == crane_x[j] && ny[i] == crane_y[j] && nx[j] == crane_x[i] && ny[j] == crane_y[i]) {\n                    act[j] = '.'; nx[j] = crane_x[j]; ny[j] = crane_y[j];\n                }\n                if (nx[i] == nx[j] && ny[i] == ny[j]) {\n                    act[j] = '.'; nx[j] = crane_x[j]; ny[j] = crane_y[j];\n                }\n            }\n        }\n        \n        for (int c = 0; c < N; c++) {\n            actions[c] += act[c];\n            if (act[c] == 'P') grid[crane_x[c]][crane_y[c]] = -1;\n            else if (act[c] == 'Q') grid[crane_x[c]][crane_y[c]] = carrying[c];\n            crane_x[c] = nx[c]; crane_y[c] = ny[c]; carrying[c] = ncarry[c];\n        }\n        \n        for (int i = 0; i < N; i++) {\n            if (grid[i][N - 1] != -1) {\n                dispatched[grid[i][N - 1]] = true;\n                grid[i][N - 1] = -1;\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)actions[i].size() < max_len) actions[i] += '.';\n        cout << actions[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Grid dimensions\nconst int N = 20;\nconst int INF = 1e9;\nconst int DX[4] = {0, 0, 1, -1};\nconst int DY[4] = {1, -1, 0, 0};\nconst char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n;\n    // N is always 20, but we read it just in case\n    if (!(cin >> n)) return 0; \n    \n    vector<int> h(n * n);\n    for (int i = 0; i < n * n; ++i) {\n        cin >> h[i];\n    }\n\n    // 1. Construct Min-Cost Flow Graph\n    // Nodes: 0 to n*n-1 are grid cells.\n    // Source S = n*n, Sink T = n*n + 1.\n    int S = n * n;\n    int T = n * n + 1;\n    mcf_graph<int, long long> graph(n * n + 2);\n    \n    long long total_supply = 0;\n\n    for (int i = 0; i < n * n; ++i) {\n        if (h[i] > 0) {\n            graph.add_edge(S, i, h[i], 0);\n            total_supply += h[i];\n        } else if (h[i] < 0) {\n            graph.add_edge(i, T, -h[i], 0);\n        }\n    }\n\n    // Add grid edges (undirected)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int u = i * n + j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + DX[k];\n                int nj = j + DY[k];\n                if (0 <= ni && ni < n && 0 <= nj && nj < n) {\n                    int v = ni * n + nj;\n                    // Cost is 1 per unit distance\n                    graph.add_edge(u, v, INF, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min-Cost Flow\n    auto result = graph.flow(S, T, total_supply);\n    // result.second is the min cost (sum of amount * distance)\n    // We don't strictly need the value, just the flow distribution.\n\n    // 3. Extract Flow Graph\n    // adj[u] stores (v, flow) pairs for flow > 0\n    vector<vector<pair<int, int>>> adj(n * n);\n    auto edges = graph.edges();\n    for (const auto& e : edges) {\n        if (e.from < S && e.to < S && e.flow > 0) {\n            adj[e.from].emplace_back(e.to, e.flow);\n        }\n    }\n\n    // 4. Construct Path using DFS simulation\n    vector<string> ops;\n    int current_pos = 0; // Start at (0,0)\n    int current_load = 0;\n    \n    // Helper to perform moves\n    auto move_to = [&](int target_pos) {\n        int cx = current_pos / n;\n        int cy = current_pos % n;\n        int tx = target_pos / n;\n        int ty = target_pos % n;\n        \n        // Simple BFS to find path (since we just need a path, but shortest is best)\n        // For simplicity, just move greedily or BFS.\n        // Given the constraints and the fact that we mostly follow flow edges,\n        // we might just need to connect components. \n        // But here we implement BFS for shortest path.\n        \n        vector<int> prev(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        prev[current_pos] = current_pos;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_pos) break;\n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        // Reconstruct path\n        vector<int> path;\n        int curr = target_pos;\n        while (curr != current_pos) {\n            path.push_back(curr);\n            curr = prev[curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        for (int next_pos : path) {\n            int dx = (next_pos / n) - (current_pos / n);\n            int dy = (next_pos % n) - (current_pos % n);\n            for (int k = 0; k < 4; ++k) {\n                if (DX[k] == dx && DY[k] == dy) {\n                    ops.push_back(string(1, DIR_CHAR[k]));\n                    break;\n                }\n            }\n            current_pos = next_pos;\n            // We assume move_to is called with 0 load or correct load.\n            // The cost update is implicit in the operations.\n        }\n    };\n\n    // Helper to load/unload\n    auto check_height = [&]() {\n        if (h[current_pos] > 0) {\n            ops.push_back(\"+\" + to_string(h[current_pos]));\n            current_load += h[current_pos];\n            h[current_pos] = 0;\n        } else if (h[current_pos] < 0) {\n            // We need to unload.\n            // However, we might not have exactly -h[current_pos] available if flow is split weirdly?\n            // In theory, inflow should cover it.\n            int needed = -h[current_pos];\n            if (current_load >= needed) {\n                ops.push_back(\"-\" + to_string(needed));\n                current_load -= needed;\n                h[current_pos] = 0;\n            } else {\n                // Should not happen in optimal flow, but just in case:\n                // This implies we need to carry more soil here.\n                // Or we are processing in a weird order.\n                // With the tree traversal, we should arrive with sufficient load.\n                // If not, it's a logic error in flow construction or traversal.\n                // We will assume it holds.\n            }\n        }\n    };\n\n    // Recursive DFS to cover flow tree\n    // Returns true if we don't need to backtrack (optimized path end)\n    function<bool(int)> dfs = [&](int u) {\n        // 1. Satisfy height at u\n        check_height();\n        \n        // 2. Process children\n        if (adj[u].empty()) {\n            return true; // Leaf\n        }\n        \n        // Optimization: Find the child with the deepest/longest path to process last (to avoid backtrack)\n        // Simple heuristic: just iterate.\n        // To avoid backtrack on the last child:\n        for (size_t i = 0; i < adj[u].size(); ++i) {\n            int v = adj[u][i].first;\n            int flow_amt = adj[u][i].second;\n            \n            // We need to carry `flow_amt` from u to v.\n            // The rest of current_load (if any) should stay at u.\n            // We unload the rest, reload later.\n            int load_to_keep = current_load - flow_amt;\n            \n            if (load_to_keep > 0) {\n                ops.push_back(\"-\" + to_string(load_to_keep));\n                current_load -= load_to_keep;\n                // Height of u increases temporarily. This is fine, we fix it later.\n                h[u] += load_to_keep; \n            }\n            \n            // Move to v\n            move_to(v);\n            // current_load should be flow_amt now\n            if (current_load != flow_amt) {\n                // Logic error\n            }\n            \n            bool should_return = true;\n            if (i == adj[u].size() - 1) {\n                should_return = false; // Last child, don't return\n            }\n            \n            bool child_is_leaf = dfs(v);\n            \n            if (!should_return) {\n                return false; // Propagate \"don't return\" up\n            }\n            \n            // Return from v\n            // At v, we should have 0 load (all deposited at its children/height)\n            // Move back to u\n            move_to(u);\n            \n            // Reload the soil we left at u\n            if (load_to_keep > 0) {\n                ops.push_back(\"+\" + to_string(load_to_keep));\n                current_load += load_to_keep;\n                h[u] -= load_to_keep;\n            }\n            // Now current_load is restored for next child\n        }\n        return true;\n    };\n\n    // Main loop to handle disconnected components\n    while (true) {\n        // Check if any flow remains\n        bool has_flow = false;\n        int best_u = -1;\n        int best_dist = INF;\n        \n        // Find closest node with remaining outflow\n        // Simple BFS from current_pos\n        vector<int> dist(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        dist[current_pos] = 0;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            \n            if (!adj[u].empty()) {\n                if (dist[u] < best_dist) {\n                    best_dist = dist[u];\n                    best_u = u;\n                }\n            }\n            \n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (dist[v] == -1) {\n                        dist[v] = dist[u] + 1;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        if (best_u == -1) break; // Done\n        \n        if (best_u != current_pos) {\n            // Move to best_u with 0 load (we assume we can reach with 0 load)\n            // We need to ensure we have 0 load to move optimally?\n            // Actually, we might have load if we are in a middle of something.\n            // But this loop handles disconnected components.\n            // So we should be at load 0 when jumping.\n            move_to(best_u);\n        }\n        \n        // Process component starting at best_u\n        dfs(best_u);\n    }\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    vector<vector<int>> X(seed_count, vector<int>(M));\n\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int t = 0; t < T; t++) {\n        // 1. Calculate total value V for each seed\n        vector<int> V(seed_count);\n        for (int i = 0; i < seed_count; i++) {\n            V[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // 2. Sort seeds by total value V descending for efficient selection of generalists\n        vector<int> sorted_indices(seed_count);\n        iota(sorted_indices.begin(), sorted_indices.end(), 0);\n        sort(sorted_indices.begin(), sorted_indices.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        // 3. Select seeds\n        vector<int> selected_indices;\n        vector<bool> used(seed_count, false);\n\n        // Strategy A: Select the best seed for each dimension (Specialists)\n        // This ensures we carry the genes for X_l\n        for (int l = 0; l < M; l++) {\n            int best_seed = -1;\n            int best_val = -1;\n            for (int i = 0; i < seed_count; i++) {\n                if (!used[i]) {\n                    if (X[i][l] > best_val) {\n                        best_val = X[i][l];\n                        best_seed = i;\n                    }\n                }\n            }\n            if (best_seed != -1) {\n                selected_indices.push_back(best_seed);\n                used[best_seed] = true;\n            }\n        }\n\n        // Strategy B: Fill the rest with the highest V seeds (Generalists)\n        // This ensures the population maintains high fitness\n        for (int idx : sorted_indices) {\n            if (!used[idx]) {\n                selected_indices.push_back(idx);\n                used[idx] = true;\n                if ((int)selected_indices.size() >= N * N) {\n                    break;\n                }\n            }\n        }\n\n        // 4. Sort selected seeds by V descending for placement\n        sort(selected_indices.begin(), selected_indices.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        // 5. Place seeds on the grid using a Snake pattern\n        // This clusters high V seeds in the top-left and lower V seeds in the bottom-right\n        // preserving strong local mating pairs for high fitness while allowing\n        // specialists (usually lower V) to cluster and innovate in the tail.\n        vector<vector<int>> A(N, vector<int>(N));\n        int ptr = 0;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) {\n                    A[i][j] = selected_indices[ptr++];\n                }\n            } else {\n                for (int j = N - 1; j >= 0; j--) {\n                    A[i][j] = selected_indices[ptr++];\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << A[i][j] << (j < N - 1 ? \" \" : \"\\n\");\n            }\n        }\n        cout.flush();\n\n        // 7. Read new seeds for the next turn\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nstruct State {\n    int x, y;\n    vector<int> arm_dirs; // 0..3\n    vector<int> holding;  // 0 or 1\n    vector<int> lengths;\n    vector<vector<int>> grid; // Current items\n    int step;\n};\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s_lines(N), t_lines(N);\n    for (int i = 0; i < N; ++i) cin >> s_lines[i];\n    for (int i = 0; i < N; ++i) cin >> t_lines[i];\n\n    // --- 1. Design the Robotic Arm ---\n    // Star topology: Root 0, children 1..V-1.\n    // Lengths: 1..V-1.\n    // This maximizes reach along the sweep direction.\n    cout << V << \"\\n\";\n    for (int i = 1; i < V; ++i) {\n        cout << 0 << \" \" << i << \"\\n\";\n    }\n\n    // Initial position: (0, 0)\n    // We will handle the (0,0) un-touchable issue by pausing initially.\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // Initialize State\n    State st;\n    st.x = 0; \n    st.y = 0;\n    st.step = 0;\n    st.arm_dirs.assign(V, 0); // All point Right (0)\n    st.holding.assign(V, 0);  // Nothing held\n    st.lengths.assign(V, 0);\n    for (int i = 1; i < V; ++i) st.lengths[i] = i; // Length 1, 2, ..., V-1\n\n    st.grid.assign(N, vector<int>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            st.grid[i][j] = s_lines[i][j] - '0';\n        }\n    }\n    vector<vector<int>> target(N, vector<int>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            target[i][j] = t_lines[i][j] - '0';\n        }\n    }\n\n    // --- 2. Logic Configuration ---\n    \n    // Movement Pattern: Snake\n    // Current direction of travel\n    int move_dir = 0; // Right\n    \n    // Arm Configuration\n    // Arm 0 (Length 1) is the \"Backward\" arm.\n    // Arms 1..V-1 (Length 2..V-1) are \"Forward\" arms.\n    // We need to set up Arm 0 to point Left before we start moving properly.\n    // State machine for setup:\n    // 0: Initial. Arm 0 is Right. Need to rotate to Left.\n    // 1: Arm 0 is Up.\n    // 2: Arm 0 is Left. Ready to go.\n    int setup_phase = 0;\n\n    auto is_done = [&]() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (st.grid[i][j] != target[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    // Simulation loop\n    while (st.step < 100000 && !is_done()) {\n        string S(2 * V, '.');\n\n        // 1. Determine Movement\n        char move_cmd = '.';\n        \n        if (setup_phase < 2) {\n            // Wait at (0,0) until Arm 0 points Left\n            move_cmd = '.';\n        } else {\n            // Normal Snake Movement\n            // Check bounds\n            int nx = st.x + DX[move_dir];\n            int ny = st.y + DY[move_dir];\n            \n            if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                move_cmd = DIR_CHAR[move_dir];\n                st.x = nx;\n                st.y = ny;\n            } else {\n                // Hit boundary, need to turn\n                // Corner logic\n                if (move_dir == 0) { // Was Right\n                    // At (r, N-1). Need to go Down.\n                    // But we are at Right edge. \n                    // If we are at bottom row, we might be done, or continue?\n                    // Snake pattern:\n                    // Right -> Down -> Left -> Down -> Right ...\n                    \n                    // We can move Down?\n                    if (st.x + 1 < N) {\n                        move_dir = 1; // Down\n                        move_cmd = 'D';\n                        st.x += 1;\n                    } else {\n                        // Reached bottom right. \n                        // Depending on parity, we might be done or need to go left?\n                        // With snake, if N is odd, we end at bottom-right. If even, bottom-left.\n                        // Actually, we just follow the logic.\n                        // If we can't move Right, try Down.\n                        // If we can't move Down (bottom row), check Left.\n                        if (st.x == N - 1) {\n                             move_dir = 2; // Left\n                             if (st.y - 1 >= 0) {\n                                 move_cmd = 'L';\n                                 st.y -= 1;\n                             } else {\n                                 // Should be done or stuck\n                                 move_cmd = '.';\n                             }\n                        }\n                    }\n                } else if (move_dir == 1) { // Was Down\n                    // If we were going Right (now Down), we want to go Left.\n                    // If we were going Left (now Down), we want to go Right.\n                    // We need to track row parity.\n                    // Simply: if we were Right (y=N-1), now Left.\n                    // If we were Left (y=0), now Right.\n                    \n                    // Previous horizontal dir was implicitly known.\n                    // We can infer from y.\n                    // If y == N-1, we came from Right. Next is Left.\n                    // If y == 0, we came from Left. Next is Right.\n                    // If we are in middle (shouldn't happen in strict snake), just continue Down?\n                    \n                    if (st.y == N - 1) {\n                        move_dir = 2; // Left\n                        if (st.y - 1 >= 0) {\n                            move_cmd = 'L';\n                            st.y -= 1;\n                        } else {\n                            // End of row? Should not happen if we came from Right.\n                        }\n                    } else if (st.y == 0) {\n                        move_dir = 0; // Right\n                        if (st.y + 1 < N) {\n                            move_cmd = 'R';\n                            st.y += 1;\n                        }\n                    } else {\n                        // Vertical run on the side? Unlikely with N<=30 and Snake.\n                        // Just continue Down if possible.\n                        if (st.x + 1 < N) {\n                            move_cmd = 'D';\n                            st.x += 1;\n                        } else {\n                            move_cmd = '.';\n                        }\n                    }\n                } else if (move_dir == 2) { // Was Left\n                    if (st.x + 1 < N) {\n                        move_dir = 1; // Down\n                        move_cmd = 'D';\n                        st.x += 1;\n                    } else {\n                         // At bottom-left.\n                         if (st.x == N - 1) {\n                             move_dir = 0; // Right\n                             if (st.y + 1 < N) {\n                                 move_cmd = 'R';\n                                 st.y += 1;\n                             } else {\n                                 move_cmd = '.';\n                             }\n                         }\n                    }\n                } else if (move_dir == 3) { // Was Up (should not happen in snake)\n                    move_dir = 0; \n                }\n            }\n        }\n        S[0] = move_cmd;\n\n        // 2. Determine Rotations and Actions\n        // We need to decide target directions for arms based on the CURRENT move_dir\n        \n        // Target Dir for Arm 0: Opposite of move_dir (Backward)\n        // Target Dir for Arms 1..V-1: Same as move_dir (Forward)\n        \n        // Special case: During setup, we force Arm 0 to rotate Left regardless of move.\n        // Arms 1..V-1 stay Right (0).\n        \n        int target_backward_dir = (move_dir + 2) % 4;\n        int target_forward_dir = move_dir;\n\n        if (setup_phase == 0) {\n            // Arm 0: 0 (R) -> 3 (U) or 1 (D)?\n            // We want Left (2). So R -> U is L rotation.\n            // Let's just fix target to 2 (Left).\n            target_backward_dir = 2;\n            target_forward_dir = 0; // Stay Right\n        } else if (setup_phase == 1) {\n             target_backward_dir = 2; // Still aiming for Left\n             target_forward_dir = 0;\n        }\n\n        for (int i = 1; i < V; ++i) {\n            int current = st.arm_dirs[i];\n            int target = (i == 0) ? target_backward_dir : target_forward_dir;\n            \n            // Calculate rotation\n            int diff = (target - current + 4) % 4;\n            char rot_cmd = '.';\n            if (diff == 1) rot_cmd = 'R';\n            else if (diff == 3) rot_cmd = 'L';\n            else if (diff == 2) rot_cmd = 'R'; // Arbitrary choice for 180\n            \n            S[i] = rot_cmd;\n            \n            // Update direction for next step logic (and pos calculation)\n            // Note: Rotation happens SIMULTANEOUSLY with move.\n            // So positions for Action 3 are based on NEW pos and NEW direction.\n            st.arm_dirs[i] = target;\n        }\n\n        // Update setup phase state\n        if (setup_phase == 0 && st.arm_dirs[0] == 3) setup_phase = 1; // Now Up\n        if (setup_phase == 1 && st.arm_dirs[0] == 2) setup_phase = 2; // Now Left\n\n        // 3. Determine Actions (Pick/Put)\n        for (int i = 0; i < V; ++i) {\n            // Calculate tip position\n            int ax = st.x + DX[st.arm_dirs[i]] * st.lengths[i];\n            int ay = st.y + DY[st.arm_dirs[i]] * st.lengths[i];\n            \n            char action_cmd = '.';\n            \n            // Check bounds\n            if (ax >= 0 && ax < N && ay >= 0 && ay < N) {\n                bool is_source = (st.grid[ax][ay] == 1 && target[ax][ay] == 0);\n                bool is_target = (target[ax][ay] == 1 && st.grid[ax][ay] == 0);\n                // Note: if grid=1 and target=1, it is correct. Ignore.\n                // Note: if grid=1 and target=0, it is source.\n                // Note: if grid=0 and target=1, it is target.\n\n                if (st.holding[i] == 1) {\n                    // Try to drop\n                    if (is_target) {\n                        action_cmd = 'P';\n                        st.grid[ax][ay] = 1; // Place\n                        st.holding[i] = 0;\n                    }\n                } else {\n                    // Try to pick\n                    if (is_source) {\n                        action_cmd = 'P';\n                        st.grid[ax][ay] = 0; // Remove\n                        st.holding[i] = 1;\n                    }\n                }\n            }\n            S[V + i] = action_cmd;\n        }\n\n        cout << S << \"\\n\";\n        st.step++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int TYPE_MACKEREL = 1;\nconst int TYPE_SARDINE = -1;\n\nstruct Point {\n    int x, y, type;\n};\n\nstruct Rect {\n    int x1, x2, y1, y2;\n    int net; // a - b\n};\n\n// Global storage for points\n// Indexed by x, stores (y, type)\nvector<vector<pair<int, int>>> cols;\n// Indexed by y, stores (x, type)\nvector<vector<pair<int, int>>> rows;\n\n// Next/Previous populated indices\nint next_x[MAX_COORD + 2];\nint prev_x[MAX_COORD + 2];\nint next_y[MAX_COORD + 2];\nint prev_y[MAX_COORD + 2];\n\nint best_global_score = -1;\nRect best_global_rect;\n\n// Calculate current net score if we expand the rect in the given direction\n// Returns {new_net_score, new_x1, new_x2, new_y1, new_y2} or {-1, ...} if invalid/no move\ntuple<int, int, int, int, int> try_expand(int x1, int x2, int y1, int y2, int dir) {\n    int nx1 = x1, nx2 = x2, ny1 = y1, ny2 = y2;\n    int delta = 0;\n\n    if (dir == 0) { // Right\n        if (next_x[x2] == -1) return {-1, -1, -1, -1, -1};\n        int target_x = next_x[x2];\n        // Check perimeter limit\n        if (2LL * (target_x - x1 + y2 - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n        \n        nx2 = target_x;\n        // Calculate gain\n        for (const auto& p : cols[target_x]) {\n            if (p.first >= y1 && p.first <= y2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 1) { // Left\n        if (prev_x[x1] == -1) return {-1, -1, -1, -1, -1};\n        int target_x = prev_x[x1];\n        if (2LL * (x2 - target_x + y2 - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        nx1 = target_x;\n        for (const auto& p : cols[target_x]) {\n            if (p.first >= y1 && p.first <= y2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 2) { // Top\n        if (next_y[y2] == -1) return {-1, -1, -1, -1, -1};\n        int target_y = next_y[y2];\n        if (2LL * (x2 - x1 + target_y - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        ny2 = target_y;\n        for (const auto& p : rows[target_y]) {\n            if (p.first >= x1 && p.first <= x2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 3) { // Bottom\n        if (prev_y[y1] == -1) return {-1, -1, -1, -1, -1};\n        int target_y = prev_y[y1];\n        if (2LL * (x2 - x1 + y2 - target_y) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        ny1 = target_y;\n        for (const auto& p : rows[target_y]) {\n            if (p.first >= x1 && p.first <= x2) {\n                delta += p.second;\n            }\n        }\n    }\n\n    return {delta, nx1, nx2, ny1, ny2};\n}\n\nvoid solve() {\n    int N;\n    cin >> N;\n    vector<Point> mackerels(N);\n    vector<Point> sardines(N);\n\n    cols.resize(MAX_COORD + 1);\n    rows.resize(MAX_COORD + 1);\n\n    // Helper to add point\n    auto add_point = [&](int x, int y, int type) {\n        cols[x].emplace_back(y, type);\n        rows[y].emplace_back(x, type);\n    };\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].type = TYPE_MACKEREL;\n        add_point(mackerels[i].x, mackerels[i].y, TYPE_MACKEREL);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].type = TYPE_SARDINE;\n        add_point(sardines[i].x, sardines[i].y, TYPE_SARDINE);\n    }\n\n    // Precompute next/prev\n    int last_x = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_x[i] = last_x;\n        if (!cols[i].empty()) last_x = i;\n    }\n    int next_x_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_x[i] = next_x_val;\n        if (!cols[i].empty()) next_x_val = i;\n    }\n\n    int last_y = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_y[i] = last_y;\n        if (!rows[i].empty()) last_y = i;\n    }\n    int next_y_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_y[i] = next_y_val;\n        if (!rows[i].empty()) next_y_val = i;\n    }\n\n    // Iterate over all mackerels as starting points\n    // Since N is 5000, we can afford many restarts\n    for (const auto& start_pt : mackerels) {\n        int cx1 = start_pt.x, cx2 = start_pt.x;\n        int cy1 = start_pt.y, cy2 = start_pt.y;\n        int cnet = 1; // Starts with 1 mackerel\n\n        unordered_set<long long> visited;\n        // Encode state to single long long for hash set\n        auto encode = [](int x1, int x2, int y1, int y2) {\n            return ((long long)x1 << 48) | ((long long)x2 << 32) | ((long long)y1 << 16) | y2;\n        };\n        visited.insert(encode(cx1, cx2, cy1, cy2));\n\n        int best_local_net = cnet;\n        Rect best_local_rect = {cx1, cx2, cy1, cy2, cnet};\n\n        while (true) {\n            int best_delta = -2; // Less than -1\n            int best_dir = -1;\n            int tx1, tx2, ty1, ty2;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                auto [delta, nx1, nx2, ny1, ny2] = try_expand(cx1, cx2, cy1, cy2, d);\n                if (delta == -1) continue; // Invalid move\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_dir = d;\n                    tx1 = nx1; tx2 = nx2; ty1 = ny1; ty2 = ny2;\n                }\n            }\n\n            if (best_dir == -1) break; // No valid moves\n\n            // Move logic\n            if (best_delta > 0) {\n                // Improve score, always take\n                cx1 = tx1; cx2 = tx2; cy1 = ty1; cy2 = ty2;\n                cnet += best_delta;\n            } else if (best_delta == 0) {\n                // Neutral move, take if not visited\n                if (visited.count(encode(tx1, tx2, ty1, ty2))) {\n                    break; // Cycle detected\n                }\n                cx1 = tx1; cx2 = tx2; cy1 = ty1; cy2 = ty2;\n                // cnet unchanged\n            } else {\n                // Negative score move, stop\n                break;\n            }\n\n            visited.insert(encode(cx1, cx2, cy1, cy2));\n\n            if (cnet > best_local_net) {\n                best_local_net = cnet;\n                best_local_rect = {cx1, cx2, cy1, cy2, cnet};\n            }\n        }\n\n        if (best_local_net > best_global_score) {\n            best_global_score = best_local_net;\n            best_global_rect = best_local_rect;\n        }\n    }\n\n    // Output the best rectangle found\n    // Vertices can be (x1, y1), (x2, y1), (x2, y2), (x1, y2)\n    cout << 4 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y2 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y2 << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\n// Global inputs\nint N, T;\nlong long sigma;\nvector<pair<long long, long long>> dims; // w', h'\n\n// Structure to store operations\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\n// Structure for placed rectangles\nstruct Rect {\n    long long w, h;\n    long long x, y;\n    int id;\n};\n\n// Best solution found\nvector<Op> best_ops;\nlong long best_score = 1e18;\n\n// Helper to check if two intervals [l1, r1) and [l2, r2) overlap\nbool overlap(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n// Function to attempt one packing arrangement\nvoid solve_one(int seed) {\n    // Initialize random generator\n    mt19937 rng(seed);\n    \n    vector<Rect> placed;\n    placed.reserve(N);\n    long long W = 0, H = 0;\n    long long skipped_sum = 0;\n    vector<Op> current_ops;\n    current_ops.reserve(N);\n    \n    for (int i = 0; i < N; ++i) {\n        long long w_i = dims[i].first;\n        long long h_i = dims[i].second;\n        \n        // Candidates: {score_increase, r, d, b, x, y}\n        // score_increase is delta(W) + delta(H)\n        vector<tuple<long long, int, char, int, long long, long long>> cands;\n        \n        // Option 1: Skip the rectangle\n        // Cost is w_i + h_i added to score\n        cands.push_back({w_i + h_i, -1, 'X', -1, 0, 0});\n        \n        // Option 2: Try placing it\n        for (int r = 0; r < 2; ++r) {\n            long long cw = (r == 0 ? w_i : h_i);\n            long long ch = (r == 1 ? w_i : h_i);\n            \n            // Case 2.1: Reference is -1 (Align with x=0 for U, y=0 for L)\n            \n            // Direction U: x = 0. Slide up.\n            {\n                long long x = 0;\n                long long min_obst_y = 0; // Boundary y=0\n                for (const auto& p : placed) {\n                    if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                        min_obst_y = min(min_obst_y, p.y + p.h);\n                    }\n                }\n                long long y_new = min_obst_y - ch;\n                if (y_new < 0) y_new = 0;\n                \n                long long new_W = max(W, x + cw);\n                long long new_H = max(H, y_new + ch);\n                long long score_inc = (new_W - W) + (new_H - H);\n                cands.push_back({score_inc, r, 'U', -1, x, y_new});\n            }\n            \n            // Direction L: y = 0. Slide left.\n            {\n                long long y = 0;\n                long long min_obst_x = 0; // Boundary x=0\n                for (const auto& p : placed) {\n                    if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                        min_obst_x = min(min_obst_x, p.x + p.w);\n                    }\n                }\n                long long x_new = min_obst_x - cw;\n                if (x_new < 0) x_new = 0;\n                \n                long long new_W = max(W, x_new + cw);\n                long long new_H = max(H, y + ch);\n                long long score_inc = (new_W - W) + (new_H - H);\n                cands.push_back({score_inc, r, 'L', -1, x_new, y});\n            }\n            \n            // Case 2.2: Reference is a previously placed rectangle\n            for (size_t k = 0; k < placed.size(); ++k) {\n                const auto& ref = placed[k];\n                \n                // Direction U: x = ref.right. Slide up.\n                {\n                    long long x = ref.x + ref.w;\n                    long long min_obst_y = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                            min_obst_y = min(min_obst_y, p.y + p.h);\n                        }\n                    }\n                    long long y_new = min_obst_y - ch;\n                    if (y_new < 0) y_new = 0;\n                    \n                    long long new_W = max(W, x + cw);\n                    long long new_H = max(H, y_new + ch);\n                    long long score_inc = (new_W - W) + (new_H - H);\n                    cands.push_back({score_inc, r, 'U', ref.id, x, y_new});\n                }\n                \n                // Direction L: y = ref.bottom. Slide left.\n                {\n                    long long y = ref.y + ref.h;\n                    long long min_obst_x = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                            min_obst_x = min(min_obst_x, p.x + p.w);\n                        }\n                    }\n                    long long x_new = min_obst_x - cw;\n                    if (x_new < 0) x_new = 0;\n                    \n                    long long new_W = max(W, x_new + cw);\n                    long long new_H = max(H, y + ch);\n                    long long score_inc = (new_W - W) + (new_H - H);\n                    cands.push_back({score_inc, r, 'L', ref.id, x_new, y});\n                }\n            }\n        }\n        \n        // Sort candidates by score increase\n        sort(cands.begin(), cands.end());\n        \n        // Select candidate: pick from top 3 to introduce randomness\n        int limit = min(3, (int)cands.size());\n        int idx = rng() % limit;\n        \n        const auto& chosen = cands[idx];\n        long long score_inc = get<0>(chosen);\n        int r = get<1>(chosen);\n        char d = get<2>(chosen);\n        int b = get<3>(chosen);\n        long long bx = get<4>(chosen);\n        long long by = get<5>(chosen);\n        \n        if (r == -1) {\n            // Skip\n            skipped_sum += w_i + h_i;\n        } else {\n            // Place\n            long long final_w = (r == 0 ? w_i : h_i);\n            long long final_h = (r == 1 ? w_i : h_i);\n            \n            placed.push_back({final_w, final_h, bx, by, i});\n            W = max(W, bx + final_w);\n            H = max(H, by + final_h);\n            \n            current_ops.push_back({i, r, d, b});\n        }\n    }\n    \n    long long total_score = W + H + skipped_sum;\n    if (total_score < best_score) {\n        best_score = total_score;\n        best_ops = current_ops;\n    }\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma)) return 0;\n    \n    dims.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> dims[i].first >> dims[i].second;\n    }\n    \n    // Run search for approximately 2.8 seconds\n    auto start_time = chrono::high_resolution_clock::now();\n    int iter = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > 2800) break;\n        \n        solve_one(iter++);\n    }\n    \n    // Output the best found sequence T times\n    // The feedback is read but ignored as we assume the static problem nature.\n    for (int t = 0; t < T; ++t) {\n        cout << best_ops.size() << \"\\n\";\n        for (const auto& op : best_ops) {\n            cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read feedback (must be done)\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> A[i];\n    }\n\n    vector<vector<int>> G(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n\n    // Read coordinates (not used for the greedy logic)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Initialization\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n\n    // Sort vertices by beauty value A in descending order.\n    // We use indices to sort.\n    vector<int> order(N);\n    for (int i = 0; i < N; ++i) order[i] = i;\n    sort(order.begin(), order.end(), [&](int u, int v) {\n        return A[u] > A[v];\n    });\n\n    // Greedy construction\n    for (int v : order) {\n        // Find the best parent u for v.\n        // Conditions:\n        // 1. u is a neighbor of v.\n        // 2. depth[u] < H (so that depth[v] = depth[u] + 1 <= H).\n        // 3. depth[u] is maximized.\n        \n        int best_u = -1;\n        int max_depth = -1;\n\n        for (int u : G[v]) {\n            if (depth[u] < H) {\n                if (depth[u] > max_depth) {\n                    max_depth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n\n        if (best_u != -1) {\n            parent[v] = best_u;\n            depth[v] = depth[best_u] + 1;\n        } else {\n            // No suitable parent found, v must be a root.\n            parent[v] = -1;\n            depth[v] = 0;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n};\n\nint N;\nvector<string> grid;\nvector<Point> onis;\nvector<bool> removed; // Track if an oni is removed\n\n// Helper to check if there is 'o' in a range\nbool has_o_up(int r, int c) {\n    for (int i = 0; i < r; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_down(int r, int c) {\n    for (int i = r + 1; i < N; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_left(int r, int c) {\n    for (int j = 0; j < c; ++j) if (grid[r][j] == 'o') return true;\n    return false;\n}\nbool has_o_right(int r, int c) {\n    for (int j = c + 1; j < N; ++j) if (grid[r][j] == 'o') return true;\n    return false;\n}\n\n// Check if 'x' at (r, c) can be removed by shifting Up\nbool can_remove_up(int r, int c) {\n    return !has_o_up(r, c);\n}\nbool can_remove_down(int r, int c) {\n    return !has_o_down(r, c);\n}\nbool can_remove_left(int r, int c) {\n    return !has_o_left(r, c);\n}\nbool can_remove_right(int r, int c) {\n    return !has_o_right(r, c);\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // Collect Oni positions\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 'x') {\n                onis.push_back({i, j});\n            }\n        }\n    }\n\n    removed.assign(onis.size(), false);\n\n    // Moves container\n    vector<pair<char, int>> moves;\n\n    // --- PHASE 1: ROW REMOVALS ---\n    // Process each row\n    for (int r = 0; r < N; ++r) {\n        // Identify segments in this row separated by 'o'\n        // A segment is a contiguous range of columns [l, r_end] containing no 'o'\n        vector<pair<int, int>> segments;\n        int l = 0;\n        while (l < N) {\n            while (l < N && grid[r][l] == 'o') l++;\n            if (l >= N) break;\n            int rend = l;\n            while (rend < N && grid[r][rend] != 'o') rend++;\n            segments.push_back({l, rend - 1});\n            l = rend;\n        }\n\n        for (auto seg : segments) {\n            int seg_l = seg.first;\n            int seg_r = seg.second;\n\n            // Collect 'x's in this segment\n            vector<int> p_idx; // indices in onis vector\n            vector<int> cols;  // column positions\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].r == r && onis[k].c >= seg_l && onis[k].c <= seg_r) {\n                    p_idx.push_back(k);\n                    cols.push_back(onis[k].c);\n                }\n            }\n\n            if (cols.empty()) continue;\n\n            // Classify into FORCED (cannot go vertical) and CHOICE (can go vertical)\n            // Actually, we solve row-wise. \n            // If an 'x' cannot go Up or Down, it MUST be removed here.\n            // If it CAN go Up/Down, it's optional, but we might remove it here if cheap.\n\n            vector<bool> is_forced(cols.size(), false);\n            vector<int> col_cost_saving(cols.size()); // Approximate saving if removed by row\n\n            for (size_t i = 0; i < cols.size(); ++i) {\n                int c = cols[i];\n                int idx = p_idx[i];\n                \n                bool can_up = can_remove_up(r, c);\n                bool can_down = can_remove_down(r, c);\n\n                if (!can_up && !can_down) {\n                    is_forced[i] = true;\n                } else {\n                    // Calculate minimal vertical cost as a proxy for savings\n                    // Up cost: 2*(r+1), Down cost: 2*(N-r)\n                    int v_cost = min(2 * (r + 1), 2 * (N - r));\n                    col_cost_saving[i] = v_cost;\n                }\n            }\n\n            // We want to find a set of intervals (Left-covers and Right-covers) \n            // that covers all 'is_forced' onis, minimizing \n            // Cost_row - Sum(savings of covered optional).\n            \n            // Since N is small (20), and segment length is small, we can use DP.\n            // DP[mask] = min cost to cover a subset of onis in this segment.\n            // But number of onis per segment can be up to 20. 2^20 is too big.\n            // Instead, use the greedy heuristic:\n            // 1. Find optimal cover for FORCED points.\n            // 2. Greedily add OPTIONAL points if beneficial.\n\n            // Step 1: DP for forced points\n            // Sort points by column\n            vector<pair<int, int>> forced_pts; // (col, index in cols)\n            for (size_t i = 0; i < cols.size(); ++i) {\n                if (is_forced[i]) forced_pts.push_back({cols[i], i});\n            }\n\n            // Structure: \n            // DP[k] = min cost to cover first k forced points (sorted by col).\n            // DP[i] = min(DP[i], DP[j-1] + cost_cover(j..i))\n            // Cost to cover points j..i:\n            //   Using Left interval (covers up to forced_pts[i].first): cost = 2*(forced_pts[i].first + 1)\n            //   Using Right interval (covers from forced_pts[j].first): cost = 2*(N - forced_pts[j].first)\n            // We also need to track which intervals are used.\n            \n            if (!forced_pts.empty()) {\n                int K = forced_pts.size();\n                vector<int> dp(K, 1e9);\n                vector<pair<int, int>> choice(K, {-1, 0}); // {prev_idx, type} 0=Left, 1=Right\n\n                for (int i = 0; i < K; ++i) {\n                    // Try covering from a previous cut j to i\n                    for (int j = 0; j <= i; ++j) {\n                        int prev_cost = (j == 0) ? 0 : dp[j-1];\n                        \n                        // Try Left cover (covers all points from j..i)\n                        int costL = prev_cost + 2 * (forced_pts[i].first + 1);\n                        if (costL < dp[i]) {\n                            dp[i] = costL;\n                            choice[i] = {j - 1, 0}; // Type 0: Left covering up to i\n                        }\n\n                        // Try Right cover (covers all points from j..i)\n                        int costR = prev_cost + 2 * (N - forced_pts[j].first);\n                        if (costR < dp[i]) {\n                            dp[i] = costR;\n                            choice[i] = {j - 1, 1}; // Type 1: Right covering from j\n                        }\n                    }\n                }\n\n                // Reconstruct intervals\n                int curr = K - 1;\n                vector<pair<int, int>> intervals; // {val, type}, type 0=L, 1=R\n                \n                while (curr >= 0) {\n                    int prev = choice[curr].first;\n                    int type = choice[curr].second;\n                    \n                    if (type == 0) {\n                        intervals.push_back({forced_pts[curr].first, 0});\n                    } else {\n                        intervals.push_back({forced_pts[prev + 1].first, 1});\n                    }\n                    curr = prev;\n                }\n                reverse(intervals.begin(), intervals.end());\n\n                // Apply these intervals (mark removed, add moves)\n                // Note: We need to check which optional points fall into these intervals\n                for (auto &iv : intervals) {\n                    int bound = iv.first;\n                    int type = iv.second;\n                    \n                    if (type == 0) { // Left cover: covers [0, bound]\n                        // Add moves\n                        moves.push_back({'L', r});\n                        for(int k=0; k<bound; ++k) moves.push_back({'L', r}); // Logic in output\n                        // Actually output format: \"L i\" repeated? No, output operations one by one.\n                        // Sequence: L (bound+1) times, then R (bound+1) times\n                        for(int k=0; k <= bound; ++k) moves.push_back({'L', r});\n                        for(int k=0; k <= bound; ++k) moves.push_back({'R', r});\n\n                        // Mark removed\n                        for (size_t i = 0; i < cols.size(); ++i) {\n                            if (!removed[p_idx[i]] && cols[i] <= bound) {\n                                removed[p_idx[i]] = true;\n                            }\n                        }\n                    } else { // Right cover: covers [bound, N-1]\n                        for(int k=0; k < N-bound; ++k) moves.push_back({'R', r});\n                        for(int k=0; k < N-bound; ++k) moves.push_back({'L', r});\n\n                        for (size_t i = 0; i < cols.size(); ++i) {\n                            if (!removed[p_idx[i]] && cols[i] >= bound) {\n                                removed[p_idx[i]] = true;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Step 2: Greedy expansion for remaining optional points\n            // We have intervals (implicit from the moves added).\n            // Simplification: Just check remaining optional points individually.\n            // If we can extend an existing interval or create a new one cheaper than col cost, do it.\n            // Since we already output moves for the forced set, we need to be careful not to duplicate logic.\n            // Actually, it's easier to re-evaluate the whole segment \"optimally\" with savings.\n            // But for simplicity, let's iterate over remaining optional points.\n            \n            // Get remaining optional points\n            vector<int> remaining_opts;\n            for(size_t i=0; i<cols.size(); ++i) {\n                if(!removed[p_idx[i]] && !is_forced[i]) {\n                    remaining_opts.push_back(cols[i]);\n                }\n            }\n\n            for (int c_opt : remaining_opts) {\n                // Cost to cover this single point with Row\n                int cost_left = 2 * (c_opt + 1);\n                int cost_right = 2 * (N - c_opt);\n                int min_row_cost = min(cost_left, cost_right);\n\n                // Benefit: col_cost_saving\n                // We need to find which 'c_opt' corresponds to in savings map.\n                // Just recompute saving.\n                int saving = min(2 * (r + 1), 2 * (N - r));\n\n                if (min_row_cost < saving) {\n                    // Cover with row\n                    if (cost_left < cost_right) {\n                        for(int k=0; k<=c_opt; ++k) moves.push_back({'L', r});\n                        for(int k=0; k<=c_opt; ++k) moves.push_back({'R', r});\n                    } else {\n                        for(int k=0; k < N-c_opt; ++k) moves.push_back({'R', r});\n                        for(int k=0; k < N-c_opt; ++k) moves.push_back({'L', r});\n                    }\n                    // Mark removed\n                     for (size_t i = 0; i < cols.size(); ++i) {\n                        if (cols[i] == c_opt && !removed[p_idx[i]]) {\n                            removed[p_idx[i]] = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // --- PHASE 2: COLUMN REMOVALS ---\n    // Similar logic for columns\n    for (int c = 0; c < N; ++c) {\n        vector<pair<int, int>> segments;\n        int u = 0;\n        while (u < N) {\n            while (u < N && grid[u][c] == 'o') u++;\n            if (u >= N) break;\n            int d = u;\n            while (d < N && grid[d][c] != 'o') d++;\n            segments.push_back({u, d - 1});\n            u = d;\n        }\n\n        for (auto seg : segments) {\n            int seg_u = seg.first;\n            int seg_d = seg.second;\n\n            vector<int> p_idx;\n            vector<int> rows;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].c == c && onis[k].r >= seg_u && onis[k].r <= seg_d) {\n                    p_idx.push_back(k);\n                    rows.push_back(onis[k].r);\n                }\n            }\n\n            if (rows.empty()) continue;\n\n            // All remaining onis are necessarily \"col_choice\", otherwise they would have been removed in row phase\n            // We just solve 1D cover for this set to minimize cost.\n            \n            // Sort rows\n            sort(rows.begin(), rows.end());\n            // Re-map indices to find oni idx\n            map<int, int> row_to_oni_idx;\n            for(size_t i=0; i<rows.size(); ++i) {\n                for(auto& p : p_idx) { // inefficient but N is small\n                    if(onis[p].r == rows[i]) row_to_oni_idx[rows[i]] = p;\n                }\n            }\n\n            // Standard 1D Cover DP for points on line\n            // Up corresponds to Left (prefix), Down corresponds to Right (suffix)\n            int K = rows.size();\n            vector<int> dp(K, 1e9);\n            vector<pair<int, int>> choice(K, {-1, 0}); // 0=Up, 1=Down\n\n            for (int i = 0; i < K; ++i) {\n                for (int j = 0; j <= i; ++j) {\n                    int prev_cost = (j == 0) ? 0 : dp[j-1];\n                    \n                    // Up (covers [seg_u, rows[i]])\n                    int costU = prev_cost + 2 * (rows[i] + 1);\n                    if (costU < dp[i]) {\n                        dp[i] = costU;\n                        choice[i] = {j - 1, 0};\n                    }\n\n                    // Down (covers [rows[j], seg_d])\n                    // Cost to shift down enough to remove rows[j] is 2 * (N - rows[j])\n                    int costD = prev_cost + 2 * (N - rows[j]);\n                    if (costD < dp[i]) {\n                        dp[i] = costD;\n                        choice[i] = {j - 1, 1};\n                    }\n                }\n            }\n\n            // Reconstruct and apply\n            int curr = K - 1;\n            while (curr >= 0) {\n                int prev = choice[curr].first;\n                int type = choice[curr].second;\n\n                if (type == 0) {\n                    int r_end = rows[curr];\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'U', c});\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'D', c});\n                    \n                    for(int r = seg_u; r <= r_end; ++r) {\n                        if(row_to_oni_idx.count(r)) removed[row_to_oni_idx[r]] = true;\n                    }\n                } else {\n                    int r_start = rows[prev + 1];\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'D', c});\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'U', c});\n\n                    for(int r = r_start; r <= seg_d; ++r) {\n                        if(row_to_oni_idx.count(r)) removed[row_to_oni_idx[r]] = true;\n                    }\n                }\n                curr = prev;\n            }\n        }\n    }\n\n    // --- OUTPUT ---\n    cout << moves.size() << \"\\n\";\n    for (auto m : moves) {\n        cout << m.first << \" \" << m.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\n// Random number generator\nmt19937 rng(0); // Fixed seed for reproducibility in testing, use random_device for submission if allowed\n\n// Simulation function to calculate counts t_i and error\nlong long simulate(const vector<int>& a, const vector<int>& b, const vector<int>& T) {\n    vector<int> cnt(N, 0);\n    int cur = 0;\n    cnt[0] = 1;\n    for (int i = 1; i < L; ++i) {\n        if (cnt[cur] % 2 == 1) {\n            cur = a[cur];\n        } else {\n            cur = b[cur];\n        }\n        cnt[cur]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(cnt[i] - T[i]);\n    }\n    return error;\n}\n\n// Greedy construction of a and b based on target T\n// Randomize the order of processing nodes to explore different configurations\nvoid construct_greedy(const vector<int>& T, vector<int>& a, vector<int>& b) {\n    // Remaining demand for each node y\n    vector<long long> demand(N);\n    for (int i = 0; i < N; ++i) {\n        demand[i] = T[i];\n    }\n\n    // Process nodes in random order\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int x : order) {\n        long long tx = T[x];\n        if (tx == 0) {\n            // If target is 0, it doesn't matter much where we point, \n            // but pointing to a node with high demand might help satisfy it (if we ever visit x)\n            // However, we likely won't visit x. Just point randomly or to self.\n            a[x] = 0;\n            b[x] = 0;\n            continue;\n        }\n\n        // We split the outflow from x into two parts.\n        // Based on parity, we will use a_x roughly ceil(tx/2) times and b_x roughly floor(tx/2) times.\n        long long w1 = (tx + 1) / 2;\n        long long w2 = tx / 2;\n\n        // Find best y for w1\n        // We want to minimize |demand[y] - w1| ideally, but demand represents what we NEED.\n        // We are ADDING w1 to the inflow. So we want the new inflow (demand[y] + w1) to be close to target T[y].\n        // Wait, demand here is effectively \"remaining needed inflow\" or \"current balance\"?\n        // Let's define demand[y] as the current estimate of how much more inflow y needs.\n        // Initially demand[y] = T[y] (it needs T[y] inflow).\n        // When we send w to y, we reduce demand[y] by w?\n        // No, standard flow formulation: Sum of inflows = Sum of T. \n        // We want sum of inflows to be T. \n        // Let current_inflow[y] = 0. Target = T[y].\n        // We want to add w to current_inflow[y] such that current_inflow[y] is close to T[y].\n        // So we minimize | (current_inflow[y] + w) - T[y] |.\n        // This is equivalent to minimizing | -demand[y] + w | if demand[y] = T[y] - current_inflow[y].\n        // Let's stick to tracking \"current_inflow\".\n        \n        // Re-thinking the greedy logic for robustness:\n        // We have \"slots\" to fill. Total slots = L.\n        // We iterate x. x produces w1 and w2.\n        // We assign w1 to some y. We assign w2 to some z.\n        // We want the final distribution of assigned weights to match T.\n        \n        // Heuristic: Pick y that minimizes | (assigned_so_far[y] + w) - T[y] |.\n        // assigned_so_far is initially 0.\n        \n        // To implement this efficiently without scanning all N every time:\n        // We can just scan all N (N=100 is small).\n    }\n\n    // Let's redo the greedy logic cleanly here.\n    vector<long long> assigned(N, 0); // How much flow assigned to each node so far\n    \n    for (int x : order) {\n        long long w1 = (T[x] + 1) / 2;\n        long long w2 = T[x] / 2;\n\n        // Helper lambda to find best target\n        auto find_best_target = [&](long long w) -> int {\n            int best_y = 0;\n            long long best_diff = -1; \n            // We want to minimize overflow/underflow.\n            // Cost = |assigned[y] + w - T[y]|.\n            // We also want to slightly penalize staying on the same node to encourage mixing?\n            // Or maybe not. Let's stick to pure flow matching.\n            \n            for (int y = 0; y < N; ++y) {\n                long long diff = abs((assigned[y] + w) - T[y]);\n                // If diff is same, prefer random to break ties consistently but randomly\n                if (best_diff == -1 || diff < best_diff || (diff == best_diff && rng() % 2 == 0)) {\n                    best_diff = diff;\n                    best_y = y;\n                }\n            }\n            return best_y;\n        };\n\n        int y1 = find_best_target(w1);\n        assigned[y1] += w1;\n        a[x] = y1;\n\n        int y2 = find_best_target(w2);\n        assigned[y2] += w2;\n        b[x] = y2;\n    }\n}\n\nvoid solve() {\n    int n_input;\n    long long l_input;\n    cin >> n_input >> l_input;\n    N; // N is fixed 100\n    L; // L is fixed 500000\n\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    vector<int> best_a(N), best_b(N);\n    long long best_error = 1e18;\n\n    // We will perform multiple random restarts.\n    // Given 2 seconds and N=100, L=500k, we can fit maybe 500-1000 simulations.\n    // Let's try 500.\n    const int TRIES = 500;\n    \n    // Seed rng based on time for the submission\n    rng.seed(static_cast<unsigned int>(chrono::steady_clock::now().time_since_epoch().count()));\n\n    for (int t = 0; t < TRIES; ++t) {\n        vector<int> a(N), b(N);\n        construct_greedy(T, a, b);\n        \n        long long err = simulate(a, b, T);\n        if (err < best_error) {\n            best_error = err;\n            best_a = a;\n            best_b = b;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    solve();\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <iomanip>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// DSU implementation\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        return true;\n    }\n    bool same(int x, int y) { return find(x) == find(y); }\n};\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<double> cx, cy;\n\n// Function to estimate distance based on box centers\nint estimated_dist(int i, int j) {\n    double dx = cx[i] - cx[j];\n    double dy = cy[i] - cy[j];\n    return (int)floor(sqrt(dx*dx + dy*dy));\n}\n\n// Perform a query\nvector<pair<int, int>> ask_query(const vector<int>& cities) {\n    cout << \"? \" << cities.size();\n    for (int c : cities) cout << \" \" << c;\n    cout << endl;\n    cout.flush();\n    \n    vector<pair<int, int>> edges;\n    // We expect |C| - 1 edges\n    for (size_t i = 0; i < cities.size() - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.emplace_back(u, v);\n    }\n    return edges;\n}\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    cx.resize(N); cy.resize(N);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n    }\n    \n    // Step 1: Assign cities to groups\n    // Sort all cities by their center coordinates to cluster nearby cities\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n    \n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < G[k]; ++i) {\n            groups[k].push_back(order[idx++]);\n        }\n    }\n    \n    // Prepare answer storage\n    // groups[k] contains the city IDs. We need to output them in some order.\n    // We also need to output edges.\n    vector<vector<pair<int, int>>> answer_edges(M);\n    \n    // Step 2: Process each group to build the tree\n    for (int k = 0; k < M; ++k) {\n        auto& vec = groups[k];\n        int sz = vec.size();\n        \n        // Re-sort by center just to be consistent within the group, though already sorted globally\n        sort(vec.begin(), vec.end(), [&](int i, int j) {\n            if (cx[i] != cx[j]) return cx[i] < cx[j];\n            return cy[i] < cy[j];\n        });\n        \n        if (sz <= L) {\n            // If the group is small enough, query the whole group to get the exact MST\n            if (sz >= 2) {\n                auto edges = ask_query(vec);\n                answer_edges[k] = edges;\n            }\n        } else {\n            // For large groups, use overlapping sliding windows\n            \n            // Set to store unique edges from queries\n            // We use a set to avoid duplicates from overlapping windows\n            set<pair<int, int>> known_edges_set;\n            \n            // We also store estimated distances for these edges to sort them later\n            vector<pair<int, pair<int, int>>> candidates; // {dist, {u, v}}\n            \n            // Determine stride. \n            // With stride L/2, we ensure significant overlap to cover local MSTs.\n            int stride = max(1, L / 2);\n            \n            for (int i = 0; i + L <= sz; i += stride) {\n                vector<int> subset(vec.begin() + i, vec.begin() + i + L);\n                auto edges = ask_query(subset);\n                for (auto& e : edges) {\n                    if (known_edges_set.find(e) == known_edges_set.end()) {\n                        known_edges_set.insert(e);\n                        int d = estimated_dist(e.first, e.second);\n                        candidates.push_back({d, e});\n                    }\n                }\n            }\n            \n            // Handle the tail if it wasn't covered by the last full window\n            // The loop condition `i + L <= sz` ensures we only query full L-sized sets.\n            // If the remaining part is large, we might miss it.\n            // But with stride L/2, we cover up to `last_start + L`.\n            // The max index covered is `floor((sz-L)/stride)*stride + L - 1`.\n            // With stride ~ L/2, coverage is good. \n            // For safety, if we have queries left (we usually do), we could query the last chunk.\n            // But let's stick to the plan. If we miss the very end, the Kruskal fallback handles it.\n            \n            // If the group is still large and we have queries left, we can query the last few nodes\n            // with the previous nodes to ensure connectivity.\n            // But simply connecting using estimated distances is acceptable if the structure is sound.\n            \n            // Add estimated edges for all pairs in the group to the candidate list\n            // Priority: edges returned by queries (likely short), then estimated edges.\n            // Actually, we should prioritize returned edges. \n            // We assign a negative weight or sort them first?\n            // Since we don't know exact weights, we assume returned edges are good.\n            // We will sort by estimated distance. \n            \n            // To ensure returned edges are preferred, we can temporarily set their estimated distance to -1?\n            // Or just sort by estimated distance. \n            // A true short edge that wasn't queried might have a smaller estimated distance than a queried long edge?\n            // Unlikely if queried edges are from MSTs of local neighborhoods.\n            \n            // Populate all other pairs\n            for (int i = 0; i < sz; ++i) {\n                for (int j = i + 1; j < sz; ++j) {\n                    int u = vec[i];\n                    int v = vec[j];\n                    if (u > v) swap(u, v);\n                    pair<int, int> p(u, v);\n                    if (known_edges_set.find(p) == known_edges_set.end()) {\n                        int d = estimated_dist(u, v);\n                        candidates.push_back({d, p});\n                    }\n                }\n            }\n            \n            // Run Kruskal\n            sort(candidates.begin(), candidates.end());\n            \n            DSU dsu(sz); // Maps index in `vec` to component\n            // We need a mapping from city ID to index in `vec` for DSU, or just use global DSU on N?\n            // Since edges are stored as city IDs, we should map city ID to its index in `vec`.\n            map<int, int> city_to_idx;\n            for(int i=0; i<sz; ++i) city_to_idx[vec[i]] = i;\n\n            int edges_needed = sz - 1;\n            for (auto& item : candidates) {\n                int d = item.first;\n                int u = item.second.first;\n                int v = item.second.second;\n                \n                int idx_u = city_to_idx[u];\n                int idx_v = city_to_idx[v];\n                \n                if (dsu.unite(idx_u, idx_v)) {\n                    answer_edges[k].push_back({u, v});\n                    if (answer_edges[k].size() == edges_needed) break;\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities in the group\n        for (int city : groups[k]) {\n            cout << city << (city == groups[k].back() ? \"\" : \" \");\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : answer_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    solve();\n    \n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\n// Coordinate system: x = column (j), y = row (i)\nstruct Point {\n    int x;\n    int y;\n};\n\nint N, M;\nvector<Point> targets;\n\nvector<pair<char, char>> actions;\n\nvoid add_action(char a, char d) {\n    actions.push_back({a, d});\n}\n\nvoid add_move(char d, int steps) {\n    for (int i = 0; i < steps; ++i) {\n        add_action('M', d);\n    }\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    targets.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int r, c;\n        cin >> r >> c;\n        targets[i].x = c; // j -> x\n        targets[i].y = r; // i -> y\n    }\n\n    Point cur = targets[0];\n\n    for (int k = 1; k < M; ++k) {\n        Point target = targets[k];\n        int dx = target.x - cur.x;\n        int dy = target.y - cur.y;\n\n        // Calculate walking cost (Manhattan distance)\n        int walk_cost = abs(dx) + abs(dy);\n        \n        // Evaluate Boundary Slide options\n        // We want to reach target T.\n        // Slide stops just before a block. The grid boundary (x=-1, x=N, y=-1, y=N) is a block.\n        // To slide to T, T must be adjacent to a boundary block in the direction of the slide.\n        // This means T must be on the grid boundary.\n        \n        int best_cost = walk_cost;\n        int best_strategy = 0; // 0: Walk, 1: Slide Vertical, 2: Slide Horizontal\n        char slide_dir = ' ';  // 'U', 'D', 'L', 'R'\n\n        // Option 1: Slide Vertical (Up or Down)\n        // Valid if T is on Top edge (y=0) or Bottom edge (y=N-1).\n        \n        // Slide Up to Top Edge\n        // Requires T.y == 0.\n        // We move vertically? No, Slide Up moves in y. We need to align x.\n        // Path: Align x (move horizontally), then Slide Up.\n        // Cost: |cur.x - T.x| + 1\n        // Valid if cur.y > 0 (since we must slide at least 1 step to hit wall effectively? \n        // Actually, if cur.y > 0, we can slide. If cur.y == 0, we are already on edge, Slide Up does nothing.\n        // Wait, if T=(0,0) and cur=(5,0), Slide U from 5,0 hits wall -1, stops at 0,0. Cost 1.\n        // Align x cost 5. Total 6. Walk 5. Slide is worse.\n        // But for large y distance:\n        // cur=(10, 10), T=(0, 0). \n        // Slide U: Align x (cost 10). Slide (1). Total 11.\n        // Walk: |10-0| + |10-0| = 20. Slide is better.\n        \n        if (target.y == 0 && cur.y > 0) {\n            int cost = abs(cur.x - target.x) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 1;\n                slide_dir = 'U';\n            }\n        }\n        \n        // Slide Down to Bottom Edge\n        // Requires T.y == N-1.\n        // Path: Align x, Slide Down.\n        // Cost: |cur.x - target.x| + 1\n        // Valid if cur.y < N-1.\n        if (target.y == N - 1 && cur.y < N - 1) {\n            int cost = abs(cur.x - target.x) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 1;\n                slide_dir = 'D';\n            }\n        }\n\n        // Option 2: Slide Horizontal (Left or Right)\n        // Valid if T is on Left edge (x=0) or Right edge (x=N-1).\n\n        // Slide Left to Left Edge\n        // Requires T.x == 0.\n        // Path: Align y, Slide Left.\n        // Cost: |cur.y - target.y| + 1\n        // Valid if cur.x > 0.\n        if (target.x == 0 && cur.x > 0) {\n            int cost = abs(cur.y - target.y) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 2;\n                slide_dir = 'L';\n            }\n        }\n\n        // Slide Right to Right Edge\n        // Requires T.x == N-1.\n        // Path: Align y, Slide Right.\n        // Cost: |cur.y - target.y| + 1\n        // Valid if cur.x < N-1.\n        if (target.x == N - 1 && cur.x < N - 1) {\n            int cost = abs(cur.y - target.y) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 2;\n                slide_dir = 'R';\n            }\n        }\n\n        // Execute the chosen strategy\n        if (best_strategy == 0) {\n            // Walk\n            // Order of moves doesn't strictly matter for cost, but let's do X then Y\n            if (dx > 0) add_move('R', dx);\n            else if (dx < 0) add_move('L', -dx);\n            \n            if (dy > 0) add_move('D', dy);\n            else if (dy < 0) add_move('U', -dy);\n        } \n        else if (best_strategy == 1) {\n            // Vertical Slide\n            // Align X\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            // Slide\n            add_action('S', slide_dir);\n        } \n        else if (best_strategy == 2) {\n            // Horizontal Slide\n            // Align Y\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            // Slide\n            add_action('S', slide_dir);\n        }\n\n        cur = target;\n    }\n\n    // Output\n    for (const auto& act : actions) {\n        cout << act.first << \" \" << act.second << \"\\n\";\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <limits>\n#include <numeric>\n\nusing namespace std;\n\n// Use long long for area and error calculations to avoid overflow\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n    int a, b, c, d; // Output rectangle coordinates\n};\n\nvector<Company> companies;\n\n// Recursive function to partition the space\n// (x1, y1) is the bottom-left of the current region, (x2, y2) is the top-right\n// ids contains the indices of companies that must be placed in this region\nvoid solve_recursive(int x1, int y1, int x2, int y2, vector<int> ids) {\n    int k = ids.size();\n    if (k == 0) return;\n    \n    // Base case: only one company, assign the whole region\n    if (k == 1) {\n        int id = ids[0];\n        companies[id].a = x1;\n        companies[id].b = y1;\n        companies[id].c = x2;\n        companies[id].d = y2;\n        return;\n    }\n\n    ll total_area = (ll)(x2 - x1) * (y2 - y1);\n    \n    // Find the best cut (vertical or horizontal)\n    // We minimize the squared error: sum((assigned_area - desired_area)^2)\n    \n    ll best_error = numeric_limits<ll>::max();\n    int best_split_axis = -1; // 0: vertical, 1: horizontal\n    int best_split_idx = -1; // Index in the sorted list to split at\n    int best_cut_pos = -1;   // Coordinate of the cut\n    \n    // --- Try Vertical Cut ---\n    // Sort companies by X coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].x < companies[j].x;\n    });\n    \n    // Calculate prefix sums of r to quickly get sum of desired areas for a split\n    vector<ll> prefix_sum(k);\n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int height = y2 - y1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        // Split between i and i+1\n        ll sum_r_left = prefix_sum[i];\n        ll sum_r_right = prefix_sum[k-1] - sum_r_left;\n        \n        // The cut position X must separate the points.\n        // Left points must have x < X, Right points must have x >= X.\n        // Since points are integers, X must be > max_x_left and <= min_x_right.\n        int max_x_left = companies[ids[i]].x;\n        int min_x_right = companies[ids[i+1]].x;\n        \n        // Also must be within the current rectangle bounds (x1, x2)\n        // Left rect: [x1, X), Right: [X, x2) -> x1 < X < x2\n        int low = max(x1 + 1, max_x_left + 1);\n        int high = min(x2 - 1, min_x_right);\n        \n        if (low > high) continue; // No valid cut position for this split\n        \n        // Calculate optimal cut position to match area\n        // We want (X - x1) * height approx sum_r_left\n        double target_x = x1 + (double)sum_r_left / height;\n        int cut_x = (int)round(target_x);\n        \n        // Clamp to valid range\n        if (cut_x < low) cut_x = low;\n        if (cut_x > high) cut_x = high;\n        \n        ll actual_area_left = (ll)(cut_x - x1) * height;\n        ll actual_area_right = total_area - actual_area_left;\n        \n        ll error = (actual_area_left - sum_r_left) * (actual_area_left - sum_r_left) \n                 + (actual_area_right - sum_r_right) * (actual_area_right - sum_r_right);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 0;\n            best_split_idx = i;\n            best_cut_pos = cut_x;\n        }\n    }\n    \n    // --- Try Horizontal Cut ---\n    // Sort companies by Y coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].y < companies[j].y;\n    });\n    \n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int width = x2 - x1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        ll sum_r_bottom = prefix_sum[i];\n        ll sum_r_top = prefix_sum[k-1] - sum_r_bottom;\n        \n        int max_y_bottom = companies[ids[i]].y;\n        int min_y_top = companies[ids[i+1]].y;\n        \n        int low = max(y1 + 1, max_y_bottom + 1);\n        int high = min(y2 - 1, min_y_top);\n        \n        if (low > high) continue;\n        \n        double target_y = y1 + (double)sum_r_bottom / width;\n        int cut_y = (int)round(target_y);\n        \n        if (cut_y < low) cut_y = low;\n        if (cut_y > high) cut_y = high;\n        \n        ll actual_area_bottom = (ll)(cut_y - y1) * width;\n        ll actual_area_top = total_area - actual_area_bottom;\n        \n        ll error = (actual_area_bottom - sum_r_bottom) * (actual_area_bottom - sum_r_bottom) \n                 + (actual_area_top - sum_r_top) * (actual_area_top - sum_r_top);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 1;\n            best_split_idx = i;\n            best_cut_pos = cut_y;\n        }\n    }\n    \n    // --- Perform the Split ---\n    vector<int> left_ids, right_ids;\n    \n    if (best_split_axis == 0) {\n        // Vertical split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].x < companies[j].x;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, best_cut_pos, y2, left_ids);\n        solve_recursive(best_cut_pos, y1, x2, y2, right_ids);\n    } else {\n        // Horizontal split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].y < companies[j].y;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, x2, best_cut_pos, left_ids);\n        solve_recursive(x1, best_cut_pos, x2, y2, right_ids);\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    companies.resize(n);\n    vector<int> all_ids(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        all_ids[i] = i;\n    }\n    \n    solve_recursive(0, 0, 10000, 10000, all_ids);\n    \n    for (int i = 0; i < n; ++i) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" << companies[i].c << \" \" << companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n#include <random>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\n// mt19937_64 for high quality random numbers\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n};\n\nstruct Tile {\n    int id;\n    int size;\n    Point cells[2];\n    int total_val;\n    bool visited;\n};\n\n// Global variables for grid\nint H = 50, W = 50;\nint si, sj;\nvector<vector<int>> tile_ids;\nvector<vector<int>> p_vals;\nvector<Tile> tiles;\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHARS[4] = {'U', 'D', 'L', 'R'};\n\n// Helper to check bounds\ninline bool inside(int r, int c) {\n    return 0 <= r && r < H && 0 <= c && c < W;\n}\n\n// Heuristic function to evaluate the \"future\" potential of a cell\n// It sums the values of unvisited neighbor tiles + a bonus for connectivity\nint get_future_potential(int r, int c, const vector<bool>& visited) {\n    int score = 0;\n    int connections = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + DR[d];\n        int nc = c + DC[d];\n        if (inside(nr, nc)) {\n            int tid = tile_ids[nr][nc];\n            if (!visited[tid]) {\n                score += tiles[tid].total_val;\n                connections++;\n            }\n        }\n    }\n    // Bonus for having multiple options (connectivity)\n    return score + connections * 10;\n}\n\n// Main solver function\nstring solve_single_run() {\n    int num_tiles = tiles.size();\n    vector<bool> visited(num_tiles, false);\n    string path = \"\";\n    int score = 0;\n    \n    // Initialize current position and tile\n    Point curr_pos(si, sj);\n    int curr_tile_id = tile_ids[si][sj];\n    \n    // Mark start tile as visited\n    visited[curr_tile_id] = true;\n    score += p_vals[si][sj]; // Add score of starting square\n    \n    // Handle start tile logic (if it's a 2-tile, we might want to move to the other cell)\n    if (tiles[curr_tile_id].size == 2) {\n        Point p0 = tiles[curr_tile_id].cells[0];\n        Point p1 = tiles[curr_tile_id].cells[1];\n        \n        Point other = (p0.r == si && p0.c == sj) ? p1 : p0;\n        \n        // Calculate heuristic for exiting from current pos vs exiting from other\n        // Note: We already 'visited' the start tile, so we can move freely within it.\n        // We haven't collected points from 'other' yet.\n        \n        int potential_curr = get_future_potential(si, sj, visited);\n        int potential_other = p_vals[other.r][other.c] + get_future_potential(other.r, other.c, visited);\n        \n        if (potential_other > potential_curr) {\n            // Move to the other cell\n            for (int d = 0; d < 4; ++d) {\n                if (si + DR[d] == other.r && sj + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    curr_pos = other;\n                    score += p_vals[other.r][other.c];\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Main greedy loop\n    while (true) {\n        Point best_next_pos(-1, -1);\n        int best_score_move = -1;\n        bool best_is_full_traverse = false; // True if we choose to visit both cells of a 2-tile\n        int best_dir_idx = -1;\n        \n        // Check neighbors\n        for (int d = 0; d < 4; ++d) {\n            int nr = curr_pos.r + DR[d];\n            int nc = curr_pos.c + DC[d];\n            \n            if (!inside(nr, nc)) continue;\n            \n            int nxt_tid = tile_ids[nr][nc];\n            if (visited[nxt_tid]) continue;\n            \n            // Evaluate moving to (nr, nc)\n            // We enter the tile at (nr, nc)\n            int gain = tiles[nxt_tid].total_val;\n            \n            // Strategy 1: Full traverse (visit all cells of the tile)\n            // We effectively collect `gain`, and end up at the \"best\" exit point of the tile\n            // But since we enter at (nr, nc), we must reach the exit point from there.\n            // For 1-tile, exit is (nr, nc).\n            // For 2-tile, we enter at (nr, nc) -> go to other -> exit. Or enter -> exit.\n            \n            int max_future = -1e9;\n            int best_exit_cell_idx = -1; // 0 or 1 relative to tile cells\n            int future_curr_entry = -1e9;\n            \n            // Evaluate exit points\n            // Entry point is always the cell adjacent to curr_pos\n            // We need to identify which cell of the target tile is (nr, nc)\n            Point entry_cell(nr, nc);\n            Point other_cell(-1, -1);\n            if (tiles[nxt_tid].size == 2) {\n                if (tiles[nxt_tid].cells[0].r == nr && tiles[nxt_tid].cells[0].c == nc) {\n                    other_cell = tiles[nxt_tid].cells[1];\n                } else {\n                    other_cell = tiles[nxt_tid].cells[0];\n                }\n            }\n\n            // Option A: Exit from entry_cell (Partial traverse if 2-tile)\n            // We only gain points of entry_cell? \n            // Wait, if we enter a 2-tile and don't visit the other cell, do we gain its points? No.\n            // But wait, problem statement: \"score... sum of values of visited squares\".\n            // So we must decide which squares to visit.\n            // If 1-tile: visit (nr, nc). Gain = p(nr, nc).\n            // If 2-tile: visit (nr, nc). Gain = p(nr, nc).\n            \n            // Let's calculate exact gain for each strategy.\n            \n            // Strat 1: Visit ONLY entry_cell\n            int gain_partial = p_vals[nr][nc];\n            int future_partial = get_future_potential(nr, nc, visited);\n            int score_partial = gain_partial + future_partial;\n            \n            int score_full = -1e9;\n            int future_full = -1;\n            \n            if (tiles[nxt_tid].size == 1) {\n                // Only one option\n                score_full = gain_partial; // gain_partial is total_val here\n                future_full = future_partial;\n            } else {\n                // Strat 2: Visit entry_cell AND other_cell\n                int gain_full = tiles[nxt_tid].total_val;\n                // We end up at other_cell. Can we exit from other_cell? Yes.\n                // Can we exit from entry_cell? No, we stepped on other_cell, we must be at other_cell.\n                // Wait, if we step on entry, then other. We are at other. We leave from other.\n                // So future depends on other_cell.\n                int future_other = get_future_potential(other_cell.r, other_cell.c, visited);\n                score_full = gain_full + future_other;\n                future_full = future_other;\n            }\n            \n            // Pick best strategy for this neighbor\n            int current_best_score = max(score_partial, score_full);\n            \n            // Add noise\n            int noise = rng() % 20;\n            current_best_score += noise;\n            \n            if (current_best_score > best_score_move) {\n                best_score_move = current_best_score;\n                best_next_pos = Point(nr, nc);\n                best_dir_idx = d;\n                \n                // Record which strategy was better to update path later\n                // If score_full > score_partial, we will traverse fully\n                // Note: For 1-tile, they are equal, doesn't matter.\n                best_is_full_traverse = (score_full > score_partial);\n            }\n        }\n        \n        if (best_score_move == -1) {\n            break; // No moves left\n        }\n        \n        // Execute best move\n        int nxt_tid = tile_ids[best_next_pos.r][best_next_pos.c];\n        visited[nxt_tid] = true;\n        \n        // Update path and score\n        path += DIR_CHARS[best_dir_idx];\n        curr_pos = best_next_pos;\n        score += p_vals[best_next_pos.r][best_next_pos.c];\n        \n        if (tiles[nxt_tid].size == 2 && best_is_full_traverse) {\n            // Find the other cell\n            Point p0 = tiles[nxt_tid].cells[0];\n            Point p1 = tiles[nxt_tid].cells[1];\n            Point other = (p0.r == best_next_pos.r && p0.c == best_next_pos.c) ? p1 : p0;\n            \n            // Move to other cell\n            // Find direction\n            for (int d = 0; d < 4; ++d) {\n                if (best_next_pos.r + DR[d] == other.r && best_next_pos.c + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    break;\n                }\n            }\n            curr_pos = other;\n            score += p_vals[other.r][other.c];\n        }\n    }\n    \n    return path;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    cin >> si >> sj;\n    \n    tile_ids.resize(H, vector<int>(W));\n    p_vals.resize(H, vector<int>(W));\n    \n    // Map tile ID to vector of cells to construct Tile objects\n    vector<vector<Point>> raw_tile_cells;\n    \n    // Temporary map to normalize tile IDs if needed (though problem says 0..M-1)\n    // Just read and store\n    \n    // First pass to find M and store points\n    int max_id = 0;\n    vector<vector<int>> temp_ids(H, vector<int>(W));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> temp_ids[i][j];\n            max_id = max(max_id, temp_ids[i][j]);\n        }\n    }\n    \n    raw_tile_cells.resize(max_id + 1);\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = temp_ids[i][j];\n            raw_tile_cells[id].push_back(Point(i, j));\n        }\n    }\n    \n    // Construct Tile objects\n    tiles.resize(raw_tile_cells.size());\n    for (int i = 0; i < raw_tile_cells.size(); ++i) {\n        tiles[i].id = i;\n        tiles[i].size = raw_tile_cells[i].size();\n        tiles[i].cells[0] = raw_tile_cells[i][0];\n        if (tiles[i].size == 2) {\n            tiles[i].cells[1] = raw_tile_cells[i][1];\n        }\n        // Will update total_val after reading p\n    }\n    \n    // Assign normalized IDs to grid (can reuse original if they are dense 0..M-1, they are)\n    tile_ids = temp_ids;\n    \n    // Read values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> p_vals[i][j];\n            tiles[tile_ids[i][j]].total_val += p_vals[i][j];\n        }\n    }\n    \n    // Run multiple trials with random variations\n    string best_path = \"\";\n    int best_score = -1;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Limit to 1.8 seconds to be safe\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800) {\n        string current_path = solve_single_run();\n        \n        // Calculate score of this path (re-simulate or just compute during solve?)\n        // Let's re-simulate to be sure and clean.\n        int score = 0;\n        int cr = si, cc = sj;\n        vector<bool> vis(tiles.size(), false);\n        vis[tile_ids[cr][cc]] = true;\n        score += p_vals[cr][cc];\n        \n        bool valid = true;\n        \n        for (char move : current_path) {\n            int d = -1;\n            if (move == 'U') d = 0;\n            else if (move == 'D') d = 1;\n            else if (move == 'L') d = 2;\n            else if (move == 'R') d = 3;\n            \n            int nr = cr + DR[d];\n            int nc = cc + DC[d];\n            \n            if (!inside(nr, nc)) { valid = false; break; }\n            \n            int tid = tile_ids[nr][nc];\n            if (vis[tid]) { valid = false; break; }\n            \n            vis[tid] = true;\n            cr = nr; cc = nc;\n            score += p_vals[cr][cc];\n        }\n        \n        if (valid && score > best_score) {\n            best_score = score;\n            best_path = current_path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Global parameters\nconst int N = 30; // Grid size\nconst int NUM_PARAMS = N * 2; // 30 row costs + 30 col costs\n\nstruct RLS_Estimator {\n    int n_params;\n    vector<double> theta; // Estimated parameters\n    vector<vector<double>> P; // Covariance matrix\n\n    RLS_Estimator(int n) : n_params(n) {\n        theta.assign(n, 5000.0); // Initial guess\n        P.assign(n, vector<double>(n, 0.0));\n        // Initialize P with large diagonal values for high initial uncertainty\n        for (int i = 0; i < n; ++i) {\n            P[i][i] = 1000.0;\n        }\n    }\n\n    void update(const vector<int>& counts, double measured_total) {\n        // Calculate predicted total\n        double predicted_total = 0.0;\n        for (int i = 0; i < n_params; ++i) {\n            predicted_total += theta[i] * counts[i];\n        }\n\n        double error = measured_total - predicted_total;\n\n        // Vector x = P * counts\n        vector<double> Px(n_params, 0.0);\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                Px[i] += P[i][j] * counts[j];\n            }\n        }\n\n        // Denominator: 1 + counts^T * P * counts = 1 + counts^T * Px\n        double denom = 1.0;\n        for (int i = 0; i < n_params; ++i) {\n            denom += counts[i] * Px[i];\n        }\n\n        // Kalman gain: K = Px / denom\n        vector<double> K(n_params);\n        for (int i = 0; i < n_params; ++i) {\n            K[i] = Px[i] / denom;\n        }\n\n        // Update theta: theta = theta + error * K\n        for (int i = 0; i < n_params; ++i) {\n            theta[i] += error * K[i];\n        }\n\n        // Update P: P = P - K * (Px)^T\n        // This is a rank-1 update\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                P[i][j] -= K[i] * Px[j];\n            }\n        }\n    }\n};\n\nstring find_path(int si, int sj, int ti, int tj, RLS_Estimator& estimator) {\n    // Dijkstra's algorithm\n    // Distances\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<pair<int, int>>> prev(N, vector<pair<int, int>>(N, {-1, -1}));\n    \n    priority_queue<tuple<double, int, int>, vector<tuple<double, int, int>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, si, sj});\n\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    string dirs = \"UDLR\";\n\n    while (!pq.empty()) {\n        auto [d, r, c] = pq.top();\n        pq.pop();\n\n        if (r == ti && c == tj) break;\n        if (d > dist[r][c]) continue;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            double cost;\n            if (k < 2) { // Vertical move (U, D)\n                // Edge weight depends on column\n                cost = estimator.theta[N + nc];\n            } else { // Horizontal move (L, R)\n                // Edge weight depends on row\n                cost = estimator.theta[r];\n            }\n\n            if (dist[r][c] + cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[r][c] + cost;\n                prev[nr][nc] = {r, c};\n                pq.push({dist[nr][nc], nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cr = ti, cc = tj;\n    while (cr != si || cc != sj) {\n        int pr = prev[cr][cc].first;\n        int pc = prev[cr][cc].second;\n        \n        if (pr == -1 && pc == -1) break; // Should not happen\n\n        if (pr < cr) path += \"D\";\n        else if (pr > cr) path += \"U\";\n        else if (pc < cc) path += \"R\";\n        else if (pc > cc) path += \"L\";\n        \n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Helper to get feature counts from a path\nvector<int> get_feature_counts(const string& path, int si, int sj) {\n    vector<int> counts(NUM_PARAMS, 0);\n    int r = si, c = sj;\n    for (char dir : path) {\n        if (dir == 'L') {\n            counts[r]++;\n            c--;\n        } else if (dir == 'R') {\n            counts[r]++;\n            c++;\n        } else if (dir == 'U') {\n            counts[N + c]++;\n            r--;\n        } else if (dir == 'D') {\n            counts[N + c]++;\n            r++;\n        }\n    }\n    return counts;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    RLS_Estimator estimator(NUM_PARAMS);\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        string path = find_path(si, sj, ti, tj, estimator);\n        cout << path << endl;\n\n        // Read feedback\n        int measured;\n        cin >> measured;\n\n        vector<int> counts = get_feature_counts(path, si, sj);\n        estimator.update(counts, (double)measured);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <cmath>\n#include <numeric>\n#include <unordered_set>\n#include <chrono>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Utility: Rolling Hash\n// ---------------------------------------------------------\nstruct RollingHash {\n    static const uint64_t mod = (1ULL << 61) - 1;\n    uint64_t base;\n    vector<uint64_t> pow;\n    \n    RollingHash(uint64_t b) : base(b) {\n        pow.resize(100); // Enough for N=20\n        pow[0] = 1;\n        for(int i=1; i<100; i++) pow[i] = mul(pow[i-1], base);\n    }\n\n    static inline uint64_t add(uint64_t a, uint64_t b) {\n        if((a += b) >= mod) a -= mod;\n        return a;\n    }\n\n    static inline uint64_t mul(uint64_t a, uint64_t b) {\n        __uint128_t c = (__uint128_t)a * b;\n        return add((c >> 61) + (c & mod), mod);\n    }\n\n    // Compute hash of string s\n    uint64_t get_hash(const string& s) {\n        uint64_t res = 0;\n        for(char c : s) res = add(mul(res, base), c);\n        return res;\n    }\n\n    // Update hash when one character changes: old_char -> new_char at pos\n    // old_h is the hash of the current string of length len\n    uint64_t update_hash(uint64_t old_h, int pos, char old_char, char new_char, int len) {\n        // h = s0*B^(len-1) + s1*B^(len-2) + ... + s_pos*B^(len-1-pos) + ...\n        // We want to remove old_char and add new_char\n        // term = old_char * B^(len-1-pos)\n        // new_h = old_h - old_term + new_term\n        \n        uint64_t p = pow[len - 1 - pos];\n        // Removing old\n        uint64_t old_term = mul(old_char, p);\n        uint64_t h = (old_h + mod - old_term) % mod;\n        \n        // Adding new\n        uint64_t new_term = mul(new_char, p);\n        h = add(h, new_term);\n        \n        return h;\n    }\n};\n\n// ---------------------------------------------------------\n// Solver Class\n// ---------------------------------------------------------\nclass Solver {\npublic:\n    int N;\n    int M;\n    vector<string> S;\n    vector<vector<int>> str_len_groups; // Group strings by length\n\n    mt19937 rng;\n    RollingHash rh;\n\n    Solver(int n, int m, const vector<string>& s) : N(n), M(m), S(s), rng(chrono::steady_clock::now().time_since_epoch().count()), rh(10007) {\n        // Group strings by length for processing\n        int max_len = 0;\n        for(auto& t : S) max_len = max(max_len, (int)t.size());\n        str_len_groups.resize(max_len + 1);\n        for(int i=0; i<M; i++) {\n            str_len_groups[S[i].size()].push_back(i);\n        }\n    }\n\n    // -----------------------------------------------------\n    // Phase 1: Assemble Sequences from Long Strings\n    // -----------------------------------------------------\n    vector<string> assemble_sequences() {\n        vector<string> sequences;\n        \n        // We focus on long strings first, as they are unique.\n        // Length >= 6 usually works well for N=20, but let's try 8 for safety.\n        // Process lengths from 12 down to 6.\n        vector<int> lens;\n        for(int i=0; i<=12; i++) lens.push_back(i);\n        sort(lens.rbegin(), lens.rend());\n\n        for(int len : lens) {\n            if(len < 6) break; // Cutoff for assembly\n            for(int idx : str_len_groups[len]) {\n                const string& s = S[idx];\n                int best_seq_idx = -1;\n                int best_overlap = -1;\n                int best_rot = -1;\n\n                // Try to fit s into existing sequences\n                for(int i=0; i<(int)sequences.size(); i++) {\n                    string& seq = sequences[i];\n                    // Try all rotations\n                    for(int r=0; r<N; r++) {\n                        int overlap = 0;\n                        bool conflict = false;\n                        for(int k=0; k<(int)s.size(); k++) {\n                            int seq_idx = (r + k) % N;\n                            char c_seq = seq[seq_idx];\n                            if(c_seq != '.') {\n                                if(c_seq != s[k]) {\n                                    conflict = true;\n                                    break;\n                                } else {\n                                    overlap++;\n                                }\n                            }\n                        }\n                        if(!conflict) {\n                            // Prefer higher overlap\n                            if(overlap > best_overlap) {\n                                best_overlap = overlap;\n                                best_seq_idx = i;\n                                best_rot = r;\n                            }\n                        }\n                    }\n                }\n\n                if(best_seq_idx != -1) {\n                    // Merge into best_seq\n                    string& seq = sequences[best_seq_idx];\n                    for(int k=0; k<(int)s.size(); k++) {\n                        int seq_idx = (best_rot + k) % N;\n                        if(seq[seq_idx] == '.') {\n                            seq[seq_idx] = s[k];\n                        }\n                    }\n                } else {\n                    // Create new sequence\n                    if(sequences.size() < 50) { // Limit total sequences\n                        string new_seq(N, '.');\n                        int start = rng() % N;\n                        for(int k=0; k<(int)s.size(); k++) {\n                            new_seq[(start + k) % N] = s[k];\n                        }\n                        sequences.push_back(new_seq);\n                    }\n                }\n            }\n        }\n        return sequences;\n    }\n\n    // -----------------------------------------------------\n    // Phase 2: Assign Sequences to Rows/Cols (Simulated Annealing)\n    // -----------------------------------------------------\n    vector<string> assign_sequences(const vector<string>& sequences) {\n        // State: 40 strings (20 rows + 20 cols). \n        // Each slot holds a string (candidate or generic).\n        \n        int num_seqs = sequences.size();\n        int slots = 40;\n        \n        // Initialize assignment\n        // indices [0, 19] -> Rows, [20, 39] -> Cols\n        vector<int> assign(slots, -1);\n        vector<int> rot(slots, 0);\n        \n        // Fill with available sequences\n        for(int i=0; i<slots && i<num_seqs; i++) {\n            assign[i] = i;\n            rot[i] = 0; // Assume standard rotation initially\n        }\n        // If we have fewer than 40 sequences, fill rest with clones or random?\n        // Better to leave them as wildcards ('.') initially or generic.\n        // Let's map remaining to random existing ones to avoid empty slots in logic\n        for(int i=num_seqs; i<slots; i++) {\n            assign[i] = rng() % num_seqs;\n        }\n\n        auto get_seq = [&](int slot) -> string {\n            if(assign[slot] == -1) return string(N, '.');\n            string s = sequences[assign[slot]];\n            string res(N, '.');\n            for(int i=0; i<N; i++) res[i] = s[(i + rot[slot]) % N];\n            return res;\n        };\n\n        // Pre-calc energy\n        auto calc_energy = [&]() {\n            int cost = 0;\n            // For each cell (i, j), check Row[i][j] vs Col[j][i]\n            // Row i is slot i. Col j is slot 20 + j.\n            for(int i=0; i<N; i++) {\n                string row = get_seq(i);\n                for(int j=0; j<N; j++) {\n                    string col = get_seq(20 + j);\n                    if(row[j] != '.' && col[i] != '.' && row[j] != col[i]) {\n                        cost++;\n                    }\n                }\n            }\n            return cost;\n        };\n\n        int current_cost = calc_energy();\n        vector<int> best_assign = assign;\n        vector<int> best_rot = rot;\n        int best_cost = current_cost;\n\n        double temp_start = 2.0;\n        double temp_end = 0.01;\n        int iter = 0;\n        int max_iter = 40000; // Should be enough for small grid\n\n        while(iter < max_iter) {\n            double temp = temp_start + (temp_end - temp_start) * (iter / max_iter);\n            iter++;\n\n            // Transition\n            // 1. Change assignment of a slot\n            // 2. Change rotation of a slot\n            int slot = rng() % slots;\n            int prev_assign = assign[slot];\n            int prev_rot = rot[slot];\n            \n            if(rng() % 2 == 0) {\n                // Change assignment\n                assign[slot] = rng() % num_seqs;\n            } else {\n                // Change rotation\n                rot[slot] = (rot[slot] + 1 + rng() % 3) % N; // Small rotations better\n            }\n\n            int new_cost = calc_energy();\n            int delta = new_cost - current_cost;\n            \n            if(delta < 0 || exp(-delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                current_cost = new_cost;\n                if(current_cost < best_cost) {\n                    best_cost = current_cost;\n                    best_assign = assign;\n                    best_rot = rot;\n                }\n            } else {\n                // Revert\n                assign[slot] = prev_assign;\n                rot[slot] = prev_rot;\n            }\n        }\n\n        // Construct grid from best assignment\n        vector<string> grid(N, string(N, '.'));\n        for(int i=0; i<N; i++) {\n            string row = sequences[best_assign[i]];\n            for(int j=0; j<N; j++) {\n                char c = row[(j + best_rot[i]) % N];\n                if(c != '.') grid[i][j] = c;\n            }\n        }\n        for(int j=0; j<N; j++) {\n            string col = sequences[best_assign[20+j]];\n            for(int i=0; i<N; i++) {\n                char c = col[(i + best_rot[20+j]) % N];\n                if(c != '.') {\n                    if(grid[i][j] == '.') grid[i][j] = c;\n                    // If conflict, keep current (heuristic)\n                }\n            }\n        }\n        return grid;\n    }\n\n    // -----------------------------------------------------\n    // Phase 3: Local Search on Grid (Greedy / Randomized)\n    // -----------------------------------------------------\n    void optimize_grid(vector<string>& grid, double time_limit_ms) {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        // Precompute hashes for input strings\n        vector<uint64_t> s_hashes(M);\n        for(int i=0; i<M; i++) {\n            s_hashes[i] = rh.get_hash(S[i]);\n        }\n\n        // Current Grid State\n        vector<uint64_t> row_hashes(N);\n        vector<uint64_t> col_hashes(N);\n        vector<string> current_grid = grid;\n\n        auto init_hashes = [&]() {\n            for(int i=0; i<N; i++) row_hashes[i] = rh.get_hash(current_grid[i]);\n            for(int j=0; j<N; j++) {\n                string col_str;\n                for(int i=0; i<N; i++) col_str += current_grid[i][j];\n                col_hashes[j] = rh.get_hash(col_str);\n            }\n        };\n        init_hashes();\n\n        // Function to check string matches\n        auto count_matches = [&]() {\n            int cnt = 0;\n            unordered_set<uint64_t> row_h_set(row_hashes.begin(), row_hashes.end());\n            unordered_set<uint64_t> col_h_set(col_hashes.begin(), col_hashes.end());\n            \n            for(int i=0; i<M; i++) {\n                // Also need to check all substrings of length L in a row.\n                // Storing only full row hash is insufficient because strings are length 2..12.\n                // We need to check if S[i] is a substring of any row or col.\n                // Since N=20 is small, and we have hashes, we can compute hash of all substrings of S[i]? No.\n                // We compute hash of all substrings of length L in grid and check against hash(S[i]).\n                \n                // Optimization: Precompute all substring hashes of grid rows/cols?\n                // N=20, M=800. 20 rows * 20 shifts * 12 lens = 4800 checks.\n                // Hash computation is fast.\n                \n                uint64_t target = s_hashes[i];\n                int L = S[i].size();\n                bool found = false;\n\n                // Check rows\n                for(int r=0; r<N; r++) {\n                    // Construct substring hash\n                    // We can compute rolling hash for the row for length L.\n                    // But we have full row hash.\n                    // Let's just extract string for simplicity, given N=20, extracting substring is fast.\n                    // Actually, extracting string is O(L).\n                    // Total ops 800 * 20 * 20 * 10 = 3.2e6 per eval. Acceptable.\n                    \n                    for(int start=0; start<N; start++) {\n                        bool match = true;\n                        for(int k=0; k<L; k++) {\n                            if(current_grid[r][(start+k)%N] != S[i][k]) {\n                                match = false;\n                                break;\n                            }\n                        }\n                        if(match) { found = true; break; }\n                    }\n                    if(found) break;\n                }\n\n                if(!found) {\n                    for(int c=0; c<N; c++) {\n                        for(int start=0; start<N; start++) {\n                            bool match = true;\n                            for(int k=0; k<L; k++) {\n                                if(current_grid[(start+k)%N][c] != S[i][k]) {\n                                    match = false;\n                                    break;\n                                }\n                            }\n                            if(match) { found = true; break; }\n                        }\n                        if(found) break;\n                    }\n                }\n                \n                if(found) cnt++;\n            }\n            return cnt;\n        };\n\n        int best_score = count_matches();\n        vector<string> best_grid = current_grid;\n\n        // Simple Hill Climbing with random restarts/moves\n        // Since SA logic is similar, let's just do random perturbations keeping best.\n        // With time limit, just loop.\n        \n        int iter = 0;\n        while(true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if(elapsed > time_limit_ms - 50) break;\n\n            iter++;\n            // Random move: change a cell\n            int r = rng() % N;\n            int c = rng() % N;\n            char old_c = current_grid[r][c];\n            char new_c = 'A' + (rng() % 8); // A-H\n            \n            if(new_c == old_c) continue;\n\n            // Update grid and hashes\n            current_grid[r][c] = new_c;\n            // Re-init hashes is easiest (N=20) -> 20 strings of len 20. Very fast.\n            // No need for incremental update complexity for N=20.\n            init_hashes();\n\n            int score = count_matches();\n            if(score > best_score) {\n                best_score = score;\n                best_grid = current_grid;\n                // If perfect match, can we stop?\n                // Maybe try to reduce '.' count? \n                // Scoring bonus for '.' is only if c=M. \n                // If c=M, maximizing score means minimizing '.' (wait, re-reading problem).\n                // Score = round(1e8 * 800 / (800-d)). Larger d is better score.\n                // So if c=M, we want MORE dots.\n                // But we established that achieving c=M usually forces d small.\n                // If we reach c=M, we can try to change '.' cells to valid chars? \n                // No, we want to change VALID chars to '.' if they are not needed?\n                // That's risky. \n                // For now, maximizing c is priority.\n                if(score == M) {\n                    // We could try to clear '.' but logic is complex. \n                    // A perfect reconstruction (d=0) gives 1e8. \n                    // The problem likely expects close to 1e8.\n                }\n            } else {\n                // Revert with probability?\n                // Just revert if not improving (Hill Climbing)\n                // Actually, pure Hill Climbing gets stuck. Use simulated annealing probability.\n                // But count_matches is expensive. \n                // Let's just do: if score >= best_score, keep. \n                // Wait, we need to explore.\n                // Simple strategy: if random < 0.1 keep even if worse.\n                if(score < best_score && (rng() % 100) > 5) {\n                    current_grid[r][c] = old_c;\n                    init_hashes(); // Restore hashes\n                } else {\n                    // Kept the \"worse\" or \"better\" move. Update best if better.\n                    if(score > best_score) {\n                        best_score = score;\n                        best_grid = current_grid;\n                    }\n                }\n            }\n        }\n        \n        grid = best_grid;\n    }\n\n    void solve() {\n        // Phase 1\n        auto seqs = assemble_sequences();\n        \n        // Phase 2\n        auto grid = assign_sequences(seqs);\n        \n        // Phase 3\n        optimize_grid(grid, 2800); // Leave margin\n\n        for(auto& row : grid) cout << row << endl;\n    }\n};\n\n// ---------------------------------------------------------\n// Main\n// ---------------------------------------------------------\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for(int i=0; i<M; i++) cin >> S[i];\n\n    Solver solver(N, M, S);\n    solver.solve();\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/scc>\n#include <atcoder/modint>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\nusing point = bg::model::point<int, 2, bg::cs::cartesian>;\nusing value = std::pair<point, size_t>; // point, index in nodes\n\nusing namespace std;\n\n// Global Constants\nconst int INF = 1e9;\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\nconst char dc[4] = {'R', 'L', 'D', 'U'};\n\nstruct Input {\n    int N;\n    int si, sj;\n    vector<string> grid;\n    int total_road;\n};\n\nInput read_input() {\n    Input in;\n    cin >> in.N >> in.si >> in.sj;\n    in.grid.resize(in.N);\n    in.total_road = 0;\n    for (int i = 0; i < in.N; ++i) {\n        cin >> in.grid[i];\n        for (int j = 0; j < in.N; ++j) {\n            if (in.grid[i][j] != '#') in.total_road++;\n        }\n    }\n    return in;\n}\n\n// Hopcroft-Karp for Maximum Bipartite Matching\nclass HopcroftKarp {\npublic:\n    int n_left, n_right;\n    vector<vector<int>> adj;\n    vector<int> pair_u, pair_v, dist;\n\n    HopcroftKarp(int n_left, int n_right) : n_left(n_left), n_right(n_right), adj(n_left) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        for (int u = 0; u < n_left; ++u) {\n            if (pair_u[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = INF;\n            }\n        }\n        dist[n_left] = INF; // Dummy node for right side check\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (dist[u] < dist[n_left]) {\n                for (int v : adj[u]) {\n                    if (pair_v[v] == -1) {\n                        dist[n_left] = dist[u] + 1;\n                    } else if (dist[pair_v[v]] == INF) {\n                        dist[pair_v[v]] = dist[u] + 1;\n                        q.push(pair_v[v]);\n                    }\n                }\n            }\n        }\n        return dist[n_left] != INF;\n    }\n\n    bool dfs(int u) {\n        if (u != n_left) {\n            for (int v : adj[u]) {\n                if (pair_v[v] == -1 || (dist[pair_v[v]] == dist[u] + 1 && dfs(pair_v[v]))) {\n                    pair_u[u] = v;\n                    pair_v[v] = u;\n                    return true;\n                }\n            }\n            dist[u] = INF;\n            return false;\n        }\n        return true;\n    }\n\n    int max_matching() {\n        pair_u.assign(n_left, -1);\n        pair_v.assign(n_right, -1);\n        dist.assign(n_left + 1, 0);\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < n_left; ++u) {\n                if (pair_u[u] == -1) {\n                    if (dfs(u)) {\n                        matching++;\n                    }\n                }\n            }\n        }\n        return matching;\n    }\n    \n    // Get Minimum Vertex Cover from Maximum Matching\n    // Returns a bitset or boolean vector for left and right nodes respectively\n    pair<vector<bool>, vector<bool>> get_min_vertex_cover() {\n        vector<bool> in_cover_left(n_left, false);\n        vector<bool> in_cover_right(n_right, false);\n        \n        // Standard Konig's theorem construction:\n        // Z = { unmatched L } U { reachable from unmatched L via alternating paths }\n        // Min VC = (L \\ Z) U (R n Z)\n        // Here dist[] is used. In BFS layering, nodes with dist[] < INF are in Z (L side)\n        // But we need to re-run or use the state from the last BFS? \n        // Let's just use the pairings to find Z.\n        // Z starts with unmatched U.\n        // Then alternating paths: U -> V (not paired) -> U (paired) ...\n        \n        queue<int> q;\n        vector<bool> visited_L(n_left, false);\n        vector<bool> visited_R(n_right, false);\n        \n        for(int u=0; u<n_left; ++u) {\n            if(pair_u[u] == -1) {\n                q.push(u);\n                visited_L[u] = true;\n            }\n        }\n        \n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            for(int v : adj[u]) {\n                if(!visited_R[v]) {\n                    visited_R[v] = true;\n                    int paired_u = pair_v[v];\n                    if(paired_u != -1 && !visited_L[paired_u]) {\n                        visited_L[paired_u] = true;\n                        q.push(paired_u);\n                    }\n                }\n            }\n        }\n        \n        for(int u=0; u<n_left; ++u) {\n            if(!visited_L[u]) in_cover_left[u] = true;\n        }\n        for(int v=0; v<n_right; ++v) {\n            if(visited_R[v]) in_cover_right[v] = true;\n        }\n        \n        return {in_cover_left, in_cover_right};\n    }\n};\n\n// Dijkstra\nvector<int> dijkstra(const Input& in, pair<int, int> start, const vector<pair<int,int>>& targets) {\n    int N = in.N;\n    int s_dist = start.first * N + start.second;\n    vector<int> dist(N*N, INF);\n    dist[s_dist] = 0;\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, s_dist});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    return dist;\n}\n\nstring get_path(const Input& in, pair<int,int> s, pair<int,int> t) {\n    // Reconstruct path using simplified Dijkstra or A* since we just need one path\n    // Given N is small, Dijkstra with prev pointer is fine.\n    int N = in.N;\n    int s_idx = s.first * N + s.second;\n    int t_idx = t.first * N + t.second;\n    \n    vector<int> dist(N*N, INF);\n    vector<int> prev(N*N, -1);\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    dist[s_idx] = 0;\n    pq.push({0, s_idx});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (idx == t_idx) break;\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                prev[nidx] = k; // store direction\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    \n    string path = \"\";\n    int curr = t_idx;\n    while(curr != s_idx) {\n        int dir = prev[curr];\n        path += dc[dir];\n        // reverse direction to go back\n        int rdir;\n        if(dir==0) rdir=1; if(dir==1) rdir=0; if(dir==2) rdir=3; if(dir==3) rdir=2;\n        \n        int ci = curr / N;\n        int cj = curr % N;\n        ci += dx[rdir];\n        cj += dy[rdir];\n        curr = ci * N + cj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid solve() {\n    Input in = read_input();\n    int N = in.N;\n    \n    // 1. Identify Segments\n    vector<vector<int>> h_id(N, vector<int>(N, -1));\n    vector<vector<int>> v_id(N, vector<int>(N, -1));\n    int h_cnt = 0, v_cnt = 0;\n    \n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                if(j>0 && in.grid[i][j-1] != '#' && h_id[i][j-1] != -1) {\n                    h_id[i][j] = h_id[i][j-1];\n                } else {\n                    h_id[i][j] = h_cnt++;\n                }\n            }\n        }\n    }\n    \n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        for(int i=0; i<N; ++i) {\n            if(in.grid[i][j] != '#') {\n                if(i>0 && in.grid[i-1][j] != '#' && v_id[i-1][j] != -1) {\n                    v_id[i][j] = v_id[i-1][j];\n                } else {\n                    v_id[i][j] = v_cnt++;\n                }\n            }\n        }\n    }\n    \n    // 2. Build Bipartite Graph\n    HopcroftKarp hk(h_cnt, v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                hk.add_edge(h_id[i][j], v_id[i][j]);\n            }\n        }\n    }\n    \n    // 3. Solve Min Vertex Cover\n    hk.max_matching();\n    auto [cover_h, cover_v] = hk.get_min_vertex_cover();\n    \n    // Set of covered segments\n    vector<bool> covered_h_seg = cover_h; // rename for clarity\n    vector<bool> covered_v_seg = cover_v;\n    \n    // 4. Select Key Points\n    // We need to visit points such that every segment in the cover is visited.\n    // Strategy: Collect all intersection points of segments in the cover.\n    // Also add representative points for segments in cover that might be isolated.\n    \n    set<pair<int, int>> key_points_set;\n    vector<pair<int, int>> key_points;\n    \n    auto add_point = [&](int i, int j) {\n        if(key_points_set.count({i,j}) == 0) {\n            key_points_set.insert({i,j});\n            key_points.push_back({i,j});\n        }\n    };\n\n    // Add intersections of covered segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                int hid = h_id[i][j];\n                int vid = v_id[i][j];\n                if(covered_h_seg[hid] && covered_v_seg[vid]) {\n                    add_point(i, j);\n                }\n            }\n        }\n    }\n    \n    // Add representative points for segments that are not \"covered\" by the intersections logic\n    // (i.e., segments in cover that don't intersect any other segment in cover)\n    // A segment is satisfied if we visit at least one point on it.\n    // So we ensure for each segment in cover, there is a key point on it.\n    \n    // Find segments without intersection\n    vector<bool> h_has_intersect(h_cnt, false);\n    vector<bool> v_has_intersect(v_cnt, false);\n    for(auto p : key_points) {\n        int i = p.first, j = p.second;\n        h_has_intersect[h_id[i][j]] = true;\n        v_has_intersect[v_id[i][j]] = true;\n    }\n    \n    // For segments in cover without intersection, add their point closest to Start\n    // Or just middle point. Middle point is safer and faster.\n    vector<vector<pair<int,int>>> h_cells(h_cnt);\n    vector<vector<pair<int,int>>> v_cells(v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                h_cells[h_id[i][j]].push_back({i,j});\n                v_cells[v_id[i][j]].push_back({i,j});\n            }\n        }\n    }\n    \n    for(int i=0; i<h_cnt; ++i) {\n        if(covered_h_seg[i] && !h_has_intersect[i]) {\n            // Add middle cell\n            int mid = h_cells[i].size() / 2;\n            add_point(h_cells[i][mid].first, h_cells[i][mid].second);\n        }\n    }\n    for(int i=0; i<v_cnt; ++i) {\n        if(covered_v_seg[i] && !v_has_intersect[i]) {\n            int mid = v_cells[i].size() / 2;\n            add_point(v_cells[i][mid].first, v_cells[i][mid].second);\n        }\n    }\n    \n    // Make sure start point is in key points to build the cycle\n    add_point(in.si, in.sj);\n    \n    // 5. Compute Distances between Key Points\n    int K = key_points.size();\n    vector<vector<int>> dist(K, vector<int>(K, INF));\n    \n    // Optimization: Only run Dijkstra from each point. K should be small.\n    // Map point to index\n    map<pair<int,int>, int> pt_to_idx;\n    for(int i=0; i<K; ++i) pt_to_idx[key_points[i]] = i;\n    \n    for(int i=0; i<K; ++i) {\n        auto ds = dijkstra(in, key_points[i], key_points);\n        for(int j=0; j<K; ++j) {\n            int idx = key_points[j].first * N + key_points[j].second;\n            dist[i][j] = ds[idx];\n        }\n    }\n    \n    // 6. Construct Path\n    // Greedy insertion to ensure coverage, then 2-opt\n    \n    int start_idx = pt_to_idx[{in.si, in.sj}];\n    \n    // Current Path: [start_idx]\n    vector<int> path = {start_idx};\n    // Current coverage: segments containing S\n    vector<bool> visited_h(h_cnt, false);\n    vector<bool> visited_v(v_cnt, false);\n    \n    auto visit_pt = [&](int idx) {\n        int i = key_points[idx].first;\n        int j = key_points[idx].second;\n        visited_h[h_id[i][j]] = true;\n        visited_v[v_id[i][j]] = true;\n    };\n    visit_pt(start_idx);\n    \n    // Check if all covered segments are satisfied\n    auto all_covered = [&]() {\n        for(int i=0; i<h_cnt; ++i) if(covered_h_seg[i] && !visited_h[i]) return false;\n        for(int i=0; i<v_cnt; ++i) if(covered_v_seg[i] && !visited_v[i]) return false;\n        return true;\n    };\n    \n    // Greedy Insertion\n    while(!all_covered()) {\n        int best_k = -1;\n        int best_pos = -1;\n        int best_gain = -INF;\n        int best_cost = INF;\n        \n        for(int k=0; k<K; ++k) {\n            if(find(path.begin(), path.end(), k) != path.end()) continue;\n            \n            // Gain: number of newly covered segments\n            int i = key_points[k].first;\n            int j = key_points[k].second;\n            int gain = 0;\n            if(covered_h_seg[h_id[i][j]] && !visited_h[h_id[i][j]]) gain++;\n            if(covered_v_seg[v_id[i][j]] && !visited_v[v_id[i][j]]) gain++;\n            \n            if(gain == 0) continue;\n            \n            // Find best insertion position\n            for(int pos=0; pos<=path.size(); ++pos) {\n                int u = (pos==0) ? path.back() : path[pos-1];\n                int v = (pos==path.size()) ? path[0] : path[pos];\n                \n                // Cost change: dist[u][k] + dist[k][v] - dist[u][v]\n                int delta = dist[u][k] + dist[k][v] - dist[u][v];\n                \n                if(gain * best_cost > best_gain * delta) {\n                    best_gain = gain;\n                    best_cost = delta;\n                    best_k = k;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if(best_k == -1) {\n            // Should not happen if graph is connected and cover is valid\n            // Fallback: add any unvisited point on required segments\n            // (omitted for brevity, break to prevent infinite loop)\n            break; \n        }\n        \n        path.insert(path.begin() + best_pos, best_k);\n        visit_pt(best_k);\n    }\n    \n    // 2-opt Optimization\n    // Simple 2-opt loop\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int n = path.size();\n        for(int i=0; i<n; ++i) {\n            for(int j=i+2; j<n + (i>0 ? 1 : 0); ++j) {\n                // Edge (i, i+1) and (j, j+1) become (i, j) and (i+1, j+1)\n                int u = path[i];\n                int v = path[(i+1)%n];\n                int x = path[j%n];\n                int y = path[(j+1)%n];\n                \n                int current = dist[u][v] + dist[x][y];\n                int proposal = dist[u][x] + dist[v][y];\n                \n                if(proposal < current) {\n                    // Reverse path between i+1 and j\n                    reverse(path.begin() + (i+1)%n, path.begin() + (j%n) + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Generate Output String\n    string full_path = \"\";\n    int p_sz = path.size();\n    for(int i=0; i<p_sz; ++i) {\n        int u = path[i];\n        int v = path[(i+1)%p_sz];\n        string sub = get_path(in, key_points[u], key_points[v]);\n        full_path += sub;\n    }\n    \n    cout << full_path << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for problem parameters\nint N, M, K, R;\nvector<vector<int>> d; // Task requirements d[1..N][1..K]\nvector<vector<int>> adj; // Graph adjacency list (dependencies)\nvector<int> in_degree; // In-degree of tasks\nvector<int> task_state; // 0: pending, 1: available, 2: assigned/completed\nvector<int> start_day; // Day when task started\n\nvector<vector<double>> s; // Estimated skills s[1..M][1..K]\nvector<int> member_task; // Task assigned to member (-1 if idle)\nvector<vector<int>> rev_adj; // For processing dependents, though standard adj works if we update deg\n\n// Parameters for skill estimation\nconst double LEARNING_RATE = 0.1;\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n        }\n    }\n\n    adj.resize(N);\n    rev_adj.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        adj[u].push_back(v);\n        rev_adj[v].push_back(u); // Actually we need forward adj to update deps?\n        // We need to know which tasks unlock when task u finishes. \n        // So adj[u] should list dependents v.\n        // Input format: (u, v) means v depends on u. So u -> v.\n        // This matches the logic: when u finishes, v's pending count decreases.\n        in_degree[v]++;\n    }\n\n    // Initialize task states\n    task_state.resize(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            task_state[i] = 1;\n        }\n    }\n\n    // Initialize estimated skills\n    // Based on generation: task len ~ 10-40, member len ~ 20-60.\n    // Initialize with a safe guess like 25.\n    s.resize(M, vector<double>(K, 25.0));\n\n    member_task.resize(M, -1);\n    start_day.resize(N, -1);\n\n    int day = 0;\n    while (true) {\n        day++;\n        \n        // --- Assignment Phase ---\n        vector<pair<int, int>> assignments; // (member, task)\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n\n        // Find available tasks (state == 1)\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 1) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Greedy Assignment\n        // Try to assign idle members to available tasks\n        // Heuristic: For each member, pick the task with minimum estimated cost\n        \n        // We iterate through idle members. For each, find best task.\n        // To avoid assigning the same task to multiple members, we mark tasks as assigned (state 2).\n        \n        for (int j : idle_members) {\n            if (available_tasks.empty()) break;\n\n            int best_task = -1;\n            double min_cost = 1e9;\n\n            // Evaluate all currently available tasks for this member\n            for (int t_idx = 0; t_idx < static_cast<int>(available_tasks.size()); ++t_idx) {\n                int i = available_tasks[t_idx];\n                \n                // Calculate estimated cost w_{i,j}\n                double cost = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = d[i][k] - s[j][k];\n                    if (diff > 0) {\n                        cost += diff;\n                    }\n                }\n                // If cost is 0, it's a perfect match (expected t=1), very high priority.\n                // Add small random jitter to break ties and add exploration\n                // But deterministic is safer for reproducibility unless random is needed.\n                // Let's stick to min cost.\n\n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_task = t_idx; // index in available_tasks\n                }\n            }\n\n            if (best_task != -1) {\n                int task_id = available_tasks[best_task];\n                assignments.push_back({j + 1, task_id + 1}); // Output is 1-indexed\n                \n                member_task[j] = task_id;\n                task_state[task_id] = 2; // Mark as assigned\n                start_day[task_id] = day;\n                \n                // Remove from available list (swap with last and pop)\n                available_tasks[best_task] = available_tasks.back();\n                available_tasks.pop_back();\n            }\n        }\n\n        // --- Output ---\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n\n        // --- Input Phase ---\n        string line;\n        if (!getline(cin, line)) {\n            // Should not happen usually, but handle EOF\n            break;\n        }\n        // The input reading is a bit tricky. We need to read the line that judge provides.\n        // However, standard cin >> n might hang if not handled correctly with getline.\n        // The sample shows input format: `n f1 ... fn` or `-1`.\n        // Let's use a stringstream or direct cin >>.\n        \n        // Re-reading logic: Since we flushed, judge replies.\n        // We need to read the line. If we used cin >> for initial data, buffer might have newline?\n        // No, initial data ends with newlines. The loop logic:\n        // 1. We output.\n        // 2. We read.\n        \n        // Use getline to read the whole line for safety, then parse.\n        // But wait, we are inside a loop. We need to ensure we read the *response* to our output.\n        \n        // Let's use cin directly to parse integers.\n        int n_finished;\n        if (!(cin >> n_finished)) break;\n\n        if (n_finished == -1) {\n            break; // All tasks done or timeout\n        }\n\n        vector<int> finished_members(n_finished);\n        for (int i = 0; i < n_finished; ++i) {\n            cin >> finished_members[i];\n            finished_members[i]--; // Convert to 0-indexed\n        }\n\n        // --- Update State ---\n        for (int member_idx : finished_members) {\n            int task_idx = member_task[member_idx];\n            if (task_idx == -1) continue; // Should not happen\n\n            // Calculate duration\n            int t = day - start_day[task_idx] + 1;\n            \n            // Update Skills (Stochastic Gradient Descent)\n            // We want s such that sum(max(0, d - s)) approx t.\n            // Current estimated cost C\n            double C = 0.0;\n            vector<int> deficit_dims;\n            for (int k = 0; k < K; ++k) {\n                double diff = d[task_idx][k] - s[member_idx][k];\n                if (diff > 0) {\n                    C += diff;\n                    deficit_dims.push_back(k);\n                }\n            }\n\n            // Error = t - C. If t > C, we underestimated difficulty, skills are too high. Decrease s.\n            // If t < C, we overestimated, skills are too low. Increase s.\n            // However, if C was 0, and t > 1, we thought we were perfect but we weren't.\n            \n            double error = t - C;\n            \n            // Update skills in dimensions where we had deficit\n            // If no deficit_dims (C=0), we need to identify which dimension to decrease.\n            // If C > 0, we just adjust the deficit dimensions.\n            \n            if (!deficit_dims.empty()) {\n                // Distribute update over deficit dimensions\n                double update_per_dim = LEARNING_RATE * error / deficit_dims.size();\n                for (int k : deficit_dims) {\n                    s[member_idx][k] += update_per_dim;\n                    if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                }\n            } else {\n                // C = 0. All s >= d.\n                // If error > 0 (t > C), we need to increase cost, so decrease s.\n                // We don't know which k to decrease.\n                // Heuristic: decrease dimensions where d is largest (most likely to be bottleneck if we are just barely under).\n                // Or decrease all uniformly?\n                // Let's decrease all dimensions slightly.\n                if (error > 0) {\n                    double update_per_dim = LEARNING_RATE * error / K;\n                    for (int k = 0; k < K; ++k) {\n                        s[member_idx][k] -= update_per_dim;\n                        if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                    }\n                }\n            }\n            \n            // Mark task completed\n            // Actually task_state is 2 (assigned). We can mark it 3 or just keep 2 as 'not available'.\n            // We just need to process dependencies.\n            // We don't have a 'completed' state distinct from assigned in terms of availability,\n            // but we should know it's done. \n            // member_task[member_idx] = -1; // Mark member idle\n            \n            // Update dependencies\n            for (int dependent_task : adj[task_idx]) {\n                in_degree[dependent_task]--;\n                if (in_degree[dependent_task] == 0) {\n                    task_state[dependent_task] = 1; // Now available\n                }\n            }\n            \n            member_task[member_idx] = -1;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nconst int CENTER = 1000; // Special index for Center\n\nint dist(const vector<pair<int, int>>& points, int i, int j) {\n    if (i == CENTER) return 400 - points[j].first + 400 - points[j].second; // dist from Center\n    if (j == CENTER) return points[i].first - 400 + points[i].second - 400; // dist to Center\n    return abs(points[i].first - points[j].first) + abs(points[i].second - points[j].second);\n}\n\nint dist_center(int x, int y) {\n    return abs(400 - x) + abs(400 - y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    int N = 1000;\n    vector<Order> orders(N);\n    // We will use points index: 0..999 for Pickup, 1000..1999 for Delivery\n    // Center is 2000 (or handled separately)\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n        orders[i].id = i + 1;\n    }\n    \n    // Best solution found\n    int best_score = -1;\n    vector<int> best_route_indices;\n    vector<int> best_order_ids;\n    long long best_len = 1e18;\n    \n    // We have time limit 2.0s. Let's run a few iterations of the heuristic with different random seeds or perturbations.\n    // Given the complexity, a single good run with local search might be sufficient, but multiple restarts helps escape local optima.\n    int NUM_ITERATIONS = 5;\n    \n    for (int iter = 0; iter < NUM_ITERATIONS; ++iter) {\n        // --- 1. Construction Phase (Greedy Insertion) ---\n        vector<int> used(N, 0);\n        vector<int> route_indices; // Stores point indices (0-999 for P, 1000-1999 for D)\n        route_indices.push_back(CENTER); // Start at center\n        \n        // Shuffle orders for randomness in selection if costs are equal, or just to explore different construction paths\n        // Actually, to make the greedy deterministic but good, we shouldn't shuffle for evaluation.\n        // We iterate all orders and pick the best.\n        \n        for (int step = 0; step < 50; ++step) {\n            int best_order = -1;\n            int best_delta = 1e9;\n            int best_u = -1;\n            int best_v = -1;\n            \n            // Pre-calculate coordinates for current route to speed up dist queries\n            // But constructing points vector on the fly is easy.\n            vector<pair<int, int>> current_points;\n            for (int idx : route_indices) {\n                if (idx == CENTER) current_points.push_back({400, 400});\n                else if (idx < 1000) current_points.push_back({orders[idx].a, orders[idx].b});\n                else current_points.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            \n            // Candidate selection (top-K)\n            // To avoid O(1000 * L^2) every step, we do a coarse filter.\n            vector<pair<int, int>> candidates; // {cost, order_id}\n            \n            for (int i = 0; i < N; ++i) {\n                if (used[i]) continue;\n                \n                // Est cost: dist(Route, P_i) + dist(P_i, D_i) + dist(D_i, Route)\n                int min_dist_P = 1e9;\n                int min_pos_P = -1;\n                int min_dist_D = 1e9;\n                int min_pos_D = -1;\n\n                // Find closest point in route to P_i and D_i\n                for (size_t k = 0; k < current_points.size(); ++k) {\n                    int dP = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    if (dP < min_dist_P) {\n                        min_dist_P = dP;\n                        min_pos_P = k;\n                    }\n                    int dD = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                    if (dD < min_dist_D) {\n                        min_dist_D = dD;\n                        min_pos_D = k;\n                    }\n                }\n                \n                // internal dist\n                int d_internal = abs(orders[i].a - orders[i].c) + abs(orders[i].b - orders[i].d);\n                int est_cost = min_dist_P + d_internal + min_dist_D;\n                \n                candidates.push_back({est_cost, i});\n            }\n            \n            // Sort by estimated cost and take top 30\n            sort(candidates.begin(), candidates.end());\n            if (candidates.size() > 30) candidates.resize(30);\n            \n            // Detailed check for top candidates\n            for (auto& cand : candidates) {\n                int i = cand.second;\n                \n                // Find exact best insertion for P_i\n                // Route has L points. Indices 0 to L-1.\n                // Insert P_i at u (between u-1 and u)\n                // Insert D_i at v (between v-1 and v), where v > u+1 (since P_i takes a spot)\n                \n                int L = route_indices.size();\n                \n                // Optimize: We can precompute distances to all nodes for P_i and D_i\n                vector<int> dists_P(L), dists_D(L);\n                for (int k = 0; k < L; ++k) {\n                    dists_P[k] = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    dists_D[k] = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                }\n                \n                // Current route edges distances (sum of edges)\n                // We compute delta added - delta removed\n                \n                for (int u = 1; u < L; ++u) {\n                    // Insert P_i between u-1 and u\n                    // Removed edge: (u-1, u). Added edges: (u-1, P_i), (P_i, u)\n                    // Note: route is path, not cycle. Center is at 0.\n                    // Edge indices: (0,1), (1,2), ..., (L-2, L-1)\n                    // But we treat insert positions as 'slots' between points.\n                    // Insert at pos u means after point u-1, before point u.\n                    // Valid u: 1 to L-1. (After Center is 1, After last is L-1)\n                    // Actually, we can append? No, route must end at Center eventually?\n                    // Greedy construction builds a path that starts at Center. \n                    // The final step will add dist(last, center).\n                    // So yes, we can insert at the end (u = L).\n                    \n                    // Cost to insert P at u\n                    int edge_old_u = (u < L) ? dists_P[u-1] + dists_P[u] - (abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second)) : dists_P[u-1];\n                    // Wait, calculating delta properly:\n                    // Base edge cost E_u = dist(route[u-1], route[u]) for u < L. \n                    // For u = L, E_L = 0 (virtual edge to nothing? no, last point connects to nothing yet)\n                    \n                    int delta_P = 0;\n                    int old_u = 0;\n                    if (u < L) {\n                         old_u = abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                         delta_P = dists_P[u-1] + dists_P[u] - old_u;\n                    } else {\n                        delta_P = dists_P[u-1];\n                    }\n                    \n                    // For D_i, insert at v > u. \n                    // Since P_i is inserted, the indices shift. \n                    // Let's say we insert P at u. The new length is L+1.\n                    // D can be inserted at v from u+1 to L.\n                    // The points involved: \n                    // segment (u-1) -> P -> (u) -> ... -> (v-1) -> (v)\n                    // New: (u-1) -> P -> (u) ... -> (v-1) -> D -> (v)\n                    \n                    // Distance from P_i to next point (original u) is dists_P[u].\n                    // Distance from prev point (original v-1) to D_i is dists_D[v-1].\n                    // Distance from D_i to next point (original v) is dists_D[v].\n                    \n                    for (int v = u + 1; v <= L; ++v) {\n                        int delta_D = 0;\n                        if (v < L) {\n                            int old_v = abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            // P_i is at index u (0-based in new array, but original indices...)\n                            // Current points array indices: 0 to L-1.\n                            // P is inserted at index u-1 in the \"gap\" sense?\n                            // Let's stick to \"insert before old index k\" logic.\n                            // u is index in OLD route. P inserted before route[u].\n                            // v is index in OLD route. D inserted before route[v].\n                            // Condition: u < v.\n                            // If v == u+1, sequence is ..., route[u-1], P, D, route[u], ...\n                            // If v == L, sequence is ..., route[u-1], P, ..., route[L-1], D.\n                            \n                            int dist_P_next = (u < L) ? dists_P[u] : 0; // dist(P, route[u])\n                            \n                            // dist(route[v-1], D)\n                            int dist_prev_D = dists_D[v-1]; \n                            // dist(D, route[v])\n                            int dist_D_next = dists_D[v];\n                            \n                            // Edge broken: (route[u-1], route[u]) and (route[v-1], route[v])\n                            // Wait, if u and v are far apart, edges between u and v-1 are shifted but not broken?\n                            // The segment route[u] ... route[v-1] shifts right by 2. No internal distance change.\n                            // Only edges at insertion points change.\n                            // 1. Edge (route[u-1], route[u]) becomes (route[u-1], P) and (P, route[u]) ?\n                            // No, route[u] moves to u+1. P is at u.\n                            // So we replace (u-1, u) with (u-1, P) and (P, u).\n                            // Wait, if v = u+1. Then (u-1, u) -> (i-1, P), (P, u). \n                            // And (u, u+1) -> (D, u+1)?\n                            // Actually, simpler:\n                            // Old edges: (u-1, u) and (v-1, v).\n                            // New edges: (u-1, P), (P, v-1) -- NO.\n                            // The path is ... -> u-1 -> P -> u -> ... -> v-1 -> D -> v -> ...\n                            // Old edges broken: (u-1, u), (v-1, v).\n                            // New edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Note: if u == v-1, then (u-1, u) broken, (u, u+1) broken. \n                            // Path ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Broken: (u-1, u), (u, u+1).\n                            // New: (u-1, P), (P, D), (D, u+1).\n                            \n                            // General case:\n                            // Removed: dist(u-1, u) + dist(v-1, v).\n                            // Added: dist(u-1, P) + dist(P, u) + dist(v-1, D) + dist(D, v).\n                            \n                            int removed = 0;\n                            if (u < L) removed += abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                            else removed = 0; // u == L\n                            \n                            if (v < L) removed += abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            else removed += 0; // v == L\n\n                            int added = dists_P[u-1];\n                            if (u < L) added += dists_P[u];\n                            else added += 0;\n                            \n                            added += dists_D[v-1];\n                            if (v < L) added += dists_D[v];\n                            else added += 0;\n                            \n                            // If u == v-1 (consecutive insertions), P connects to D?\n                            // Logic: ... -> u-1 -> P -> u -> ...\n                            // If v = u+1: ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Edges added: (u-1, P), (P, D), (D, u+1).\n                            // dists_P[u] is dist(P, route[u]). \n                            // dists_D[u] is dist(D, route[u]).\n                            // My logic above:\n                            // Added: dist(u-1, P) + dist(P, u) + dist(u, D) + dist(D, u+1).\n                            // Wait, v-1 = u. So dists_D[v-1] = dist(D, route[u]).\n                            // Correct.\n                            // What if u and v are not consecutive?\n                            // ... -> u-1 -> P -> u -> u+1 -> ... -> v-1 -> D -> v -> ...\n                            // Edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Correct.\n                            \n                            // Wait, there is a case where u > v?\n                            // We loop u from 1 to L. v from u+1 to L. So u < v always.\n                            // This ensures P is before D.\n                            \n                            int delta = added - removed;\n                            if (delta < best_delta) {\n                                best_delta = delta;\n                                best_order = i;\n                                best_u = u;\n                                best_v = v;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (best_order != -1) {\n                used[best_order] = 1;\n                // Insert P\n                route_indices.insert(route_indices.begin() + best_u, best_order);\n                // Insert D (index shifted by 1 because P was inserted)\n                route_indices.insert(route_indices.begin() + best_v, best_order + 1000);\n            }\n        }\n        \n        // Add final return to center\n        // Route construction logic didn't account for return to center yet, \n        // but since we always start at Center (index 0), and we never insert before it,\n        // and we only append/insert after, the route is valid path.\n        // Total length will be calculated later.\n        \n        // --- 2. Optimization Phase (2-opt + Order Swap) ---\n        \n        // Helper to calculate total length\n        auto calc_len = [&](const vector<int>& route) -> long long {\n            long long len = 0;\n            vector<pair<int, int>> coords;\n            for (int idx : route) {\n                if (idx == CENTER) coords.push_back({400, 400});\n                else if (idx < 1000) coords.push_back({orders[idx].a, orders[idx].b});\n                else coords.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            for (size_t i = 0; i < coords.size() - 1; ++i) {\n                len += abs(coords[i].first - coords[i+1].first) + abs(coords[i].second - coords[i+1].second);\n            }\n            len += abs(coords.back().first - 400) + abs(coords.back().second - 400); // Return to center\n            return len;\n        };\n        \n        // 2-opt\n        // Route: Center, ..., last\n        // Cycle is Center -> ... -> last -> Center.\n        // Indices in `route_indices` vector: 0, 1, ..., M.\n        // 2-opt swaps edges (i, i+1) and (j, j+1) for 0 <= i < j < M.\n        // Segment [i+1, j] is reversed.\n        // Note: Center (index 0) is fixed? \n        // Actually, standard 2-opt on the cycle.\n        // The cycle is nodes 0..M where 0 is Center.\n        // Edge (M, 0) exists (return to center).\n        // If we include edge (M, 0) in swaps, we might move Center? No, Center is fixed node 0.\n        // But the edge (M, 0) can be swapped with (i, i+1).\n        // That would mean segment [i+1, M] is reversed, and 0 connects to M, i connects to 0?\n        // Standard 2-opt logic on array `route`:\n        // Edges are (0,1), (1,2), ..., (M-1, M), (M, 0).\n        // We fix node 0 (Center) at position 0.\n        // Edges (k, k+1) for k=0..M-1.\n        // Edge (M, 0) is special.\n        \n        // Let's treat the route as Center fixed at start.\n        // We can swap edges (u, u+1) and (v, v+1) where 0 <= u < v < M.\n        // New path: 0 -> ... -> u -> v -> v-1 -> ... -> u+1 -> v+1 -> ... -> M -> 0.\n        // Constraint: For every order k, P_k before D_k.\n        // Reversing segment [u+1, v].\n        \n        // Validity check:\n        // Map order id -> indices of P and D in route.\n        \n        bool improved = true;\n        while (improved && (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800)) {\n            improved = false;\n            int M = route_indices.size();\n            \n            // Precompute positions for validity check\n            // This changes every swap, so recomputing is slow.\n            // Check validity of swap locally.\n            // Segment [u+1, v] reversed.\n            // For an order with nodes at p, q:\n            // If p and q are both in [u+1, v], their relative order reverses -> INVALID (unless we check specific case, but generally P before D fails).\n            //   Wait, if P is before D in original, after reversal P is after D. So INVALID.\n            //   Exception: If we reverse a segment containing P and D, it becomes invalid.\n            //   So swap is valid ONLY IF for every order, it has 0 or 1 nodes in the segment.\n            //   If it has 1 node, the node moves, but P is still before D relative to outside nodes?\n            //   Consider P inside, D outside (after segment). Original: ... P ... D. After rev: ... (rev) ... D. P moves to end of segment. Still before D. OK.\n            //   Consider P outside (before segment), D inside. Original: P ... D. After rev: P ... (rev) ... D. D moves to start of segment. Still after P. OK.\n            //   So condition: No order has BOTH P and D in the segment.\n            \n            for (int u = 0; u < M - 1; ++u) {\n                // Optimization: only iterate v reasonably far? Standard 2-opt is O(N^2).\n                for (int v = u + 1; v < M; ++v) {\n                    // Check validity\n                    bool valid = true;\n                    // Scan segment [u+1, v]\n                    // Use a frequency array for current segment scan?\n                    // N=50, so 100 nodes. Scanning 100 orders for each pair is 10,000 checks per pair.\n                    // Pairs 5000. Total 50M. A bit high but doable in C++.\n                    // Faster: count P and D in segment.\n                    vector<char> in_segment(N, 0);\n                    for (int k = u + 1; k <= v; ++k) {\n                        int idx = route_indices[k];\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (idx < 1000) in_segment[oid] |= 1; // P\n                        else in_segment[oid] |= 2; // D\n                        if (in_segment[oid] == 3) {\n                            valid = false;\n                            break;\n                        }\n                    }\n                    if (!valid) continue;\n                    \n                    // Calculate delta\n                    // Edges removed: (u, u+1) and (v, v+1)\n                    // Edges added: (u, v) and (u+1, v+1)\n                    // Note: v < M, so v+1 exists.\n                    // Coordinates\n                    auto get_pt = [&](int idx) -> pair<int,int> {\n                        if (idx == CENTER) return {400, 400};\n                        if (idx < 1000) return {orders[idx].a, orders[idx].b};\n                        return {orders[idx-1000].c, orders[idx-1000].d};\n                    };\n\n                    auto p_u = get_pt(route_indices[u]);\n                    auto p_u1 = get_pt(route_indices[u+1]);\n                    auto p_v = get_pt(route_indices[v]);\n                    auto p_v1 = get_pt(route_indices[v+1]);\n                    \n                    long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                      + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                    long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                     + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                    \n                    if (added < removed) {\n                        // Perform swap\n                        reverse(route_indices.begin() + u + 1, route_indices.begin() + v + 1);\n                        improved = true;\n                        // Reset search? Or continue?\n                        // With found improvement, resetting loops is safer to find new structure.\n                        // But breaking and restarting outer loop is standard.\n                        goto next_opt_pass; \n                    }\n                }\n            }\n            next_opt_pass:;\n        }\n        \n        // Local Search: Swap one order\n        // Try removing an order and inserting another\n        for (int step = 0; step < 5; ++step) {\n            if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 1900) break;\n            \n            // Current route length\n            long long current_len = calc_len(route_indices);\n            \n            // Try remove each order\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) continue;\n                \n                // Remove order i\n                auto it_p = find(route_indices.begin(), route_indices.end(), i);\n                auto it_d = find(route_indices.begin(), route_indices.end(), i + 1000);\n                if (it_p == route_indices.end() || it_d == route_indices.end()) continue;\n                \n                int pos_p = distance(route_indices.begin(), it_p);\n                int pos_d = distance(route_indices.begin(), it_d);\n                \n                // Indices: pos_p < pos_d\n                // Remove D then P to keep indices correct\n                route_indices.erase(it_d);\n                route_indices.erase(route_indices.begin() + pos_p);\n                \n                // Try insert all j not used\n                bool found_better = false;\n                for (int j = 0; j < N; ++j) {\n                    if (used[j] || j == i) continue;\n                    \n                    // Try insert P_j and D_j optimally\n                    // Similar to construction but smaller\n                    int L = route_indices.size();\n                    \n                    // We need to calculate insertion cost\n                    // This is O(L^2) per j. N ~ 1000. L ~ 100. 1000 * 10000 = 10M.\n                    // Plus the loop over i (50). Total 500M. Too slow.\n                    // Optimization: Only try a subset of j?\n                    // Or only try replacing with \"good\" candidates?\n                    // Or break early.\n                    \n                    // Just pick the best j to insert.\n                    // We can check the \"approximate\" cost of j first.\n                    // dist(route, P_j) + dist(P_j, D_j) + dist(D_j, route)\n                    \n                    // Let's limit this local search.\n                    // Instead of iterating all i, iterate random i.\n                    // Instead of iterating all j, iterate top 50 candidates.\n                }\n                \n                // Revert if not better\n                route_indices.insert(route_indices.begin() + pos_p, i);\n                route_indices.insert(route_indices.begin() + pos_d, i + 1000);\n            }\n        }\n\n        // Calculate final length for this iteration\n        long long current_len = calc_len(route_indices);\n        if (current_len < best_len) {\n            best_len = current_len;\n            best_route_indices = route_indices;\n            // best_order_ids not needed if we reconstruct from route_indices\n        }\n    }\n    \n    // --- Output ---\n    // Extract order IDs from best_route_indices\n    vector<int> final_orders;\n    set<int> seen;\n    for (int idx : best_route_indices) {\n        if (idx == CENTER) continue;\n        int oid = (idx < 1000) ? idx : idx - 1000;\n        if (seen.find(oid) == seen.end()) {\n            final_orders.push_back(oid + 1);\n            seen.insert(oid);\n        }\n    }\n    // final_orders should be 50.\n    // Ensure exactly 50? My logic inserts exactly 50.\n    \n    // Output format\n    // m r1 ... rm\n    // n x1 y1 ... xn yn\n    \n    cout << 50;\n    for (int oid : final_orders) cout << \" \" << oid;\n    cout << \"\\n\";\n    \n    cout << best_route_indices.size() + 1; // +1 for final Center\n    for (int idx : best_route_indices) {\n        int x, y;\n        if (idx == CENTER) { x = 400; y = 400; }\n        else if (idx < 1000) { x = orders[idx].a; y = orders[idx].b; }\n        else { x = orders[idx-1000].c; y = orders[idx-1000].d; }\n        cout << \" \" << x << \" \" << y;\n    }\n    // Final center\n    cout << \" \" << 400 << \" \" << 400 << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct DSU {\n    vector<int> parent;\n    int components;\n\n    DSU(int n) : parent(n), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        components--;\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Fixed constraints\n    int N = 400;\n    int M = 1995;\n\n    vector<pair<int, int>> points(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = points[edges[i].u].first - points[edges[i].v].first;\n        int dy = points[edges[i].u].second - points[edges[i].v].second;\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        edges[i].d = (int)round(dist);\n    }\n\n    DSU dsu(N);\n    int taken = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        // If we already have a spanning tree, we don't need more edges (though we should output 0)\n        // The problem statement implies we must output 0 or 1 for all inputs.\n        // But if taken == N-1, we reject all remaining to save cost (no need to add cycles).\n        if (taken == N - 1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int need = dsu.components - 1;\n        \n        // Collect distances of remaining useful edges\n        vector<int> candidate_ds;\n        candidate_ds.reserve(M - i - 1);\n        \n        for (int j = i + 1; j < M; ++j) {\n            // Check if edge j connects different components\n            if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                candidate_ds.push_back(edges[j].d);\n            }\n        }\n\n        // If we don't have enough candidates in the future, we must take the current one\n        if ((int)candidate_ds.size() < need) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n        } else {\n            // Find the distance of the 'need'-th shortest edge in the future candidates\n            // This represents the \"worst\" edge we expect to take in an optimal future scenario\n            sort(candidate_ds.begin(), candidate_ds.end());\n            int d_ref = candidate_ds[need - 1];\n            \n            // Heuristic threshold: take current edge if its cost l is <= 2 * d_ref\n            // 2 * d_ref is the expected cost of an edge with distance d_ref\n            // This is a \"secretary problem\" style threshold.\n            int threshold = 2 * d_ref;\n\n            if (l <= threshold) {\n                cout << 1 << endl;\n                dsu.unite(u, v);\n                taken++;\n            } else {\n                cout << 0 << endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multi_array.hpp>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int TURNS = 300;\nconstexpr int DX[4] = {0, 0, 1, -1};\nconstexpr int DY[4] = {1, -1, 0, 0};\nconstexpr char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\nconstexpr char BLOCK_CHAR[4] = {'r', 'l', 'd', 'u'}; // Action to block (x+dx, y+dy)\n\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int x, int y) : x(x), y(y) {}\n    bool operator==(const Point& p) const { return x == p.x && y == p.y; }\n    int dist(const Point& p) const { return abs(x - p.x) + abs(y - p.y); }\n};\n\n// Global State\nint N, M;\nvector<Point> pets;\nvector<Point> humans;\nvector<int> pet_types; \n// grid[x][y] : true if impassable (wall)\n// Note: walls are built on squares. Humans/Pets can be on squares that are passable.\n// Once a wall is built on (x,y), it becomes impassable.\n// Humans and Pets can be on the same square? \"each square can contain any number of humans and pets.\"\n// So grid state is independent of entity positions, except for the \"cannot build adjacent to pet\" rule.\nvector<vector<bool>> grid; \n\n// Input parsing\nvoid read_init() {\n    cin >> N;\n    pets.resize(N);\n    pet_types.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> pet_types[i];\n        // Convert to 0-based for internal logic if needed, but problem is 1-based\n        pets[i].x--; pets[i].y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    grid.assign(H, vector<bool>(W, false));\n}\n\n// Read pet movements for one turn\n// pet_moves[i] is a string of characters like \"U\", \"R.\", etc.\nvoid read_turn(vector<string>& pet_moves) {\n    pet_moves.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_moves[i];\n    }\n}\n\n// Apply pet movements\nvoid apply_moves(const vector<string>& pet_moves) {\n    for (int i = 0; i < N; ++i) {\n        int cx = pets[i].x;\n        int cy = pets[i].y;\n        for (char c : pet_moves[i]) {\n            int dir = -1;\n            if (c == 'U') dir = 3;\n            else if (c == 'D') dir = 2;\n            else if (c == 'L') dir = 1;\n            else if (c == 'R') dir = 0;\n            \n            if (dir != -1) {\n                int nx = cx + DX[dir];\n                int ny = cy + DY[dir];\n                // Pets move randomly but logically. \n                // The problem says they move to passable squares chosen randomly.\n                // Assuming the server provides valid moves that respect grid bounds and walls.\n                // We just update coordinates.\n                cx = nx;\n                cy = ny;\n            }\n        }\n        pets[i].x = cx;\n        pets[i].y = cy;\n    }\n}\n\n// Helper to check bounds\nbool inside(int x, int y) {\n    return 0 <= x && x < H && 0 <= y && y < W;\n}\n\n// Helper to check if a cell is buildable (wall action)\n// Cannot build if:\n// 1. The cell contains a pet or human at the START of the turn.\n// 2. The cell is already a wall.\n// 3. An adjacent cell contains a pet.\nbool is_buildable(int x, int y, const vector<Point>& current_pets, const vector<Point>& current_humans) {\n    if (!inside(x, y)) return false;\n    if (grid[x][y]) return false; // Already impassable\n    \n    // Check if pet or human is on (x, y)\n    for (const auto& p : current_pets) {\n        if (p.x == x && p.y == y) return false;\n    }\n    for (const auto& h : current_humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    \n    // Check if adjacent cell contains a pet\n    for (int i = 0; i < 4; ++i) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (!inside(nx, ny)) continue;\n        for (const auto& p : current_pets) {\n            if (p.x == nx && p.y == ny) return false;\n        }\n    }\n    return true;\n}\n\n// Strategy: Secure a large rectangle with 0 pets.\nstruct Rect {\n    int r1, r2, c1, c2;\n    int area;\n};\n\n// Find best rectangle to secure\n// Criteria: \n// 1. Contains 0 pets currently.\n// 2. Maximize Area.\n// 3. Minimize Wall Length (perimeter).\n// 4. Maximize distance from pets to wall (safety).\nRect find_best_rectangle() {\n    // 2D prefix sum for pet counts\n    vector<vector<int>> ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int cnt = 0;\n            for (const auto& p : pets) {\n                if (p.x == i && p.y == j) cnt++;\n            }\n            ps[i+1][j+1] = ps[i][j+1] + ps[i+1][j] - ps[i][j] + cnt;\n        }\n    }\n    \n    auto get_pet_count = [&](int r1, int c1, int r2, int c2) {\n        return ps[r2+1][c2+1] - ps[r1][c2+1] - ps[r2+1][c1] + ps[r1][c1];\n    };\n\n    double best_score = -1e9;\n    Rect best_r = {0, H-1, 0, W-1, 0};\n\n    // Iterate over all rectangles\n    // To limit search, maybe only consider those touching boundary? \n    // No, a central island is also valid, though walls are expensive.\n    // Let's iterate all.\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (get_pet_count(r1, c1, r2, c2) > 0) continue;\n                    \n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    \n                    // Calculate required wall length\n                    // Walls needed on sides that are not touching map boundary\n                    int wall_len = 0;\n                    if (r1 > 0) wall_len += (c2 - c1 + 1);\n                    if (r2 < H - 1) wall_len += (c2 - c1 + 1);\n                    if (c1 > 0) wall_len += (r2 - r1 + 1);\n                    if (c2 < W - 1) wall_len += (r2 - r1 + 1);\n                    \n                    // Safety: min distance of any pet to the rectangle boundary\n                    // If a pet is very close, we can't build there easily.\n                    // This is a heuristic.\n                    int min_dist = H + W;\n                    for (const auto& p : pets) {\n                        // If inside, skip (already filtered)\n                        // Distance to rectangle\n                        int dx = max({r1 - p.x, 0, p.x - r2});\n                        int dy = max({c1 - p.y, 0, p.y - c2});\n                        int d = dx + dy;\n                        // If pet is outside, d >= 1\n                        if (d < min_dist) min_dist = d;\n                    }\n                    \n                    // We cannot build adjacent to pet. So we need buffer of 1.\n                    // If min_dist < 2, the wall is adjacent to pet.\n                    // Actually, if min_dist == 1, pet is adjacent to rect. \n                    // We need to build wall outside rect. So dist to wall is min_dist - 1.\n                    // If dist_to_wall == 0 (pet touching rect), we CANNOT build the wall on that side.\n                    // So such rectangles are dangerous.\n                    \n                    // Score: Area - Cost\n                    // Cost = Wall_Length * K1 + (if unsafe) * LargePenalty\n                    double score = (double)area;\n                    \n                    // Penalty for walls\n                    score -= wall_len * 0.5; // Tunable factor\n                    \n                    // Penalty for low safety margin\n                    // Buffer needed is 1.\n                    // If pet is touching boundary (min_dist=1), we are blocked.\n                    if (min_dist == 0) { /* Should not happen since count=0 */ }\n                    else if (min_dist == 1) {\n                        score -= 100; // Heavily penalize touching pets\n                    } else {\n                        // Slight penalty for being close\n                        score -= (5.0 / min_dist);\n                    }\n                    \n                    // Bonus for containing humans? No, we can move them in.\n                    // Penalty for humans being far away?\n                    // Sum of distances from humans to rect.\n                    int total_dist = 0;\n                    for (const auto& h : humans) {\n                        // Closest point in rect\n                        int cx = max(r1, min(h.x, r2));\n                        int cy = max(c1, min(h.y, c2));\n                        total_dist += abs(h.x - cx) + abs(h.y - cy);\n                    }\n                    score -= total_dist * 0.05;\n\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = {r1, r2, c1, c2, area};\n                    }\n                }\n            }\n        }\n    }\n    return best_r;\n}\n\n// Action Generation\nvector<char> generate_actions(Rect& target_rect, vector<Point>& current_humans, int& phase, vector<Point>& wall_tasks, int turn_cnt) {\n    vector<char> actions(M, '.');\n    \n    // Wall cells needed to seal the rectangle\n    vector<Point> needed_walls;\n    // r1-1, r2+1, c1-1, c2+1\n    if (target_rect.r1 > 0) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r1 - 1, c);\n    if (target_rect.r2 < H - 1) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r2 + 1, c);\n    if (target_rect.c1 > 0) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c1 - 1);\n    if (target_rect.c2 < W - 1) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c2 + 1);\n    \n    // Remove already built walls\n    needed_walls.erase(remove_if(needed_walls.begin(), needed_walls.end(), \n        [&](const Point& p){ return grid[p.x][p.y]; }), \n        needed_walls.end());\n        \n    // Phase 1: Move humans into the rectangle\n    if (phase == 1) {\n        bool all_in = true;\n        for (int i = 0; i < M; ++i) {\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            if (target_rect.r1 <= hx && hx <= target_rect.r2 && target_rect.c1 <= hy && hy <= target_rect.c2) {\n                actions[i] = '.';\n                continue;\n            }\n            all_in = false;\n            \n            // Move towards closest point in rect\n            int tx = max(target_rect.r1, min(hx, target_rect.r2));\n            int ty = max(target_rect.c1, min(hy, target_rect.c2));\n            \n            // BFS to find shortest path to (tx, ty) or any cell in rect?\n            // Simple greedy: reduce Manhattan distance\n            int best_d = abs(hx - tx) + abs(hy - ty);\n            int best_dir = -1;\n            \n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + DX[d];\n                int ny = hy + DY[d];\n                if (!inside(nx, ny)) continue;\n                if (grid[nx][ny]) continue; // Can't move into wall\n                \n                // Check if (nx, ny) is in rect (good)\n                bool in_rect = (target_rect.r1 <= nx && nx <= target_rect.r2 && target_rect.c1 <= ny && ny <= target_rect.c2);\n                int d_score = abs(nx - tx) + abs(ny - ty);\n                if (in_rect) d_score = -1000; // Priority to enter\n                \n                if (d_score < best_d) {\n                    best_d = d_score;\n                    best_dir = d;\n                }\n            }\n            if (best_dir != -1) {\n                actions[i] = DIR_CHAR[best_dir];\n                current_humans[i].x += DX[best_dir];\n                current_humans[i].y += DY[best_dir];\n            }\n        }\n        \n        if (all_in) {\n            phase = 2;\n            // Assign wall tasks\n            wall_tasks = needed_walls;\n            // Shuffle to distribute work randomly? Or keep sorted?\n            // Keep simple.\n        }\n    } \n    // Phase 2: Build walls\n    else if (phase == 2) {\n        if (wall_tasks.empty()) {\n            phase = 3;\n            return actions;\n        }\n        \n        // Greedy assignment: each human picks closest task\n        // To avoid conflict, we process humans in order of distance to tasks? \n        // Or simply assign static chunks? \n        // Static chunks are better for consistency.\n        \n        // Let's use a persistent assignment.\n        // If no assignment yet, create one.\n        static vector<int> assignment(M, -1);\n        static bool assigned = false;\n        \n        if (!assigned || wall_tasks.size() != (unsigned)(assignment.size())) {\n             // Simple Round Robin assignment based on human index\n             assignment.clear();\n             assignment.resize(M, -1);\n             for (size_t i = 0; i < wall_tasks.size(); ++i) {\n                 assignment[i % M] = i;\n             }\n             assigned = true;\n        }\n        \n        // Execute\n        for (int i = 0; i < M; ++i) {\n            int task_idx = assignment[i];\n            if (task_idx == -1 || task_idx >= (int)wall_tasks.size()) {\n                actions[i] = '.';\n                continue;\n            }\n            \n            Point target = wall_tasks[task_idx];\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            // If adjacent, try build\n            bool adj = false;\n            int build_dir = -1;\n            for (int d = 0; d < 4; ++d) {\n                if (hx + DX[d] == target.x && hy + DY[d] == target.y) {\n                    adj = true;\n                    build_dir = d;\n                    break;\n                }\n            }\n            \n            if (adj) {\n                // Check if buildable\n                // Need to check adjacency to pets at the START of this turn\n                // We have `pets` vector which is already updated for this turn?\n                // No, `pets` in global state is updated at the START of the loop in main.\n                // So `pets` holds positions at the START of the turn.\n                // We check buildability against `pets`.\n                \n                // is_buildable checks `grid` and `pets` and `current_humans`\n                // But `current_humans` is being modified. We should use previous pos? \n                // Rule: \"cannot choose a square that contains pets or humans at the start of this turn\"\n                // So we check against `humans` (initial state of turn).\n                // `current_humans` is a copy we modify to simulate moves. \n                // We need the actual start positions.\n                // Let's pass `humans` (the vector holding start-of-turn pos) to is_buildable?\n                // Or just check `current_humans[i]` before moving? No, that's wrong for other humans.\n                // Let's assume `humans` is not modified yet.\n                // Wait, I modify `current_humans` in place.\n                // So at the start of generate_actions, `current_humans` IS the start position.\n                // Good.\n                \n                if (is_buildable(target.x, target.y, pets, current_humans)) {\n                    actions[i] = BLOCK_CHAR[build_dir];\n                    grid[target.x][target.y] = true; // Mark as built immediately for logic?\n                    // Note: The problem says \"perform each action simultaneously\".\n                    // However, for our planning in the next turn, we update grid.\n                    // If two humans build the same wall, the second one does nothing (rule: \"If you choose a square that is already impassable, nothing happens\").\n                    // But we shouldn't assign two humans to the same task ideally.\n                    // With round robin, tasks are distinct.\n                    \n                    // Remove task\n                    wall_tasks.erase(wall_tasks.begin() + task_idx);\n                    // Update assignments?\n                    // Shift indices down for those > task_idx\n                    for (int k = 0; k < M; ++k) {\n                        if (assignment[k] > task_idx) assignment[k]--;\n                    }\n                } else {\n                    actions[i] = '.'; // Cannot build now\n                }\n            } else {\n                // Move towards target\n                // BFS or simple Manhattan\n                int best_d = abs(hx - target.x) + abs(hy - target.y);\n                int best_dir = -1;\n                \n                for (int d = 0; d < 4; ++d) {\n                    int nx = hx + DX[d];\n                    int ny = hy + DY[d];\n                    if (!inside(nx, ny)) continue;\n                    if (grid[nx][ny]) continue;\n                    if (nx == target.x && ny == target.y) continue; // Moving onto the wall square? No, can only build adjacent. \n                    // Actually, can we move onto a square that will be a wall? \n                    // \"It is not possible to move to a square that becomes impassable by another person's action in this turn.\"\n                    // We are the person. If we move to target, we can't build it (must be adjacent).\n                    // So we shouldn't move onto target.\n                    \n                    int d_score = abs(nx - target.x) + abs(ny - target.y);\n                    if (d_score < best_d) {\n                        best_d = d_score;\n                        best_dir = d;\n                    }\n                }\n                if (best_dir != -1) {\n                    actions[i] = DIR_CHAR[best_dir];\n                    current_humans[i].x += DX[best_dir];\n                    current_humans[i].y += DY[best_dir];\n                } else {\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        if (wall_tasks.empty()) phase = 3;\n    }\n    // Phase 3: Done\n    else {\n        for (int i = 0; i < M; ++i) actions[i] = '.';\n    }\n    \n    return actions;\n}\n\nvoid solve() {\n    read_init();\n    \n    Rect target_rect;\n    int phase = 1; // 1: Enter, 2: Build, 3: Done\n    vector<Point> wall_tasks;\n    \n    for (int t = 0; t < TURNS; ++t) {\n        // Read Pet Moves\n        vector<string> pet_moves;\n        read_turn(pet_moves);\n        \n        // Update Pet Positions\n        apply_moves(pet_moves);\n        \n        // Check if plan is still valid\n        bool valid = true;\n        if (phase == 3) {\n            // Just stay put\n            cout << string(M, '.') << endl;\n            continue;\n        }\n        \n        // Check if pets entered target rect\n        for (const auto& p : pets) {\n            if (target_rect.r1 <= p.x && p.x <= target_rect.r2 &&\n                target_rect.c1 <= p.y && p.y <= target_rect.c2) {\n                valid = false;\n                break;\n            }\n        }\n        \n        if (!valid || phase == 0) {\n            // Re-plan\n            target_rect = find_best_rectangle();\n            phase = 1;\n            wall_tasks.clear();\n            // cout << \"# Turn \" << t << \" Replanning. Rect: \" \n            //      << target_rect.r1 << \" \" << target_rect.r2 << \" \"\n            //      << target_rect.c1 << \" \" << target_rect.c2 << \" Area: \" << target_rect.area << endl;\n        }\n        \n        // Generate Actions\n        // We need a copy of human positions to simulate moves for next turn logic?\n        // No, the problem state updates based on our output.\n        // We just need to update our internal `humans` state for the next iteration's `is_buildable` check.\n        // So `generate_actions` should update `humans`.\n        // But `is_buildable` needs \"start of turn\" positions.\n        // So we pass `humans` (which holds start pos) and update it at the end.\n        \n        vector<char> actions = generate_actions(target_rect, humans, phase, wall_tasks, t);\n        \n        // Output\n        string s(actions.begin(), actions.end());\n        cout << s << endl;\n        cout.flush();\n    }\n}\n\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n    solve();\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Global configuration\nconst int H = 20;\nconst int W = 20;\nconst int MAX_LEN = 200;\nconst double INF = 1e9;\n\n// Directions\nconst int DY[4] = {-1, 1, 0, 0};\nconst int DX[4] = {0, 0, -1, 1};\nconst char DC[4] = {'U', 'D', 'L', 'R'};\n\n// Input\nint si, sj, ti, tj;\ndouble p;\nvector<string> h_grid(H);\nvector<string> v_grid(H-1);\n\n// Helper to check wall\n// dir: 0=U, 1=D, 2=L, 3=R\ninline bool is_wall(int y, int x, int dir) {\n    if (dir == 0) { // U\n        if (y == 0) return true;\n        return v_grid[y-1][x] == '1';\n    } else if (dir == 1) { // D\n        if (y == H-1) return true;\n        return v_grid[y][x] == '1';\n    } else if (dir == 2) { // L\n        if (x == 0) return true;\n        return h_grid[y][x-1] == '1';\n    } else { // R\n        if (x == W-1) return true;\n        return h_grid[y][x] == '1';\n    }\n    return false;\n}\n\n// Buffers for calculation to avoid allocation overhead\nvector<vector<double>> prob_buff1(H, vector<double>(W, 0.0));\nvector<vector<double>> prob_buff2(H, vector<double>(W, 0.0));\n\n// Function to calculate expected score of a sequence\n// Uses DP on probability distribution\ndouble calculate_score(const string& s) {\n    // Initialize buffers\n    for(int i=0; i<H; ++i) fill(prob_buff1[i].begin(), prob_buff1[i].end(), 0.0);\n    \n    prob_buff1[si][sj] = 1.0;\n    double expected_score = 0.0;\n    int L = s.length();\n\n    auto& curr_prob = prob_buff1;\n    auto& next_prob = prob_buff2;\n\n    for (int t = 0; t < L; ++t) {\n        // Reset next_prob\n        for(int i=0; i<H; ++i) fill(next_prob[i].begin(), next_prob[i].end(), 0.0);\n\n        int dir_idx = -1;\n        if (s[t] == 'U') dir_idx = 0;\n        else if (s[t] == 'D') dir_idx = 1;\n        else if (s[t] == 'L') dir_idx = 2;\n        else if (s[t] == 'R') dir_idx = 3;\n\n        // If invalid char (should not happen), just stay\n        if (dir_idx == -1) {\n            // Treat as staying, effectively just p stays, 1-p stays (if wall) or moves\n            // but since char is invalid, we assume it maps to nothing or self-loop? \n            // Problem guarantees UDLR.\n        }\n\n        double ny_off = DY[dir_idx];\n        double nx_off = DX[dir_idx];\n\n        for (int y = 0; y < H; ++y) {\n            for (int x = 0; x < W; ++x) {\n                double cur_p = curr_prob[y][x];\n                if (cur_p == 0.0) continue;\n\n                // Probability of forgetting: stay in place\n                double p_forget = cur_p * p;\n                next_prob[y][x] += p_forget;\n\n                // Probability of trying to move\n                double p_move = cur_p * (1.0 - p);\n                \n                int nx = x + (int)nx_off;\n                int ny = y + (int)ny_off;\n\n                // Check wall collision\n                if (is_wall(y, x, dir_idx)) {\n                    next_prob[y][x] += p_move;\n                } else {\n                    if (ny == ti && nx == tj) {\n                        // Reached goal\n                        expected_score += p_move * (401.0 - (t + 1));\n                        // Mass absorbed into score, not propagated to next state\n                    } else {\n                        next_prob[ny][nx] += p_move;\n                    }\n                }\n            }\n        }\n        swap(curr_prob, next_prob);\n    }\n    return expected_score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < H; ++i) cin >> h_grid[i];\n    for (int i = 0; i < H-1; ++i) cin >> v_grid[i];\n\n    // 1. Find shortest path (A*)\n    // priority_queue: (estimated_cost, y, x)\n    using Node = pair<int, pair<int, int>>;\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    vector<vector<int>> dist(H, vector<int>(W, INF));\n    vector<vector<int>> parent(H, vector<int>(W, -1));\n    \n    auto heuristic = [&](int y, int x) {\n        return abs(y - ti) + abs(x - tj);\n    };\n\n    dist[si][sj] = 0;\n    pq.push({heuristic(si, sj), {si, sj}});\n\n    while (!pq.empty()) {\n        auto curr = pq.top();\n        pq.pop();\n        int y = curr.second.first;\n        int x = curr.second.second;\n        int cost = dist[y][x];\n\n        if (y == ti && x == tj) break;\n        if (cost > dist[y][x]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int ny = y + DY[i];\n            int nx = x + DX[i];\n            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;\n            if (is_wall(y, x, i)) continue;\n            \n            if (dist[ny][nx] > cost + 1) {\n                dist[ny][nx] = cost + 1;\n                parent[ny][nx] = i;\n                pq.push({dist[ny][nx] + heuristic(ny, nx), {ny, nx}});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cy = ti, cx = tj;\n    while (cy != si || cx != sj) {\n        int dir = parent[cy][cx];\n        path.push_back(DC[dir]);\n        cy -= DY[dir];\n        cx -= DX[dir];\n    }\n    reverse(path.begin(), path.end());\n    \n    // 2. Build initial robust string\n    // Strategy: Repeat each character in the path K times\n    // K depends on p. Higher p -> Higher K.\n    int path_len = path.length();\n    string ans = \"\";\n    \n    // Calculate optimal K\n    // Empirically chosen thresholds\n    int K = 1;\n    if (p > 0.15) K = 2;\n    if (p > 0.35) K = 3;\n    if (p > 0.45) K = 4;\n    \n    // Ensure K * path_len fits reasonably, or reduce K if too long\n    // We want to repeat the sequence to allow multiple attempts.\n    // A single run of robust path should consume most of the length or leave room for repeats.\n    // If K*path_len is very small, we can repeat it many times.\n    // If K*path_len is close to 200, we run it once.\n    \n    // Cap K such that we can at least run the path once\n    while (K > 1 && K * path_len > 200) {\n        K--;\n    }\n\n    string robust_seg = \"\";\n    for (char c : path) {\n        robust_seg += string(K, c);\n    }\n    \n    // Fill ans by repeating the robust segment\n    while ((int)ans.size() < 200) {\n        ans += robust_seg;\n    }\n    ans.resize(200);\n\n    // 3. Local Search (Hill Climbing)\n    auto start_time = chrono::high_resolution_clock::now();\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis_idx(0, 199);\n    uniform_int_distribution<> dis_dir(0, 3);\n\n    double current_score = calculate_score(ans);\n    string best_ans = ans;\n    double best_score = current_score;\n    \n    const int time_limit_ms = 1900;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > time_limit_ms) break;\n\n        // Mutation 1: Change a random character\n        int idx = dis_idx(gen);\n        int new_dir = dis_dir(gen);\n        char original = ans[idx];\n        char new_char = DC[new_dir];\n        \n        if (original != new_char) {\n            ans[idx] = new_char;\n            double new_score = calculate_score(ans);\n            \n            if (new_score > current_score) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_ans = ans;\n                }\n            } else {\n                ans[idx] = original; // Revert\n            }\n        }\n\n        // Mutation 2: Swap two random characters (less frequent or just mixed in)\n        // To keep it fast, we can just do change mutations mostly.\n        // Let's try a swap occasionally\n        if (dis_idx(gen) % 10 == 0) {\n             int idx2 = dis_idx(gen);\n             if (idx != idx2) {\n                 swap(ans[idx], ans[idx2]);\n                 double new_score = calculate_score(ans);\n                 if (new_score > current_score) {\n                     current_score = new_score;\n                     if (new_score > best_score) {\n                         best_score = new_score;\n                         best_ans = ans;\n                     }\n                 } else {\n                     swap(ans[idx], ans[idx2]); // Revert\n                 }\n             }\n        }\n    }\n\n    cout << best_ans << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <ctime>\n#include <cassert>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\nconst int N = H * W;\n\n// Directions: 0:Up, 1:Right, 2:Down, 3:Left\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\n\n// to[type][in_dir] = out_dir\n// in_dir: direction from which the train enters the tile\n// out_dir: direction to which the train exits the tile\n// -1 if no connection\nint to[8][4] = {\n    {1, 0, -1, -1}, // 0: TR\n    {-1, 2, 1, -1}, // 1: RD\n    {-1, -1, 3, 2}, // 2: DL\n    {0, -1, -1, 3}, // 3: LU\n    {1, 0, 3, 2},   // 4: TR & DL\n    {3, 2, 1, 0},   // 5: RD & LU\n    {2, -1, 0, -1}, // 6: Vert\n    {-1, 3, -1, 1}  // 7: Horz\n};\n\nint grid[H][W]; // Initial types\nint rot[H][W];  // Current rotations\nint state[H][W]; // Effective types after rotation\nint vis[H][W][4]; // Visited stamps\nint stamp = 0;\n\nmt19937 rng(123456789);\n\n// Precomputed effective types\nint effective_type[8][4];\n\nvoid init_effective_types() {\n    for (int base = 0; base < 8; ++base) {\n        for (int r = 0; r < 4; ++r) {\n            if (base <= 3) effective_type[base][r] = (base + r) % 4;\n            else if (base == 4 || base == 5) effective_type[base][r] = ((base + r) % 2 == 0) ? 4 : 5;\n            else effective_type[base][r] = ((base + r) % 2 == 0) ? 6 : 7;\n        }\n    }\n}\n\nlong long calc_score() {\n    stamp++;\n    vector<int> loops;\n    \n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int t = state[i][j];\n            for (int d = 0; d < 4; ++d) {\n                if (vis[i][j][d] == stamp) continue;\n                \n                int nd = to[t][d];\n                if (nd == -1) continue;\n                \n                // Start walk\n                int cr = i, cc = j, cd = d;\n                int len = 0;\n                bool is_loop = true;\n                vis[cr][cc][cd] = stamp;\n                \n                while (true) {\n                    int nr = cr + dr[nd];\n                    int nc = cc + dc[nd];\n                    len++;\n                    \n                    if (nr < 0 || nr >= H || nc < 0 || nc >= W) {\n                        is_loop = false;\n                        break;\n                    }\n                    \n                    int next_cd = (nd + 2) % 4;\n                    if (vis[nr][nc][next_cd] == stamp) {\n                        if (nr == i && nc == j && next_cd == d) {\n                            break;\n                        } else {\n                            is_loop = false;\n                            break;\n                        }\n                    }\n                    \n                    vis[nr][nc][next_cd] = stamp;\n                    cr = nr; cc = nc; cd = next_cd;\n                    \n                    int next_nd = to[state[cr][cc]][cd];\n                    if (next_nd == -1) {\n                        is_loop = false;\n                        break;\n                    }\n                    nd = next_nd;\n                }\n                \n                if (is_loop) {\n                    loops.push_back(len);\n                }\n            }\n        }\n    }\n    \n    if (loops.empty()) return 0;\n    sort(loops.begin(), loops.end());\n    \n    // Remove duplicates (since each loop is traversed in both directions)\n    // loops contains [L1, L1, L2, L2, ...]\n    vector<int> uniq_loops;\n    uniq_loops.push_back(loops[0]);\n    for (size_t k = 1; k < loops.size(); ++k) {\n        if (loops[k] != loops[k-1]) {\n            uniq_loops.push_back(loops[k]);\n        }\n    }\n    \n    if (uniq_loops.size() < 2) return 0;\n    \n    int L1 = uniq_loops.back();\n    int L2 = uniq_loops[uniq_loops.size() - 2];\n    \n    return (long long)L1 * L2;\n}\n\nint main() {\n    init_effective_types();\n    \n    // Input\n    for (int i = 0; i < H; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < W; ++j) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Initialize rotations (random)\n    // Try to minimize boundary exits for better start\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            rot[i][j] = rng() % 4;\n            state[i][j] = effective_type[grid[i][j]][rot[i][j]];\n        }\n    }\n    \n    long long current_score = calc_score();\n    long long best_score = current_score;\n    int best_rot[H][W];\n    for(int i=0; i<H; ++i) \n        for(int j=0; j<W; ++j) \n            best_rot[i][j] = rot[i][j];\n            \n    auto start_time = clock();\n    const double TIME_LIMIT = 1.9 * CLOCKS_PER_SEC;\n    \n    int iter = 0;\n    while ((clock() - start_time) < TIME_LIMIT) {\n        // Temperature cooling\n        double progress = (double)(clock() - start_time) / TIME_LIMIT;\n        double T = 500.0 * (1.0 - progress);\n        if (T < 0.1) T = 0.1;\n        \n        // Transition\n        int r = rng() % H;\n        int c = rng() % W;\n        \n        int old_rot = rot[r][c];\n        int new_rot = rng() % 4;\n        \n        if (new_rot == old_rot) continue;\n        \n        rot[r][c] = new_rot;\n        state[r][c] = effective_type[grid[r][c]][new_rot];\n        \n        long long new_score = calc_score();\n        \n        long long diff = new_score - current_score;\n        // Accept if better or with probability exp(diff/T)\n        if (diff > 0 || (rng() % 10000 < 10000 * exp(diff / T))) {\n            current_score = new_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                for(int i=0; i<H; ++i) \n                    for(int j=0; j<W; ++j) \n                        best_rot[i][j] = rot[i][j];\n            }\n        } else {\n            // Revert\n            rot[r][c] = old_rot;\n            state[r][c] = effective_type[grid[r][c]][old_rot];\n        }\n        iter++;\n    }\n    \n    // Output best solution\n    string ans = \"\";\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ans += (char)('0' + best_rot[i][j]);\n        }\n    }\n    cout << ans << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <array>\n\nusing namespace std;\n\n// Bitmask constants\nconst int LEFT = 1;\nconst int UP = 2;\nconst int RIGHT = 4;\nconst int DOWN = 8;\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n    bool operator==(const Point& p) const { return r == p.r && c == p.c; }\n    bool operator!=(const Point& p) const { return !(*this == p); }\n};\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\n// Corresponding bit required for the NEIGHBOR to connect back\n// If we move U (empty square goes up, tile goes down), tile at (r+1, c) moves up.\n// The problem says: \"sliding the ... tile ... into the empty square\"\n// U: Move tile from (r+1, c) to (r, c). Empty was at (r, c), moves to (r+1, c).\n// Let's define operation 'U' as \"The tile ABOVE the empty square moves DOWN into the empty square\".\n// This is consistent with standard notations (U pushes tile Up, so empty goes Down? No).\n// Standard: \"U\" means move the tile \"Up\" (relative to the board) or \"Up\" relative to the empty square?\n// Problem statement: \"sliding the ... tile ... into the empty square ... U, D, L, or R\"\n// Usually means the direction the TILE moves.\n// Let's verify with example or standard.\n// If empty is at (r, c). Tile at (r+1, c) moves UP to (r, c).\n// So \"U\" corresponds to empty square moving DOWN.\n// Wait. \"sliding the ... adjacent tile ... into the empty square ... U, D, L, R\"\n// This usually refers to the direction the tile moves.\n// If I output 'U', the tile moves Up. Empty square moves Down.\n// Let's stick to: U/D/L/R = direction the tile moves.\n// Corresponding empty square moves: D/U/R/L.\n\nconst char MOVE_CHARS[4] = {'U', 'D', 'L', 'R'};\n// Mapping tile move direction to empty move direction\n// Tile moves U (r-1) -> Empty moves D (r+1) relative to tile, but essentially\n// If Tile is at (r, c) and moves U, it goes to (r-1, c). Empty was at (r-1, c), now at (r, c).\n// So Empty moves D.\n\nclass Solver {\npublic:\n    int N;\n    int T_limit;\n    vector<vector<int>> board;\n    Point empty_pos;\n    string moves;\n    mt19937 rng;\n\n    Solver(int n, int t_limit) : N(n), T_limit(t_limit), rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void set_board(const vector<vector<int>>& b, Point ep) {\n        board = b;\n        empty_pos = ep;\n        moves = \"\";\n    }\n\n    bool is_valid(int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    }\n\n    // Returns the connected component containing (sr, sc) based on edge connections\n    vector<Point> get_component(int sr, int sc) {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<Point> comp;\n        queue<Point> q;\n        q.push(Point(sr, sc));\n        visited[sr][sc] = true;\n        comp.push_back(Point(sr, sc));\n\n        while (!q.empty()) {\n            Point cur = q.front(); q.pop();\n            int cr = cur.r, cc = cur.c;\n            int tile = board[cr][cc];\n\n            for (int d = 0; d < 4; ++d) {\n                int nr = cr + DR[d];\n                int nc = cc + DC[d];\n                if (is_valid(nr, nc) && board[nr][nc] != 0) {\n                    // Check connection\n                    // Edge exists if (cr, cc) has bit d and (nr, nc) has opposite bit\n                    bool connects = false;\n                    if (d == 0 && (tile & UP) && (board[nr][nc] & DOWN)) connects = true;\n                    if (d == 1 && (tile & DOWN) && (board[nr][nc] & UP)) connects = true;\n                    if (d == 2 && (tile & LEFT) && (board[nr][nc] & RIGHT)) connects = true;\n                    if (d == 3 && (tile & RIGHT) && (board[nr][nc] & LEFT)) connects = true;\n\n                    if (connects && !visited[nr][nc]) {\n                        visited[nr][nc] = true;\n                        comp.push_back(Point(nr, nc));\n                        q.push(Point(nr, nc));\n                    }\n                }\n            }\n        }\n        return comp;\n    }\n\n    // Find the largest connected component on the board\n    vector<Point> get_largest_component() {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<Point> largest;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] != 0 && !visited[i][j]) {\n                    // BFS\n                    vector<Point> comp;\n                    queue<Point> q;\n                    q.push(Point(i, j));\n                    visited[i][j] = true;\n                    comp.push_back(Point(i, j));\n\n                    while (!q.empty()) {\n                        Point cur = q.front(); q.pop();\n                        int cr = cur.r, cc = cur.c;\n                        int tile = board[cr][cc];\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (is_valid(nr, nc) && board[nr][nc] != 0 && !visited[nr][nc]) {\n                                bool connects = false;\n                                int neighbor_tile = board[nr][nc];\n                                if (d == 0 && (tile & UP) && (neighbor_tile & DOWN)) connects = true;\n                                if (d == 1 && (tile & DOWN) && (neighbor_tile & UP)) connects = true;\n                                if (d == 2 && (tile & LEFT) && (neighbor_tile & RIGHT)) connects = true;\n                                if (d == 3 && (tile & RIGHT) && (neighbor_tile & LEFT)) connects = true;\n                                \n                                if (connects) {\n                                    visited[nr][nc] = true;\n                                    comp.push_back(Point(nr, nc));\n                                    q.push(Point(nr, nc));\n                                }\n                            }\n                        }\n                    }\n                    if (comp.size() > largest.size()) largest = comp;\n                }\n            }\n        }\n        return largest;\n    }\n\n    // Move tile at (fr, fc) to (tr, tc)\n    // We assume we just want to get the tile there.\n    // Implementation: Move empty square to adjacent to target, push.\n    // This is simplified \"greedy\" tile movement.\n    void move_tile(Point from, Point to) {\n        if (from == to) return;\n\n        // We want to move tile at 'from' to 'to'.\n        // We perform BFS to find a sequence of moves for the empty square\n        // such that it pushes 'from' towards 'to'.\n        \n        // Current state: Empty at empty_pos. Tile at 'from'.\n        // We need to move the empty square to a neighbor of 'from' in the direction of 'to'.\n        \n        Point cur = from;\n        while (cur != to) {\n            // Determine primary direction to move 'cur'\n            Point diff = Point(to.r - cur.r, to.c - cur.c);\n            \n            vector<int> dirs;\n            if (diff.r > 0) dirs.push_back(1); // Down\n            else if (diff.r < 0) dirs.push_back(0); // Up\n            \n            if (diff.c > 0) dirs.push_back(3); // Right\n            else if (diff.c < 0) dirs.push_back(2); // Left\n            \n            // Shuffle directions to avoid simple loops if path blocked\n            shuffle(dirs.begin(), dirs.end(), rng);\n\n            bool moved = false;\n            for (int d : dirs) {\n                int nr = cur.r + DR[d];\n                int nc = cur.c + DC[d];\n                Point next_target(nr, nc);\n\n                if (next_target == to) {\n                    // Try to move 'cur' to 'to'.\n                    // Empty square must be at 'to'.\n                    // BFS empty to 'to'.\n                    vector<Point> path = get_path_for_empty(to);\n                    execute_empty_path(path);\n                    \n                    // Now empty is at 'to'. Push 'cur' to 'to'.\n                    // Move tile at 'cur' in direction d.\n                    // This corresponds to moving empty square in opposite direction.\n                    // Wait. Tile moves U -> Empty moves D.\n                    // d is tile move direction.\n                    // If d=1 (Down), tile goes (r+1, c). Empty was (r+1, c), becomes (r, c).\n                    // So we append MOVE_CHARS[d] to moves.\n                    // Update empty pos to 'cur'.\n                    moves += MOVE_CHARS[d];\n                    empty_pos = cur;\n                    board[to.r][to.c] = board[cur.r][cur.c];\n                    board[cur.r][cur.c] = 0;\n                    cur = to;\n                    moved = true;\n                    break;\n                } else {\n                    // Move 'cur' one step towards 'to' to 'next_target'.\n                    // Empty square must be at 'next_target'.\n                    vector<Point> path = get_path_for_empty(next_target);\n                    execute_empty_path(path);\n\n                    // Push 'cur' to 'next_target'.\n                    moves += MOVE_CHARS[d];\n                    empty_pos = cur;\n                    board[next_target.r][next_target.c] = board[cur.r][cur.c];\n                    board[cur.r][cur.c] = 0;\n                    cur = next_target;\n                    moved = true;\n                    break;\n                }\n            }\n            if (!moved) {\n                // Stuck? Should not happen with simple connectivity, but just in case.\n                // Random move to unstuck?\n                // Or retry. Let's break to avoid infinite loop.\n                break;\n            }\n        }\n    }\n\n    // BFS to find path for empty square to target (r, c)\n    // Avoids moving the tile that we intend to move? No, just simple path.\n    // We don't have a \"current tile to protect\" in this abstraction,\n    // but the logic implies we are moving specific tiles.\n    // To simplify, we just BFS shortest path.\n    vector<Point> get_path_for_empty(Point target) {\n        if (empty_pos == target) return {};\n        \n        queue<Point> q;\n        vector<vector<Point>> parent(N, vector<Point>(N, Point(-1, -1)));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        \n        q.push(empty_pos);\n        visited[empty_pos.r][empty_pos.c] = true;\n        \n        bool found = false;\n        while(!q.empty()) {\n            Point p = q.front(); q.pop();\n            if(p == target) { found = true; break; }\n            \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) && !visited[nr][nc]) {\n                    // We can move empty square to (nr, nc) if there is a tile there to swap.\n                    // Which is always true unless (nr, nc) is empty (which it isn't, except start).\n                    visited[nr][nc] = true;\n                    parent[nr][nc] = p;\n                    q.push(Point(nr, nc));\n                }\n            }\n        }\n        \n        vector<Point> path;\n        if(found) {\n            Point curr = target;\n            while(curr != empty_pos) {\n                path.push_back(curr);\n                curr = parent[curr.r][curr.c];\n            }\n            reverse(path.begin(), path.end());\n        }\n        return path;\n    }\n\n    void execute_empty_path(const vector<Point>& path) {\n        for (Point p : path) {\n            // Move empty from empty_pos to p.\n            // Determine direction from p to empty_pos (where tile is).\n            // Wait. Empty moves to p. Tile at p moves to empty_pos.\n            // Direction is (empty_pos - p).\n            int dr = empty_pos.r - p.r;\n            int dc = empty_pos.c - p.c;\n            \n            int d = -1;\n            if(dr == 1) d = 0; // Empty moves Down (Tile moves Up)\n            else if(dr == -1) d = 1; // Empty moves Up (Tile moves Down)\n            else if(dc == 1) d = 2; // Empty moves Right (Tile moves Left)\n            else if(dc == -1) d = 3; // Empty moves Left (Tile moves Right)\n            \n            // The output string corresponds to TILE movement.\n            // Tile moves from p to empty_pos.\n            // Vector is p -> empty_pos.\n            // If empty moves D (dr=1), Tile moves U (d=0).\n            // Yes, mapping matches.\n            moves += MOVE_CHARS[d];\n            \n            // Swap\n            board[empty_pos.r][empty_pos.c] = board[p.r][p.c];\n            board[p.r][p.c] = 0;\n            empty_pos = p;\n        }\n    }\n\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        // Main loop\n        while ((int)moves.size() < T_limit) {\n            auto curr_time = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(curr_time - start_time).count();\n            if (elapsed > 2.8) break; // Time limit\n\n            vector<Point> cc = get_largest_component();\n            if (cc.size() == N * N - 1) {\n                // Solved! Minimize moves?\n                // Just stop.\n                break;\n            }\n\n            // Try to expand CC\n            bool moved = false;\n            \n            // Boundary nodes of CC\n            vector<Point> boundary;\n            vector<bool> in_cc(N*N, false);\n            for (auto& p : cc) in_cc[p.r * N + p.c] = true;\n\n            for (auto& p : cc) {\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) && !in_cc[nr * N + nc] && board[nr][nc] != 0) {\n                        boundary.push_back(Point(nr, nc));\n                    }\n                }\n            }\n\n            // Shuffle boundary\n            shuffle(boundary.begin(), boundary.end(), rng);\n\n            // Strategy 1: One-sided expansion\n            // Look for edge (u, v) where u in CC, v not in CC.\n            // If u points to v, find v' (replacement for v) that points to u.\n            // If v points to u, find u' (replacement for u) that points to v.\n\n            for (Point v : boundary) {\n                // Check neighbors of v\n                for (int d = 0; d < 4; ++d) {\n                    int ur = v.r + DR[d];\n                    int uc = v.c + DC[d];\n                    Point u(ur, uc);\n                    \n                    if (is_valid(ur, uc) && in_cc[ur * N + uc]) {\n                        int tile_u = board[u.r][u.c];\n                        int tile_v = board[v.r][v.c];\n                        \n                        // Check u -> v\n                        bool u_points_v = false;\n                        if (d == 0 && (tile_v & UP)) u_points_v = true; // v points to u -> u needs down to point back? No.\n                        // Connection requires: u has bit(d) and v has opposite_bit(d)\n                        // bit(Up)=2, opp=8(Down)\n                        // If u is above v (u.r < v.r), d=1(Down) for u. u needs 8. v needs 2.\n                        // Let's just check connection condition.\n                        \n                        bool u_has_bit = false;\n                        bool v_has_bit = false;\n                        int bit_u = 0, bit_v = 0;\n                        \n                        // Dir from u to v\n                        int du = DR[d]; // 0: u at v-1 (Up). u needs Down(8). v needs Up(2)\n                        int dv = DC[d];\n                        \n                        if (du == 1) { bit_u = 8; bit_v = 2; } // u down, v up\n                        else if (du == -1) { bit_u = 2; bit_v = 8; } // u up, v down\n                        else if (dv == 1) { bit_u = 4; bit_v = 1; } // u right, v left\n                        else if (dv == -1) { bit_u = 1; bit_v = 4; } // u left, v right\n                        \n                        if (tile_u & bit_u) u_has_bit = true;\n                        if (tile_v & bit_v) v_has_bit = true;\n\n                        if (u_has_bit && !v_has_bit) {\n                            // Case: u connects to v, v does not connect to u.\n                            // Find a replacement for v (v') that has bit_v.\n                            // Move v' to v.\n                            for (int r = 0; r < N; ++r) {\n                                for (int c = 0; c < N; ++c) {\n                                    if (r == v.r && c == v.c) continue;\n                                    if (in_cc[r * N + c]) continue; // Don't take from CC\n                                    \n                                    int candidate = board[r][c];\n                                    if ((candidate & bit_v) == bit_v) {\n                                        // Move (r,c) to v.\n                                        // Check cost estimation (Manhattan distance)\n                                        int dist = abs(r - v.r) + abs(c - v.c);\n                                        if (dist > 5) continue; // Optimization: don't move too far\n                                        \n                                        move_tile(Point(r, c), v);\n                                        moved = true;\n                                        break;\n                                    }\n                                }\n                                if (moved) break;\n                            }\n                        } else if (!u_has_bit && v_has_bit) {\n                             // Case: v connects to u, u does not connect to v.\n                             // Find replacement for u (u').\n                             // u' must have bit_u AND maintain u's other connections?\n                             // This is harder. For now, skip \"fix u\" to save complexity.\n                             // Focus on \"fix v\" which is outside CC.\n                        }\n                        \n                        if (moved) break;\n                    }\n                }\n                if (moved) break;\n            }\n\n            if (moved) continue;\n\n            // Strategy 2: Two-sided expansion (connect u in CC to v outside)\n            // Need u' and v'.\n            // Only try if we can find a pair quickly.\n            \n            // Strategy 3: Just move a random tile adjacent to CC to shake it up? \n            // Or try to merge small components.\n            // For heuristic simplicity, if we can't grow CC, we try to connect ANY two components.\n            \n            // Find two adjacent cells (u, v) not connected.\n            // u in C1, v in C2.\n            // Try to connect them.\n            // This is complex to do in one go.\n            \n            // Fallback: Just perform a random valid move to get out of local minima?\n            // If no improvement, maybe stop.\n            // Actually, just move a random tile outside CC to a random spot.\n            // Or better: pick a random tile on board, move it to a random empty spot (no, 1 empty).\n            \n            // Just try to find ANY semi-edge anywhere on board and complete it.\n            // If it connects to CC, great.\n            for (int r = 0; r < N && !moved; ++r) {\n                for (int c = 0; c < N && !moved; ++c) {\n                    if (board[r][c] == 0) continue;\n                    for (int d = 0; d < 4; ++d) {\n                        int nr = r + DR[d];\n                        int nc = c + DC[d];\n                        if (is_valid(nr, nc) && board[nr][nc] != 0) {\n                             // Check if r,c connects to nr,nc\n                             int bit_c = 0, bit_n = 0;\n                             if (DR[d]==1) { bit_c=8; bit_n=2; }\n                             else if (DR[d]==-1) { bit_c=2; bit_n=8; }\n                             else if (DC[d]==1) { bit_c=4; bit_n=1; }\n                             else if (DC[d]==-1) { bit_c=1; bit_n=4; }\n                             \n                             int t1 = board[r][c];\n                             int t2 = board[nr][nc];\n                             \n                             if ((t1 & bit_c) && !(t2 & bit_n)) {\n                                 // Find t2' with bit_n\n                                 for (int i=0; i<N && !moved; ++i) {\n                                     for (int j=0; j<N && !moved; ++j) {\n                                         if (i==nr && j==nc) continue;\n                                         if (board[i][j] & bit_n) {\n                                             // Move (i,j) to (nr,nc)\n                                             move_tile(Point(i, j), Point(nr, nc));\n                                             moved = true;\n                                         }\n                                     }\n                                 }\n                             } else if (!(t1 & bit_c) && (t2 & bit_n)) {\n                                 // Find t1' with bit_c\n                                 for (int i=0; i<N && !moved; ++i) {\n                                     for (int j=0; j<N && !moved; ++j) {\n                                         if (i==r && j==c) continue;\n                                         if (board[i][j] & bit_c) {\n                                             move_tile(Point(i, j), Point(r, c));\n                                             moved = true;\n                                         }\n                                     }\n                                 }\n                             }\n                        }\n                    }\n                }\n            }\n            \n            if (!moved) {\n                // Should not happen often. Panic move: move random tile?\n                // Or just stop.\n                // For safety, stop if we can't make progress.\n                break;\n            }\n        }\n        \n        cout << moves << endl;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    \n    vector<vector<int>> board(N, vector<int>(N));\n    Point empty_pos;\n    \n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) {\n            char c = line[j];\n            if (c == '0') {\n                board[i][j] = 0;\n                empty_pos = Point(i, j);\n            } else {\n                if (c >= 'a') board[i][j] = 10 + (c - 'a');\n                else board[i][j] = c - '0';\n            }\n        }\n    }\n\n    Solver solver(N, T);\n    solver.set_board(board, empty_pos);\n    solver.solve();\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <set>\n#include <cmath>\n#include <bitset>\n#include <chrono>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\ntypedef long long ll;\n\n// Define the maximum number of cuts allowed\nconst int K_MAX = 100;\n\n// Structure to represent a point\nstruct Point {\n    ll x, y;\n};\n\n// Structure to represent a line defined by two points\nstruct Line {\n    ll x1, y1, x2, y2;\n};\n\n// Global variables for problem input\nint N, K;\nvector<int> a(11); // Demands a[1]...a[10]\nvector<Point> points;\n\n// Random number generator\nmt19937 rng(1337); // Fixed seed for reproducibility, can use time(0) for random\n\n// Utility to get random integer in range [l, r]\nll rand_ll(ll l, ll r) {\n    uniform_int_distribution<ll> dist(l, r);\n    return dist(rng);\n}\n\n// Calculate cross product of (b-a) and (c-a)\nll cross_product(const Point& a, const Point& b, const Point& c) {\n    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n// Function to compute the score given a set of lines\n// Returns a pair: (score, number_of_dead_points)\n// Dead points are those lying exactly on a cut line.\npair<int, int> compute_score(const vector<Line>& lines) {\n    int k = lines.size();\n    if (k == 0) {\n        // Only one region containing all points\n        int cnt = 0;\n        for (int i = 0; i < N; ++i) {\n            // Check if points are valid (always true for input)\n            cnt++;\n        }\n        if (cnt > 0 && cnt <= 10) {\n            return {min(a[cnt], 1), 0};\n        }\n        return {0, 0};\n    }\n\n    // Map to store counts of points in each region\n    // Since we can't easily hash a vector<bool> or bitset, we use the signature directly\n    // However, map with bitset is fine. \n    // Optimization: Just use a string or vector<int> as key. \n    // But bitset<100> is faster and smaller.\n    \n    map<bitset<K_MAX>, int> region_counts;\n    int dead_points = 0;\n\n    for (int i = 0; i < N; ++i) {\n        bitset<K_MAX> signature;\n        bool is_dead = false;\n\n        for (int j = 0; j < k; ++j) {\n            ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n            if (val == 0) {\n                is_dead = true;\n                break;\n            }\n            if (val > 0) {\n                signature.set(j);\n            }\n        }\n\n        if (is_dead) {\n            dead_points++;\n        } else {\n            region_counts[signature]++;\n        }\n    }\n\n    int score = 0;\n    for (const auto& p : region_counts) {\n        int cnt = p.second;\n        if (1 <= cnt && cnt <= 10) {\n            score += min(a[cnt], 1); // We count how many demands we satisfy\n        }\n    }\n    return {score, dead_points};\n}\n\n// Generate a random line that avoids passing through points\n// Ideally passes through the region of interest\nLine generate_random_line() {\n    // Generate lines passing through points inside the bounding box of the cake\n    // Cake radius 10^4, so box is [-10000, 10000].\n    // We pick two points in this box.\n    \n    while (true) {\n        ll x1 = rand_ll(-10000, 10000);\n        ll y1 = rand_ll(-10000, 10000);\n        ll x2 = rand_ll(-10000, 10000);\n        ll y2 = rand_ll(-10000, 10000);\n\n        if (x1 == x2 && y1 == y2) continue;\n\n        Line l{x1, y1, x2, y2};\n        \n        // Check if this line passes through any point\n        bool hits_point = false;\n        for (const auto& p : points) {\n            if (cross_product({x1, y1}, {x2, y2}, p) == 0) {\n                hits_point = true;\n                break;\n            }\n        }\n        if (!hits_point) {\n            return l;\n        }\n    }\n}\n\nvoid solve() {\n    // Input reading\n    cin >> N >> K;\n    for (int i = 1; i <= 10; ++i) cin >> a[i];\n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n\n    // Simulated Annealing / Local Search parameters\n    double start_temp = 1000.0;\n    double end_temp = 1.0;\n    int iterations = 20000; // Number of iterations\n    \n    // State initialization\n    vector<Line> current_lines;\n    \n    // Try to add some initial random lines\n    int initial_lines = min(K, 20); \n    for (int i = 0; i < initial_lines; ++i) {\n        current_lines.push_back(generate_random_line());\n    }\n    \n    auto [current_score, current_dead] = compute_score(current_lines);\n    // Penalize dead points heavily\n    double current_energy = - (double)current_score * 1000.0 - current_dead * 500000.0;\n\n    vector<Line> best_lines = current_lines;\n    double best_energy = current_energy;\n\n    // Main loop\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        // Generate neighbor\n        vector<Line> next_lines = current_lines;\n        \n        double r = (double)rand_ll(0, 10000) / 10000.0;\n        int action = -1;\n\n        if (next_lines.size() == 0) {\n            action = 0; // Add\n        } else if (next_lines.size() == K) {\n             // Can only replace or remove\n             if (r < 0.7) action = 2; // Replace\n             else action = 1; // Remove\n        } else {\n            if (r < 0.4) action = 0; // Add\n            else if (r < 0.7) action = 1; // Remove\n            else action = 2; // Replace\n        }\n\n        if (action == 0) {\n            // Add line\n            next_lines.push_back(generate_random_line());\n        } else if (action == 1) {\n            // Remove line\n            int idx = rand_ll(0, next_lines.size() - 1);\n            next_lines.erase(next_lines.begin() + idx);\n        } else if (action == 2) {\n            // Replace line\n            int idx = rand_ll(0, next_lines.size() - 1);\n            next_lines[idx] = generate_random_line();\n        }\n\n        auto [next_score, next_dead] = compute_score(next_lines);\n        double next_energy = - (double)next_score * 1000.0 - next_dead * 500000.0;\n\n        double delta = next_energy - current_energy;\n        \n        // Metropolis criterion\n        if (delta < 0 || exp(-delta / temp) > (double)rand_ll(0, 10000) / 10000.0) {\n            current_lines = next_lines;\n            current_energy = next_energy;\n            \n            if (next_energy < best_energy) {\n                best_lines = next_lines;\n                best_energy = next_energy;\n            }\n        }\n    }\n\n    // Final Calculation to extract actual score for display/debug if needed\n    // But output is just the lines\n    int output_k = best_lines.size();\n    cout << output_k << endl;\n    for (const auto& l : best_lines) {\n        cout << l.x1 << \" \" << l.y1 << \" \" << l.x2 << \" \" << l.y2 << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    // Set seed based on time for different runs, though specific seeds can be good for debugging\n    // rng.seed(time(0)); \n    \n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <tuple>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst int MAX_N = 61;\nint N, M;\nint center;\nbool grid[MAX_N][MAX_N];\n\n// Directions: 8 vectors\nconst int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};\nconst int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};\n\n// Helper to check perpendicularity (dot product 0)\n// dir 0 (1,0) perp to 1,3\n// dir 1 (0,1) perp to 0,2\n// dir 2 (-1,0) perp to 1,3\n// dir 3 (0,-1) perp to 0,2\n// dir 4 (1,1) perp to 5,6\n// dir 5 (1,-1) perp to 4,7\n// dir 6 (-1,1) perp to 4,7\n// dir 7 (-1,-1) perp to 5,6\nconst vector<vector<int>> perp_dirs = {\n    {1, 3}, {0, 2}, {1, 3}, {0, 2}, // Axis\n    {5, 6}, {4, 7}, {4, 7}, {5, 6}  // Diagonal\n};\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\nbool time_limit_exceeded = false;\n\nvoid check_time() {\n    auto now = chrono::high_resolution_clock::now();\n    auto duration = chrono::duration_cast<chrono::milliseconds>(now - start_time);\n    if (duration.count() > 4800) { // 4.8s limit\n        time_limit_exceeded = true;\n    }\n}\n\n// Data structures for 1D prefix sums\n// We need to manage sums for Grid Points and Segments along 4 directions\n// H, V, D1 (\\), D2 (/)\n\ntemplate <int SIZE>\nstruct PrefixManager {\n    int sums[SIZE][MAX_N + 2]; // 1-based prefix sums. sums[k][i] is sum up to i (exclusive of i if using typical logic, but we can do inclusive).\n    // Let's use: sums[k][i] is sum of elements from 0 to i-1. Range [l, r) is sums[k][r] - sums[k][l].\n    // For segments: sums[k][i] is sum of segments starting at indices < i.\n    \n    void init() {\n        for(int i=0; i<SIZE; ++i) {\n            for(int j=0; j<=N+1; ++j) sums[i][j] = 0;\n        }\n    }\n\n    // Update: add 1 to all indices >= idx on line k\n    void update_line(int k, int idx) {\n        // idx is the index of the modified element (point or segment)\n        // Prefix sums logic: sums[i] stores sum of elements [0, i).\n        // If we add 1 to element at idx, we add 1 to sums[k][idx+1 ... N]\n        for (int i = idx + 1; i <= N + 1; ++i) {\n            sums[k][i]++;\n        }\n    }\n    \n    // Query range [l, r) (points at l, l+1, ..., r-1)\n    int query(int k, int l, int r) {\n        if (l >= r) return 0;\n        return sums[k][r] - sums[k][l];\n    }\n};\n\n// We have 2 sets: Grid Points, Segments\n// For each set, 4 directions.\n// Grid Points:\n// H Rows: N rows, each length N.\n// V Cols: N cols, each length N.\n// D1 Diagonals: 2N-1 diagonals. Length varies. Max length N. Array size 2N-1.\n// D2 Diagonals: 2N-1 diagonals.\n// Segments:\n// H: N rows, N-1 segments.\n// V: N cols, N-1 segments.\n// D1: 2N-2 diagonals (main diagonals of unit squares). Max length N-1.\n// D2: 2N-2 diagonals.\n\nPrefixManager<MAX_N> grid_rows;\nPrefixManager<MAX_N> grid_cols;\nPrefixManager<2 * MAX_N> grid_d1; // y - x + (N-1)\nPrefixManager<2 * MAX_N> grid_d2; // y + x\n\nPrefixManager<MAX_N> seg_rows;\nPrefixManager<MAX_N> seg_cols;\nPrefixManager<2 * MAX_N> seg_d1;\nPrefixManager<2 * MAX_N> seg_d2;\n\n// Indices mapping for diagonals\n// For Grid D1 (y-x = const): k = y - x + (N-1). Index along diagonal: \n// Top-left start: x from max(0, k - (N-1)) to min(N-1, k). \n// Let's define index `i` along diagonal starting from the top-most or left-most point.\n// Simple mapping: `idx` = x (or y). We need a consistent way to query range sum.\n// Let's say we map point (x,y) to `x` coordinate on the diagonal `k=y-x+N-1`.\n// Then points on same diagonal have increasing x.\n// Range [x1, x2] on diagonal k corresponds to points (x, y) where x in [x1, x2].\n// Update: update_line(k, x).\n// Query: query(k, x1, x2+1).\n\n// For Grid D2 (y+x = const): k = y + x. \n// Map (x,y) to `x`.\n// Points on same diagonal have increasing x (and decreasing y).\n// Update: update_line(k, x).\n// Query: query(k, x1, x2+1).\n\n// For Seg D1 (\\): Segment connecting (x,y) and (x+1,y+1).\n// This segment lies on the same diagonal line as grid points, but \"between\" them.\n// The diagonal index is `k = y - x + (N-1)`.\n// We can map this segment to the `x` coordinate of the left/top point.\n// Valid x: 0..N-2.\n// Update: update_line(k, x).\n\n// For Seg D2 (/): Segment connecting (x+1,y) and (x,y+1).\n// Diagonal index `k = y + x`.\n// Map to `x` coordinate of the left point (the one with smaller x).\n// Valid x: 0..N-2.\n// Update: update_line(k, x).\n\n\nvoid init_prefix_structures() {\n    grid_rows.init();\n    grid_cols.init();\n    grid_d1.init();\n    grid_d2.init();\n    \n    seg_rows.init();\n    seg_cols.init();\n    seg_d1.init();\n    seg_d2.init();\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (grid[x][y]) {\n                grid_rows.update_line(y, x);\n                grid_cols.update_line(x, y);\n                int k1 = y - x + (N - 1);\n                grid_d1.update_line(k1, x);\n                int k2 = y + x;\n                grid_d2.update_line(k2, x);\n            }\n        }\n    }\n}\n\nbool is_segment_free(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    \n    // Length\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return true;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    \n    // Check bounds for segment existence\n    // Segment exists between (x1, y1) and (x2, y2) inclusive of intermediate points?\n    // A segment is a set of unit segments.\n    // e.g. (0,0) to (0,2) has segments (0,0)-(0,1) and (0,1)-(0,2).\n    \n    if (sx == 1 && sy == 0) { // Right\n        // Check horizontal segments on row y1, from x1 to x1+len-1\n        // seg_rows[k] sum of segments starting at x < idx.\n        // Segments involved: indices x1, x1+1, ..., x1+len-1.\n        // Query sum [x1, x1+len)\n        return seg_rows.query(y1, x1, x1 + len) == 0;\n    } else if (sx == -1 && sy == 0) { // Left\n        // Same, symmetry handled by x1 < x2 in query?\n        // No, x1 is start, x2 is end. We assume x1 < x2 for internal logic usually,\n        // but here x1 might be > x2.\n        // Let's normalize: lx = min(x1, x2), rx = max(x1, x2). ly = min(y1, y2)...\n        // But simpler: just use the direction.\n        // Segments are at x1, x1-1, ...\n        // Better to normalize to range [lx, rx).\n        int lx = min(x1, x2);\n        int ly = y1; // same row\n        return seg_rows.query(ly, lx, lx + len) == 0;\n    } else if (sx == 0 && sy == 1) { // Up\n        int lx = x1; // same col\n        int ly = min(y1, y2);\n        return seg_cols.query(lx, ly, ly + len) == 0;\n    } else if (sx == 0 && sy == -1) { // Down\n        int lx = x1;\n        int ly = min(y1, y2);\n        return seg_cols.query(lx, ly, ly + len) == 0;\n    } else if (sx == 1 && sy == 1) { // Up-Right (D1)\n        // Diagonal segments. k = y - x + (N-1).\n        // Index mapped to x of top-left point.\n        // Start (x1, y1), End (x2, y2). x2 = x1+len.\n        // Segments indices: x1, x1+1, ...\n        int lx = min(x1, x2);\n        int ly = min(y1, y2);\n        int k = ly - lx + (N - 1); // Same k for all\n        return seg_d1.query(k, lx, lx + len) == 0;\n    } else if (sx == -1 && sy == -1) { // Down-Left (D1 reverse)\n        int lx = min(x1, x2);\n        int ly = min(y1, y2);\n        int k = ly - lx + (N - 1);\n        return seg_d1.query(k, lx, lx + len) == 0;\n    } else if (sx == -1 && sy == 1) { // Up-Left (D2)\n        // k = y + x.\n        // Index mapped to x of left point (smaller x).\n        // Start (x1, y1). x1 > x2.\n        // Segments at x2, x2+1, ..., x1-1.\n        // Indices x in [x2, x1).\n        int lx = min(x1, x2);\n        int ly = max(y1, y2); // Top-left point\n        int k = ly + lx;\n        // Segment index corresponds to x (smaller x).\n        return seg_d2.query(k, lx, lx + len) == 0;\n    } else if (sx == 1 && sy == -1) { // Down-Right (D2 reverse)\n        int lx = min(x1, x2);\n        int ly = max(y1, y2); // Top-left\n        int k = ly + lx;\n        return seg_d2.query(k, lx, lx + len) == 0;\n    }\n    return false;\n}\n\nbool is_perimeter_clean(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len <= 1) return true; // Adjacent points, nothing in between\n    \n    int lx = min(x1, x2);\n    int rx = max(x1, x2);\n    int ly = min(y1, y2);\n    int ry = max(y1, y2);\n\n    if (y1 == y2) { // Horizontal\n        // Points at lx+1 ... rx-1 on row y1\n        return grid_rows.query(y1, lx + 1, rx) == 0;\n    } else if (x1 == x2) { // Vertical\n        return grid_cols.query(x1, ly + 1, ry) == 0;\n    } else if (x2 - x1 == y2 - y1) { // D1\n        int k = ly - lx + (N - 1);\n        // Points strictly between. x from lx+1 to rx-1.\n        return grid_d1.query(k, lx + 1, rx) == 0;\n    } else { // D2\n        int k = ry + lx; // y + x is constant. Using top-left (lx, ry)\n        // Points x from lx+1 to rx-1.\n        return grid_d2.query(k, lx + 1, rx) == 0;\n    }\n}\n\nvoid update_segment(int x1, int y1, int x2, int y2) {\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    int cx = x1, cy = y1;\n    for (int i = 0; i < len; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        \n        // Mark segment (cx, cy)-(nx, ny)\n        // Update corresponding prefix sum array\n        // Horizontal\n        if (cy == ny) {\n            int lx = min(cx, nx);\n            seg_rows.update_line(cy, lx);\n        } \n        // Vertical\n        else if (cx == nx) {\n            int ly = min(cy, ny);\n            seg_cols.update_line(cx, ly);\n        }\n        // D1\n        else if (nx == cx + 1 && ny == cy + 1) {\n            int lx = min(cx, nx);\n            int k = min(cy, ny) - lx + (N - 1);\n            seg_d1.update_line(k, lx);\n        }\n        // D1 reverse\n        else if (nx == cx - 1 && ny == cy - 1) {\n            int lx = min(cx, nx);\n            int k = min(cy, ny) - lx + (N - 1);\n            seg_d1.update_line(k, lx);\n        }\n        // D2\n        else if (nx == cx - 1 && ny == cy + 1) {\n            int lx = min(cx, nx);\n            int ly = max(cy, ny); // Top-left\n            int k = ly + lx;\n            seg_d2.update_line(k, lx);\n        }\n        // D2 reverse\n        else if (nx == cx + 1 && ny == cy - 1) {\n            int lx = min(cx, nx);\n            int ly = max(cy, ny);\n            int k = ly + lx;\n            seg_d2.update_line(k, lx);\n        }\n        \n        cx = nx; cy = ny;\n    }\n}\n\nstruct Point {\n    int x, y;\n    int weight;\n};\n\nstruct ComparePoint {\n    bool operator()(const Point& a, const Point& b) {\n        return a.weight < b.weight; // Min-heap behavior, but we want max weight.\n        // Wait, priority_queue puts largest element at top if we use less.\n        // To get largest weight at top: return a.weight < b.weight.\n    }\n};\n\nvector<tuple<int, int, int, int, int, int, int, int>> ops;\n\n// Try to place a dot at (x, y).\n// Returns true if successful.\nbool try_place(int x, int y) {\n    if (grid[x][y]) return false;\n\n    // Iterate u directions\n    for (int du = 0; du < 8; ++du) {\n        // Iterate v directions (perpendicular)\n        for (int dv : perp_dirs[du]) {\n            // Iterate lengths (try small rectangles first)\n            // Limit length search? N is small enough (60).\n            // Maybe try length 1..10 first? Then extend?\n            // For robustness, try all, but start small.\n            for (int len_u = 1; len_u < N; ++len_u) {\n                int bx = x + dx[du] * len_u;\n                int by = y + dy[du] * len_u;\n                if (bx < 0 || bx >= N || by < 0 || by >= N) break; // Out of bounds\n                if (!grid[bx][by]) continue; // Not a dot\n\n                for (int len_v = 1; len_v < N; ++len_v) {\n                    int cx_coord = x + dx[dv] * len_v; // Actually this is D (p4) based on problem description order?\n                    // Let's map:\n                    // p1 = (x,y)\n                    // u = p1 -> p2. p2 = (bx, by).\n                    // v = p1 -> p4. p4 = (dx_coord, dy_coord).\n                    // p3 = p2 + v = p4 + u = (bx, by) + (dx[dv]*len_v, dy[dv]*len_v).\n                    \n                    int dx_coord = x + dx[dv] * len_v;\n                    int dy_coord = y + dy[dv] * len_v;\n                    \n                    int cx = bx + dx[dv] * len_v;\n                    int cy = by + dy[dv] * len_v;\n\n                    if (dx_coord < 0 || dx_coord >= N || dy_coord < 0 || dy_coord >= N) break;\n                    if (cx < 0 || cx >= N || cy < 0 || cy >= N) break;\n\n                    if (!grid[dx_coord][dy_coord]) continue;\n                    if (!grid[cx][cy]) continue;\n\n                    // Check segments\n                    // p1-p2, p2-p3, p3-p4, p4-p1\n                    if (!is_segment_free(x, y, bx, by)) continue;\n                    if (!is_segment_free(bx, by, cx, cy)) continue;\n                    if (!is_segment_free(cx, cy, dx_coord, dy_coord)) continue;\n                    if (!is_segment_free(dx_coord, dy_coord, x, y)) continue;\n\n                    // Check clean perimeter\n                    // No dots on perimeter except vertices\n                    if (!is_perimeter_clean(x, y, bx, by)) continue;\n                    if (!is_perimeter_clean(bx, by, cx, cy)) continue;\n                    if (!is_perimeter_clean(cx, cy, dx_coord, dy_coord)) continue;\n                    if (!is_perimeter_clean(dx_coord, dy_coord, x, y)) continue;\n\n                    // Found!\n                    \n                    // Apply updates\n                    grid[x][y] = true;\n                    grid_rows.update_line(y, x);\n                    grid_cols.update_line(x, y);\n                    grid_d1.update_line(y - x + (N - 1), x);\n                    grid_d2.update_line(y + x, x);\n\n                    update_segment(x, y, bx, by);\n                    update_segment(bx, by, cx, cy);\n                    update_segment(cx, cy, dx_coord, dy_coord);\n                    update_segment(dx_coord, dy_coord, x, y);\n\n                    ops.emplace_back(x, y, bx, by, cx, cy, dx_coord, dy_coord);\n                    return true;\n                }\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    center = (N - 1) / 2;\n    \n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = false;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        grid[x][y] = true;\n    }\n    \n    init_prefix_structures();\n    \n    priority_queue<Point, vector<Point>, ComparePoint> pq;\n    \n    // Push all empty points\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!grid[i][j]) {\n                int dist_sq = (i - center) * (i - center) + (j - center) * (j - center);\n                pq.push({i, j, dist_sq});\n            }\n        }\n    }\n    \n    int total_processed = 0;\n    \n    while (!pq.empty() && !time_limit_exceeded) {\n        check_time();\n        \n        Point p = pq.top();\n        pq.pop();\n        \n        // If already filled (by previous operation), skip\n        if (grid[p.x][p.y]) continue;\n        \n        if (try_place(p.x, p.y)) {\n            // Success! Push neighbors back to PQ to handle dependencies\n            // Neighbors are points that might be unblocked by this new dot.\n            // Range: +/- 10\n            int R = 10;\n            int x_min = max(0, p.x - R);\n            int x_max = min(N - 1, p.x + R);\n            int y_min = max(0, p.y - R);\n            int y_max = min(N - 1, p.y + R);\n            \n            for (int nx = x_min; nx <= x_max; ++nx) {\n                for (int ny = y_min; ny <= y_max; ++ny) {\n                    if (!grid[nx][ny]) {\n                        int dist_sq = (nx - center) * (nx - center) + (ny - center) * (ny - center);\n                        pq.push({nx, ny, dist_sq});\n                    }\n                }\n            }\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \" \"\n             << get<4>(op) << \" \" << get<5>(op) << \" \"\n             << get<6>(op) << \" \" << get<7>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int H = 10;\nconst int W = 10;\n\nstruct Solver {\n    vector<vector<int>> board;\n    vector<int> flavors;\n    int step;\n    // Targets for each flavor (1-indexed flavor -> target coordinates)\n    // We choose corners/edges to maximize separation.\n    // Flavor 1: Top-Left (0,0)\n    // Flavor 2: Top-Right (0,9)\n    // Flavor 3: Bottom-Center (9,4)\n    vector<pair<int, int>> targets;\n    \n    Solver(vector<int> f) : flavors(f), step(0) {\n        board.assign(H, vector<int>(W, 0));\n        targets = {{0, 0}, {0, 9}, {9, 4}};\n    }\n\n    // Maps the 1-based index p to the actual empty cell coordinates\n    pair<int, int> get_pos(int p) {\n        int cnt = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (board[i][j] == 0) {\n                    cnt++;\n                    if (cnt == p) return {i, j};\n                }\n            }\n        }\n        return {-1, -1}; \n    }\n\n    // Simulates tilting the board\n    // 0: F (Forward/Up), 1: B (Backward/Down), 2: L (Left), 3: R (Right)\n    vector<vector<int>> tilt(vector<vector<int>> b, int dir) {\n        if (dir == 0) { // Forward\n            for (int j = 0; j < W; ++j) {\n                int write_i = 0;\n                for (int i = 0; i < H; ++i) {\n                    if (b[i][j] != 0) {\n                        if (write_i != i) {\n                            b[write_i][j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_i++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // Backward\n            for (int j = 0; j < W; ++j) {\n                int write_i = H - 1;\n                for (int i = H - 1; i >= 0; --i) {\n                    if (b[i][j] != 0) {\n                        if (write_i != i) {\n                            b[write_i][j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_i--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // Left\n            for (int i = 0; i < H; ++i) {\n                int write_j = 0;\n                for (int j = 0; j < W; ++j) {\n                    if (b[i][j] != 0) {\n                        if (write_j != j) {\n                            b[i][write_j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_j++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < H; ++i) {\n                int write_j = W - 1;\n                for (int j = W - 1; j >= 0; --j) {\n                    if (b[i][j] != 0) {\n                        if (write_j != j) {\n                            b[i][write_j] = b[i][j];\n                            b[i][j] = 0;\n                        }\n                        write_j--;\n                    }\n                }\n            }\n        }\n        return b;\n    }\n\n    // Evaluate the board state\n    double evaluate(const vector<vector<int>>& b) {\n        int sum_sq = 0;\n        vector<vector<bool>> visited(H, vector<bool>(W, false));\n        \n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0 && !visited[i][j]) {\n                    queue<pair<int,int>> q;\n                    q.push({i,j});\n                    visited[i][j] = true;\n                    int size = 0;\n                    int type = b[i][j];\n                    while (!q.empty()) {\n                        auto [r, c] = q.front(); q.pop();\n                        size++;\n                        int dr[] = {0, 0, 1, -1};\n                        int dc[] = {1, -1, 0, 0};\n                        for (int k = 0; k < 4; ++k) {\n                            int nr = r + dr[k];\n                            int nc = c + dc[k];\n                            if (nr >= 0 && nr < H && nc >= 0 && nc < W && !visited[nr][nc] && b[nr][nc] == type) {\n                                visited[nr][nc] = true;\n                                q.push({nr,nc});\n                            }\n                        }\n                    }\n                    sum_sq += size * size;\n                }\n            }\n        }\n\n        double penalty = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0) {\n                    int flavor_idx = b[i][j] - 1;\n                    penalty += abs(i - targets[flavor_idx].first) + abs(j - targets[flavor_idx].second);\n                }\n            }\n        }\n        \n        // Weight the penalty. \n        // We want to cluster (maximize sum_sq) and separate flavors (minimize penalty).\n        // sum_sq grows quadratically, penalty linearly.\n        // However, early in the game, sum_sq is small (mostly 1s), so penalty dominates naturally if weight is significant.\n        // We use a constant weight. Since sum_sq is at most 10000 and penalty at most ~1800,\n        // a weight of 2.0 ensures that until clusters form, we optimize for position (penalty),\n        // and once clusters are large, sum_sq dominates.\n        double weight = 3.0;\n        \n        return (double)sum_sq - weight * penalty;\n    }\n\n    char solve(int p) {\n        // Place candy\n        auto [r, c] = get_pos(p);\n        board[r][c] = flavors[step];\n        \n        double best_score = -1e18;\n        int best_dir = -1;\n        \n        // Try all 4 directions\n        for (int d = 0; d < 4; ++d) {\n            auto next_board = tilt(board, d);\n            double score = evaluate(next_board);\n            if (score > best_score) {\n                best_score = score;\n                best_dir = d;\n            }\n        }\n        \n        // Apply best move\n        board = tilt(board, best_dir);\n        step++;\n        \n        if (best_dir == 0) return 'F';\n        if (best_dir == 1) return 'B';\n        if (best_dir == 2) return 'L';\n        return 'R';\n    }\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) cin >> f[i];\n    \n    Solver solver(f);\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        if (t < 99) {\n            char out = solver.solve(p);\n            cout << out << endl;\n            cout.flush();\n        } else {\n            solver.solve(p); // 100th move, no output needed\n        }\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Use random_device for seeding to ensure different graphs on different runs, \n// though for consistency in AHC, fixed seed is sometimes preferred. \n// Here we use a fixed seed for reproducibility of the \"optimal\" N logic, \n// but we could use random_device if we wanted.\nmt19937 rng(42); \n\n// Constants\nconst int MAX_N = 100;\nconst int QUERIES = 100;\n\n// Analytical estimation of expected number of errors for given parameters\ndouble estimate_expected_errors(int M, double eps, int N) {\n    int P = N * (N - 1) / 2;\n    \n    // If we don't have enough distinct edge counts possible, we must rely on structure.\n    // But structure is weaker. We assume distinct edge counts are the primary discriminator.\n    if (P < M) {\n        return 100.0; // Assume high failure if P < M\n    }\n\n    // Target edge counts for graphs 0 to M-1\n    // We distribute them uniformly in [0, P]\n    // Step is roughly P / (M - 1)\n    double step = (double)P / (M - 1);\n    \n    // Calculate the minimum gap between expected edge counts in the noisy space.\n    // Expected observed edge count for a graph with true edges e:\n    // E_obs = e * (1 - 2*eps) + P * eps\n    // The gap in observed space is scaled by (1 - 2*eps)\n    double gap_observed = step * (1.0 - 2.0 * eps);\n    \n    // Noise standard deviation for edge count\n    // Var = P * eps * (1 - eps)\n    double sigma = sqrt((double)P * eps * (1.0 - eps));\n    \n    if (sigma < 1e-9) return 0.0; // No noise\n    \n    // We model the probability of error.\n    // We have M points on a line with average gap gap_observed.\n    // A query falls near the true point with noise sigma.\n    // Probability of misclassification is related to how far the neighbors are.\n    // Simplified model: Z-score of gap/2.\n    double z = (gap_observed / 2.0) / sigma;\n    \n    // Error probability for one boundary (approx)\n    // P(Z > z) * 2 (two sides)\n    double p_boundary = erfc(z / sqrt(2.0));\n    \n    // Expected errors per query roughly sum of boundary errors\n    // Note: this is a heuristic.\n    double E_query = (M - 1) * p_boundary;\n    \n    return E_query * QUERIES;\n}\n\n// Choose optimal N\nint choose_N(int M, double eps) {\n    int best_N = 15; // Minimum reasonable\n    double best_score = -1.0;\n    \n    // We must have enough possible edges to separate graphs\n    // At least P >= M\n    int min_N = 0;\n    for(int n=4; n<=MAX_N; ++n) {\n        if(n*(n-1)/2 >= M) {\n            min_N = n;\n            break;\n        }\n    }\n    if (min_N == 0) min_N = MAX_N; // Fallback\n\n    for (int N = min_N; N <= MAX_N; ++N) {\n        double E_est = estimate_expected_errors(M, eps, N);\n        \n        // Score formula: 10^9 * 0.9^E / N\n        // We can ignore 10^9 for comparison\n        double score = pow(0.9, E_est) / (double)N;\n        \n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n        }\n    }\n    return best_N;\n}\n\n// Generate a graph with specific edge count\n// Returns string representation\nstring generate_graph_with_edges(int N, int target_edges) {\n    int P = N * (N - 1) / 2;\n    string graph(P, '0');\n    \n    // Create list of all possible edge indices\n    vector<int> indices(P);\n    iota(indices.begin(), indices.end(), 0);\n    \n    // Shuffle to pick random edges\n    shuffle(indices.begin(), indices.end(), rng);\n    \n    for (int i = 0; i < target_edges; ++i) {\n        graph[indices[i]] = '1';\n    }\n    \n    return graph;\n}\n\n// Extract degree sequence from graph string\nvector<int> get_degree_sequence(int N, const string& graph) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (graph[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    // 1. Determine N\n    int N = choose_N(M, eps);\n    \n    // 2. Generate M Graphs\n    // Strategy: Distinct edge counts, spread uniformly.\n    // This ensures they are maximally separated in the \"feature space\" of edge count.\n    int P = N * (N - 1) / 2;\n    \n    // To avoid issues with P < M (if estimation logic missed it or if we want to use structure),\n    // we just clamp target_edges.\n    \n    vector<string> graphs(M);\n    vector<vector<int>> expected_degrees(M); // Stores sorted expected degrees for H\n    \n    for (int i = 0; i < M; ++i) {\n        // Target edges for G_i\n        // Linearly interpolate from 0 to P\n        int target_edges = (int)round((double)i * P / (M - 1));\n        \n        graphs[i] = generate_graph_with_edges(N, target_edges);\n        \n        // Precompute expected degree sequence for H\n        // H is derived from G_i by flipping edges with eps.\n        // Expected degree of vertex v in H:\n        // d_H(v) ~ Binomial(d_G(v), 1-eps) + Binomial(N-1-d_G(v), eps)\n        // E[d_H] = d_G(v) * (1-eps) + (N-1-d_G(v)) * eps\n        //        = eps*(N-1) + d_G(v)*(1-2*eps)\n        \n        vector<int> d_G = get_degree_sequence(N, graphs[i]);\n        expected_degrees[i].resize(N);\n        \n        for (int j = 0; j < N; ++j) {\n            // Calculate expected value as double for distance comparison\n            // We store as double, but for speed we can multiply by something or just use double in comparison.\n            // Let's compute on the fly or precompute.\n            expected_degrees[i][j] = eps * (N - 1) + d_G[j] * (1.0 - 2.0 * eps);\n        }\n    }\n    \n    cout << N << endl;\n    for (int i = 0; i < M; ++i) {\n        cout << graphs[i] << endl;\n    }\n    cout << flush;\n    \n    // 3. Process Queries\n    for (int q = 0; q < QUERIES; ++q) {\n        string H;\n        cin >> H;\n        \n        vector<int> d_H = get_degree_sequence(N, H);\n        \n        int best_k = 0;\n        double min_dist = 1e9;\n        \n        for (int k = 0; k < M; ++k) {\n            double dist = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = d_H[j] - expected_degrees[k][j];\n                dist += diff * diff; // Squared Euclidean distance\n                // Alternatively L1: abs(diff)\n                // L2 is slightly more sensitive to outliers in degree distribution.\n                // With sorted degrees, matching shapes is important.\n            }\n            \n            if (dist < min_dist) {\n                min_dist = dist;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <climits>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\n// Global variables for efficient access\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<pair<int, int>>> adj; // (neighbor, edge_id)\nvector<int> edge_day; // -1 if not assigned, otherwise day index (0-based)\nvector<long long> load; // Sum of usage of edges assigned to each day\nvector<int> day_size; // Number of edges assigned to each day\nvector<int> visited; // For connectivity check\nint iter_id = 0;\n\n// Check if graph remains connected after removing edges assigned to day_k\n// and the hypothetically removed edge 'check_eid'.\n// Using BFS from node 0.\nbool is_connected(int day_k, int check_eid) {\n    iter_id++;\n    queue<int> q;\n    q.push(0);\n    visited[0] = iter_id;\n    int count = 1;\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n\n        // Early exit if we have visited all nodes\n        if (count == N) return true;\n\n        for (auto& [v, eid] : adj[u]) {\n            if (visited[v] == iter_id) continue;\n\n            // Check if this edge is effectively removed\n            // It is removed if it's scheduled for day_k, or if it's the edge we are currently checking\n            if (edge_day[eid] == day_k || eid == check_eid) continue;\n\n            visited[v] = iter_id;\n            count++;\n            q.push(v);\n        }\n    }\n    return count == N;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> D >> K;\n\n    edges.resize(M);\n    adj.resize(N);\n\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        adj[edges[i].u].emplace_back(edges[i].v, i);\n        adj[edges[i].v].emplace_back(edges[i].u, i);\n    }\n\n    // Consume coordinates (not needed for algorithm)\n    for (int i = 0; i < N; ++i) {\n        double x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate Edge Usage (Centrality)\n    // Usage = number of times edge appears in any shortest path\n    vector<long long> usage(M, 0);\n\n    for (int s = 0; s < N; ++s) {\n        vector<long long> dist(N, INF);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                long long w = edges[eid].w;\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n\n        // Count contributions to usage\n        for (int i = 0; i < M; ++i) {\n            int u = edges[i].u;\n            int v = edges[i].v;\n            long long w = edges[i].w;\n            if (dist[u] + w == dist[v]) usage[i]++;\n            if (dist[v] + w == dist[u]) usage[i]++;\n        }\n    }\n\n    // 2. Sort edges by usage (descending) to handle critical edges first\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return usage[a] > usage[b];\n    });\n\n    // 3. Initialize State\n    edge_day.assign(M, -1);\n    load.assign(D, 0);\n    day_size.assign(D, 0);\n    visited.assign(N, 0);\n\n    // 4. Greedy Assignment\n    for (int i = 0; i < M; ++i) {\n        int eid = edge_order[i];\n        long long e_usage = usage[eid];\n\n        // Create a list of days sorted by current load (ascending)\n        // We want to assign this edge to the day that causes the least \"frustration\" so far\n        vector<int> day_indices(D);\n        iota(day_indices.begin(), day_indices.end(), 0);\n        sort(day_indices.begin(), day_indices.end(), [&](int a, int b) {\n            if (load[a] != load[b]) return load[a] < load[b];\n            return day_size[a] < day_size[b]; // Tie-breaker: size\n        });\n\n        bool assigned = false;\n        for (int d : day_indices) {\n            if (day_size[d] >= K) continue;\n\n            // Check if adding this edge to day 'd' disconnects the graph\n            if (is_connected(d, eid)) {\n                edge_day[eid] = d;\n                load[d] += e_usage;\n                day_size[d]++;\n                assigned = true;\n                break;\n            }\n        }\n\n        // Fallback: If no day maintains connectivity (e.g., strict constraints),\n        // we must assign it to a valid day anyway to satisfy output format and constraints.\n        // We choose the day with minimum load that has space.\n        if (!assigned) {\n            int best_d = -1;\n            long long min_load = LLONG_MAX;\n            \n            for (int d = 0; d < D; ++d) {\n                if (day_size[d] < K) {\n                    if (load[d] < min_load) {\n                        min_load = load[d];\n                        best_d = d;\n                    }\n                }\n            }\n\n            // Assign to the best found day\n            if (best_d != -1) {\n                edge_day[eid] = best_d;\n                load[best_d] += e_usage;\n                day_size[best_d]++;\n            } else {\n                // This should theoretically not happen given problem constraints (slack),\n                // but as a last resort, assign to day 0 (or first available) ignoring K? \n                // No, we MUST respect K. If all full, input is invalid or logic error.\n                // Given constraints ceil(M/D) < K, there will always be space.\n            }\n        }\n    }\n\n    // 5. Output\n    for (int i = 0; i < M; ++i) {\n        if (i > 0) cout << \" \";\n        cout << edge_day[i] + 1; // Convert to 1-based index\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nconst int D_MAX = 14;\nconst int XY_MAX = 14;\n\n// Timer for managing execution time\nclass Timer {\n    chrono::system_clock::time_point start;\npublic:\n    Timer() : start(chrono::system_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::system_clock::now() - start).count();\n    }\n};\n\n// Global state\nint D;\nbool f[2][D_MAX][D_MAX]; // Front silhouette: z, x\nbool r[2][D_MAX][D_MAX]; // Right silhouette: z, y\n\n// Grid representation of the two objects\n// grid[id][z][x][y] = 1 if occupied\n// Using bitset for efficiency and easy copy/overlap\nbitset<XY_MAX * XY_MAX> grid[2][D_MAX]; // Flattened x,y for z layer. Index = x*D + y\n\n// Helper structures for fast operations during SA\nvector<int> active_x[2][D_MAX];\nvector<int> active_y[2][D_MAX];\nint y_of_x[2][D_MAX][D_MAX]; // Mapping x -> y for active cells in a layer\nint cnt_of_y[2][D_MAX][D_MAX]; // Count of x mapped to y\n\nint current_overlap = 0;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Coordinates structure\nstruct Point {\n    int x, y, z;\n};\n\nint get_idx(int x, int y) {\n    return x * D + y;\n}\n\nvoid init() {\n    // Read D\n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int x = 0; x < D; ++x) {\n                f[i][z][x] = (s[x] == '1');\n                if (f[i][z][x]) active_x[i][z].push_back(x);\n            }\n        }\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int y = 0; y < D; ++y) {\n                r[i][z][y] = (s[y] == '1');\n                if (r[i][z][y]) active_y[i][z].push_back(y);\n            }\n        }\n    }\n}\n\nvoid construct_initial(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        \n        int kx = xs.size();\n        int ky = ys.size();\n        \n        // Reset mappings\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n        \n        if (kx == 0 || ky == 0) continue;\n        \n        // Greedy matching to maximize initial overlap potential\n        // If kx >= ky, match first ky xs to all ys, remaining xs to first y\n        // If kx < ky, match all xs to first ky ys. But remaining ys must be covered.\n        // Wait, if kx < ky, we must cover all ys.\n        // Basic logic: create a set of pairs (x, y) such that all x in xs, all y in ys are covered.\n        \n        // Simplified logic for minimal volume intersection\n        // We just need a valid configuration. SA will optimize it.\n        \n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            for (int i = ky; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[0]; // Map to first y\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            // Cover remaining ys. Reuse the first x (index 0)\n            for (int i = kx; i < ky; ++i) {\n                int x = xs[0];\n                int y = ys[i];\n                // Add pair (x, y)\n                // Note: x=0 might already have a pair.\n                y_of_x[obj_id][z][x] = y; // Overwrite? No, we just add to grid and counts.\n                // y_of_x only stores ONE y for x, but an x can map to multiple y if needed?\n                // Our structure assumes 1-to-1 or 1-to-many.\n                // In this case, x=0 maps to many y.\n                // y_of_x needs to support list of y, or we just iterate to find neighbors.\n                // For SA, we used y_of_x to find current y. If x maps to multiple, this fails.\n                // So we should stick to matchings or near-matchings.\n                // Since kx < ky, we have fewer columns than rows. Some columns MUST cover multiple rows.\n                // Let's change logic: use a matching where possible, then add extra edges.\n                // Since k is small, let's just make sure every x maps to at least 1 y, and every y is mapped by some x.\n                // This is a bipartite graph cover.\n                // Minimal edges = max(kx, ky).\n                // Structure: A spanning tree structure on the bipartite graph of xs and ys.\n                // Since xs and ys are sets of integers, we can sort them and try to match proximity.\n            }\n        }\n        \n        // Re-doing the construction more robustly for the kx < ky case\n        // and handling the \"multiple y per x\" issue.\n        // Let's store edges explicitly?\n        // Given D=14, we can just store a vector of pairs per layer.\n        // But SA needs O(1) modification.\n        // Let's allow \"y_of_x\" to be just one representative y, but counts to be correct.\n        // Actually, if x maps to multiple y, which one do we move?\n        // We can restrict to matchings (kx=ky) or star graphs (one central x or one central y).\n        // Let's use the star graph approach which covers all minimal volumes.\n        \n        // Clear again\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n\n        if (kx >= ky) {\n            // Star centered at ys.\n            // Each y gets at least one distinct x.\n            // Remaining x connect to y[0].\n            for(int i=0; i<ky; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            for(int i=ky; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y; \n                // If y_of_x already had this y from previous loop, it's fine.\n                // It just means x maps to y.\n                cnt_of_y[obj_id][z][y]++;\n            }\n        } else {\n            // Star centered at xs.\n            // Each x gets at least one distinct y.\n            // Remaining y connect to x[0].\n            for(int i=0; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            // Remaining ys\n            for(int i=kx; i<ky; i++) {\n                int y = ys[i];\n                int x = xs[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                // x[0] already maps to some y. We add another edge.\n                // y_of_x[x[0]] points to ys[0]. It doesn't capture this new edge.\n                // So y_of_x is insufficient for \"many y per x\".\n                // We need a list of edges.\n                // But D=14. Max edges per layer ~14.\n                // Let's store vector<pair<int,int>> cells[obj][z].\n                // SA moves:\n                // Pick an edge (x,y). Change to (x, y_new).\n                // If cnt[y] > 1, valid.\n                // If cnt[y] == 1, must swap with (x2, y_new).\n                // This works with edge lists.\n                \n                // Let's switch to edge lists representation.\n            }\n        }\n    }\n}\n\n// Let's use a unified representation that supports the move logic perfectly.\n// We will maintain:\n// - vector<pair<int, int>> cells[2][D_MAX];  List of active cells (x,y) at layer z.\n// - This is sufficient to reconstruct the grid.\n// - Counts are derived.\n// - \"Pick x, move y\" logic:\n//   We need to find if there is an edge (x, y_curr).\n//   With vector, searching is O(N).\n//   N is small (<=14). O(14) is fine.\n//   Swapping is also O(N).\n\nvector<pair<int, int>> layer_cells[2][D_MAX];\n\nvoid build_initial_with_edge_list(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        layer_cells[obj_id][z].clear();\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        int kx = xs.size();\n        int ky = ys.size();\n        \n        if (kx == 0 || ky == 0) continue;\n\n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = ky; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[0]});\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = kx; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[0], ys[i]});\n            }\n        }\n        \n        // Update bitset\n        grid[obj_id][z].reset();\n        for (auto& p : layer_cells[obj_id][z]) {\n            grid[obj_id][z].set(get_idx(p.first, p.second));\n        }\n    }\n}\n\nvoid solve() {\n    init();\n    \n    // Construct initial states\n    build_initial_with_edge_list(0);\n    build_initial_with_edge_list(1);\n    \n    // Calculate initial overlap\n    current_overlap = 0;\n    for (int z = 0; z < D; ++z) {\n        current_overlap += (grid[0][z] & grid[1][z]).count();\n    }\n    \n    // Simulated Annealing\n    double start_time = Timer().elapsed();\n    double time_limit = 5.8; // leave margin\n    double temp_start = 100.0;\n    double temp_end = 1e-4;\n    int iter = 0;\n    \n    // Helper to calculate counts from cells\n    auto get_counts = [&](int obj, int z) {\n        vector<int> cnt(D, 0);\n        for (auto& p : layer_cells[obj][z]) cnt[p.second]++;\n        return cnt;\n    };\n    \n    while (true) {\n        double now = Timer().elapsed();\n        if (now - start_time > time_limit) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, (now - start_time) / time_limit);\n        \n        // Pick operation\n        // 0: modify obj 0, 1: modify obj 1\n        int obj = (rng() % 2);\n        int z = rng() % D;\n        \n        vector<pair<int,int>>& cells = layer_cells[obj][z];\n        if (cells.empty()) continue;\n        \n        // Select a random edge to modify\n        int idx = rng() % cells.size();\n        int x_a = cells[idx].first;\n        int y_curr = cells[idx].second;\n        \n        // Pick target y\n        // Must be active y in silhouettes\n        vector<int>& active_ys = active_y[obj][z];\n        if (active_ys.empty()) continue;\n        int y_new = active_ys[rng() % active_ys.size()];\n        \n        if (y_new == y_curr) continue;\n        \n        // Check feasibility\n        auto counts = get_counts(obj, z);\n        \n        // Proposed change: move (x_a, y_curr) to (x_a, y_new)\n        // Valid if counts[y_curr] > 1 OR we swap with another edge ending at y_new\n        \n        bool valid = false;\n        int idx_swap = -1;\n        \n        if (counts[y_curr] > 1) {\n            valid = true;\n        } else {\n            // Must swap\n            // Find edge (x_b, y_new)\n            for (int i = 0; i < cells.size(); ++i) {\n                if (cells[i].second == y_new) {\n                    idx_swap = i;\n                    break;\n                }\n            }\n            if (idx_swap != -1) valid = true;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate Delta Overlap\n        int delta = 0;\n        int other = 1 - obj;\n        \n        // Remove (x_a, y_curr)\n        int pos1 = get_idx(x_a, y_curr);\n        if (grid[other][z].test(pos1)) delta--;\n        \n        // Add (x_a, y_new)\n        int pos2 = get_idx(x_a, y_new);\n        if (grid[other][z].test(pos2)) delta++;\n        \n        if (idx_swap != -1) {\n            // Remove (x_b, y_new)\n            int x_b = cells[idx_swap].first;\n            int pos3 = get_idx(x_b, y_new);\n            if (grid[other][z].test(pos3)) delta--;\n            \n            // Add (x_b, y_curr)\n            int pos4 = get_idx(x_b, y_curr);\n            if (grid[other][z].test(pos4)) delta++;\n        }\n        \n        // Acceptance\n        if (delta >= 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n            // Apply change\n            if (idx_swap == -1) {\n                // Simple move\n                cells[idx].second = y_new;\n            } else {\n                // Swap\n                int x_b = cells[idx_swap].first;\n                cells[idx].second = y_new;\n                cells[idx_swap].second = y_curr;\n            }\n            \n            // Update grid bitset\n            grid[obj][z].reset();\n            for (auto& p : cells) {\n                grid[obj][z].set(get_idx(p.first, p.second));\n            }\n            \n            current_overlap += delta;\n        }\n    }\n    \n    // Final block construction\n    // We need to assign Block IDs.\n    \n    // 1. Identify shared cells\n    vector<int> b1(D*D*D, 0);\n    vector<int> b2(D*D*D, 0);\n    \n    // Helper to convert x,y,z to linear index\n    auto lin = [&](int x, int y, int z) { return x * D * D + y * D + z; };\n    \n    // Map to store block IDs\n    // We will perform BFS to find connected components\n    int current_id = 0;\n    \n    // Visited arrays\n    int visited[2][D_MAX][D_MAX][D_MAX]; // 0=unvisited, 1=visited\n    for(int i=0; i<2; ++i) for(int z=0; z<D; ++z) for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) visited[i][z][x][y] = 0;\n\n    // First process Shared Components\n    // Cells that are in both grid[0] and grid[1]\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && grid[1][z].test(get_idx(x,y))) {\n                    if (visited[0][z][x][y] == 0) { // Not yet assigned\n                        // Start BFS for shared component\n                        current_id++;\n                        queue<Point> q;\n                        q.push({x,y,z});\n                        visited[0][z][x][y] = current_id;\n                        visited[1][z][x][y] = current_id; // Mark visited in both\n                        \n                        while (!q.empty()) {\n                            Point p = q.front(); q.pop();\n                            int idx = lin(p.x, p.y, p.z);\n                            b1[idx] = current_id;\n                            b2[idx] = current_id;\n                            \n                            // Neighbors: 6 directions\n                            int dx[6] = {1, -1, 0, 0, 0, 0};\n                            int dy[6] = {0, 0, 1, -1, 0, 0};\n                            int dz[6] = {0, 0, 0, 0, 1, -1};\n                            \n                            for (int k = 0; k < 6; ++k) {\n                                int nx = p.x + dx[k];\n                                int ny = p.y + dy[k];\n                                int nz = p.z + dz[k];\n                                \n                                if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                    // Check if cell is shared and unvisited\n                                    if (visited[0][nz][nx][ny] == 0 && \n                                        grid[0][nz].test(get_idx(nx, ny)) && \n                                        grid[1][nz].test(get_idx(nx, ny))) {\n                                        visited[0][nz][nx][ny] = current_id;\n                                        visited[1][nz][nx][ny] = current_id;\n                                        q.push({nx, ny, nz});\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Second process Unique Components for Object 1\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && visited[0][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b1[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[0][nz][nx][ny] == 0 && grid[0][nz].test(get_idx(nx, ny))) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Third process Unique Components for Object 2\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[1][z].test(get_idx(x,y)) && visited[1][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[1][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b2[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[1][nz][nx][ny] == 0 && grid[1][nz].test(get_idx(nx, ny))) {\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    int n = current_id;\n    \n    // Output\n    cout << n << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b1[i];\n    }\n    cout << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b2[i];\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <tuple>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Solver {\n    int N, M, K;\n    vector<pair<int, int>> coords;\n    vector<tuple<int, int, long long>> edges;\n    vector<pair<int, int>> residents;\n    vector<vector<long long>> dist_nodes; \n    vector<vector<int>> dist_res; \n    vector<int> P;\n    vector<int> B;\n    \n    // Heuristic data\n    vector<vector<int>> resident_order; // Sorted vertices by distance for each resident\n    vector<int> assign; // Assign resident k to vertex assign[k]\n    vector<bool> active;\n\n    Solver(int n, int m, int k) : N(n), M(m), K(k) {\n        coords.resize(N);\n        edges.resize(M);\n        residents.resize(K);\n        dist_nodes.assign(N, vector<long long>(N, 1e18));\n        dist_res.assign(N, vector<int>(K));\n        P.assign(N, 0);\n        B.assign(M, 0);\n        resident_order.assign(K, vector<int>(N));\n        assign.assign(K, -1);\n        active.assign(N, false);\n    }\n\n    void solve() {\n        // 1. Floyd-Warshall\n        for (int i = 0; i < N; ++i) dist_nodes[i][i] = 0;\n        for (auto& e : edges) {\n            int u, v;\n            long long w;\n            tie(u, v, w) = e;\n            u--; v--;\n            if (w < dist_nodes[u][v]) {\n                dist_nodes[u][v] = w;\n                dist_nodes[v][u] = w;\n            }\n        }\n        for (int k = 0; k < N; ++k) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (dist_nodes[i][k] + dist_nodes[k][j] < dist_nodes[i][j]) {\n                        dist_nodes[i][j] = dist_nodes[i][k] + dist_nodes[k][j];\n                    }\n                }\n            }\n        }\n\n        // 2. Precompute resident distances and sort\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < K; ++k) {\n                long long dx = (long long)coords[i].first - residents[k].first;\n                long long dy = (long long)coords[i].second - residents[k].second;\n                dist_res[i][k] = (int)round(sqrt((double)dx*dx + dy*dy));\n            }\n        }\n        \n        vector<int> temp_nodes(N);\n        iota(temp_nodes.begin(), temp_nodes.end(), 0);\n        for (int k = 0; k < K; ++k) {\n            sort(temp_nodes.begin(), temp_nodes.end(), [&](int a, int b) {\n                return dist_res[a][k] < dist_res[b][k];\n            });\n            resident_order[k] = temp_nodes;\n        }\n\n        // 3. Helper functions\n        auto calc_mst_cost = [&]() {\n            long long cost = 0;\n            vector<bool> in_mst(N, false);\n            vector<long long> min_dist(N, 1e18);\n            min_dist[0] = 0;\n            for (int i = 0; i < N; ++i) {\n                int u = -1;\n                for (int j = 0; j < N; ++j) {\n                    if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                        u = j;\n                    }\n                }\n                if (u == -1) break;\n                in_mst[u] = true;\n                cost += min_dist[u];\n                for (int v = 0; v < N; ++v) {\n                    if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                        min_dist[v] = dist_nodes[u][v];\n                    }\n                }\n            }\n            return cost;\n        };\n\n        auto calc_node_cost = [&]() {\n            long long cost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (active[i]) {\n                    cost += (long long)P[i] * P[i];\n                }\n            }\n            return cost;\n        };\n\n        auto reassign = [&]() {\n            // Assign residents to nearest active vertex\n            // Also calculate P\n            // Returns true if any resident is uncovered (>5000)\n            bool uncovered = false;\n            fill(P.begin(), P.end(), 0);\n            for (int k = 0; k < K; ++k) {\n                for (int v : resident_order[k]) {\n                    if (active[v]) {\n                        assign[k] = v;\n                        int d = dist_res[v][k];\n                        if (d > P[v]) P[v] = d;\n                        if (d > 5000) uncovered = true;\n                        break;\n                    }\n                }\n            }\n            return uncovered;\n        };\n\n        // 4. Initial Solution (Greedy Coverage)\n        active[0] = true;\n        bool valid = reassign();\n        \n        // Add vertices until valid\n        while (valid) {\n            int best_u = -1;\n            int best_k = -1;\n            int max_dist = -1;\n            \n            // Find the resident with max distance to nearest active\n            for (int k = 0; k < K; ++k) {\n                int d = dist_res[assign[k]][k];\n                if (d > max_dist) {\n                    max_dist = d;\n                    best_k = k;\n                }\n            }\n            \n            // Find vertex u that covers best_k best\n            for (int u : resident_order[best_k]) {\n                if (!active[u]) {\n                    best_u = u;\n                    break;\n                }\n            }\n            \n            if (best_u != -1) {\n                active[best_u] = true;\n                valid = reassign();\n            } else {\n                // Should not happen given problem constraints\n                break; \n            }\n        }\n\n        long long current_edge_cost = calc_mst_cost();\n        long long current_node_cost = calc_node_cost();\n        long long total_cost = current_edge_cost + current_node_cost;\n\n        // 5. Optimization Loop\n        mt19937 rng(20240520);\n        \n        // Run multiple passes of Add/Remove\n        for (int iter = 0; iter < 10; ++iter) {\n            vector<int> indices(N);\n            iota(indices.begin(), indices.end(), 0);\n            \n            // Greedy Remove\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (u == 0 || !active[u]) continue;\n                \n                // Check if we can remove u\n                // We need to reassign residents of u to other active vertices\n                // And check if cost decreases\n                \n                vector<int> saved_P_u(N, 0); // Only need to track changes for modified P\n                vector<int> modified_nodes;\n                \n                // Tentative removal\n                active[u] = false;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost - (long long)P[u] * P[u];\n                \n                // For residents assigned to u, find new owner\n                for (int k = 0; k < K; ++k) {\n                    if (assign[k] == u) {\n                        int new_v = -1;\n                        for (int v : resident_order[k]) {\n                            if (active[v]) {\n                                new_v = v;\n                                break;\n                            }\n                        }\n                        if (new_v == -1) {\n                            invalid = true;\n                            break;\n                        }\n                        int d = dist_res[new_v][k];\n                        if (d > 5000) {\n                            invalid = true;\n                            break;\n                        }\n                        \n                        // Update tentative P for new_v\n                        if (d > P[new_v]) {\n                            if (saved_P_u[new_v] == 0) saved_P_u[new_v] = P[new_v];\n                            P[new_v] = d;\n                        }\n                    }\n                }\n                \n                if (!invalid) {\n                    // Calculate new node cost based on changes\n                    for (int v = 0; v < N; ++v) {\n                        if (v != u && saved_P_u[v] != 0) {\n                            tentative_node_cost += (long long)P[v] * P[v];\n                            tentative_node_cost -= (long long)saved_P_u[v] * saved_P_u[v];\n                        }\n                    }\n                    \n                    long long new_edge_cost = calc_mst_cost();\n                    if (tentative_node_cost + new_edge_cost < total_cost) {\n                        // Accept removal\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = tentative_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        // Reassign permanently\n                        reassign(); \n                        // P is updated by reassign\n                        continue; \n                    }\n                }\n                \n                // Reject: Revert\n                active[u] = true;\n                for (int v = 0; v < N; ++v) {\n                    if (saved_P_u[v] != 0) P[v] = saved_P_u[v];\n                }\n            }\n\n            // Greedy Add\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (active[u]) continue;\n                \n                // Try add u\n                active[u] = true;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost; // P[u] starts at 0, might increase\n                \n                // Check residents who might move to u\n                vector<int> saved_P(N, 0);\n                \n                // We only care if cost decreases.\n                // Simply run reassign to get new P.\n                // But reassign is O(KN). Since N=100, K=5000, O(5e5) per check is okay.\n                // 200 checks -> 1e8 ops. A bit slow but acceptable in C++.\n                \n                // Optimization: only check residents where u is closer than current owner\n                // Or just run reassign on a copy? No, just run reassign and revert.\n                \n                // Let's do fast check first: if dist(u, any resident in C_v) < P_v, potential gain.\n                // This is heuristic. For safety, let's just use reassign.\n                \n                reassign(); \n                \n                // Check validity\n                valid = true;\n                for (int i=0; i<N; ++i) if (active[i] && P[i] > 5000) valid = false;\n                \n                if (valid) {\n                    long long new_node_cost = calc_node_cost();\n                    long long new_edge_cost = calc_mst_cost();\n                    if (new_node_cost + new_edge_cost < total_cost) {\n                        // Accept\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = new_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        continue;\n                    }\n                }\n                \n                // Reject\n                active[u] = false;\n                // Revert P and assign\n                reassign();\n            }\n        }\n\n        // 6. Construct Output Edges\n        // Prim's MST on active vertices, then expand to shortest paths\n        vector<vector<int>> mst_adj(N, vector<int>(N, 0));\n        vector<bool> in_mst(N, false);\n        vector<int> parent(N, -1);\n        vector<long long> min_dist(N, 1e18);\n        min_dist[0] = 0;\n\n        for (int i = 0; i < N; ++i) {\n            int u = -1;\n            for (int j = 0; j < N; ++j) {\n                if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                    u = j;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (parent[u] != -1) {\n                // Find path between parent[u] and u\n                int s = parent[u];\n                int t = u;\n                \n                // Dijkstra\n                vector<long long> d(N, 1e18);\n                vector<int> prev(N, -1);\n                d[s] = 0;\n                priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n                pq.push({0, s});\n                \n                while(!pq.empty()){\n                    auto [dist, v] = pq.top(); pq.pop();\n                    if(dist > d[v]) continue;\n                    if(v == t) break;\n                    for(auto& edge : edges){\n                        int a, b; long long w;\n                        tie(a, b, w) = edge;\n                        a--; b--;\n                        if(v == a && d[a] + w < d[b]){\n                            d[b] = d[a] + w;\n                            prev[b] = a;\n                            pq.push({d[b], b});\n                        } else if (v == b && d[b] + w < d[a]){\n                            d[a] = d[b] + w;\n                            prev[a] = b;\n                            pq.push({d[a], a});\n                        }\n                    }\n                }\n                \n                int curr = t;\n                while(curr != s && curr != -1) {\n                    int p = prev[curr];\n                    if (p == -1) break;\n                    for (int j = 0; j < M; ++j) {\n                        int uj, vj; long long wj;\n                        tie(uj, vj, wj) = edges[j];\n                        uj--; vj--;\n                        if ((uj == p && vj == curr) || (uj == curr && vj == p)) {\n                            B[j] = 1;\n                            break;\n                        }\n                    }\n                    curr = p;\n                }\n            }\n            \n            for (int v = 0; v < N; ++v) {\n                if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                    min_dist[v] = dist_nodes[u][v];\n                    parent[v] = u;\n                }\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if (i > 0) cout << \" \";\n            cout << P[i];\n        }\n        cout << \"\\n\";\n        for (int j = 0; j < M; ++j) {\n            if (j > 0) cout << \" \";\n            cout << B[j];\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    \n    Solver solver(N, M, K);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        solver.edges[i] = {u, v, w};\n    }\n    for (int i = 0; i < K; ++i) {\n        cin >> solver.residents[i].first >> solver.residents[i].second;\n    }\n    \n    solver.solve();\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <numeric>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 30;\nconst int INF = 1e9;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> all_vals;\n    map<int, pair<int, int>> pos; // value -> (x, y)\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            grid[x][y] = v;\n            pos[v] = {x, y};\n            all_vals.push_back(v);\n        }\n    }\n\n    // Determine target tiers\n    // Sort values to determine their rank\n    sort(all_vals.begin(), all_vals.end());\n    map<int, int> rank_of_val;\n    for (int i = 0; i < (int)all_vals.size(); ++i) {\n        rank_of_val[all_vals[i]] = i;\n    }\n\n    // Map rank to target tier\n    // Total balls M = N(N+1)/2.\n    // Tier x contains balls with ranks T(x) to T(x+1)-1\n    // where T(x) = x(x+1)/2.\n    auto get_tier = [&](int rank) -> int {\n        // Solve t(t+1)/2 <= rank\n        // t^2 + t - 2*rank <= 0\n        // t = (-1 + sqrt(1 + 8*rank)) / 2\n        int t = (int)((-1 + sqrt(1 + 8.0 * rank)) / 2);\n        while ((t + 1) * (t + 2) / 2 <= rank) t++;\n        while (t * (t + 1) / 2 > rank) t--;\n        return t;\n    };\n\n    vector<int> target_tier(465);\n    for (int i = 0; i < 465; ++i) {\n        target_tier[i] = get_tier(i);\n    }\n\n    // Output operations\n    vector<tuple<int, int, int, int>> operations;\n\n    // Helper: Distance on hexagonal grid\n    // Based on analysis, dist((x1,y1), (x2,y2)) = max(|x1-x2|, |y1-y2|)\n    auto dist = [](int x1, int y1, int x2, int y2) -> int {\n        return max(abs(x1 - x2), abs(y1 - y2));\n    };\n\n    // Helper: Neighbors\n    vector<pair<int, int>> directions = {\n        {0, -1}, {0, 1}, {-1, 0}, {-1, -1}, {1, 0}, {1, 1}\n    };\n\n    // Process tiers from bottom to top\n    for (int t = N - 1; t >= 0; --t) {\n        // Identify balls belonging to this tier\n        // Start rank = t(t+1)/2, count = t+1\n        int start_rank = t * (t + 1) / 2;\n        int count = t + 1;\n        \n        vector<int> balls_in_tier;\n        for (int i = 0; i < count; ++i) {\n            balls_in_tier.push_back(all_vals[start_rank + i]);\n        }\n\n        // Get current positions of these balls\n        // We need to assign them to (t, 0), (t, 1), ..., (t, t)\n        // Minimum Cost Flow Assignment\n        \n        int s_idx = 0; // Source index for graph (virtual)\n        // We use 0..(t) for balls, (t+1)..(2t+1) for targets\n        \n        mcf_graph<int, int> g((t + 1) * 2 + 2);\n        int SRC = (t + 1) * 2;\n        int SNK = (t + 1) * 2 + 1;\n\n        for (int i = 0; i < count; ++i) {\n            int val = balls_in_tier[i];\n            auto [cx, cy] = pos[val];\n            \n            g.add_edge(SRC, i, 1, 0); // Source to ball node\n            \n            for (int j = 0; j < count; ++j) {\n                int cost = dist(cx, cy, t, j);\n                g.add_edge(i, (t + 1) + j, 1, cost); // Ball node to target node\n            }\n        }\n        \n        for (int j = 0; j < count; ++j) {\n             g.add_edge((t + 1) + j, SNK, 1, 0); // Target node to Sink\n        }\n\n        auto flow_res = g.flow(SRC, SNK);\n        // vector<pair<int, int>> assignment; // ball_index -> target_y\n        // The edges in flow_res correspond to the graph edges.\n        // We need to reconstruct which ball goes to which target.\n        \n        map<int, pair<int, int>> final_targets; // val -> (tx, ty)\n        \n        // Iterate edges to find matches\n        auto edges = g.edges();\n        for (auto &e : edges) {\n            if (e.from >= SRC || e.to >= SNK || e.to == SRC || e.from == SNK) continue;\n            if (e.from < t + 1 && e.to >= t + 1 && e.to < (t + 1) * 2 && e.flow > 0) {\n                int ball_idx = e.from;\n                int target_y = e.to - (t + 1);\n                int val = balls_in_tier[ball_idx];\n                final_targets[val] = {t, target_y};\n            }\n        }\n\n        // Now move balls to their targets\n        // We maintain a set of 'blocked' nodes (already settled balls)\n        // Initially, all balls in tiers > t are blocked.\n        // As we place balls in tier t, they become blocked.\n        \n        // To check if a node (x,y) is blocked:\n        // The ball at (x,y) must have target_tier > t, OR (target_tier == t AND already placed).\n        \n        // We process the balls in this tier one by one.\n        // Note: The order might matter slightly for pathfinding length if we consider other unplaced balls in this tier as obstacles? \n        // But they are not obstacles; we can swap with them.\n        // Only 'settled' balls are obstacles.\n        \n        for (int val : balls_in_tier) {\n            auto [tx, ty] = final_targets[val];\n            auto [sx, sy] = pos[val];\n\n            if (sx == tx && sy == ty) {\n                // Already there, mark as settled (implicit)\n                continue;\n            }\n\n            // BFS to find path from (sx, sy) to (tx, ty)\n            // Cannot pass through settled nodes.\n            \n            queue<pair<int, int>> q;\n            map<pair<int, int>, pair<int, int>> parent;\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            \n            q.push({sx, sy});\n            visited[sx][sy] = true;\n            \n            bool found = false;\n            \n            while (!q.empty() && !found) {\n                auto [cx, cy] = q.front();\n                q.pop();\n                \n                for (auto [dx, dy] : directions) {\n                    int nx = cx + dx;\n                    int ny = cy + dy;\n                    \n                    // Bounds check\n                    if (nx < 0 || nx >= N || ny < 0 || ny > nx) continue;\n                    \n                    if (visited[nx][ny]) continue;\n                    \n                    // Check obstacle\n                    int ball_at_nx = grid[nx][ny];\n                    int b_tier = target_tier[rank_of_val[ball_at_nx]];\n                    \n                    bool is_obstacle = false;\n                    if (b_tier > t) is_obstacle = true;\n                    else if (b_tier == t) {\n                        // Check if this ball is already settled (placed in its target)\n                        // We know the target of this ball if it is in final_targets\n                        // But we are iterating balls_in_tier.\n                        // If ball_at_nx is in final_targets, check if it's already placed.\n                        if (final_targets.count(ball_at_nx)) {\n                             // This ball belongs to this tier.\n                             // Is it already in its target?\n                             auto [b_tx, b_ty] = final_targets[ball_at_nx];\n                             if (nx == b_tx && ny == b_ty) {\n                                 is_obstacle = true;\n                             }\n                        }\n                    }\n                    \n                    if (!is_obstacle) {\n                        visited[nx][ny] = true;\n                        parent[{nx, ny}] = {cx, cy};\n                        q.push({nx, ny});\n                        if (nx == tx && ny == ty) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            // Reconstruct path and execute swaps\n            vector<pair<int, int>> path;\n            {\n                auto curr = make_pair(tx, ty);\n                while (curr != make_pair(sx, sy)) {\n                    path.push_back(curr);\n                    curr = parent[curr];\n                }\n                path.push_back({sx, sy});\n                reverse(path.begin(), path.end());\n            }\n\n            // Execute swaps\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                auto [u1, v1] = path[i];\n                auto [u2, v2] = path[i+1];\n                \n                // Swap in grid\n                int val1 = grid[u1][v1];\n                int val2 = grid[u2][v2];\n                \n                swap(grid[u1][v1], grid[u2][v2]);\n                \n                // Update pos map\n                pos[val1] = {u2, v2};\n                pos[val2] = {u1, v1};\n                \n                operations.push_back({u1, v1, u2, v2});\n            }\n        }\n    }\n\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <numeric>\n\nusing namespace std;\n\n// Grid configuration\nconst int D = 9;\nconst int INF = 1e9;\n// Entrance\nconst int ER = 0;\nconst int EC = 4;\n\nstruct State {\n    vector<vector<bool>> obstacle;\n    vector<vector<int>> dist;\n    vector<vector<bool>> occupied;\n    int total_containers;\n\n    State(int n, const vector<pair<int, int>>& obs_coords) {\n        obstacle.assign(D, vector<bool>(D, false));\n        occupied.assign(D, vector<bool>(D, false));\n        dist.assign(D, vector<int>(D, -1));\n        \n        // Mark entrance and adjacent as not obstacles (problem guarantee)\n        // But we also treat them as not storage space.\n        \n        // Mark obstacles\n        for (auto p : obs_coords) {\n            obstacle[p.first][p.second] = true;\n        }\n\n        // Calculate distances from entrance\n        queue<pair<int, int>> q;\n        q.push({ER, EC});\n        dist[ER][EC] = 0;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (dist[nr][nc] == -1 && !obstacle[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + 1;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Count available spots\n        total_containers = 0;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                // Entrance and obstacles are not for storage\n                if ((i == ER && j == EC) || obstacle[i][j]) continue;\n                // Problem statement says entrance and its 3 adjacent are not obstacles\n                // But they are valid storage spots? \n                // \"Each D x D - 1 - N square other than the entrance and obstacles can hold at most 1 container.\"\n                // So adjacent squares (0,3), (0,5), (1,4) ARE valid storage spots.\n                total_containers++;\n            }\n        }\n    }\n    \n    // Find empty cells reachable from entrance via empty cells\n    vector<pair<int, int>> get_reachable_empty() {\n        vector<pair<int, int>> reachable;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        \n        // Start from entrance\n        q.push({ER, EC});\n        visited[ER][EC] = true;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (!visited[nr][nc] && !obstacle[nr][nc] && !occupied[nr][nc]) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                        reachable.push_back({nr, nc});\n                    }\n                }\n            }\n        }\n        return reachable;\n    }\n\n    // Check if placing a container at (tr, tc) blocks other empty cells from entrance\n    // It blocks if, after marking (tr, tc) occupied, some previously reachable empty cell becomes unreachable.\n    bool is_safe_placement(int tr, int tc) {\n        // Temporarily mark as occupied\n        occupied[tr][tc] = true;\n        \n        vector<pair<int, int>> new_reachable = get_reachable_empty();\n        \n        // Restore\n        occupied[tr][tc] = false;\n\n        // Count previously reachable (excluding the cell itself)\n        auto prev_reachable = get_reachable_empty();\n        \n        // Actually, we can just compare counts of reachable nodes (excluding the one we are filling)\n        // Since we are adding an obstacle, the set of reachable empty cells can only shrink.\n        // We want it to NOT shrink (except for the cell itself).\n        // Note: get_reachable_empty returns EMPTY cells.\n        // (tr, tc) is empty before placement. It is in prev_reachable.\n        // After placement, it is not in new_reachable.\n        // So we expect |new_reachable| == |prev_reachable| - 1.\n        \n        if (new_reachable.size() == prev_reachable.size() - 1) return true;\n        return false;\n    }\n\n    // Choose best cell for container t\n    pair<int, int> choose_placement(int t) {\n        auto reachable = get_reachable_empty();\n        \n        if (reachable.empty()) {\n            // Should not happen\n            return {-1, -1};\n        }\n\n        // Target distance\n        // Map t from [0, M-1] to a distance range\n        // Max distance is around 15.\n        double ratio = (double)t / total_containers;\n        \n        // We want to sort candidates.\n        // Heuristic: \n        // 1. Is safe (doesn't block).\n        // 2. Distance is close to target.\n        // 3. (Optional) Prefer low degree or corners?\n        \n        vector<tuple<int, int, double>> candidates; // score, r, c\n        // Score > 0 means safe, < 0 unsafe.\n        \n        int max_dist = 0;\n        for(auto& p : reachable) max_dist = max(max_dist, dist[p.first][p.second]);\n        \n        for (auto& p : reachable) {\n            int r = p.first;\n            int c = p.second;\n            int d = dist[r][c];\n            \n            double ideal_d = ratio * max_dist;\n            double dist_error = abs(d - ideal_d);\n            \n            int safe_score = is_safe_placement(r, c) ? 1000 : 0;\n            \n            // Combine: safety is most important. Then distance match.\n            // We maximize score.\n            double final_score = safe_score - dist_error;\n            \n            // If unsafe, we might still want to place it if we have no other choice,\n            // but we pick the one with max_dist_error (least bad? or best distance?).\n            // Let's say if unsafe, score is just -dist_error.\n            // If safe, score is 1000 - dist_error.\n            \n            candidates.push_back({final_score, r, c});\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<tuple<double, int, int>>());\n        \n        // Pick the best one\n        return {get<1>(candidates[0]), get<2>(candidates[0])};\n    }\n\n    void place(int t, int r, int c) {\n        occupied[r][c] = true;\n        cout << r << \" \" << c << endl;\n        // cout << \"# Placed \" << t << \" at \" << r << \" \" << c << endl;\n    }\n\n    // Retrieve phase\n    void retrieve_all(const map<int, pair<int, int>>& id_to_coord) {\n        vector<pair<int, int>> retrieval_order;\n        \n        // Set of remaining IDs\n        set<int> remaining;\n        for (auto p : id_to_coord) remaining.insert(p.first);\n        \n        // While there are containers\n        while (!remaining.empty()) {\n            // Find reachable occupied cells\n            queue<pair<int, int>> q;\n            vector<vector<bool>> visited(D, vector<bool>(D, false));\n            q.push({ER, EC});\n            visited[ER][EC] = true;\n            \n            vector<int> reachable_ids;\n            \n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n\n            while (!q.empty()) {\n                auto curr = q.front(); 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                    if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                        if (!visited[nr][nc] && !obstacle[nr][nc]) {\n                            // Check if occupied\n                            bool is_occupied = false;\n                            int id_at = -1;\n                            // We need to check if this coordinate has a container that is still in 'remaining'\n                            // We can look up in id_to_coord map (inverse map needed?)\n                            // Actually we have id_to_coord. We need coord_to_id.\n                            // Or just iterate remaining? remaining size is up to 80. O(80*80) is fine.\n                            for (int rid : remaining) {\n                                if (id_to_coord.at(rid) == make_pair(nr, nc)) {\n                                    is_occupied = true;\n                                    id_at = rid;\n                                    break;\n                                }\n                            }\n\n                            if (is_occupied) {\n                                visited[nr][nc] = true; // Can reach this square (but stop here?)\n                                // Actually we pass through it? No.\n                                // Rule: \"passing through adjacent empty squares\".\n                                // Occupied squares are NOT empty.\n                                // So we CANNOT pass through occupied squares.\n                                // We can only reach the occupied square itself if we are adjacent to an empty square.\n                                // But we CANNOT go THROUGH an occupied square.\n                                // However, the square containing the container is the target.\n                                // The rule says: \"The square containing the container to be transported out must be reachable... by passing through adjacent empty squares.\"\n                                // This means the path ends at the square. The square itself is occupied.\n                                // So we just check connectivity via EMPTY squares.\n                                // If (nr, nc) is occupied, we don't push it to queue.\n                                // But we record it as a retrievable target.\n                                reachable_ids.push_back(id_at);\n                            } else {\n                                // Empty, traverse\n                                visited[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (reachable_ids.empty()) {\n                // Should not happen\n                break;\n            }\n            \n            // Pick smallest ID\n            sort(reachable_ids.begin(), reachable_ids.end());\n            int to_retrieve = reachable_ids[0];\n            \n            retrieval_order.push_back(id_to_coord.at(to_retrieve));\n            remaining.erase(to_retrieve);\n        }\n        \n        // Output\n        for (auto p : retrieval_order) {\n            cout << p.first << \" \" << p.second << endl;\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N;\n    cin >> N;\n    \n    vector<pair<int, int>> obstacles(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    State solver(N, obstacles);\n    \n    map<int, pair<int, int>> id_to_coord;\n    \n    for (int i = 0; i < solver.total_containers; ++i) {\n        int t;\n        cin >> t;\n        \n        auto p = solver.choose_placement(t);\n        solver.place(t, p.first, p.second);\n        id_to_coord[t] = p;\n    }\n    \n    solver.retrieve_all(id_to_coord);\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/convolution>\n#include <atcoder/math>\n#include <atcoder/maxflow>\n#include <atcoder/modint>\n#include <atcoder/scc>\n#include <atcoder/segtree>\n#include <atcoder/string>\n#include <boost/multiprecision/cpp_int.hpp>\n\nusing namespace std;\nusing namespace atcoder;\nnamespace bmp = boost::multiprecision;\n\n// Constants\nconstexpr int N = 50;\nconstexpr int M = 100;\n\n// Global variables\nint n, m;\nint grid[N][N];\nvector<pair<int, int>> pos[M + 1];\nset<pair<int, int>> region[M + 1];\nvector<int> adj[M + 1];\nset<int> adj_set[M + 1];\nbool is_boundary[M + 1];\nint color_cnt[M + 1];\n\n// Directions\nint dx[4] = {0, 1, 0, -1};\nint dy[4] = {1, 0, -1, 0};\n\n// Heuristic variables\nset<pair<int, int>> kept[M + 1];\nbool removed[N][N];\n\n// Helper functions\nbool in_grid(int x, int y) {\n    return 0 <= x && x < n && 0 <= y && y < n;\n}\n\nvoid build_graph() {\n    // Initialize adj_set\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int c = grid[i][j];\n            region[c].insert({i, j});\n            color_cnt[c]++;\n            \n            // Check boundary for color 0 (outside)\n            if (i == 0 || i == N - 1 || j == 0 || j == N - 1) {\n                is_boundary[c] = true;\n            }\n        }\n    }\n\n    // Build adj\n    for (int c = 1; c <= m; ++c) {\n        for (auto [x, y] : region[c]) {\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny)) {\n                    int nc = grid[nx][ny];\n                    if (nc != c) {\n                        if (adj_set[c].find(nc) == adj_set[c].end()) {\n                            adj_set[c].insert(nc);\n                            adj[c].push_back(nc);\n                            adj_set[nc].insert(c);\n                            adj[nc].push_back(c);\n                        }\n                    }\n                } else {\n                    // Outside is color 0\n                    if (adj_set[c].find(0) == adj_set[c].end()) {\n                        adj_set[c].insert(0);\n                        adj[c].push_back(0);\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Check if removing v (x, y) of color c is valid\nbool can_remove(int c, int x, int y) {\n    // 1. Connectivity check for kept[c] - {v}\n    // We need to verify if removing v disconnects the kept cells of c.\n    // Since we remove one by one, we can just check if v is an articulation point in the subgraph induced by kept[c].\n    // However, kept[c] is a subset of grid cells.\n    // Simple BFS from one neighbor of v in kept[c] (excluding v) to see if it reaches all other kept cells of c.\n    \n    // If kept[c] has only 1 cell (v), we cannot remove it if c has neighbors or c is boundary.\n    // Actually, we can't remove it if c has any neighbors in adj (needs witnesses).\n    // Since c must be connected, kept[c] must be non-empty.\n    if (kept[c].size() == 1) return false;\n\n    vector<pair<int, int>> neighbors_in_c;\n    for (int k = 0; k < 4; ++k) {\n        int nx = x + dx[k];\n        int ny = y + dy[k];\n        if (in_grid(nx, ny) && kept[c].count({nx, ny})) {\n            neighbors_in_c.push_back({nx, ny});\n        }\n    }\n\n    if (neighbors_in_c.empty()) {\n        // v is isolated in kept[c]? No, v is connected to kept[c].\n        // If v has no neighbors in kept[c], then kept[c] = {v} (size 1 case) or v is disconnected from kept[c] (impossible).\n        // So if size > 1, must have neighbors.\n        return false; \n    }\n\n    // Perform BFS from neighbors_in_c[0]\n    // Target: visit all nodes in kept[c] except v\n    queue<pair<int, int>> q;\n    set<pair<int, int>> visited;\n    q.push(neighbors_in_c[0]);\n    visited.insert(neighbors_in_c[0]);\n    \n    int count = 0;\n    while (!q.empty()) {\n        auto [cx, cy] = q.front(); q.pop();\n        count++;\n        for (int k = 0; k < 4; ++k) {\n            int nx = cx + dx[k];\n            int ny = cy + dy[k];\n            if (in_grid(nx, ny) && (nx != x || ny != y) && kept[c].count({nx, ny}) && !visited.count({nx, ny})) {\n                visited.insert({nx, ny});\n                q.push({nx, ny});\n            }\n        }\n    }\n\n    // We should be able to visit kept[c].size() - 1 nodes\n    if (count != kept[c].size() - 1) {\n        return false; // v is an articulation point\n    }\n\n    // 2. Witness check\n    // For each neighbor d of c, we need some u in kept[c] (u != v) adjacent to kept[d].\n    // Since we only remove v, if v was the ONLY witness for some d, we cannot remove it.\n    \n    for (int d : adj[c]) {\n        if (d == 0) continue; // 0 is outside, handled by boundary property\n        \n        bool has_witness = false;\n        // Check if any cell u in kept[c] - {v} is adjacent to kept[d]\n        // We can iterate over boundary of kept[d] or just iterate kept[c] - {v}\n        // Optimization: Only check neighbors of v in kept[c]? No, because other cells of c might witness d.\n        // But if v was NOT a witness for d, removing it doesn't affect d.\n        // If v WAS a witness, we need to check if there's another witness.\n        \n        // Is v a witness for d?\n        bool v_is_witness = false;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && kept[d].count({nx, ny})) {\n                v_is_witness = true;\n                break;\n            }\n        }\n        \n        if (!v_is_witness) continue; // Safe to remove\n        \n        // v is a witness. Find another one.\n        has_witness = false;\n        for (auto [cx, cy] : kept[c]) {\n            if (cx == x && cy == y) continue;\n            for (int k = 0; k < 4; ++k) {\n                int nx = cx + dx[k];\n                int ny = cy + dy[k];\n                if (in_grid(nx, ny) && kept[d].count({nx, ny})) {\n                    has_witness = true;\n                    break;\n                }\n            }\n            if (has_witness) break;\n        }\n        \n        if (!has_witness) return false;\n    }\n\n    return true;\n}\n\nvoid solve() {\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    build_graph();\n\n    // Initialize kept sets\n    for (int c = 1; c <= m; ++c) {\n        kept[c] = region[c];\n    }\n    memset(removed, false, sizeof(removed));\n\n    // Greedy removal BFS queue\n    // Start with all boundary cells of the grid\n    queue<pair<int, int>> q;\n    \n    // Find all boundary cells (grid boundary)\n    for (int i = 0; i < n; ++i) {\n        if (!removed[i][0]) q.push({i, 0});\n        if (!removed[i][n-1]) q.push({i, n-1});\n    }\n    for (int j = 0; j < n; ++j) {\n        if (!removed[0][j]) q.push({0, j});\n        if (!removed[n-1][j]) q.push({n-1, j});\n    }\n\n    // Also, any cell adjacent to a removed cell is a candidate\n    // We will add them to q dynamically.\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        \n        if (removed[x][y]) continue;\n        \n        int c = grid[x][y];\n        \n        // If color is not boundary, we generally shouldn't remove it (as per analysis)\n        // Unless it's \"shielded\" from 0? But we start from boundary 0, so we only reach boundary colors.\n        // So we only process c in is_boundary.\n        if (!is_boundary[c]) continue;\n\n        if (can_remove(c, x, y)) {\n            // Remove v\n            removed[x][y] = true;\n            kept[c].erase({x, y});\n            \n            // Add neighbors to queue\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny) && !removed[nx][ny]) {\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Construct output\n    // Fill with 0 first\n    int out_grid[N][N];\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            out_grid[i][j] = 0;\n        }\n    }\n\n    // Fill kept cells\n    for (int c = 1; c <= m; ++c) {\n        for (auto [x, y] : kept[c]) {\n            out_grid[x][y] = c;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << out_grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <iomanip>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\n\n// Structure to represent a node in the tournament tree\n// We only need to store the winner index at each node for the standard logic,\n// but to recover the \"depth\" or status of losers for weight estimation, we might need more.\n// However, standard tournament sort only maintains the path of winners.\n// To estimate weights of losers, we can just look at the remaining tree.\n// Items that are closer to the root in the remaining tree are \"winners\" of sub-tournaments, hence heavier.\n// Items that are leaves are losers of the first round, hence lighter.\n// So we can assign weights by traversing the remaining tree in level order.\n\nstruct Node {\n    int winner = -1;\n    int left = -1;\n    int right = -1;\n    int depth = 0; // Distance from root (0 is root)\n};\n\nvector<Node> tree;\nvector<int> extracted_indices; // Stores the indices of items in sorted order (heaviest first)\nvector<int> item_to_weight_est; // Estimated weight for each item\n\nint ask(int l, int r) {\n    cout << 1 << \" \" << 1 << \" \" << l << \" \" << r << endl;\n    cout.flush();\n    query_count++;\n    string res;\n    cin >> res;\n    if (res == \"<\") return -1;\n    if (res == \">\") return 1;\n    return 0;\n}\n\n// Build tournament tree.\n// Returns the index of the root node in the 'tree' vector.\nint build_tournament(const vector<int>& items, int depth) {\n    int node_idx = tree.size();\n    tree.emplace_back();\n    tree[node_idx].depth = depth;\n\n    if (items.size() == 1) {\n        tree[node_idx].winner = items[0];\n        return node_idx;\n    }\n\n    int mid = items.size() / 2;\n    vector<int> left_items(items.begin(), items.begin() + mid);\n    vector<int> right_items(items.begin() + mid, items.end());\n\n    int left_idx = build_tournament(left_items, depth + 1);\n    int right_idx = build_tournament(right_items, depth + 1);\n\n    tree[node_idx].left = left_idx;\n    tree[node_idx].right = right_idx;\n\n    int w_left = tree[left_idx].winner;\n    int w_right = tree[right_idx].winner;\n\n    // If one side is empty (shouldn't happen with split logic but good for safety)\n    if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n    return node_idx;\n}\n\n// Re-evaluate the node based on its children.\n// Used after a winner is extracted and removed.\nvoid update_node(int node_idx) {\n    if (tree[node_idx].left == -1 && tree[node_idx].right == -1) {\n        // Leaf\n        tree[node_idx].winner = -1;\n        return;\n    }\n\n    int w_left = -1;\n    int w_right = -1;\n    \n    if (tree[node_idx].left != -1) w_left = tree[tree[node_idx].left].winner;\n    if (tree[node_idx].right != -1) w_right = tree[tree[node_idx].right].winner;\n\n    if (w_left == -1 && w_right == -1) {\n        tree[node_idx].winner = -1;\n    } else if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n}\n\n// Extract the winner from the tree and update the structure.\n// Returns the index of the extracted item.\nint extract_max(int root_idx) {\n    int winner_idx = tree[root_idx].winner;\n    \n    // Trace down to the leaf\n    int curr = root_idx;\n    while (curr != -1) {\n        int left_child = tree[curr].left;\n        int right_child = tree[curr].right;\n        \n        // If leaf, winner is removed\n        if (left_child == -1 && right_child == -1) {\n            tree[curr].winner = -1;\n            break;\n        }\n\n        int w_left = (left_child != -1) ? tree[left_child].winner : -1;\n        int w_right = (right_child != -1) ? tree[right_child].winner : -1;\n\n        // Determine which child contains the current winner\n        if (w_left == winner_idx) {\n            curr = left_child;\n        } else {\n            curr = right_child;\n        }\n    }\n\n    // Propagate changes back up to root\n    // We need to reconstruct the path. We didn't store parents.\n    // Alternative: simply traverse down again? No, we need to update ancestors.\n    // Let's just rebuild winners along the path from root to where winner was found?\n    // Better approach for small N (100): Just re-update everything bottom-up? No.\n    // We can do a recursive update.\n    // Or simply: when we removed the leaf, we can walk back up? We don't have parent pointers.\n    \n    // Let's modify extraction: we know the winner. We search for it in the tree? No, structure is fixed.\n    // We can implement a recursive function `remove(node, target_winner)`\n    \n    return winner_idx;\n}\n\n// Helper to recursively remove and update\nbool remove_winner(int node_idx, int target_winner) {\n    if (node_idx == -1) return false;\n    \n    int left = tree[node_idx].left;\n    int right = tree[node_idx].right;\n    \n    // If this is the leaf node holding the winner\n    if (left == -1 && right == -1) {\n        if (tree[node_idx].winner == target_winner) {\n            tree[node_idx].winner = -1; // Mark as empty\n            return true;\n        }\n        return false;\n    }\n\n    // Recurse\n    int next_child = -1;\n    int w_left = (left != -1) ? tree[left].winner : -1;\n    \n    if (w_left == target_winner) {\n        if (remove_winner(left, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    } else {\n        if (remove_winner(right, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    }\n    return false;\n}\n\n// Assign weights to items remaining in the tree\nvoid estimate_weights_from_tree(int node_idx, int base_weight) {\n    if (node_idx == -1) return;\n    \n    int winner = tree[node_idx].winner;\n    if (winner != -1) {\n        // If this item hasn't been assigned a weight yet (not in extracted list)\n        // Since we process extracted items first, we only assign to unassigned ones.\n        if (item_to_weight_est[winner] == -1) {\n            // Heuristic: The winner of a subtree is heavier than items in sub-subtrees.\n            // We traverse down, so we give larger weight to higher nodes?\n            // Actually, DFS pre-order visits root, then children.\n            // Root is max. Children are smaller.\n            // So assign current base_weight to winner, then smaller to children.\n            item_to_weight_est[winner] = base_weight;\n        }\n    }\n\n    // Recurse to children with smaller weight\n    // We want to maintain order. We don't know order of left/right children without querying.\n    // But we can just average the weight or decrement by a small amount.\n    // Since N is small, we can just spread the remaining weights.\n    \n    estimate_weights_from_tree(tree[node_idx].left, base_weight - 2); // Arbitrary decrement\n    estimate_weights_from_tree(tree[node_idx].right, base_weight - 2);\n}\n\nvoid solve() {\n    cin >> N >> D >> Q;\n    \n    // Initialize indices\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    // Shuffle indices? \n    // For tournament sort, initial order affects which items meet in early rounds.\n    // It doesn't change the set of Top K found.\n    // Random shuffle might help if we were approximating, but exact Top K is exact.\n    // Shuffle might be useful to randomize which \"branch\" heavy items fall into, \n    // but strictly speaking not necessary for correctness of top K.\n    // However, for the \"remaining\" items, if we assume distribution, random order is fine.\n    // Let's shuffle to ensure no bias in early rounds for equal weights (though unlikely).\n    mt19937 rng(0); // Fixed seed for reproducibility or random?\n    // Problem says \"seed\" for input generation, but we can use random for our logic.\n    // Actually, usually deterministic is better for debugging, but random helps break patterns.\n    // Let's use default random_device or fixed seed.\n    shuffle(indices.begin(), indices.end(), rng);\n\n    tree.clear();\n    int root = build_tournament(indices, 0);\n\n    item_to_weight_est.assign(N, -1);\n    extracted_indices.clear();\n\n    // We used N-1 queries to build. Remaining Q - (N-1).\n    // We want to extract top K.\n    // Each extraction takes approx log2(N) queries.\n    // But update_node might ask queries again.\n    // In worst case, update_node asks 1 query per level.\n    // So extraction costs O(log N).\n    \n    // Reserve 5 queries for safety/flushing\n    int limit = Q - 5;\n    \n    while (query_count < limit) {\n        int winner = tree[root].winner;\n        if (winner == -1) break; // No items left\n        \n        extracted_indices.push_back(winner);\n        \n        // Remove this winner from the tree\n        remove_winner(root, winner);\n        \n        // Check if we exceeded limit during removal (query inside update_node)\n        if (query_count > limit) {\n            // Revert? No, just stop. \n            // The last extraction might be incomplete if update stopped early?\n            // remove_winner calls update_node recursively. \n            // If a query pushes us over, the update is done but we should stop.\n            break;\n        }\n    }\n\n    int K = extracted_indices.size();\n    \n    // Assign weights to extracted items\n    // Heaviest gets N, then N-1, etc.\n    for (int i = 0; i < K; ++i) {\n        item_to_weight_est[extracted_indices[i]] = N - i;\n    }\n    \n    // Assign weights to remaining items\n    // Use a DFS/BFS traversal. \n    // We want to assign weights smaller than N-K.\n    // The root of the current tree holds the max of remaining.\n    // We can give it N-K-1.\n    // We need to traverse.\n    // Since we don't know the exact order of remaining, we just give them weights\n    // based on depth or random values in the range [1, N-K].\n    \n    // Let's assign based on BFS order.\n    // Root gets next largest weight. Children get smaller.\n    if (tree[root].winner != -1) {\n       queue<int> q;\n       q.push(root);\n       int next_w = N - K;\n       \n       while(!q.empty()) {\n           int node = q.front();\n           q.pop();\n           \n           int winner = tree[node].winner;\n           if (winner != -1 && item_to_weight_est[winner] == -1) {\n               item_to_weight_est[winner] = next_w;\n               next_w = max(1, next_w - 1); // Decrement weight\n           }\n           \n           if (tree[node].left != -1) q.push(tree[node].left);\n           if (tree[node].right != -1) q.push(tree[node].right);\n       }\n    }\n\n    // Fill any unassigned items (shouldn't happen if tree covers all)\n    for (int i = 0; i < N; ++i) {\n        if (item_to_weight_est[i] == -1) {\n            item_to_weight_est[i] = 1;\n        }\n    }\n\n    // Now partition using LPT (Longest Processing Time) heuristic\n    // Create pairs of (estimated weight, original index)\n    vector<pair<int, int>> items_with_est;\n    for (int i = 0; i < N; ++i) {\n        items_with_est.push_back({item_to_weight_est[i], i});\n    }\n    \n    // Sort by estimated weight descending\n    sort(items_with_est.begin(), items_with_est.end(), greater<pair<int, int>>());\n\n    // Maintain D bins with their current sums\n    // Since we need to assign indices to bins, we can just store the sum\n    // and a reference to the bin assignments.\n    \n    // For small N and D, simple linear scan for min bin is fine.\n    // Optimization: priority_queue.\n    \n    // We need to output d_i for each item 0..N-1\n    vector<int> assignment(N);\n    vector<long long> bin_sums(D, 0); // Use long long to avoid overflow (though weights are small)\n    \n    // Min-heap to find the bin with smallest sum\n    // pair<sum, bin_index>\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n    for (int i = 0; i < D; ++i) {\n        pq.push({0, i});\n    }\n    \n    for (auto& p : items_with_est) {\n        int w = p.first;\n        int idx = p.second;\n        \n        auto top = pq.top();\n        pq.pop();\n        \n        int bin_idx = top.second;\n        bin_sums[bin_idx] += w;\n        assignment[idx] = bin_idx;\n        \n        pq.push({bin_sums[bin_idx], bin_idx});\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for state and parameters\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // 0-indexed stack and height\nvector<pair<int, int>> operations;\n\n// Structure to hold heuristic evaluation results\nstruct DestInfo {\n    int id;\n    long long score;\n    int min_val; // Smallest element in the stack (used for tie-breaking)\n};\n\n// Helper to get the top element of a stack, return large number if empty\nint get_top(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return stacks[stack_id].back();\n}\n\n// Helper to get the minimum element in a stack\nint get_min(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return *min_element(stacks[stack_id].begin(), stacks[stack_id].end());\n}\n\n// Evaluate the cost of moving a segment 'seg' to stack 'dest'\n// Score represents the \"badness\", lower is better.\n// Badness is defined as the number of inversions created.\n// An inversion is a pair (t, s) where t is in destination, s is in segment, and t > s.\n// We also want to prefer keeping segments intact if they are sorted,\n// but the split logic handles that before calling this.\nlong long evaluate_move(int dest, const vector<int>& seg) {\n    if (stacks[dest].empty()) return 0; // No inversions possible with empty stack\n\n    long long inv_count = 0;\n    \n    // Optimization: Since we sum counts of t > s for all s in seg\n    // We can iterate through t in destination and count how many s it is greater than.\n    // Complexity: O(Size(D) * Size(S)). Max 20 * 200 = 4000. Negligible.\n    \n    const vector<int>& dest_stack = stacks[dest];\n    \n    // Pre-calculate prefix sums? Not necessary for N=200.\n    // Just brute force double loop.\n    for (int t : dest_stack) {\n        for (int s : seg) {\n            if (t > s) {\n                inv_count++;\n            }\n        }\n    }\n    return inv_count;\n}\n\n// Execute operation type 1: Move box 'v' (and above it) to stack 'dest'\nvoid move_box(int v, int dest) {\n    // Find current stack\n    int s = pos[v].first;\n    int h = pos[v].second;\n    \n    if (s == dest) return; // Should not happen based on logic\n\n    // Identify segment to move\n    vector<int> boxes_to_move;\n    // stacks[s] has boxes from bottom (0) to top (size-1)\n    // v is at index h. We move h to size-1.\n    for (int i = h; i < stacks[s].size(); ++i) {\n        boxes_to_move.push_back(stacks[s][i]);\n    }\n    \n    // Update Source Stack\n    stacks[s].resize(h);\n    \n    // Update Destination Stack\n    for (int box : boxes_to_move) {\n        stacks[dest].push_back(box);\n    }\n    \n    // Update Positions\n    int new_h = stacks[dest].size() - boxes_to_move.size();\n    for (int i = 0; i < boxes_to_move.size(); ++i) {\n        int box = boxes_to_move[i];\n        pos[box] = {dest, new_h + i};\n    }\n    \n    operations.push_back({v, dest});\n}\n\n// Execute operation type 2: Carry out box 'v'\nvoid carry_out(int v) {\n    int s = pos[v].first;\n    // Check if v is at top (should be guaranteed by caller)\n    if (stacks[s].back() != v) {\n        // Error or should not happen\n        return;\n    }\n    \n    stacks[s].pop_back();\n    // pos[v] is no longer valid, but we won't query v again\n    operations.push_back({v, 0});\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M;\n    stacks.resize(M);\n    pos.resize(N + 1);\n    \n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Process boxes 1 to N\n    for (int v = 1; v <= N; ++v) {\n        // While v is not at top of its stack\n        while (true) {\n            int s = pos[v].first;\n            int h = pos[v].second;\n            \n            // If stack has been emptied or v is at top (h == size-1)\n            if (stacks[s].size() == h + 1) {\n                break;\n            }\n            \n            // Identify the top box of the stack containing v\n            int top_box = stacks[s].back();\n            \n            // We want to move segments that are \"inverted\" or simply move the blocking segment.\n            // Strategy:\n            // Look at the box immediately above v. Let's call it 'blocker'.\n            // Or look at the top of the stack.\n            // If the top of the stack is larger than the box below it, it creates an inversion.\n            // Moving just the top box resolves that inversion for the pair (top, below).\n            // Recursively doing this sorts the stack.\n            // Once the stack above v is sorted (small on top), we move the whole block.\n            \n            bool moved = false;\n            \n            // Check for shallow inversion at the top of the current stack\n            if (stacks[s].size() >= 2) {\n                int top = stacks[s].back();\n                int below = stacks[s][stacks[s].size() - 2];\n                \n                // If top > below, moving top alone is usually beneficial to fix the inversion.\n                // However, if 'below' is v, and top is v+1, moving top is bad.\n                // But if top > below, they are not consecutive (unless v, v+1 is inverted which is impossible in sorted 1..N).\n                // So top > below implies they are not in order.\n                if (top > below) {\n                    // Find best destination for 'top_box'\n                    // We want to minimize inversions created by adding 'top_box' to dest.\n                    \n                    vector<DestInfo> candidates;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == s) continue;\n                        \n                        // Segment is just {top_box}\n                        long long inv = evaluate_move(i, {top_box});\n                        candidates.push_back({i, inv, get_min(i)});\n                    }\n                    \n                    // Sort by score (inversions), then by min_val (larger is better buffer)\n                    sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                        if (a.score != b.score) return a.score < b.score;\n                        return a.min_val > b.min_val;\n                    });\n                    \n                    int best_dest = candidates[0].id;\n                    move_box(top_box, best_dest);\n                    moved = true;\n                }\n            }\n            \n            if (!moved) {\n                // No shallow inversion at the top, or we decided not to split.\n                // Move the entire segment above v.\n                // Segment starts at index h+1.\n                vector<int> seg;\n                for (int i = h + 1; i < stacks[s].size(); ++i) {\n                    seg.push_back(stacks[s][i]);\n                }\n                \n                // Find best destination for the whole segment\n                vector<DestInfo> candidates;\n                for (int i = 0; i < M; ++i) {\n                    if (i == s) continue;\n                    \n                    long long inv = evaluate_move(i, seg);\n                    candidates.push_back({i, inv, get_min(i)});\n                }\n                \n                sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.min_val > b.min_val;\n                });\n                \n                int best_dest = candidates[0].id;\n                \n                // The segment starts at seg[0], which is the box just above v.\n                move_box(seg[0], best_dest);\n            }\n        }\n        \n        // v is now at top. Carry out.\n        carry_out(v);\n    }\n\n    // Output\n    cout << operations.size() << endl;\n    for (auto op : operations) {\n        cout << op.first << \" \" << op.second << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <array>\n#include <numeric>\n\nusing namespace std;\n\nconst int MAX_N = 40;\nconst int MAX_NODES = MAX_N * MAX_N;\nconst int MAX_MOVES = 100000;\nconst double INF = 1e18;\n\nint N;\nint d[MAX_NODES];\nvector<int> adj[MAX_NODES];\nint cnt[MAX_NODES][MAX_NODES]; // Traversal counts for edges\nlong long k[MAX_NODES]; // Visit counts\nlong long total_len = 0;\n\nint dir_map[4] = {1, 0, -1, 0};\nint dj_map[4] = {0, 1, 0, -1};\nchar char_map[4] = {'D', 'R', 'U', 'L'};\n\nint to_idx(int i, int j) {\n    return i * N + j;\n}\n\nvoid from_idx(int idx, int& i, int& j) {\n    i = idx / N;\n    j = idx % N;\n}\n\nvoid dfs_init(int u, int p, vector<string>& h, vector<string>& v) {\n    // For constructing the initial spanning tree path\n    // We will just build the adjacency list and run a DFS to find a path that visits all nodes\n    // Then we set cnt[u][v] = 2 for tree edges.\n    // Wait, the problem says \"cleaning route\".\n    // A simple DFS that returns to start visits each edge twice.\n    // Let's store the DFS traversal to build the initial cnt.\n}\n\nstruct State {\n    int u;\n    int v;\n    double score;\n    State(int _u, int _v, double _score) : u(_u), v(_v), score(_score) {}\n    bool operator>(const State& other) const {\n        return score > other.score; // Min-heap based on score? No, we want max score.\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    vector<string> h(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[to_idx(i, j)];\n            k[to_idx(i, j)] = 0;\n        }\n    }\n\n    // Build adjacency list\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = to_idx(i, j);\n            if (i < N-1 && h[i][j] == '0') {\n                int v_idx = to_idx(i+1, j);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n            if (j < N-1 && v[i][j] == '0') {\n                int v_idx = to_idx(i, j+1);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n        }\n    }\n\n    // Initial DFS to ensure connectivity and set baseline k\n    // We don't need the string, just the edge counts and k\n    // Run DFS from 0\n    vector<bool> visited(N*N, false);\n    vector<pair<int, int>> stack; // parent, current\n    stack.push_back({-1, 0});\n    \n    // We perform a DFS and record the path as edges\n    // Actually, we just need to traverse edges.\n    // Standard DFS iterative\n    stack.push_back({-1, 0});\n    visited[0] = true;\n    \n    // We need to actually construct a cycle.\n    // Simple recursive DFS is easier to implement for logic.\n    // Since N is small, recursion depth is fine.\n    // We just need to modify 'cnt' and 'k'.\n    \n    // Use a lambda for DFS\n    // To compute 'k', we need to know how many times we \"arrive\" at a node.\n    // Start at 0. Go to neighbor...\n    // DFS traversal visits each node deg times (except root).\n    // Let's implement a DFS that returns to parent.\n    \n    vector<int> parent(N*N, -1);\n    // Re-usable stack for DFS\n    vector<int> dfs_stack;\n    dfs_stack.push_back(0);\n    vector<int> order;\n    \n    // To count k properly:\n    // A DFS tour: start at root.\n    // For each neighbor not visited: \n    //   go to neighbor (move 1), visit neighbor subtree\n    //   return to parent (move 1)\n    // This visits each edge twice.\n    // k[u] is the number of times we arrive at u.\n    // In a tree, arrival at root happens at the end (1 time).\n    // Arrival at internal node happens when returning from children + coming from parent.\n    // Effectively, for a tree, k[u] is the degree in the tree, except root is 1.\n    // But we don't have a tree, we have a grid.\n    // Let's just perform a standard DFS on the grid graph.\n    \n    fill(visited.begin(), visited.end(), false);\n    \n    // Recursive DFS function\n    // We need to pass `adj` and `cnt`, `k`, `visited`\n    // We can capture by reference\n    std::function<void(int, int)> dfs = [&](int u, int p) {\n        visited[u] = true;\n        for (int v : adj[u]) {\n            if (!visited[v]) {\n                // Go u -> v\n                cnt[u][v]++;\n                k[v]++; // Arrive at v\n                dfs(v, u);\n                // Return v -> u\n                cnt[v][u]++;\n                k[u]++; // Arrive at u (return)\n            }\n        }\n    };\n    \n    // The root is 0. k[0] starts at 0.\n    // We arrive at 0 at the end?\n    // In DFS above, we don't explicitly return to root at the very top level.\n    // So k[0] will be equal to the number of children (returns from children).\n    // The problem requires a cycle starting and ending at (0,0).\n    // The DFS path starts at 0 and ends at 0.\n    // So we arrive at 0 at the end.\n    // My DFS logic: `dfs(0, -1)`\n    // Inside, for each child `c`:\n    //   0->c (cnt++, k[c]++)\n    //   dfs(c)\n    //   c->0 (cnt++, k[0]++)\n    // So k[0] is incremented for each child.\n    // This matches the number of times we visit 0 (except start? No, start is 0).\n    // The definition of k is number of visits.\n    // In sequence p0, p1, ..., pL. p0=0, pL=0.\n    // k[0] is number of times 0 appears in p1..pL.\n    // In DFS, we visit 0 at the end. That's 1 visit?\n    // Wait. If we have children, we return from each child to 0.\n    // So we visit 0 multiple times.\n    // Is this a cycle?\n    // Sequence: 0 -> c1 -> ... -> c1 -> 0 -> c2 -> ... -> c2 -> 0.\n    // This is a valid cycle.\n    // k[0] is equal to number of children in DFS tree.\n    // Correct.\n    \n    dfs(0, -1);\n    \n    // Calculate total length\n    total_len = 0;\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            total_len += cnt[u][v];\n        }\n    }\n    // Divide by 2 because we counted u->v and v->u\n    total_len /= 2;\n    \n    // Greedy additions\n    // Priority queue: (score, u, v)\n    // score = d_u/k_u^2 + d_v/k_v^2\n    // Note: k can be 0 initially?\n    // DFS ensures all visited, so k >= 1 for all nodes except maybe root if isolated? \n    // Graph is connected. Root visited.\n    // k[u] > 0 for all u reachable from 0. Since all reachable, k[u] > 0.\n    \n    priority_queue<pair<double, pair<int, int>>> pq;\n    \n    // Initialize PQ\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            if (u < v) { // Add each edge once\n                double val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n                pq.push({val, {u, v}});\n            }\n        }\n    }\n    \n    // Loop\n    while (total_len < MAX_MOVES) {\n        if (pq.empty()) break;\n        \n        auto item = pq.top();\n        pq.pop();\n        double score = item.first;\n        int u = item.second.first;\n        int v = item.second.second;\n        \n        // Re-evaluate score lazily or just assume it's ok?\n        // Since scores decrease as k increases, the top is likely the best.\n        // But we should check.\n        double current_val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n        if (current_val < score - 1e-9) {\n            pq.push({current_val, {u, v}});\n            continue;\n        }\n        \n        // Add detour\n        if (total_len + 2 > MAX_MOVES) break;\n        \n        cnt[u][v]++;\n        cnt[v][u]++;\n        k[u]++;\n        k[v]++;\n        total_len += 2;\n        \n        // Push updates for neighbors of u and v\n        for (int w : adj[u]) {\n            int a = min(u, w);\n            int b = max(u, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n        for (int w : adj[v]) {\n            int a = min(v, w);\n            int b = max(v, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n    }\n    \n    // Hierholzer's Algorithm\n    // We need to construct the path string.\n    // Start at 0.\n    \n    // We need a mutable copy of adj with edge counts to remove edges.\n    // Or just use cnt array and decrement.\n    // Since max moves is 100k, recursion is safe? 100k depth might be too much for stack.\n    // Use iterative stack or manual stack.\n    \n    vector<char> path;\n    vector<int> stack_path;\n    stack_path.push_back(0);\n    \n    // To optimize neighbor iteration in Hierholzer, we can store current edge index?\n    // Or just loop.\n    \n    while (!stack_path.empty()) {\n        int u = stack_path.back();\n        bool found = false;\n        for (int v : adj[u]) {\n            if (cnt[u][v] > 0) {\n                // Take this edge\n                cnt[u][v]--;\n                \n                // Find direction char\n                int i1, j1, i2, j2;\n                from_idx(u, i1, j1);\n                from_idx(v, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                \n                stack_path.push_back(v);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) {\n            stack_path.pop_back();\n            if (!stack_path.empty()) {\n                int prev = stack_path.back();\n                // Find direction from prev to u\n                int i1, j1, i2, j2;\n                from_idx(prev, i1, j1);\n                from_idx(u, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                path.push_back(c);\n            }\n        }\n    }\n    \n    // Path is constructed backwards\n    reverse(path.begin(), path.end());\n    \n    // Output\n    for (char c : path) {\n        cout << c;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <atcoder/random>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\nusing namespace atcoder;\n\n// ---------------------------------------------------\n// Constants and Globals\n// ---------------------------------------------------\n\nconstexpr int N = 15;\nconstexpr int N2 = N * N;\nconstexpr int M = 200;\nconstexpr int INF = 1e9;\n\nint grid[N][N];\nvector<int> char_pos[26]; // Stores positions (indices 0..N2-1) for each character\nint start_pos;\nvector<string> targets(M);\n\n// Precomputed distances\nint dist[N2][N2];\n\n// Timer for time limit management\nstd::chrono::system_clock::time_point start_time;\n\n// ---------------------------------------------------\n// Utilities\n// ---------------------------------------------------\n\nint get_elapsed_ms() {\n    auto now = std::chrono::system_clock::now();\n    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n}\n\n// ---------------------------------------------------\n// Precomputation\n// ---------------------------------------------------\n\nvoid precompute() {\n    // Calculate Manhattan distances between all pairs of cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            for (int k = 0; k < N; ++k) {\n                for (int l = 0; l < N; ++l) {\n                    int v = k * N + l;\n                    dist[u][v] = abs(i - k) + abs(j - l);\n                }\n            }\n        }\n    }\n}\n\n// ---------------------------------------------------\n// Overlap Calculation\n// ---------------------------------------------------\n\n// Calculate max overlap between A's suffix and B's prefix\nint calc_overlap(const string& A, const string& B) {\n    int max_ov = 0;\n    int len_A = A.size();\n    int len_B = B.size();\n    // Max possible overlap is 4\n    for (int k = 1; k <= min(len_A, 4); ++k) {\n        if (A.compare(len_A - k, k, B, 0, k) == 0) {\n            max_ov = k;\n        }\n    }\n    return max_ov;\n}\n\n// Precompute overlap matrix to save time during SA\nint overlap_mat[M][M];\n\nvoid build_overlap_matrix() {\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                overlap_mat[i][j] = 0; // Or maybe min(4, len) if self-overlap makes sense? Targets are distinct.\n                continue;\n            }\n            overlap_mat[i][j] = calc_overlap(targets[i], targets[j]);\n        }\n    }\n}\n\n// ---------------------------------------------------\n// String Construction from Permutation\n// ---------------------------------------------------\n\nstring build_string(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s = targets[order[0]];\n    for (size_t i = 1; i < order.size(); ++i) {\n        int u = order[i-1];\n        int v = order[i];\n        int ov = overlap_mat[u][v];\n        s += targets[v].substr(ov);\n    }\n    return s;\n}\n\n// ---------------------------------------------------\n// DP to calculate cost\n// ---------------------------------------------------\n\n// Returns the minimum cost and stores the path (if store_path is true)\npair<int, vector<pair<int, int>>> solve_grid(const string& s, bool store_path = false) {\n    if (s.empty()) return {0, {}};\n\n    // dp[u] = min cost to reach cell u having processed up to current char\n    vector<int> dp(N2, INF);\n    dp[start_pos] = 0;\n    \n    // To reconstruct path\n    // We only need to store the previous cell for the optimal path for each cell at each step\n    // Memory: L * N2 integers. L <= 1000, N2 = 225. ~225k integers. ~1MB. OK.\n    vector<vector<int>> prev_step; \n    if (store_path) {\n        prev_step.assign(s.size(), vector<int>(N2, -1));\n    }\n\n    for (size_t i = 0; i < s.size(); ++i) {\n        char c = s[i];\n        vector<int> next_dp(N2, INF);\n        \n        // For each cell v that has character c\n        for (int v : char_pos[c - 'A']) {\n            int best_cost = INF;\n            int best_prev = -1;\n            \n            // Find min_u (dp[u] + dist(u, v))\n            for (int u = 0; u < N2; ++u) {\n                if (dp[u] == INF) continue;\n                int cost = dp[u] + dist[u][v] + 1; // +1 for typing action\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_prev = u;\n                }\n            }\n            \n            next_dp[v] = best_cost;\n            if (store_path) {\n                prev_step[i][v] = best_prev;\n            }\n        }\n        dp = next_dp;\n    }\n\n    int min_cost = *min_element(dp.begin(), dp.end());\n    vector<pair<int, int>> path;\n\n    if (store_path) {\n        // Find the end position\n        int end_pos = -1;\n        for (int i = 0; i < N2; ++i) {\n            if (dp[i] == min_cost) {\n                end_pos = i;\n                break;\n            }\n        }\n        \n        if (end_pos != -1) {\n            path.resize(s.size());\n            int curr = end_pos;\n            for (int i = s.size() - 1; i >= 0; --i) {\n                path[i] = {curr / N, curr % N};\n                curr = prev_step[i][curr];\n            }\n        }\n    }\n\n    return {min_cost, path};\n}\n\n// ---------------------------------------------------\n// Heuristics\n// ---------------------------------------------------\n\nvector<int> initial_order_greedy() {\n    vector<int> order;\n    vector<bool> used(M, false);\n    \n    // Start with a random target to avoid bias\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis(0, M-1);\n    int first = dis(gen);\n    \n    order.push_back(first);\n    used[first] = true;\n    \n    for (int count = 1; count < M; ++count) {\n        int last = order.back();\n        string current_str = build_string(order); // Rebuild string to get suffix? No, just use the last target.\n        // Actually, we only need the suffix of the constructed string to check overlap.\n        // build_string is O(M^2 * 5) if called inside loop. M=200, M^2=40000. Fast.\n        // But we can just look at the last target for overlap calculation.\n        \n        int best_next = -1;\n        int max_ov = -1;\n        // To add randomness for variety, shuffle candidate checks or pick randomly from max overlaps\n        vector<int> candidates;\n        \n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlap_mat[last][i];\n            if (ov > max_ov) {\n                max_ov = ov;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (ov == max_ov) {\n                candidates.push_back(i);\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        uniform_int_distribution<> cand_dis(0, (int)candidates.size()-1);\n        best_next = candidates[cand_dis(gen)];\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\n// ---------------------------------------------------\n// Main Solving Logic\n// ---------------------------------------------------\n\nvoid solve() {\n    // Input\n    int si, sj;\n    cin >> si >> sj;\n    start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = row[j];\n            char_pos[row[j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i];\n    }\n    \n    // Sort targets to ensure deterministic behavior for overlap matrix calculation logic\n    // Actually, the input generation says they are sorted lexicographically.\n    // So we rely on that order for indices.\n    \n    precompute();\n    build_overlap_matrix();\n\n    // Initial State\n    vector<int> current_order = initial_order_greedy();\n    string current_s = build_string(current_order);\n    auto [current_cost, _] = solve_grid(current_s);\n    \n    vector<int> best_order = current_order;\n    int best_cost = current_cost;\n    \n    // Simulated Annealing\n    // Parameters\n    double start_temp = 2000.0; // Based on estimated cost range\n    double end_temp = 0.1;\n    double time_limit = 1950.0; // ms\n    \n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> idx_dist(0, M-1);\n    uniform_real_distribution<> prob_dist(0.0, 1.0);\n\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        // Generate neighbor: Swap two random indices\n        int idx1 = idx_dist(gen);\n        int idx2 = idx_dist(gen);\n        while(idx1 == idx2) idx2 = idx_dist(gen);\n        \n        swap(current_order[idx1], current_order[idx2]);\n        \n        string new_s = build_string(current_order);\n        auto [new_cost, _] = solve_grid(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            swap(current_order[idx1], current_order[idx2]);\n        }\n    }\n    \n    // Output Best Solution\n    string final_s = build_string(best_order);\n    auto [final_cost, path] = solve_grid(final_s, true);\n    \n    for (auto p : path) {\n        cout << p.first << \" \" << p.second << endl;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = std::chrono::system_clock::now();\n    \n    solve();\n    \n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\n#include <atcoder/random>\nusing namespace std;\nusing namespace atcoder;\n\nconst double INF = 1e9;\nconst int MAX_N = 20;\nconst int MAX_M = 20;\n\n// Global variables\nint N, M;\ndouble eps;\nvector<vector<pair<int, int>>> shapes; // Relative coordinates of each shape\nvector<pair<int, int>> shape_sizes;   // (height, width) of each shape\nmap<pair<int, int>, int> fixed_cells; // Known values: (r,c) -> value\n\n// Estimated sums from divination\nvector<double> est_row_sums;\nvector<double> est_col_sums;\n\n// Inverse variances for chi-squared\ndouble inv_var_row;\ndouble inv_var_col;\n\n// Random number generator\nrandom_device rd;\nmt19937 gen(rd());\n\n// Operation cost tracking\ndouble total_cost = 0.0;\n\n// Helper to output and flush\nvoid flush_output() {\n    cout << flush;\n}\n\n// Divination operation\ndouble divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto [r, c] : cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0 / sqrt(k);\n    \n    // Invert the noise model\n    // y ~ round(max(0, x)), x ~ N(k*eps + T(1-2*eps), k*eps(1-eps))\n    // Estimate T\n    double T_est = (res - k * eps) / (1.0 - 2.0 * eps);\n    if (T_est < 0) T_est = 0; // T must be non-negative\n    return T_est;\n}\n\n// Drilling operation\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0;\n    fixed_cells[{r, c}] = res;\n    return res;\n}\n\n// Answer operation\nbool answer(const vector<pair<int, int>>& pos_cells) {\n    cout << \"a \" << pos_cells.size();\n    for (auto [r, c] : pos_cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    return res == 1;\n}\n\n// State representation for SA\nstruct State {\n    vector<pair<int, int>> pos; // (r, c) for each field\n    int grid[MAX_N][MAX_N];\n    double energy;\n\n    void compute_grid_and_energy() {\n        // Reset grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = 0;\n            }\n        }\n\n        // Place fields\n        for (int k = 0; k < M; ++k) {\n            auto [pr, pc] = pos[k];\n            for (auto [dr, dc] : shapes[k]) {\n                int r = pr + dr;\n                int c = pc + dc;\n                grid[r][c]++;\n            }\n        }\n\n        // Check fixed cells constraint\n        for (auto [p, val] : fixed_cells) {\n            if (grid[p.first][p.second] != val) {\n                energy = INF;\n                return;\n            }\n        }\n\n        // Calculate chi-squared distance to observed row/col sums\n        double err = 0.0;\n        \n        // Row sums\n        for (int i = 0; i < N; ++i) {\n            int sum = 0;\n            for (int j = 0; j < N; ++j) sum += grid[i][j];\n            double diff = sum - est_row_sums[i];\n            err += diff * diff * inv_var_row;\n        }\n\n        // Column sums\n        for (int j = 0; j < N; ++j) {\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += grid[i][j];\n            double diff = sum - est_col_sums[j];\n            err += diff * diff * inv_var_col;\n        }\n\n        energy = err;\n    }\n};\n\n// Simulated Annealing\nState run_sa(int iterations) {\n    State cur, best;\n    cur.pos.resize(M);\n    best.pos.resize(M);\n\n    // Initialize random valid positions\n    for (int k = 0; k < M; ++k) {\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        cur.pos[k] = {dist_r(gen), dist_c(gen)};\n    }\n    cur.compute_grid_and_energy();\n    best = cur;\n\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        State nxt = cur;\n        \n        // Pick a field to move\n        int k = uniform_int_distribution<>(0, M - 1)(gen);\n        \n        // Generate new position\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        \n        if (uniform_real_distribution<>(0, 1)(gen) < 0.1) {\n            // Jump\n            nxt.pos[k] = {dist_r(gen), dist_c(gen)};\n        } else {\n            // Small step\n            int dr = uniform_int_distribution<>(-2, 2)(gen);\n            int dc = uniform_int_distribution<>(-2, 2)(gen);\n            int nr = nxt.pos[k].first + dr;\n            int nc = nxt.pos[k].second + dc;\n            \n            // Clamp to valid range\n            nr = max(0, min(N - h, nr));\n            nc = max(0, min(N - w, nc));\n            nxt.pos[k] = {nr, nc};\n        }\n\n        nxt.compute_grid_and_energy();\n\n        if (nxt.energy < cur.energy || uniform_real_distribution<>(0, 1)(gen) < exp((cur.energy - nxt.energy) / max(temp, 0.1))) {\n            cur = nxt;\n        }\n\n        if (cur.energy < best.energy) {\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M >> eps;\n    shapes.resize(M);\n    shape_sizes.resize(M);\n\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n            shapes[k].emplace_back(r, c);\n            max_r = max(max_r, r);\n            max_c = max(max_c, c);\n        }\n        shape_sizes[k] = {max_r, max_c};\n    }\n\n    // Precompute inverse variances\n    // Variance = k * eps * (1 - eps)\n    inv_var_row = 1.0 / (N * eps * (1.0 - eps));\n    inv_var_col = 1.0 / (N * eps * (1.0 - eps));\n    est_row_sums.resize(N);\n    est_col_sums.resize(N);\n\n    // Initial Probing: Rows and Columns\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_cells;\n        for (int j = 0; j < N; ++j) row_cells.emplace_back(i, j);\n        est_row_sums[i] = divine(row_cells);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_cells;\n        for (int i = 0; i < N; ++i) col_cells.emplace_back(i, j);\n        est_col_sums[j] = divine(col_cells);\n    }\n\n    // Main search loop\n    int max_ops = 2 * N * N;\n    int sa_iters = 3000; // Per iteration\n    \n    // We want to leave some buffer for the answer query\n    while (total_cost < max_ops - 1) {\n        // Run SA\n        State best_state = run_sa(sa_iters);\n\n        // If energy is very low, we might be done\n        // Heuristic: if energy < 10 (which is small for 40 degrees of freedom)\n        if (best_state.energy < 5.0) {\n            // Verify a few random cells or just submit?\n            // Let's try to submit if we are very confident\n            // Or drill one last cell to be safe\n            \n            // Construct answer\n            vector<pair<int, int>> ans;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0) {\n                        ans.emplace_back(i, j);\n                    }\n                }\n            }\n            \n            // Check if we have budget for another drill\n            if (total_cost + 1 + 0.01 > max_ops) {\n                 // Submit\n                if (answer(ans)) return;\n                else {\n                    // If wrong, we shouldn't really get here often if energy is low.\n                    // If we do, we break loop because we can't afford more ops?\n                    // Actually, we just continue if we have time.\n                    // But answer costs 1. So we lost 1 op.\n                }\n            } else {\n                // Try to verify a high-value cell\n                // Find a cell with max v that is not fixed\n                pair<int, int> target = {-1, -1};\n                int max_v = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                            if (best_state.grid[i][j] > max_v) {\n                                max_v = best_state.grid[i][j];\n                                target = {i, j};\n                            }\n                        }\n                    }\n                }\n\n                if (target.first != -1) {\n                    drill(target.first, target.second);\n                } else {\n                    // All positive cells fixed. Submit.\n                    if (answer(ans)) return;\n                }\n            }\n        } else {\n            // Energy is not low enough. Drill a cell to improve.\n            // Strategy: Drill a cell that is positive in the best model\n            pair<int, int> target = {-1, -1};\n            int max_v = -1;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                        if (best_state.grid[i][j] > max_v) {\n                            max_v = best_state.grid[i][j];\n                            target = {i, j};\n                        }\n                    }\n                }\n            }\n\n            // If no positive cell found (all fixed?), check empty?\n            // Or just pick a cell with v=0 that is surrounded by v>0?\n            if (target.first == -1) {\n                 // This case implies model says no undrilled positive cells.\n                 // But energy is high. Means model is wrong (missed some oil).\n                 // We should drill somewhere to find the missing oil.\n                 // Pick a random undrilled cell with v=0 in model.\n                 vector<pair<int,int>> candidates;\n                 for (int i=0; i<N; ++i) {\n                     for (int j=0; j<N; ++j) {\n                         if (best_state.grid[i][j] == 0 && fixed_cells.count({i,j}) == 0) {\n                             candidates.emplace_back(i,j);\n                         }\n                     }\n                 }\n                 if (!candidates.empty()) {\n                     target = candidates[uniform_int_distribution<>(0, candidates.size()-1)(gen)];\n                 } else {\n                     // All cells fixed? Just submit.\n                     vector<pair<int, int>> ans;\n                     for (int i = 0; i < N; ++i) {\n                        for (int j = 0; j < N; ++j) {\n                            if (best_state.grid[i][j] > 0) ans.emplace_back(i, j);\n                        }\n                    }\n                    if (answer(ans)) return;\n                 }\n            }\n            \n            if (target.first != -1) drill(target.first, target.second);\n        }\n    }\n    \n    // Fallback / Time up: Submit current best guess\n    State final_state = run_sa(1000); // Quick last run\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (final_state.grid[i][j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    answer(ans);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <deque>\n\nusing namespace std;\n\nconst int W = 1000;\nconst long long INF = 1e18;\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_input, D, N;\n    cin >> W_input >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // prev_cuts[k] stores the y-coordinate of the k-th cut (0-indexed) from the previous day.\n    // Initially, we can assume cuts are at 0 (or any value, as L_0=0).\n    vector<int> prev_cuts(N - 1, 0);\n\n    for (int d = 0; d < D; ++d) {\n        // dp_prev[v] = min cost to place the first (k-1) cuts, with the (k-1)-th cut at y=v.\n        // We start with k=1 (placing the 0th cut).\n        // Initial state: 0 cuts placed, virtual cut at y=0, cost 0.\n        vector<long long> dp_prev(W + 1, INF);\n        dp_prev[0] = 0;\n        \n        // choice[k][v] stores the position of the previous cut 'u' that led to cut 'k' being at 'v'.\n        // k is 1-indexed for cuts (1 to N-1).\n        vector<vector<int>> choice(N, vector<int>(W + 1, -1));\n\n        // Iterate to place the k-th cut (1-indexed)\n        for (int k = 1; k < N; ++k) {\n            // The rectangle to the left of this cut is rectangle (k-1) (0-indexed).\n            int A = a[d][k-1];\n            int min_h = (A + W - 1) / W; // Minimum height to avoid deficit\n            if (min_h == 0) min_h = 1;\n\n            // Precompute B[u] = dp_prev[u] + 100 * W * u\n            // Used for calculating cost when deficit occurs.\n            vector<long long> B(W + 1);\n            for (int i = 0; i <= W; ++i) {\n                B[i] = dp_prev[i] + (long long)100 * W * i;\n            }\n\n            vector<long long> dp_curr(W + 1, INF);\n            \n            // Prefix minima for dp_prev (Case 1: No deficit)\n            // pmin[i] = min(dp_prev[0...i-1])\n            vector<long long> pmin(W + 2, INF);\n            vector<int> parg(W + 2, -1);\n            for (int i = 0; i <= W; ++i) {\n                if (dp_prev[i] < pmin[i]) {\n                    pmin[i+1] = dp_prev[i];\n                    parg[i+1] = i;\n                } else {\n                    pmin[i+1] = pmin[i];\n                    parg[i+1] = parg[i];\n                }\n            }\n            \n            // Sliding window minimum for B[u] (Case 2: Deficit)\n            // We need min(B[u]) for u in [v - min_h + 1, v - 1]\n            deque<int> dq;\n\n            for (int v = 1; v <= W; ++v) {\n                // Update deque for the current window ending at v-1\n                // 1. Add u = v - 1\n                while (!dq.empty() && B[dq.back()] >= B[v - 1]) {\n                    dq.pop_back();\n                }\n                dq.push_back(v - 1);\n                \n                // 2. Remove indices < v - min_h + 1\n                while (!dq.empty() && dq.front() < v - min_h + 1) {\n                    dq.pop_front();\n                }\n\n                // Calculate costs\n                long long best_inner_cost = INF;\n                int best_u = -1;\n\n                // Case 1: u <= v - min_h (No deficit)\n                // Cost is dp_prev[u]. We want min over u in [0, v - min_h]\n                if (v - min_h >= 0) {\n                    long long c1 = pmin[v - min_h + 1];\n                    if (c1 < best_inner_cost) {\n                        best_inner_cost = c1;\n                        best_u = parg[v - min_h + 1];\n                    }\n                }\n\n                // Case 2: u in [v - min_h + 1, v - 1] (Deficit)\n                // Cost is 100*A - 100*W*v + min(B[u])\n                if (!dq.empty()) {\n                    int idx = dq.front();\n                    long long c2 = B[idx] + (long long)100 * A - (long long)100 * W * v;\n                    if (c2 < best_inner_cost) {\n                        best_inner_cost = c2;\n                        best_u = idx;\n                    }\n                }\n\n                if (best_inner_cost < INF) {\n                    // Add move cost.\n                    // On Day 0 (d==0), L_0=0, so move cost is 0.\n                    // For d > 0, cost is 2 * W * |v - prev_cuts[k-1]|\n                    long long move_cost = (d == 0) ? 0 : 2000 * abs(v - prev_cuts[k-1]);\n                    dp_curr[v] = best_inner_cost + move_cost;\n                    choice[k][v] = best_u;\n                } else {\n                    dp_curr[v] = INF;\n                }\n            }\n            \n            dp_prev = dp_curr;\n        }\n\n        // Determine the optimal position for the last cut (N-1)\n        // And account for the last rectangle (N-1)\n        int last_min_h = (a[d][N-1] + W - 1) / W;\n        int best_v = -1;\n        long long min_total_cost = INF;\n\n        for (int v = 0; v <= W; ++v) {\n            if (dp_prev[v] >= INF) continue;\n            \n            long long cost = dp_prev[v];\n            int h_last = W - v;\n            if (h_last < last_min_h) {\n                cost += (long long)100 * (a[d][N-1] - (long long)W * h_last);\n            }\n            \n            if (cost < min_total_cost) {\n                min_total_cost = cost;\n                best_v = v;\n            }\n        }\n\n        // Fallback in case no valid configuration found (should not happen with correct constraints)\n        if (best_v == -1) {\n            best_v = W / 2; // Just a fallback to avoid crash\n        }\n\n        // Reconstruct cuts\n        vector<int> new_cuts(N - 1);\n        int curr_v = best_v;\n        bool valid_reconstruction = true;\n        \n        for (int k = N - 1; k >= 1; --k) {\n            new_cuts[k-1] = curr_v;\n            if (curr_v < 0 || curr_v > W || choice[k][curr_v] == -1) {\n                // Fallback to equal partition if reconstruction fails\n                valid_reconstruction = false;\n                break;\n            }\n            curr_v = choice[k][curr_v];\n        }\n\n        if (!valid_reconstruction) {\n            // Fallback strategy: Divide equally\n            int step = W / N;\n            for (int i = 0; i < N - 1; ++i) {\n                new_cuts[i] = step * (i + 1);\n            }\n        }\n\n        // Output\n        int y_prev = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            int y_curr = new_cuts[k];\n            // Ensure strictly increasing coordinates\n            if (y_curr <= y_prev) y_curr = y_prev + 1; \n            if (y_curr > W) y_curr = W;\n            \n            cout << y_prev << \" \" << 0 << \" \" << y_curr << \" \" << W << \"\\n\";\n            y_prev = y_curr;\n        }\n        // Last rectangle\n        if (y_prev >= W) y_prev = W - 1; // Safety\n        cout << y_prev << \" \" << 0 << \" \" << W << \" \" << W << \"\\n\";\n\n        // Update previous cuts for next day\n        prev_cuts = new_cuts;\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <tuple>\n#include <functional>\n\nusing namespace std;\n\nconst int MOD = 998244353;\n\n// Configuration for Beam Search\nconst int BEAM_WIDTH = 50;\nconst int MAX_BRANCHES = 20; // Top moves to consider per state\n\nstruct State {\n    array<long long, 81> board; // Flattened 9x9 board\n    long long score;\n    int parent_id;\n    signed char m, p, q; // Operation used to reach this state. -1 for do-nothing.\n\n    // Helper to get board value\n    inline long long& at(int i, int j) {\n        return board[i * 9 + j];\n    }\n    inline const long long& at(int i, int j) const {\n        return board[i * 9 + j];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    // Read initial board\n    State initial_state;\n    initial_state.score = 0;\n    initial_state.parent_id = -1;\n    initial_state.m = -1; \n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            long long val;\n            cin >> val;\n            initial_state.at(i, j) = val;\n            initial_state.score += val % MOD;\n        }\n    }\n\n    // Read stamps\n    // Stamps are 3x3. We store them flattened or just as is.\n    // Storing as 2D array for easier access.\n    array<array<array<long long, 3>, 3>, 20> stamps{};\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    // Beam Search\n    // We maintain a global list of all states to allow referencing by parent_id.\n    // But to avoid managing a huge list and fragmentation, we can use a vector \n    // that grows, and a separate vector for the current beam indices.\n    \n    vector<State> all_states;\n    all_states.push_back(initial_state);\n    \n    vector<int> beam;\n    beam.push_back(0);\n\n    for (int step = 0; step < K; ++step) {\n        // Buffer for new candidates\n        vector<State> candidates;\n        // Reserve approximate size to reduce reallocations\n        candidates.reserve(beam.size() * (MAX_BRANCHES + 1));\n\n        for (int curr_idx : beam) {\n            const State& curr = all_states[curr_idx];\n\n            // 1. Generate \"Do Nothing\" move\n            State st_noop = curr;\n            st_noop.parent_id = curr_idx;\n            st_noop.m = -1; // Marker for do-nothing\n            candidates.push_back(st_noop);\n\n            // 2. Evaluate all possible stamp placements\n            // We store temporary gain to sort moves\n            vector<tuple<long long, int, int, int>> potential_moves; // (gain, m, p, q)\n            potential_moves.reserve(M * (N - 2) * (N - 2));\n\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p <= N - 3; ++p) {\n                    for (int q = 0; q <= N - 3; ++q) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                long long old_v = curr.at(p+i, q+j);\n                                long long new_v = old_v + stamps[m][i][j];\n                                gain += (new_v % MOD) - (old_v % MOD);\n                            }\n                        }\n                        potential_moves.emplace_back(gain, m, p, q);\n                    }\n                }\n            }\n\n            // Sort moves by gain descending\n            // Optim: we only need top MAX_BRANCHES. nth_element is better.\n            int limit = min((int)potential_moves.size(), MAX_BRANCHES);\n            if (limit > 0) {\n                nth_element(potential_moves.begin(), potential_moves.begin() + limit, potential_moves.end(), \n                    [](const auto& a, const auto& b) { return get<0>(a) > get<0>(b); });\n                \n                // Note: nth_element doesn't fully sort the first part, but that's fine, \n                // we just need the best ones.\n                // However, to be deterministic or slightly better, we can sort the first part.\n                sort(potential_moves.begin(), potential_moves.begin() + limit, \n                    [](const auto& a, const auto& b) { return get<0>(a) > get<0>(b); });\n\n                for (int k = 0; k < limit; ++k) {\n                    auto [gain, m, p, q] = potential_moves[k];\n                    // Only consider moves that are not terrible?\n                    // Greedy stops at <=0. Beam search should explore slight negatives.\n                    // But we already filtered by top gain. If all are negative, we take the \"least negative\".\n                    \n                    State st_new = curr;\n                    for (int i = 0; i < 3; ++i) {\n                        for (int j = 0; j < 3; ++j) {\n                            st_new.at(p+i, q+j) += stamps[m][i][j];\n                        }\n                    }\n                    st_new.score += gain;\n                    st_new.parent_id = curr_idx;\n                    st_new.m = m;\n                    st_new.p = p;\n                    st_new.q = q;\n                    candidates.push_back(st_new);\n                }\n            }\n        }\n\n        // Select top BEAM_WIDTH candidates\n        int next_beam_size = min((int)candidates.size(), BEAM_WIDTH);\n        \n        if (next_beam_size > 0) {\n            auto mid = candidates.begin() + next_beam_size;\n            nth_element(candidates.begin(), mid, candidates.end(), \n                [](const State& a, const State& b) { return a.score > b.score; });\n            \n            // We don't need to fully sort them for the next iteration, just need the indices.\n            // However, adding them to all_states requires knowing where they are.\n            \n            // Append selected states to all_states\n            // Calculate starting index\n            int start_idx = all_states.size();\n            \n            // Resize all_states to fit new ones\n            all_states.resize(start_idx + next_beam_size);\n            \n            // Copy candidates to all_states\n            // Since we only partially sorted, the first 'next_beam_size' are the top ones.\n            for (int i = 0; i < next_beam_size; ++i) {\n                all_states[start_idx + i] = candidates[i];\n            }\n\n            // Update beam indices\n            beam.clear();\n            beam.reserve(next_beam_size);\n            for (int i = 0; i < next_beam_size; ++i) {\n                beam.push_back(start_idx + i);\n            }\n        } else {\n            // No candidates? Should not happen because of do-nothing.\n            // But if it does, we are stuck.\n        }\n    }\n\n    // Find best state in the final beam\n    int best_idx = -1;\n    long long best_score = -1;\n    for (int idx : beam) {\n        if (all_states[idx].score > best_score) {\n            best_score = all_states[idx].score;\n            best_idx = idx;\n        }\n    }\n\n    // Reconstruct path\n    vector<tuple<int, int, int>> ops;\n    int curr = best_idx;\n    while (curr != -1) {\n        const State& st = all_states[curr];\n        if (st.m != -1) {\n            ops.emplace_back(st.m, st.p, st.q);\n        }\n        curr = st.parent_id;\n    }\n\n    // Path is reconstructed backwards, reverse it\n    reverse(ops.begin(), ops.end());\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (auto [m, p, q] : ops) {\n        cout << m << \" \" << p << \" \" << q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    vector<vector<int>> A(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> A[i][j];\n        }\n    }\n    \n    vector<int> target_row(N * N);\n    for (int c = 0; c < N * N; c++) target_row[c] = c / N;\n    \n    vector<vector<int>> arrival(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) arrival[i][j] = A[i][j];\n    \n    vector<int> arrived(N, 0);\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_x(N), crane_y(N);\n    vector<int> carrying(N, -1);\n    \n    for (int i = 0; i < N; i++) {\n        crane_x[i] = i;\n        crane_y[i] = 0;\n    }\n    \n    vector<string> actions(N);\n    vector<bool> dispatched(N * N, false);\n    \n    for (int t = 0; t < MAX_TURNS; t++) {\n        for (int i = 0; i < N; i++) {\n            if (arrived[i] < N && grid[i][0] == -1) {\n                bool blocked = false;\n                for (int c = 0; c < N; c++)\n                    if (crane_x[c] == i && crane_y[c] == 0 && carrying[c] != -1) blocked = true;\n                if (!blocked) grid[i][0] = arrival[i][arrived[i]++];\n            }\n        }\n        \n        vector<char> act(N, '.');\n        vector<int> nx = crane_x, ny = crane_y;\n        vector<int> ncarry = carrying;\n        \n        for (int c = 0; c < N; c++) {\n            if (c == 0) {\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (crane_x[c] < tr) { act[c] = 'D'; nx[c]++; }\n                    else if (crane_x[c] > tr) { act[c] = 'U'; nx[c]--; }\n                    else if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                    else if (crane_y[c] > N - 1) { act[c] = 'L'; ny[c]--; }\n                    else { act[c] = 'Q'; ncarry[c] = -1; }\n                } else {\n                    int best_i = -1, best_j = -1, best_score = -1;\n                    for (int i = 0; i < N; i++) {\n                        for (int j = 0; j < N; j++) {\n                            int cont = grid[i][j];\n                            if (cont != -1 && !dispatched[cont]) {\n                                int wrong = (i != target_row[cont]);\n                                int dist = abs(i - crane_x[c]) + abs(j - crane_y[c]);\n                                int score = wrong * 1000 - dist;\n                                if (score > best_score) {\n                                    best_score = score; best_i = i; best_j = j;\n                                }\n                            }\n                        }\n                    }\n                    if (best_i != -1) {\n                        if (crane_x[c] < best_i) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > best_i) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < best_j) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > best_j) { act[c] = 'L'; ny[c]--; }\n                        else { act[c] = 'P'; ncarry[c] = grid[best_i][best_j]; }\n                    }\n                }\n            } else {\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (tr == c) {\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c] + 1] == -1) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] == N - 1) { act[c] = 'Q'; ncarry[c] = -1; }\n                    } else { act[c] = 'Q'; ncarry[c] = -1; }\n                } else {\n                    int cont = grid[c][crane_y[c]];\n                    if (cont != -1 && target_row[cont] == c) { act[c] = 'P'; ncarry[c] = cont; }\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (nx[i] == crane_x[j] && ny[i] == crane_y[j] && nx[j] == crane_x[i] && ny[j] == crane_y[i]) {\n                    act[j] = '.'; nx[j] = crane_x[j]; ny[j] = crane_y[j];\n                }\n                if (nx[i] == nx[j] && ny[i] == ny[j]) {\n                    act[j] = '.'; nx[j] = crane_x[j]; ny[j] = crane_y[j];\n                }\n            }\n        }\n        \n        for (int c = 0; c < N; c++) {\n            actions[c] += act[c];\n            if (act[c] == 'P') grid[crane_x[c]][crane_y[c]] = -1;\n            else if (act[c] == 'Q') grid[crane_x[c]][crane_y[c]] = carrying[c];\n            crane_x[c] = nx[c]; crane_y[c] = ny[c]; carrying[c] = ncarry[c];\n        }\n        \n        for (int i = 0; i < N; i++) {\n            if (grid[i][N - 1] != -1) {\n                dispatched[grid[i][N - 1]] = true;\n                grid[i][N - 1] = -1;\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)actions[i].size() < max_len) actions[i] += '.';\n        cout << actions[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Grid dimensions\nconst int N = 20;\nconst int INF = 1e9;\nconst int DX[4] = {0, 0, 1, -1};\nconst int DY[4] = {1, -1, 0, 0};\nconst char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n;\n    // N is always 20, but we read it just in case\n    if (!(cin >> n)) return 0; \n    \n    vector<int> h(n * n);\n    for (int i = 0; i < n * n; ++i) {\n        cin >> h[i];\n    }\n\n    // 1. Construct Min-Cost Flow Graph\n    // Nodes: 0 to n*n-1 are grid cells.\n    // Source S = n*n, Sink T = n*n + 1.\n    int S = n * n;\n    int T = n * n + 1;\n    mcf_graph<int, long long> graph(n * n + 2);\n    \n    long long total_supply = 0;\n\n    for (int i = 0; i < n * n; ++i) {\n        if (h[i] > 0) {\n            graph.add_edge(S, i, h[i], 0);\n            total_supply += h[i];\n        } else if (h[i] < 0) {\n            graph.add_edge(i, T, -h[i], 0);\n        }\n    }\n\n    // Add grid edges (undirected)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int u = i * n + j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + DX[k];\n                int nj = j + DY[k];\n                if (0 <= ni && ni < n && 0 <= nj && nj < n) {\n                    int v = ni * n + nj;\n                    // Cost is 1 per unit distance\n                    graph.add_edge(u, v, INF, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min-Cost Flow\n    auto result = graph.flow(S, T, total_supply);\n    // result.second is the min cost (sum of amount * distance)\n    // We don't strictly need the value, just the flow distribution.\n\n    // 3. Extract Flow Graph\n    // adj[u] stores (v, flow) pairs for flow > 0\n    vector<vector<pair<int, int>>> adj(n * n);\n    auto edges = graph.edges();\n    for (const auto& e : edges) {\n        if (e.from < S && e.to < S && e.flow > 0) {\n            adj[e.from].emplace_back(e.to, e.flow);\n        }\n    }\n\n    // 4. Construct Path using DFS simulation\n    vector<string> ops;\n    int current_pos = 0; // Start at (0,0)\n    int current_load = 0;\n    \n    // Helper to perform moves\n    auto move_to = [&](int target_pos) {\n        int cx = current_pos / n;\n        int cy = current_pos % n;\n        int tx = target_pos / n;\n        int ty = target_pos % n;\n        \n        // Simple BFS to find path (since we just need a path, but shortest is best)\n        // For simplicity, just move greedily or BFS.\n        // Given the constraints and the fact that we mostly follow flow edges,\n        // we might just need to connect components. \n        // But here we implement BFS for shortest path.\n        \n        vector<int> prev(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        prev[current_pos] = current_pos;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_pos) break;\n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        // Reconstruct path\n        vector<int> path;\n        int curr = target_pos;\n        while (curr != current_pos) {\n            path.push_back(curr);\n            curr = prev[curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        for (int next_pos : path) {\n            int dx = (next_pos / n) - (current_pos / n);\n            int dy = (next_pos % n) - (current_pos % n);\n            for (int k = 0; k < 4; ++k) {\n                if (DX[k] == dx && DY[k] == dy) {\n                    ops.push_back(string(1, DIR_CHAR[k]));\n                    break;\n                }\n            }\n            current_pos = next_pos;\n            // We assume move_to is called with 0 load or correct load.\n            // The cost update is implicit in the operations.\n        }\n    };\n\n    // Helper to load/unload\n    auto check_height = [&]() {\n        if (h[current_pos] > 0) {\n            ops.push_back(\"+\" + to_string(h[current_pos]));\n            current_load += h[current_pos];\n            h[current_pos] = 0;\n        } else if (h[current_pos] < 0) {\n            // We need to unload.\n            // However, we might not have exactly -h[current_pos] available if flow is split weirdly?\n            // In theory, inflow should cover it.\n            int needed = -h[current_pos];\n            if (current_load >= needed) {\n                ops.push_back(\"-\" + to_string(needed));\n                current_load -= needed;\n                h[current_pos] = 0;\n            } else {\n                // Should not happen in optimal flow, but just in case:\n                // This implies we need to carry more soil here.\n                // Or we are processing in a weird order.\n                // With the tree traversal, we should arrive with sufficient load.\n                // If not, it's a logic error in flow construction or traversal.\n                // We will assume it holds.\n            }\n        }\n    };\n\n    // Recursive DFS to cover flow tree\n    // Returns true if we don't need to backtrack (optimized path end)\n    function<bool(int)> dfs = [&](int u) {\n        // 1. Satisfy height at u\n        check_height();\n        \n        // 2. Process children\n        if (adj[u].empty()) {\n            return true; // Leaf\n        }\n        \n        // Optimization: Find the child with the deepest/longest path to process last (to avoid backtrack)\n        // Simple heuristic: just iterate.\n        // To avoid backtrack on the last child:\n        for (size_t i = 0; i < adj[u].size(); ++i) {\n            int v = adj[u][i].first;\n            int flow_amt = adj[u][i].second;\n            \n            // We need to carry `flow_amt` from u to v.\n            // The rest of current_load (if any) should stay at u.\n            // We unload the rest, reload later.\n            int load_to_keep = current_load - flow_amt;\n            \n            if (load_to_keep > 0) {\n                ops.push_back(\"-\" + to_string(load_to_keep));\n                current_load -= load_to_keep;\n                // Height of u increases temporarily. This is fine, we fix it later.\n                h[u] += load_to_keep; \n            }\n            \n            // Move to v\n            move_to(v);\n            // current_load should be flow_amt now\n            if (current_load != flow_amt) {\n                // Logic error\n            }\n            \n            bool should_return = true;\n            if (i == adj[u].size() - 1) {\n                should_return = false; // Last child, don't return\n            }\n            \n            bool child_is_leaf = dfs(v);\n            \n            if (!should_return) {\n                return false; // Propagate \"don't return\" up\n            }\n            \n            // Return from v\n            // At v, we should have 0 load (all deposited at its children/height)\n            // Move back to u\n            move_to(u);\n            \n            // Reload the soil we left at u\n            if (load_to_keep > 0) {\n                ops.push_back(\"+\" + to_string(load_to_keep));\n                current_load += load_to_keep;\n                h[u] -= load_to_keep;\n            }\n            // Now current_load is restored for next child\n        }\n        return true;\n    };\n\n    // Main loop to handle disconnected components\n    while (true) {\n        // Check if any flow remains\n        bool has_flow = false;\n        int best_u = -1;\n        int best_dist = INF;\n        \n        // Find closest node with remaining outflow\n        // Simple BFS from current_pos\n        vector<int> dist(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        dist[current_pos] = 0;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            \n            if (!adj[u].empty()) {\n                if (dist[u] < best_dist) {\n                    best_dist = dist[u];\n                    best_u = u;\n                }\n            }\n            \n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (dist[v] == -1) {\n                        dist[v] = dist[u] + 1;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        if (best_u == -1) break; // Done\n        \n        if (best_u != current_pos) {\n            // Move to best_u with 0 load (we assume we can reach with 0 load)\n            // We need to ensure we have 0 load to move optimally?\n            // Actually, we might have load if we are in a middle of something.\n            // But this loop handles disconnected components.\n            // So we should be at load 0 when jumping.\n            move_to(best_u);\n        }\n        \n        // Process component starting at best_u\n        dfs(best_u);\n    }\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    vector<vector<int>> X(seed_count, vector<int>(M));\n\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int t = 0; t < T; t++) {\n        // 1. Calculate total value V for each seed\n        vector<int> V(seed_count);\n        for (int i = 0; i < seed_count; i++) {\n            V[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // 2. Sort seeds by total value V descending for efficient selection of generalists\n        vector<int> sorted_indices(seed_count);\n        iota(sorted_indices.begin(), sorted_indices.end(), 0);\n        sort(sorted_indices.begin(), sorted_indices.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        // 3. Select seeds\n        vector<int> selected_indices;\n        vector<bool> used(seed_count, false);\n\n        // Strategy A: Select the best seed for each dimension (Specialists)\n        // This ensures we carry the genes for X_l\n        for (int l = 0; l < M; l++) {\n            int best_seed = -1;\n            int best_val = -1;\n            for (int i = 0; i < seed_count; i++) {\n                if (!used[i]) {\n                    if (X[i][l] > best_val) {\n                        best_val = X[i][l];\n                        best_seed = i;\n                    }\n                }\n            }\n            if (best_seed != -1) {\n                selected_indices.push_back(best_seed);\n                used[best_seed] = true;\n            }\n        }\n\n        // Strategy B: Fill the rest with the highest V seeds (Generalists)\n        // This ensures the population maintains high fitness\n        for (int idx : sorted_indices) {\n            if (!used[idx]) {\n                selected_indices.push_back(idx);\n                used[idx] = true;\n                if ((int)selected_indices.size() >= N * N) {\n                    break;\n                }\n            }\n        }\n\n        // 4. Sort selected seeds by V descending for placement\n        sort(selected_indices.begin(), selected_indices.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        // 5. Place seeds on the grid using a Snake pattern\n        // This clusters high V seeds in the top-left and lower V seeds in the bottom-right\n        // preserving strong local mating pairs for high fitness while allowing\n        // specialists (usually lower V) to cluster and innovate in the tail.\n        vector<vector<int>> A(N, vector<int>(N));\n        int ptr = 0;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) {\n                    A[i][j] = selected_indices[ptr++];\n                }\n            } else {\n                for (int j = N - 1; j >= 0; j--) {\n                    A[i][j] = selected_indices[ptr++];\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                cout << A[i][j] << (j < N - 1 ? \" \" : \"\\n\");\n            }\n        }\n        cout.flush();\n\n        // 7. Read new seeds for the next turn\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    // Grid state\n    vector<vector<int>> grid(N, vector<int>(N, 0)); // 0: empty, 1: item present\n    vector<vector<int>> target(N, vector<int>(N, 0));\n\n    string s_row, t_row;\n    for (int i = 0; i < N; ++i) {\n        cin >> s_row;\n        for (int j = 0; j < N; ++j) grid[i][j] = s_row[j] - '0';\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> t_row;\n        for (int j = 0; j < N; ++j) target[i][j] = t_row[j] - '0';\n    }\n\n    // --- 1. Design Robotic Arm ---\n    // Star topology: Root 0, children 1..V-1.\n    // Lengths: 1, 2, ..., V-1.\n    // This provides distinct reach for each arm.\n    cout << V << \"\\n\";\n    vector<int> lengths(V);\n    for (int i = 1; i < V; ++i) {\n        lengths[i] = i;\n        cout << 0 << \" \" << i << \"\\n\";\n    }\n\n    // Initial position: (0, 0)\n    int rx = 0, ry = 0;\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // --- 2. Operate ---\n    vector<int> arm_dirs(V, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(V, 0);  // 0 or 1, whether fingertip i holds an item\n\n    int total_steps = 0;\n    const int MAX_STEPS = 100000;\n\n    // Snake movement state\n    int move_dir = 0; // 0: Right\n    int current_row = 0;\n\n    auto is_finished = [&]() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] != target[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    while (total_steps < MAX_STEPS && !is_finished()) {\n        string S(2 * V, '.');\n\n        // --- A. Determine Movement (Snake) ---\n        if (move_dir == 0) { // Moving Right\n            if (ry + 1 < N) {\n                S[0] = 'R';\n                ry++;\n            } else {\n                // Reached right end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 2; // Switch to Left\n                } else {\n                    S[0] = '.'; // End of grid\n                }\n            }\n        } else if (move_dir == 2) { // Moving Left\n            if (ry - 1 >= 0) {\n                S[0] = 'L';\n                ry--;\n            } else {\n                // Reached left end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 0; // Switch to Right\n                } else {\n                    S[0] = '.';\n                }\n            }\n        }\n\n        // --- B. Determine Rotations (Greedy) ---\n        // For each arm (excluding root), evaluate which direction points to the most valuable square.\n        for (int i = 1; i < V; ++i) {\n            int best_dir = arm_dirs[i];\n            int best_score = -1;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                int tx = rx + DX[d] * lengths[i];\n                int ty = ry + DY[d] * lengths[i];\n                int score = 0;\n\n                if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                    // Logic: High value if:\n                    // 1. It's a source (grid=1, target=0) and we can pick it.\n                    // 2. It's a target (grid=0, target=1) and we are holding an item to place.\n                    if (grid[tx][ty] == 1 && target[tx][ty] == 0) {\n                        score += 10; // Prioritize picking up sources\n                    } else if (grid[tx][ty] == 0 && target[tx][ty] == 1) {\n                        score += 5;  // Next prioritize filling targets\n                    } else if (grid[tx][ty] == 1 && target[tx][ty] == 1) {\n                        score += 1;   // Already correct\n                    }\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_dir = d;\n                }\n            }\n\n            // Set rotation command\n            if (best_dir != arm_dirs[i]) {\n                int diff = (best_dir - arm_dirs[i] + 4) % 4;\n                if (diff == 1) S[i] = 'R';\n                else if (diff == 3) S[i] = 'L';\n                else if (diff == 2) {\n                    // 180 degree turn, choose L (arbitrary, or shortest path)\n                    S[i] = 'L'; \n                    best_dir = (arm_dirs[i] + 3) % 4; // Update to intermediate state\n                }\n            }\n            \n            // Update internal state for this step (so Action phase uses correct coords)\n            arm_dirs[i] = best_dir;\n        }\n\n        // --- C. Determine Actions (Pick/Put) ---\n        // Loop from 1 to V-1 (Vertex 0 is root/internal, cannot act).\n        for (int i = 1; i < V; ++i) {\n            int cx = rx + DX[arm_dirs[i]] * lengths[i];\n            int cy = ry + DY[arm_dirs[i]] * lengths[i];\n\n            char action_cmd = '.';\n            if (cx >= 0 && cx < N && cy >= 0 && cy < N) {\n                if (holding[i] == 1) {\n                    // Try to Place\n                    if (grid[cx][cy] == 0 && target[cx][cy] == 1) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 1;\n                        holding[i] = 0;\n                    }\n                } else {\n                    // Try to Pick\n                    if (grid[cx][cy] == 1 && target[cx][cy] == 0) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 0;\n                        holding[i] = 1;\n                    }\n                }\n            }\n            S[V + i] = action_cmd;\n        }\n\n        cout << S << \"\\n\";\n        total_steps++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int TYPE_MACKEREL = 1;\nconst int TYPE_SARDINE = -1;\n\nstruct Point {\n    int x, y, type;\n};\n\nstruct Rect {\n    int x1, x2, y1, y2;\n    int net; // a - b\n};\n\n// Global storage for points\n// Indexed by x, stores (y, type)\nvector<vector<pair<int, int>>> cols;\n// Indexed by y, stores (x, type)\nvector<vector<pair<int, int>>> rows;\n\n// Next/Previous populated indices\nint next_x[MAX_COORD + 2];\nint prev_x[MAX_COORD + 2];\nint next_y[MAX_COORD + 2];\nint prev_y[MAX_COORD + 2];\n\nint best_global_score = -1;\nRect best_global_rect;\n\n// Calculate current net score if we expand the rect in the given direction\n// Returns {new_net_score, new_x1, new_x2, new_y1, new_y2} or {-1, ...} if invalid/no move\ntuple<int, int, int, int, int> try_expand(int x1, int x2, int y1, int y2, int dir) {\n    int nx1 = x1, nx2 = x2, ny1 = y1, ny2 = y2;\n    int delta = 0;\n\n    if (dir == 0) { // Right\n        if (next_x[x2] == -1) return {-1, -1, -1, -1, -1};\n        int target_x = next_x[x2];\n        // Check perimeter limit\n        if (2LL * (target_x - x1 + y2 - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n        \n        nx2 = target_x;\n        // Calculate gain\n        for (const auto& p : cols[target_x]) {\n            if (p.first >= y1 && p.first <= y2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 1) { // Left\n        if (prev_x[x1] == -1) return {-1, -1, -1, -1, -1};\n        int target_x = prev_x[x1];\n        if (2LL * (x2 - target_x + y2 - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        nx1 = target_x;\n        for (const auto& p : cols[target_x]) {\n            if (p.first >= y1 && p.first <= y2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 2) { // Top\n        if (next_y[y2] == -1) return {-1, -1, -1, -1, -1};\n        int target_y = next_y[y2];\n        if (2LL * (x2 - x1 + target_y - y1) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        ny2 = target_y;\n        for (const auto& p : rows[target_y]) {\n            if (p.first >= x1 && p.first <= x2) {\n                delta += p.second;\n            }\n        }\n    } else if (dir == 3) { // Bottom\n        if (prev_y[y1] == -1) return {-1, -1, -1, -1, -1};\n        int target_y = prev_y[y1];\n        if (2LL * (x2 - x1 + y2 - target_y) > MAX_PERIMETER) return {-1, -1, -1, -1, -1};\n\n        ny1 = target_y;\n        for (const auto& p : rows[target_y]) {\n            if (p.first >= x1 && p.first <= x2) {\n                delta += p.second;\n            }\n        }\n    }\n\n    return {delta, nx1, nx2, ny1, ny2};\n}\n\nvoid solve() {\n    int N;\n    cin >> N;\n    vector<Point> mackerels(N);\n    vector<Point> sardines(N);\n\n    cols.resize(MAX_COORD + 1);\n    rows.resize(MAX_COORD + 1);\n\n    // Helper to add point\n    auto add_point = [&](int x, int y, int type) {\n        cols[x].emplace_back(y, type);\n        rows[y].emplace_back(x, type);\n    };\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].type = TYPE_MACKEREL;\n        add_point(mackerels[i].x, mackerels[i].y, TYPE_MACKEREL);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].type = TYPE_SARDINE;\n        add_point(sardines[i].x, sardines[i].y, TYPE_SARDINE);\n    }\n\n    // Precompute next/prev\n    int last_x = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_x[i] = last_x;\n        if (!cols[i].empty()) last_x = i;\n    }\n    int next_x_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_x[i] = next_x_val;\n        if (!cols[i].empty()) next_x_val = i;\n    }\n\n    int last_y = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_y[i] = last_y;\n        if (!rows[i].empty()) last_y = i;\n    }\n    int next_y_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_y[i] = next_y_val;\n        if (!rows[i].empty()) next_y_val = i;\n    }\n\n    // Iterate over all mackerels as starting points\n    // Since N is 5000, we can afford many restarts\n    for (const auto& start_pt : mackerels) {\n        int cx1 = start_pt.x, cx2 = start_pt.x;\n        int cy1 = start_pt.y, cy2 = start_pt.y;\n        int cnet = 1; // Starts with 1 mackerel\n\n        unordered_set<long long> visited;\n        // Encode state to single long long for hash set\n        auto encode = [](int x1, int x2, int y1, int y2) {\n            return ((long long)x1 << 48) | ((long long)x2 << 32) | ((long long)y1 << 16) | y2;\n        };\n        visited.insert(encode(cx1, cx2, cy1, cy2));\n\n        int best_local_net = cnet;\n        Rect best_local_rect = {cx1, cx2, cy1, cy2, cnet};\n\n        while (true) {\n            int best_delta = -2; // Less than -1\n            int best_dir = -1;\n            int tx1, tx2, ty1, ty2;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                auto [delta, nx1, nx2, ny1, ny2] = try_expand(cx1, cx2, cy1, cy2, d);\n                if (delta == -1) continue; // Invalid move\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_dir = d;\n                    tx1 = nx1; tx2 = nx2; ty1 = ny1; ty2 = ny2;\n                }\n            }\n\n            if (best_dir == -1) break; // No valid moves\n\n            // Move logic\n            if (best_delta > 0) {\n                // Improve score, always take\n                cx1 = tx1; cx2 = tx2; cy1 = ty1; cy2 = ty2;\n                cnet += best_delta;\n            } else if (best_delta == 0) {\n                // Neutral move, take if not visited\n                if (visited.count(encode(tx1, tx2, ty1, ty2))) {\n                    break; // Cycle detected\n                }\n                cx1 = tx1; cx2 = tx2; cy1 = ty1; cy2 = ty2;\n                // cnet unchanged\n            } else {\n                // Negative score move, stop\n                break;\n            }\n\n            visited.insert(encode(cx1, cx2, cy1, cy2));\n\n            if (cnet > best_local_net) {\n                best_local_net = cnet;\n                best_local_rect = {cx1, cx2, cy1, cy2, cnet};\n            }\n        }\n\n        if (best_local_net > best_global_score) {\n            best_global_score = best_local_net;\n            best_global_rect = best_local_rect;\n        }\n    }\n\n    // Output the best rectangle found\n    // Vertices can be (x1, y1), (x2, y1), (x2, y2), (x1, y2)\n    cout << 4 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y2 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y2 << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <tuple>\n\nusing namespace std;\n\n// Global inputs\nint N, T;\nlong long sigma;\nvector<pair<long long, long long>> dims; // w', h'\n\n// Structure to store operations\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\n// Structure for placed rectangles\nstruct Rect {\n    long long w, h;\n    long long x, y;\n    int id;\n};\n\n// Best solution found\nvector<Op> best_ops;\nlong long best_score = 1e18;\n\n// Helper to check if two intervals [l1, r1) and [l2, r2) overlap\nbool overlap(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n// Function to attempt one packing arrangement\nvoid solve_one(int seed) {\n    // Initialize random generator\n    mt19937 rng(seed);\n    \n    vector<Rect> placed;\n    placed.reserve(N);\n    long long W = 0, H = 0;\n    long long skipped_sum = 0;\n    vector<Op> current_ops;\n    current_ops.reserve(N);\n    \n    for (int i = 0; i < N; ++i) {\n        long long w_i = dims[i].first;\n        long long h_i = dims[i].second;\n        \n        // Candidates: {score_increase, r, d, b, x, y}\n        // score_increase is delta(W) + delta(H)\n        vector<tuple<long long, int, char, int, long long, long long>> cands;\n        \n        // Option 1: Skip the rectangle\n        // Cost is w_i + h_i added to score\n        cands.push_back({w_i + h_i, -1, 'X', -1, 0, 0});\n        \n        // Option 2: Try placing it\n        for (int r = 0; r < 2; ++r) {\n            long long cw = (r == 0 ? w_i : h_i);\n            long long ch = (r == 1 ? w_i : h_i);\n            \n            // Case 2.1: Reference is -1 (Align with x=0 for U, y=0 for L)\n            \n            // Direction U: x = 0. Slide up.\n            {\n                long long x = 0;\n                long long min_obst_y = 0; // Boundary y=0\n                for (const auto& p : placed) {\n                    if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                        min_obst_y = min(min_obst_y, p.y + p.h);\n                    }\n                }\n                long long y_new = min_obst_y - ch;\n                if (y_new < 0) y_new = 0;\n                \n                long long new_W = max(W, x + cw);\n                long long new_H = max(H, y_new + ch);\n                long long score_inc = (new_W - W) + (new_H - H);\n                cands.push_back({score_inc, r, 'U', -1, x, y_new});\n            }\n            \n            // Direction L: y = 0. Slide left.\n            {\n                long long y = 0;\n                long long min_obst_x = 0; // Boundary x=0\n                for (const auto& p : placed) {\n                    if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                        min_obst_x = min(min_obst_x, p.x + p.w);\n                    }\n                }\n                long long x_new = min_obst_x - cw;\n                if (x_new < 0) x_new = 0;\n                \n                long long new_W = max(W, x_new + cw);\n                long long new_H = max(H, y + ch);\n                long long score_inc = (new_W - W) + (new_H - H);\n                cands.push_back({score_inc, r, 'L', -1, x_new, y});\n            }\n            \n            // Case 2.2: Reference is a previously placed rectangle\n            for (size_t k = 0; k < placed.size(); ++k) {\n                const auto& ref = placed[k];\n                \n                // Direction U: x = ref.right. Slide up.\n                {\n                    long long x = ref.x + ref.w;\n                    long long min_obst_y = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                            min_obst_y = min(min_obst_y, p.y + p.h);\n                        }\n                    }\n                    long long y_new = min_obst_y - ch;\n                    if (y_new < 0) y_new = 0;\n                    \n                    long long new_W = max(W, x + cw);\n                    long long new_H = max(H, y_new + ch);\n                    long long score_inc = (new_W - W) + (new_H - H);\n                    cands.push_back({score_inc, r, 'U', ref.id, x, y_new});\n                }\n                \n                // Direction L: y = ref.bottom. Slide left.\n                {\n                    long long y = ref.y + ref.h;\n                    long long min_obst_x = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                            min_obst_x = min(min_obst_x, p.x + p.w);\n                        }\n                    }\n                    long long x_new = min_obst_x - cw;\n                    if (x_new < 0) x_new = 0;\n                    \n                    long long new_W = max(W, x_new + cw);\n                    long long new_H = max(H, y + ch);\n                    long long score_inc = (new_W - W) + (new_H - H);\n                    cands.push_back({score_inc, r, 'L', ref.id, x_new, y});\n                }\n            }\n        }\n        \n        // Sort candidates by score increase\n        sort(cands.begin(), cands.end());\n        \n        // Select candidate: pick from top 3 to introduce randomness\n        int limit = min(3, (int)cands.size());\n        int idx = rng() % limit;\n        \n        const auto& chosen = cands[idx];\n        long long score_inc = get<0>(chosen);\n        int r = get<1>(chosen);\n        char d = get<2>(chosen);\n        int b = get<3>(chosen);\n        long long bx = get<4>(chosen);\n        long long by = get<5>(chosen);\n        \n        if (r == -1) {\n            // Skip\n            skipped_sum += w_i + h_i;\n        } else {\n            // Place\n            long long final_w = (r == 0 ? w_i : h_i);\n            long long final_h = (r == 1 ? w_i : h_i);\n            \n            placed.push_back({final_w, final_h, bx, by, i});\n            W = max(W, bx + final_w);\n            H = max(H, by + final_h);\n            \n            current_ops.push_back({i, r, d, b});\n        }\n    }\n    \n    long long total_score = W + H + skipped_sum;\n    if (total_score < best_score) {\n        best_score = total_score;\n        best_ops = current_ops;\n    }\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma)) return 0;\n    \n    dims.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> dims[i].first >> dims[i].second;\n    }\n    \n    // Run search for approximately 2.8 seconds\n    auto start_time = chrono::high_resolution_clock::now();\n    int iter = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > 2800) break;\n        \n        solve_one(iter++);\n    }\n    \n    // Output the best found sequence T times\n    // The feedback is read but ignored as we assume the static problem nature.\n    for (int t = 0; t < T; ++t) {\n        cout << best_ops.size() << \"\\n\";\n        for (const auto& op : best_ops) {\n            cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read feedback (must be done)\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables to store input\nint N, M, H;\nvector<int> A;\nvector<vector<int>> G;\n\n// Structure to hold the result of a trial run\nstruct Solution {\n    vector<int> parent;\n    long long score;\n};\n\n// Function to construct trees based on a specific processing order\nSolution solve(const vector<int>& order) {\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<bool> processed(N, false);\n    \n    long long current_score = 0;\n\n    for (int v : order) {\n        int best_u = -1;\n        int best_depth = -1;\n\n        // Find the best parent among processed neighbors\n        for (int u : G[v]) {\n            if (processed[u] && depth[u] < H) {\n                if (depth[u] > best_depth) {\n                    best_depth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n\n        if (best_u != -1) {\n            parent[v] = best_u;\n            depth[v] = depth[best_u] + 1;\n        } else {\n            parent[v] = -1;\n            depth[v] = 0;\n        }\n\n        // Mark as processed\n        processed[v] = true;\n        \n        // Calculate score contribution: (h_v + 1) * A_v\n        current_score += (long long)(depth[v] + 1) * A[v];\n    }\n\n    return {parent, 1 + current_score};\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> H)) return 0;\n\n    A.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> A[i];\n    }\n\n    G.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n\n    // Read and ignore coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Generate base indices 0 to N-1\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n\n    // List of orders to try\n    vector<vector<int>> orders;\n\n    // 1. Ascending order of Beauty (Low to High)\n    vector<int> asc = indices;\n    sort(asc.begin(), asc.end(), [&](int u, int v) { return A[u] < A[v]; });\n    orders.push_back(asc);\n\n    // 2. Descending order of Beauty (High to Low)\n    vector<int> desc = indices;\n    sort(desc.begin(), desc.end(), [&](int u, int v) { return A[u] > A[v]; });\n    orders.push_back(desc);\n\n    // 3. Random orders\n    random_device rd;\n    mt19937 g(rd());\n\n    // Fully random shuffles\n    for (int i = 0; i < 30; ++i) {\n        vector<int> rnd = indices;\n        shuffle(rnd.begin(), rnd.end(), g);\n        orders.push_back(rnd);\n    }\n\n    // 4. Sorted orders with randomized ties\n    // Ascending with random tie-breaking\n    for (int i = 0; i < 10; ++i) {\n        vector<int> rnd = indices;\n        shuffle(rnd.begin(), rnd.end(), g);\n        stable_sort(rnd.begin(), rnd.end(), [&](int u, int v) { return A[u] < A[v]; });\n        orders.push_back(rnd);\n    }\n    // Descending with random tie-breaking\n    for (int i = 0; i < 10; ++i) {\n        vector<int> rnd = indices;\n        shuffle(rnd.begin(), rnd.end(), g);\n        stable_sort(rnd.begin(), rnd.end(), [&](int u, int v) { return A[u] > A[v]; });\n        orders.push_back(rnd);\n    }\n\n    // Find the best solution among all trials\n    long long best_score = -1;\n    vector<int> best_parent(N);\n\n    for (const auto& order : orders) {\n        Solution sol = solve(order);\n        if (sol.score > best_score) {\n            best_score = sol.score;\n            best_parent = sol.parent;\n        }\n    }\n\n    // Output the best solution found\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << best_parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n};\n\nint N;\nvector<string> grid;\nvector<Point> onis;\nvector<bool> removed; // Track if an oni is removed\n\n// Helper to check if there is 'o' in a range\nbool has_o_up(int r, int c) {\n    for (int i = 0; i < r; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_down(int r, int c) {\n    for (int i = r + 1; i < N; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_left(int r, int c) {\n    for (int j = 0; j < c; ++j) if (grid[r][j] == 'o') return true;\n    return false;\n}\nbool has_o_right(int r, int c) {\n    for (int j = c + 1; j < N; ++j) if (grid[r][j] == 'o') return true;\n    return false;\n}\n\n// Check if 'x' at (r, c) can be removed by shifting Up\nbool can_remove_up(int r, int c) {\n    return !has_o_up(r, c);\n}\nbool can_remove_down(int r, int c) {\n    return !has_o_down(r, c);\n}\nbool can_remove_left(int r, int c) {\n    return !has_o_left(r, c);\n}\nbool can_remove_right(int r, int c) {\n    return !has_o_right(r, c);\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    // Collect Oni positions\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 'x') {\n                onis.push_back({i, j});\n            }\n        }\n    }\n\n    removed.assign(onis.size(), false);\n\n    // Moves container\n    vector<pair<char, int>> moves;\n\n    // --- PHASE 1: ROW REMOVALS ---\n    // Process each row\n    for (int r = 0; r < N; ++r) {\n        // Identify segments in this row separated by 'o'\n        // A segment is a contiguous range of columns [l, r_end] containing no 'o'\n        vector<pair<int, int>> segments;\n        int l = 0;\n        while (l < N) {\n            while (l < N && grid[r][l] == 'o') l++;\n            if (l >= N) break;\n            int rend = l;\n            while (rend < N && grid[r][rend] != 'o') rend++;\n            segments.push_back({l, rend - 1});\n            l = rend;\n        }\n\n        for (auto seg : segments) {\n            int seg_l = seg.first;\n            int seg_r = seg.second;\n\n            // Collect 'x's in this segment\n            vector<int> p_idx; // indices in onis vector\n            vector<int> cols;  // column positions\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].r == r && onis[k].c >= seg_l && onis[k].c <= seg_r) {\n                    p_idx.push_back(k);\n                    cols.push_back(onis[k].c);\n                }\n            }\n\n            if (cols.empty()) continue;\n\n            // Classify into FORCED (cannot go vertical) and CHOICE (can go vertical)\n            // Actually, we solve row-wise. \n            // If an 'x' cannot go Up or Down, it MUST be removed here.\n            // If it CAN go Up/Down, it's optional, but we might remove it here if cheap.\n\n            vector<bool> is_forced(cols.size(), false);\n            vector<int> col_cost_saving(cols.size()); // Approximate saving if removed by row\n\n            for (size_t i = 0; i < cols.size(); ++i) {\n                int c = cols[i];\n                int idx = p_idx[i];\n                \n                bool can_up = can_remove_up(r, c);\n                bool can_down = can_remove_down(r, c);\n\n                if (!can_up && !can_down) {\n                    is_forced[i] = true;\n                } else {\n                    // Calculate minimal vertical cost as a proxy for savings\n                    // Up cost: 2*(r+1), Down cost: 2*(N-r)\n                    int v_cost = min(2 * (r + 1), 2 * (N - r));\n                    col_cost_saving[i] = v_cost;\n                }\n            }\n\n            // We want to find a set of intervals (Left-covers and Right-covers) \n            // that covers all 'is_forced' onis, minimizing \n            // Cost_row - Sum(savings of covered optional).\n            \n            // Since N is small (20), and segment length is small, we can use DP.\n            // DP[mask] = min cost to cover a subset of onis in this segment.\n            // But number of onis per segment can be up to 20. 2^20 is too big.\n            // Instead, use the greedy heuristic:\n            // 1. Find optimal cover for FORCED points.\n            // 2. Greedily add OPTIONAL points if beneficial.\n\n            // Step 1: DP for forced points\n            // Sort points by column\n            vector<pair<int, int>> forced_pts; // (col, index in cols)\n            for (size_t i = 0; i < cols.size(); ++i) {\n                if (is_forced[i]) forced_pts.push_back({cols[i], i});\n            }\n\n            // Structure: \n            // DP[k] = min cost to cover first k forced points (sorted by col).\n            // DP[i] = min(DP[i], DP[j-1] + cost_cover(j..i))\n            // Cost to cover points j..i:\n            //   Using Left interval (covers up to forced_pts[i].first): cost = 2*(forced_pts[i].first + 1)\n            //   Using Right interval (covers from forced_pts[j].first): cost = 2*(N - forced_pts[j].first)\n            // We also need to track which intervals are used.\n            \n            if (!forced_pts.empty()) {\n                int K = forced_pts.size();\n                vector<int> dp(K, 1e9);\n                vector<pair<int, int>> choice(K, {-1, 0}); // {prev_idx, type} 0=Left, 1=Right\n\n                for (int i = 0; i < K; ++i) {\n                    // Try covering from a previous cut j to i\n                    for (int j = 0; j <= i; ++j) {\n                        int prev_cost = (j == 0) ? 0 : dp[j-1];\n                        \n                        // Try Left cover (covers all points from j..i)\n                        int costL = prev_cost + 2 * (forced_pts[i].first + 1);\n                        if (costL < dp[i]) {\n                            dp[i] = costL;\n                            choice[i] = {j - 1, 0}; // Type 0: Left covering up to i\n                        }\n\n                        // Try Right cover (covers all points from j..i)\n                        int costR = prev_cost + 2 * (N - forced_pts[j].first);\n                        if (costR < dp[i]) {\n                            dp[i] = costR;\n                            choice[i] = {j - 1, 1}; // Type 1: Right covering from j\n                        }\n                    }\n                }\n\n                // Reconstruct intervals\n                int curr = K - 1;\n                vector<pair<int, int>> intervals; // {val, type}, type 0=L, 1=R\n                \n                while (curr >= 0) {\n                    int prev = choice[curr].first;\n                    int type = choice[curr].second;\n                    \n                    if (type == 0) {\n                        intervals.push_back({forced_pts[curr].first, 0});\n                    } else {\n                        intervals.push_back({forced_pts[prev + 1].first, 1});\n                    }\n                    curr = prev;\n                }\n                reverse(intervals.begin(), intervals.end());\n\n                // Apply these intervals (mark removed, add moves)\n                // Note: We need to check which optional points fall into these intervals\n                for (auto &iv : intervals) {\n                    int bound = iv.first;\n                    int type = iv.second;\n                    \n                    if (type == 0) { // Left cover: covers [0, bound]\n                        // Add moves\n                        moves.push_back({'L', r});\n                        for(int k=0; k<bound; ++k) moves.push_back({'L', r}); // Logic in output\n                        // Actually output format: \"L i\" repeated? No, output operations one by one.\n                        // Sequence: L (bound+1) times, then R (bound+1) times\n                        for(int k=0; k <= bound; ++k) moves.push_back({'L', r});\n                        for(int k=0; k <= bound; ++k) moves.push_back({'R', r});\n\n                        // Mark removed\n                        for (size_t i = 0; i < cols.size(); ++i) {\n                            if (!removed[p_idx[i]] && cols[i] <= bound) {\n                                removed[p_idx[i]] = true;\n                            }\n                        }\n                    } else { // Right cover: covers [bound, N-1]\n                        for(int k=0; k < N-bound; ++k) moves.push_back({'R', r});\n                        for(int k=0; k < N-bound; ++k) moves.push_back({'L', r});\n\n                        for (size_t i = 0; i < cols.size(); ++i) {\n                            if (!removed[p_idx[i]] && cols[i] >= bound) {\n                                removed[p_idx[i]] = true;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Step 2: Greedy expansion for remaining optional points\n            // We have intervals (implicit from the moves added).\n            // Simplification: Just check remaining optional points individually.\n            // If we can extend an existing interval or create a new one cheaper than col cost, do it.\n            // Since we already output moves for the forced set, we need to be careful not to duplicate logic.\n            // Actually, it's easier to re-evaluate the whole segment \"optimally\" with savings.\n            // But for simplicity, let's iterate over remaining optional points.\n            \n            // Get remaining optional points\n            vector<int> remaining_opts;\n            for(size_t i=0; i<cols.size(); ++i) {\n                if(!removed[p_idx[i]] && !is_forced[i]) {\n                    remaining_opts.push_back(cols[i]);\n                }\n            }\n\n            for (int c_opt : remaining_opts) {\n                // Cost to cover this single point with Row\n                int cost_left = 2 * (c_opt + 1);\n                int cost_right = 2 * (N - c_opt);\n                int min_row_cost = min(cost_left, cost_right);\n\n                // Benefit: col_cost_saving\n                // We need to find which 'c_opt' corresponds to in savings map.\n                // Just recompute saving.\n                int saving = min(2 * (r + 1), 2 * (N - r));\n\n                if (min_row_cost < saving) {\n                    // Cover with row\n                    if (cost_left < cost_right) {\n                        for(int k=0; k<=c_opt; ++k) moves.push_back({'L', r});\n                        for(int k=0; k<=c_opt; ++k) moves.push_back({'R', r});\n                    } else {\n                        for(int k=0; k < N-c_opt; ++k) moves.push_back({'R', r});\n                        for(int k=0; k < N-c_opt; ++k) moves.push_back({'L', r});\n                    }\n                    // Mark removed\n                     for (size_t i = 0; i < cols.size(); ++i) {\n                        if (cols[i] == c_opt && !removed[p_idx[i]]) {\n                            removed[p_idx[i]] = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // --- PHASE 2: COLUMN REMOVALS ---\n    // Similar logic for columns\n    for (int c = 0; c < N; ++c) {\n        vector<pair<int, int>> segments;\n        int u = 0;\n        while (u < N) {\n            while (u < N && grid[u][c] == 'o') u++;\n            if (u >= N) break;\n            int d = u;\n            while (d < N && grid[d][c] != 'o') d++;\n            segments.push_back({u, d - 1});\n            u = d;\n        }\n\n        for (auto seg : segments) {\n            int seg_u = seg.first;\n            int seg_d = seg.second;\n\n            vector<int> p_idx;\n            vector<int> rows;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].c == c && onis[k].r >= seg_u && onis[k].r <= seg_d) {\n                    p_idx.push_back(k);\n                    rows.push_back(onis[k].r);\n                }\n            }\n\n            if (rows.empty()) continue;\n\n            // All remaining onis are necessarily \"col_choice\", otherwise they would have been removed in row phase\n            // We just solve 1D cover for this set to minimize cost.\n            \n            // Sort rows\n            sort(rows.begin(), rows.end());\n            // Re-map indices to find oni idx\n            map<int, int> row_to_oni_idx;\n            for(size_t i=0; i<rows.size(); ++i) {\n                for(auto& p : p_idx) { // inefficient but N is small\n                    if(onis[p].r == rows[i]) row_to_oni_idx[rows[i]] = p;\n                }\n            }\n\n            // Standard 1D Cover DP for points on line\n            // Up corresponds to Left (prefix), Down corresponds to Right (suffix)\n            int K = rows.size();\n            vector<int> dp(K, 1e9);\n            vector<pair<int, int>> choice(K, {-1, 0}); // 0=Up, 1=Down\n\n            for (int i = 0; i < K; ++i) {\n                for (int j = 0; j <= i; ++j) {\n                    int prev_cost = (j == 0) ? 0 : dp[j-1];\n                    \n                    // Up (covers [seg_u, rows[i]])\n                    int costU = prev_cost + 2 * (rows[i] + 1);\n                    if (costU < dp[i]) {\n                        dp[i] = costU;\n                        choice[i] = {j - 1, 0};\n                    }\n\n                    // Down (covers [rows[j], seg_d])\n                    // Cost to shift down enough to remove rows[j] is 2 * (N - rows[j])\n                    int costD = prev_cost + 2 * (N - rows[j]);\n                    if (costD < dp[i]) {\n                        dp[i] = costD;\n                        choice[i] = {j - 1, 1};\n                    }\n                }\n            }\n\n            // Reconstruct and apply\n            int curr = K - 1;\n            while (curr >= 0) {\n                int prev = choice[curr].first;\n                int type = choice[curr].second;\n\n                if (type == 0) {\n                    int r_end = rows[curr];\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'U', c});\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'D', c});\n                    \n                    for(int r = seg_u; r <= r_end; ++r) {\n                        if(row_to_oni_idx.count(r)) removed[row_to_oni_idx[r]] = true;\n                    }\n                } else {\n                    int r_start = rows[prev + 1];\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'D', c});\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'U', c});\n\n                    for(int r = r_start; r <= seg_d; ++r) {\n                        if(row_to_oni_idx.count(r)) removed[row_to_oni_idx[r]] = true;\n                    }\n                }\n                curr = prev;\n            }\n        }\n    }\n\n    // --- OUTPUT ---\n    cout << moves.size() << \"\\n\";\n    for (auto m : moves) {\n        cout << m.first << \" \" << m.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\n// Random number generator\nmt19937 rng(0); // Fixed seed for reproducibility in testing, use random_device for submission if allowed\n\n// Simulation function to calculate counts t_i and error\nlong long simulate(const vector<int>& a, const vector<int>& b, const vector<int>& T) {\n    vector<int> cnt(N, 0);\n    int cur = 0;\n    cnt[0] = 1;\n    for (int i = 1; i < L; ++i) {\n        if (cnt[cur] % 2 == 1) {\n            cur = a[cur];\n        } else {\n            cur = b[cur];\n        }\n        cnt[cur]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(cnt[i] - T[i]);\n    }\n    return error;\n}\n\n// Greedy construction of a and b based on target T\n// Randomize the order of processing nodes to explore different configurations\nvoid construct_greedy(const vector<int>& T, vector<int>& a, vector<int>& b) {\n    // Remaining demand for each node y\n    vector<long long> demand(N);\n    for (int i = 0; i < N; ++i) {\n        demand[i] = T[i];\n    }\n\n    // Process nodes in random order\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int x : order) {\n        long long tx = T[x];\n        if (tx == 0) {\n            // If target is 0, it doesn't matter much where we point, \n            // but pointing to a node with high demand might help satisfy it (if we ever visit x)\n            // However, we likely won't visit x. Just point randomly or to self.\n            a[x] = 0;\n            b[x] = 0;\n            continue;\n        }\n\n        // We split the outflow from x into two parts.\n        // Based on parity, we will use a_x roughly ceil(tx/2) times and b_x roughly floor(tx/2) times.\n        long long w1 = (tx + 1) / 2;\n        long long w2 = tx / 2;\n\n        // Find best y for w1\n        // We want to minimize |demand[y] - w1| ideally, but demand represents what we NEED.\n        // We are ADDING w1 to the inflow. So we want the new inflow (demand[y] + w1) to be close to target T[y].\n        // Wait, demand here is effectively \"remaining needed inflow\" or \"current balance\"?\n        // Let's define demand[y] as the current estimate of how much more inflow y needs.\n        // Initially demand[y] = T[y] (it needs T[y] inflow).\n        // When we send w to y, we reduce demand[y] by w?\n        // No, standard flow formulation: Sum of inflows = Sum of T. \n        // We want sum of inflows to be T. \n        // Let current_inflow[y] = 0. Target = T[y].\n        // We want to add w to current_inflow[y] such that current_inflow[y] is close to T[y].\n        // So we minimize | (current_inflow[y] + w) - T[y] |.\n        // This is equivalent to minimizing | -demand[y] + w | if demand[y] = T[y] - current_inflow[y].\n        // Let's stick to tracking \"current_inflow\".\n        \n        // Re-thinking the greedy logic for robustness:\n        // We have \"slots\" to fill. Total slots = L.\n        // We iterate x. x produces w1 and w2.\n        // We assign w1 to some y. We assign w2 to some z.\n        // We want the final distribution of assigned weights to match T.\n        \n        // Heuristic: Pick y that minimizes | (assigned_so_far[y] + w) - T[y] |.\n        // assigned_so_far is initially 0.\n        \n        // To implement this efficiently without scanning all N every time:\n        // We can just scan all N (N=100 is small).\n    }\n\n    // Let's redo the greedy logic cleanly here.\n    vector<long long> assigned(N, 0); // How much flow assigned to each node so far\n    \n    for (int x : order) {\n        long long w1 = (T[x] + 1) / 2;\n        long long w2 = T[x] / 2;\n\n        // Helper lambda to find best target\n        auto find_best_target = [&](long long w) -> int {\n            int best_y = 0;\n            long long best_diff = -1; \n            // We want to minimize overflow/underflow.\n            // Cost = |assigned[y] + w - T[y]|.\n            // We also want to slightly penalize staying on the same node to encourage mixing?\n            // Or maybe not. Let's stick to pure flow matching.\n            \n            for (int y = 0; y < N; ++y) {\n                long long diff = abs((assigned[y] + w) - T[y]);\n                // If diff is same, prefer random to break ties consistently but randomly\n                if (best_diff == -1 || diff < best_diff || (diff == best_diff && rng() % 2 == 0)) {\n                    best_diff = diff;\n                    best_y = y;\n                }\n            }\n            return best_y;\n        };\n\n        int y1 = find_best_target(w1);\n        assigned[y1] += w1;\n        a[x] = y1;\n\n        int y2 = find_best_target(w2);\n        assigned[y2] += w2;\n        b[x] = y2;\n    }\n}\n\nvoid solve() {\n    int n_input;\n    long long l_input;\n    cin >> n_input >> l_input;\n    N; // N is fixed 100\n    L; // L is fixed 500000\n\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    vector<int> best_a(N), best_b(N);\n    long long best_error = 1e18;\n\n    // We will perform multiple random restarts.\n    // Given 2 seconds and N=100, L=500k, we can fit maybe 500-1000 simulations.\n    // Let's try 500.\n    const int TRIES = 500;\n    \n    // Seed rng based on time for the submission\n    rng.seed(static_cast<unsigned int>(chrono::steady_clock::now().time_since_epoch().count()));\n\n    for (int t = 0; t < TRIES; ++t) {\n        vector<int> a(N), b(N);\n        construct_greedy(T, a, b);\n        \n        long long err = simulate(a, b, T);\n        if (err < best_error) {\n            best_error = err;\n            best_a = a;\n            best_b = b;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    solve();\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n\nusing namespace std;\n\n// DSU implementation\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        return true;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<double> cx, cy;\nvector<int> city_to_group; // Maps city index to group index\n\n// Function to estimate distance based on box centers\nint estimated_dist(int i, int j) {\n    double dx = cx[i] - cx[j];\n    double dy = cy[i] - cy[j];\n    return (int)floor(sqrt(dx*dx + dy*dy));\n}\n\n// Perform a query\nvector<pair<int, int>> ask_query(const vector<int>& cities) {\n    cout << \"? \" << cities.size();\n    for (int c : cities) cout << \" \" << c;\n    cout << endl;\n    cout.flush();\n    \n    vector<pair<int, int>> edges;\n    // We expect |C| - 1 edges\n    for (size_t i = 0; i < cities.size() - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.emplace_back(u, v);\n    }\n    return edges;\n}\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    cx.resize(N); cy.resize(N);\n    city_to_group.resize(N);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n    }\n\n    // 1. Assign cities to groups\n    // Sort all cities by their center coordinates\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n    \n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < G[k]; ++i) {\n            int city = order[idx++];\n            groups[k].push_back(city);\n            city_to_group[city] = k;\n        }\n    }\n\n    // 2. Global Scanning with Queries\n    // We scan the cities in the global order to capture local MST information\n    // without exceeding the query limit.\n    \n    // Sort cities again globally for the scanning phase.\n    // Using a simple X then Y sort.\n    vector<int> global_order(N);\n    iota(global_order.begin(), global_order.end(), 0);\n    sort(global_order.begin(), global_order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n\n    // Store known edges (u, v) where u < v\n    set<pair<int, int>> known_edges;\n    \n    int queries_used = 0;\n    // Stride of L/2 ensures overlap to catch edges that might cross window boundaries\n    int stride = max(1, L / 2);\n    \n    // Sliding window over globally sorted cities\n    for (int i = 0; i <= N - L; i += stride) {\n        if (queries_used >= Q) break;\n        \n        vector<int> subset(global_order.begin() + i, global_order.begin() + i + L);\n        auto res = ask_query(subset);\n        queries_used++;\n        \n        for (auto& e : res) {\n            known_edges.insert(e);\n        }\n    }\n\n    // 3. Construct Answer for each group\n    vector<vector<pair<int, int>>> answer_edges(M);\n    \n    for (int k = 0; k < M; ++k) {\n        auto& vec = groups[k];\n        int sz = vec.size();\n        \n        if (sz <= 1) continue;\n        \n        // Candidates: (priority, estimated_dist, u, v)\n        // Known edges get priority 0, Estimated get priority 1\n        // This ensures we use verified edges first, as estimates can be wrong\n        vector<tuple<int, int, int, int>> candidates;\n        \n        // Add known edges belonging to this group\n        for (auto& e : known_edges) {\n            if (city_to_group[e.first] == k && city_to_group[e.second] == k) {\n                int d = estimated_dist(e.first, e.second);\n                candidates.push_back({0, d, e.first, e.second});\n            }\n        }\n        \n        // Add estimated edges for all pairs in group\n        for (int i = 0; i < sz; ++i) {\n            for (int j = i + 1; j < sz; ++j) {\n                int u = vec[i];\n                int v = vec[j];\n                // Check if already in known_edges to avoid duplicates in candidates\n                // Although sorting handles duplicates, it saves work.\n                if (u > v) swap(u, v); // Ensure consistent order for lookup\n                if (known_edges.find({u, v}) != known_edges.end()) continue;\n                \n                int d = estimated_dist(u, v);\n                candidates.push_back({1, d, u, v});\n            }\n        }\n        \n        // Sort candidates\n        sort(candidates.begin(), candidates.end());\n        \n        // Run Kruskal\n        map<int, int> local_id;\n        for(int i=0; i<sz; ++i) local_id[vec[i]] = i;\n        \n        DSU dsu(sz);\n        int edges_needed = sz - 1;\n        \n        for (auto& item : candidates) {\n            int u = get<2>(item);\n            int v = get<3>(item);\n            int uid = local_id[u];\n            int vid = local_id[v];\n            \n            if (dsu.unite(uid, vid)) {\n                answer_edges[k].push_back({u, v});\n                if (answer_edges[k].size() == edges_needed) break;\n            }\n        }\n    }\n    \n    // Output\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities\n        for (int city : groups[k]) {\n            cout << city << (city == groups[k].back() ? \"\" : \" \");\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : answer_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    solve();\n    \n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\n// Coordinate system: x = column (j), y = row (i)\nstruct Point {\n    int x;\n    int y;\n};\n\nint N, M;\nvector<Point> targets;\n\nvector<pair<char, char>> actions;\n\nvoid add_action(char a, char d) {\n    actions.push_back({a, d});\n}\n\nvoid add_move(char d, int steps) {\n    for (int i = 0; i < steps; ++i) {\n        add_action('M', d);\n    }\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    targets.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int r, c;\n        cin >> r >> c;\n        targets[i].x = c; // j -> x\n        targets[i].y = r; // i -> y\n    }\n\n    Point cur = targets[0];\n\n    for (int k = 1; k < M; ++k) {\n        Point target = targets[k];\n        int dx = target.x - cur.x;\n        int dy = target.y - cur.y;\n\n        // Calculate walking cost (Manhattan distance)\n        int walk_cost = abs(dx) + abs(dy);\n        \n        // Evaluate Boundary Slide options\n        // We want to reach target T.\n        // Slide stops just before a block. The grid boundary (x=-1, x=N, y=-1, y=N) is a block.\n        // To slide to T, T must be adjacent to a boundary block in the direction of the slide.\n        // This means T must be on the grid boundary.\n        \n        int best_cost = walk_cost;\n        int best_strategy = 0; // 0: Walk, 1: Slide Vertical, 2: Slide Horizontal\n        char slide_dir = ' ';  // 'U', 'D', 'L', 'R'\n\n        // Option 1: Slide Vertical (Up or Down)\n        // Valid if T is on Top edge (y=0) or Bottom edge (y=N-1).\n        \n        // Slide Up to Top Edge\n        // Requires T.y == 0.\n        // We move vertically? No, Slide Up moves in y. We need to align x.\n        // Path: Align x (move horizontally), then Slide Up.\n        // Cost: |cur.x - T.x| + 1\n        // Valid if cur.y > 0 (since we must slide at least 1 step to hit wall effectively? \n        // Actually, if cur.y > 0, we can slide. If cur.y == 0, we are already on edge, Slide Up does nothing.\n        // Wait, if T=(0,0) and cur=(5,0), Slide U from 5,0 hits wall -1, stops at 0,0. Cost 1.\n        // Align x cost 5. Total 6. Walk 5. Slide is worse.\n        // But for large y distance:\n        // cur=(10, 10), T=(0, 0). \n        // Slide U: Align x (cost 10). Slide (1). Total 11.\n        // Walk: |10-0| + |10-0| = 20. Slide is better.\n        \n        if (target.y == 0 && cur.y > 0) {\n            int cost = abs(cur.x - target.x) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 1;\n                slide_dir = 'U';\n            }\n        }\n        \n        // Slide Down to Bottom Edge\n        // Requires T.y == N-1.\n        // Path: Align x, Slide Down.\n        // Cost: |cur.x - target.x| + 1\n        // Valid if cur.y < N-1.\n        if (target.y == N - 1 && cur.y < N - 1) {\n            int cost = abs(cur.x - target.x) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 1;\n                slide_dir = 'D';\n            }\n        }\n\n        // Option 2: Slide Horizontal (Left or Right)\n        // Valid if T is on Left edge (x=0) or Right edge (x=N-1).\n\n        // Slide Left to Left Edge\n        // Requires T.x == 0.\n        // Path: Align y, Slide Left.\n        // Cost: |cur.y - target.y| + 1\n        // Valid if cur.x > 0.\n        if (target.x == 0 && cur.x > 0) {\n            int cost = abs(cur.y - target.y) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 2;\n                slide_dir = 'L';\n            }\n        }\n\n        // Slide Right to Right Edge\n        // Requires T.x == N-1.\n        // Path: Align y, Slide Right.\n        // Cost: |cur.y - target.y| + 1\n        // Valid if cur.x < N-1.\n        if (target.x == N - 1 && cur.x < N - 1) {\n            int cost = abs(cur.y - target.y) + 1;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_strategy = 2;\n                slide_dir = 'R';\n            }\n        }\n\n        // Execute the chosen strategy\n        if (best_strategy == 0) {\n            // Walk\n            // Order of moves doesn't strictly matter for cost, but let's do X then Y\n            if (dx > 0) add_move('R', dx);\n            else if (dx < 0) add_move('L', -dx);\n            \n            if (dy > 0) add_move('D', dy);\n            else if (dy < 0) add_move('U', -dy);\n        } \n        else if (best_strategy == 1) {\n            // Vertical Slide\n            // Align X\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            // Slide\n            add_action('S', slide_dir);\n        } \n        else if (best_strategy == 2) {\n            // Horizontal Slide\n            // Align Y\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            // Slide\n            add_action('S', slide_dir);\n        }\n\n        cur = target;\n    }\n\n    // Output\n    for (const auto& act : actions) {\n        cout << act.first << \" \" << act.second << \"\\n\";\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <limits>\n#include <numeric>\n\nusing namespace std;\n\n// Use long long for area and error calculations to avoid overflow\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n    int a, b, c, d; // Output rectangle coordinates\n};\n\nvector<Company> companies;\n\n// Recursive function to partition the space\n// (x1, y1) is the bottom-left of the current region, (x2, y2) is the top-right\n// ids contains the indices of companies that must be placed in this region\nvoid solve_recursive(int x1, int y1, int x2, int y2, vector<int> ids) {\n    int k = ids.size();\n    if (k == 0) return;\n    \n    // Base case: only one company, assign the whole region\n    if (k == 1) {\n        int id = ids[0];\n        companies[id].a = x1;\n        companies[id].b = y1;\n        companies[id].c = x2;\n        companies[id].d = y2;\n        return;\n    }\n\n    ll total_area = (ll)(x2 - x1) * (y2 - y1);\n    \n    // Find the best cut (vertical or horizontal)\n    // We minimize the squared error: sum((assigned_area - desired_area)^2)\n    \n    ll best_error = numeric_limits<ll>::max();\n    int best_split_axis = -1; // 0: vertical, 1: horizontal\n    int best_split_idx = -1; // Index in the sorted list to split at\n    int best_cut_pos = -1;   // Coordinate of the cut\n    \n    // --- Try Vertical Cut ---\n    // Sort companies by X coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].x < companies[j].x;\n    });\n    \n    // Calculate prefix sums of r to quickly get sum of desired areas for a split\n    vector<ll> prefix_sum(k);\n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int height = y2 - y1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        // Split between i and i+1\n        ll sum_r_left = prefix_sum[i];\n        ll sum_r_right = prefix_sum[k-1] - sum_r_left;\n        \n        // The cut position X must separate the points.\n        // Left points must have x < X, Right points must have x >= X.\n        // Since points are integers, X must be > max_x_left and <= min_x_right.\n        int max_x_left = companies[ids[i]].x;\n        int min_x_right = companies[ids[i+1]].x;\n        \n        // Also must be within the current rectangle bounds (x1, x2)\n        // Left rect: [x1, X), Right: [X, x2) -> x1 < X < x2\n        int low = max(x1 + 1, max_x_left + 1);\n        int high = min(x2 - 1, min_x_right);\n        \n        if (low > high) continue; // No valid cut position for this split\n        \n        // Calculate optimal cut position to match area\n        // We want (X - x1) * height approx sum_r_left\n        double target_x = x1 + (double)sum_r_left / height;\n        int cut_x = (int)round(target_x);\n        \n        // Clamp to valid range\n        if (cut_x < low) cut_x = low;\n        if (cut_x > high) cut_x = high;\n        \n        ll actual_area_left = (ll)(cut_x - x1) * height;\n        ll actual_area_right = total_area - actual_area_left;\n        \n        ll error = (actual_area_left - sum_r_left) * (actual_area_left - sum_r_left) \n                 + (actual_area_right - sum_r_right) * (actual_area_right - sum_r_right);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 0;\n            best_split_idx = i;\n            best_cut_pos = cut_x;\n        }\n    }\n    \n    // --- Try Horizontal Cut ---\n    // Sort companies by Y coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].y < companies[j].y;\n    });\n    \n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int width = x2 - x1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        ll sum_r_bottom = prefix_sum[i];\n        ll sum_r_top = prefix_sum[k-1] - sum_r_bottom;\n        \n        int max_y_bottom = companies[ids[i]].y;\n        int min_y_top = companies[ids[i+1]].y;\n        \n        int low = max(y1 + 1, max_y_bottom + 1);\n        int high = min(y2 - 1, min_y_top);\n        \n        if (low > high) continue;\n        \n        double target_y = y1 + (double)sum_r_bottom / width;\n        int cut_y = (int)round(target_y);\n        \n        if (cut_y < low) cut_y = low;\n        if (cut_y > high) cut_y = high;\n        \n        ll actual_area_bottom = (ll)(cut_y - y1) * width;\n        ll actual_area_top = total_area - actual_area_bottom;\n        \n        ll error = (actual_area_bottom - sum_r_bottom) * (actual_area_bottom - sum_r_bottom) \n                 + (actual_area_top - sum_r_top) * (actual_area_top - sum_r_top);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 1;\n            best_split_idx = i;\n            best_cut_pos = cut_y;\n        }\n    }\n    \n    // --- Perform the Split ---\n    vector<int> left_ids, right_ids;\n    \n    if (best_split_axis == 0) {\n        // Vertical split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].x < companies[j].x;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, best_cut_pos, y2, left_ids);\n        solve_recursive(best_cut_pos, y1, x2, y2, right_ids);\n    } else {\n        // Horizontal split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].y < companies[j].y;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, x2, best_cut_pos, left_ids);\n        solve_recursive(x1, best_cut_pos, x2, y2, right_ids);\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    companies.resize(n);\n    vector<int> all_ids(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        all_ids[i] = i;\n    }\n    \n    solve_recursive(0, 0, 10000, 10000, all_ids);\n    \n    for (int i = 0; i < n; ++i) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" << companies[i].c << \" \" << companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n#include <random>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\n// mt19937_64 for high quality random numbers\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n};\n\nstruct Tile {\n    int id;\n    int size;\n    Point cells[2];\n    int total_val;\n    bool visited;\n};\n\n// Global variables for grid\nint H = 50, W = 50;\nint si, sj;\nvector<vector<int>> tile_ids;\nvector<vector<int>> p_vals;\nvector<Tile> tiles;\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHARS[4] = {'U', 'D', 'L', 'R'};\n\n// Helper to check bounds\ninline bool inside(int r, int c) {\n    return 0 <= r && r < H && 0 <= c && c < W;\n}\n\n// Heuristic function to evaluate the \"future\" potential of a cell\n// It sums the values of unvisited neighbor tiles + a bonus for connectivity\nint get_future_potential(int r, int c, const vector<bool>& visited) {\n    int score = 0;\n    int connections = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + DR[d];\n        int nc = c + DC[d];\n        if (inside(nr, nc)) {\n            int tid = tile_ids[nr][nc];\n            if (!visited[tid]) {\n                score += tiles[tid].total_val;\n                connections++;\n            }\n        }\n    }\n    // Bonus for having multiple options (connectivity)\n    return score + connections * 10;\n}\n\n// Main solver function\nstring solve_single_run() {\n    int num_tiles = tiles.size();\n    vector<bool> visited(num_tiles, false);\n    string path = \"\";\n    int score = 0;\n    \n    // Initialize current position and tile\n    Point curr_pos(si, sj);\n    int curr_tile_id = tile_ids[si][sj];\n    \n    // Mark start tile as visited\n    visited[curr_tile_id] = true;\n    score += p_vals[si][sj]; // Add score of starting square\n    \n    // Handle start tile logic (if it's a 2-tile, we might want to move to the other cell)\n    if (tiles[curr_tile_id].size == 2) {\n        Point p0 = tiles[curr_tile_id].cells[0];\n        Point p1 = tiles[curr_tile_id].cells[1];\n        \n        Point other = (p0.r == si && p0.c == sj) ? p1 : p0;\n        \n        // Calculate heuristic for exiting from current pos vs exiting from other\n        // Note: We already 'visited' the start tile, so we can move freely within it.\n        // We haven't collected points from 'other' yet.\n        \n        int potential_curr = get_future_potential(si, sj, visited);\n        int potential_other = p_vals[other.r][other.c] + get_future_potential(other.r, other.c, visited);\n        \n        if (potential_other > potential_curr) {\n            // Move to the other cell\n            for (int d = 0; d < 4; ++d) {\n                if (si + DR[d] == other.r && sj + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    curr_pos = other;\n                    score += p_vals[other.r][other.c];\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Main greedy loop\n    while (true) {\n        Point best_next_pos(-1, -1);\n        int best_score_move = -1;\n        bool best_is_full_traverse = false; // True if we choose to visit both cells of a 2-tile\n        int best_dir_idx = -1;\n        \n        // Check neighbors\n        for (int d = 0; d < 4; ++d) {\n            int nr = curr_pos.r + DR[d];\n            int nc = curr_pos.c + DC[d];\n            \n            if (!inside(nr, nc)) continue;\n            \n            int nxt_tid = tile_ids[nr][nc];\n            if (visited[nxt_tid]) continue;\n            \n            // Evaluate moving to (nr, nc)\n            // We enter the tile at (nr, nc)\n            int gain = tiles[nxt_tid].total_val;\n            \n            // Strategy 1: Full traverse (visit all cells of the tile)\n            // We effectively collect `gain`, and end up at the \"best\" exit point of the tile\n            // But since we enter at (nr, nc), we must reach the exit point from there.\n            // For 1-tile, exit is (nr, nc).\n            // For 2-tile, we enter at (nr, nc) -> go to other -> exit. Or enter -> exit.\n            \n            int max_future = -1e9;\n            int best_exit_cell_idx = -1; // 0 or 1 relative to tile cells\n            int future_curr_entry = -1e9;\n            \n            // Evaluate exit points\n            // Entry point is always the cell adjacent to curr_pos\n            // We need to identify which cell of the target tile is (nr, nc)\n            Point entry_cell(nr, nc);\n            Point other_cell(-1, -1);\n            if (tiles[nxt_tid].size == 2) {\n                if (tiles[nxt_tid].cells[0].r == nr && tiles[nxt_tid].cells[0].c == nc) {\n                    other_cell = tiles[nxt_tid].cells[1];\n                } else {\n                    other_cell = tiles[nxt_tid].cells[0];\n                }\n            }\n\n            // Option A: Exit from entry_cell (Partial traverse if 2-tile)\n            // We only gain points of entry_cell? \n            // Wait, if we enter a 2-tile and don't visit the other cell, do we gain its points? No.\n            // But wait, problem statement: \"score... sum of values of visited squares\".\n            // So we must decide which squares to visit.\n            // If 1-tile: visit (nr, nc). Gain = p(nr, nc).\n            // If 2-tile: visit (nr, nc). Gain = p(nr, nc).\n            \n            // Let's calculate exact gain for each strategy.\n            \n            // Strat 1: Visit ONLY entry_cell\n            int gain_partial = p_vals[nr][nc];\n            int future_partial = get_future_potential(nr, nc, visited);\n            int score_partial = gain_partial + future_partial;\n            \n            int score_full = -1e9;\n            int future_full = -1;\n            \n            if (tiles[nxt_tid].size == 1) {\n                // Only one option\n                score_full = gain_partial; // gain_partial is total_val here\n                future_full = future_partial;\n            } else {\n                // Strat 2: Visit entry_cell AND other_cell\n                int gain_full = tiles[nxt_tid].total_val;\n                // We end up at other_cell. Can we exit from other_cell? Yes.\n                // Can we exit from entry_cell? No, we stepped on other_cell, we must be at other_cell.\n                // Wait, if we step on entry, then other. We are at other. We leave from other.\n                // So future depends on other_cell.\n                int future_other = get_future_potential(other_cell.r, other_cell.c, visited);\n                score_full = gain_full + future_other;\n                future_full = future_other;\n            }\n            \n            // Pick best strategy for this neighbor\n            int current_best_score = max(score_partial, score_full);\n            \n            // Add noise\n            int noise = rng() % 20;\n            current_best_score += noise;\n            \n            if (current_best_score > best_score_move) {\n                best_score_move = current_best_score;\n                best_next_pos = Point(nr, nc);\n                best_dir_idx = d;\n                \n                // Record which strategy was better to update path later\n                // If score_full > score_partial, we will traverse fully\n                // Note: For 1-tile, they are equal, doesn't matter.\n                best_is_full_traverse = (score_full > score_partial);\n            }\n        }\n        \n        if (best_score_move == -1) {\n            break; // No moves left\n        }\n        \n        // Execute best move\n        int nxt_tid = tile_ids[best_next_pos.r][best_next_pos.c];\n        visited[nxt_tid] = true;\n        \n        // Update path and score\n        path += DIR_CHARS[best_dir_idx];\n        curr_pos = best_next_pos;\n        score += p_vals[best_next_pos.r][best_next_pos.c];\n        \n        if (tiles[nxt_tid].size == 2 && best_is_full_traverse) {\n            // Find the other cell\n            Point p0 = tiles[nxt_tid].cells[0];\n            Point p1 = tiles[nxt_tid].cells[1];\n            Point other = (p0.r == best_next_pos.r && p0.c == best_next_pos.c) ? p1 : p0;\n            \n            // Move to other cell\n            // Find direction\n            for (int d = 0; d < 4; ++d) {\n                if (best_next_pos.r + DR[d] == other.r && best_next_pos.c + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    break;\n                }\n            }\n            curr_pos = other;\n            score += p_vals[other.r][other.c];\n        }\n    }\n    \n    return path;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    cin >> si >> sj;\n    \n    tile_ids.resize(H, vector<int>(W));\n    p_vals.resize(H, vector<int>(W));\n    \n    // Map tile ID to vector of cells to construct Tile objects\n    vector<vector<Point>> raw_tile_cells;\n    \n    // Temporary map to normalize tile IDs if needed (though problem says 0..M-1)\n    // Just read and store\n    \n    // First pass to find M and store points\n    int max_id = 0;\n    vector<vector<int>> temp_ids(H, vector<int>(W));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> temp_ids[i][j];\n            max_id = max(max_id, temp_ids[i][j]);\n        }\n    }\n    \n    raw_tile_cells.resize(max_id + 1);\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = temp_ids[i][j];\n            raw_tile_cells[id].push_back(Point(i, j));\n        }\n    }\n    \n    // Construct Tile objects\n    tiles.resize(raw_tile_cells.size());\n    for (int i = 0; i < raw_tile_cells.size(); ++i) {\n        tiles[i].id = i;\n        tiles[i].size = raw_tile_cells[i].size();\n        tiles[i].cells[0] = raw_tile_cells[i][0];\n        if (tiles[i].size == 2) {\n            tiles[i].cells[1] = raw_tile_cells[i][1];\n        }\n        // Will update total_val after reading p\n    }\n    \n    // Assign normalized IDs to grid (can reuse original if they are dense 0..M-1, they are)\n    tile_ids = temp_ids;\n    \n    // Read values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> p_vals[i][j];\n            tiles[tile_ids[i][j]].total_val += p_vals[i][j];\n        }\n    }\n    \n    // Run multiple trials with random variations\n    string best_path = \"\";\n    int best_score = -1;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Limit to 1.8 seconds to be safe\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800) {\n        string current_path = solve_single_run();\n        \n        // Calculate score of this path (re-simulate or just compute during solve?)\n        // Let's re-simulate to be sure and clean.\n        int score = 0;\n        int cr = si, cc = sj;\n        vector<bool> vis(tiles.size(), false);\n        vis[tile_ids[cr][cc]] = true;\n        score += p_vals[cr][cc];\n        \n        bool valid = true;\n        \n        for (char move : current_path) {\n            int d = -1;\n            if (move == 'U') d = 0;\n            else if (move == 'D') d = 1;\n            else if (move == 'L') d = 2;\n            else if (move == 'R') d = 3;\n            \n            int nr = cr + DR[d];\n            int nc = cc + DC[d];\n            \n            if (!inside(nr, nc)) { valid = false; break; }\n            \n            int tid = tile_ids[nr][nc];\n            if (vis[tid]) { valid = false; break; }\n            \n            vis[tid] = true;\n            cr = nr; cc = nc;\n            score += p_vals[cr][cc];\n        }\n        \n        if (valid && score > best_score) {\n            best_score = score;\n            best_path = current_path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Global parameters\nconst int N = 30; // Grid size\nconst int NUM_PARAMS = N * 2; // 30 row costs + 30 col costs\n\nstruct RLS_Estimator {\n    int n_params;\n    vector<double> theta; // Estimated parameters\n    vector<vector<double>> P; // Covariance matrix\n\n    RLS_Estimator(int n) : n_params(n) {\n        theta.assign(n, 5000.0); // Initial guess\n        P.assign(n, vector<double>(n, 0.0));\n        // Initialize P with large diagonal values for high initial uncertainty\n        for (int i = 0; i < n; ++i) {\n            P[i][i] = 1000.0;\n        }\n    }\n\n    void update(const vector<int>& counts, double measured_total) {\n        // Calculate predicted total\n        double predicted_total = 0.0;\n        for (int i = 0; i < n_params; ++i) {\n            predicted_total += theta[i] * counts[i];\n        }\n\n        double error = measured_total - predicted_total;\n\n        // Vector x = P * counts\n        vector<double> Px(n_params, 0.0);\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                Px[i] += P[i][j] * counts[j];\n            }\n        }\n\n        // Denominator: 1 + counts^T * P * counts = 1 + counts^T * Px\n        double denom = 1.0;\n        for (int i = 0; i < n_params; ++i) {\n            denom += counts[i] * Px[i];\n        }\n\n        // Kalman gain: K = Px / denom\n        vector<double> K(n_params);\n        for (int i = 0; i < n_params; ++i) {\n            K[i] = Px[i] / denom;\n        }\n\n        // Update theta: theta = theta + error * K\n        for (int i = 0; i < n_params; ++i) {\n            theta[i] += error * K[i];\n        }\n\n        // Update P: P = P - K * (Px)^T\n        // This is a rank-1 update\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                P[i][j] -= K[i] * Px[j];\n            }\n        }\n    }\n};\n\nstring find_path(int si, int sj, int ti, int tj, RLS_Estimator& estimator) {\n    // Dijkstra's algorithm\n    // Distances\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<pair<int, int>>> prev(N, vector<pair<int, int>>(N, {-1, -1}));\n    \n    priority_queue<tuple<double, int, int>, vector<tuple<double, int, int>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, si, sj});\n\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    string dirs = \"UDLR\";\n\n    while (!pq.empty()) {\n        auto [d, r, c] = pq.top();\n        pq.pop();\n\n        if (r == ti && c == tj) break;\n        if (d > dist[r][c]) continue;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            double cost;\n            if (k < 2) { // Vertical move (U, D)\n                // Edge weight depends on column\n                cost = estimator.theta[N + nc];\n            } else { // Horizontal move (L, R)\n                // Edge weight depends on row\n                cost = estimator.theta[r];\n            }\n\n            if (dist[r][c] + cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[r][c] + cost;\n                prev[nr][nc] = {r, c};\n                pq.push({dist[nr][nc], nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cr = ti, cc = tj;\n    while (cr != si || cc != sj) {\n        int pr = prev[cr][cc].first;\n        int pc = prev[cr][cc].second;\n        \n        if (pr == -1 && pc == -1) break; // Should not happen\n\n        if (pr < cr) path += \"D\";\n        else if (pr > cr) path += \"U\";\n        else if (pc < cc) path += \"R\";\n        else if (pc > cc) path += \"L\";\n        \n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Helper to get feature counts from a path\nvector<int> get_feature_counts(const string& path, int si, int sj) {\n    vector<int> counts(NUM_PARAMS, 0);\n    int r = si, c = sj;\n    for (char dir : path) {\n        if (dir == 'L') {\n            counts[r]++;\n            c--;\n        } else if (dir == 'R') {\n            counts[r]++;\n            c++;\n        } else if (dir == 'U') {\n            counts[N + c]++;\n            r--;\n        } else if (dir == 'D') {\n            counts[N + c]++;\n            r++;\n        }\n    }\n    return counts;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    RLS_Estimator estimator(NUM_PARAMS);\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        string path = find_path(si, sj, ti, tj, estimator);\n        cout << path << endl;\n\n        // Read feedback\n        int measured;\n        cin >> measured;\n\n        vector<int> counts = get_feature_counts(path, si, sj);\n        estimator.update(counts, (double)measured);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <unordered_map>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Rolling Hash\n// ---------------------------------------------------------\nstruct RollingHash {\n    static const uint64_t BASE = 1009;\n    vector<uint64_t> pow;\n\n    RollingHash() {\n        pow.resize(50); \n        pow[0] = 1;\n        for (int i = 1; i < 50; i++) pow[i] = pow[i-1] * BASE;\n    }\n\n    // Compute hash of full string s\n    uint64_t get_hash(const string& s) {\n        uint64_t h = 0;\n        for (char c : s) h = h * BASE + c;\n        return h;\n    }\n\n    // Compute prefix hashes of a string s (length N)\n    vector<uint64_t> get_prefix(const string& s) {\n        vector<uint64_t> h(s.size() + 1, 0);\n        for (int i = 0; i < (int)s.size(); i++) h[i+1] = h[i] * BASE + s[i];\n        return h;\n    }\n\n    // Get hash of substring [l, r) using prefix hashes\n    uint64_t get_sub(const vector<uint64_t>& pref, int l, int r) {\n        return pref[r] - pref[l] * pow[r - l];\n    }\n};\n\n// ---------------------------------------------------------\n// Solver\n// ---------------------------------------------------------\nclass Solver {\npublic:\n    int N;\n    int M;\n    vector<string> S;\n    vector<uint64_t> S_hashes;\n    RollingHash rh;\n    mt19937 rng;\n\n    Solver(int n, int m, const vector<string>& s) : N(n), M(m), S(s), rng(chrono::steady_clock::now().time_since_epoch().count()) {\n        for (const auto& t : S) S_hashes.push_back(rh.get_hash(t));\n    }\n\n    // -----------------------------------------------------\n    // Greedy Initialization\n    // -----------------------------------------------------\n    vector<string> greedy_init() {\n        vector<string> grid(N, string(N, '.'));\n        // Indices of strings\n        vector<int> indices(M);\n        iota(indices.begin(), indices.end(), 0);\n        shuffle(indices.begin(), indices.end(), rng);\n        \n        // Sort by length descending\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            return S[a].size() > S[b].size();\n        });\n\n        for (int idx : indices) {\n            const string& s = S[idx];\n            int len = s.size();\n            int best_r = -1, best_c = -1;\n            bool is_row = false;\n            int min_cost = len + 1;\n\n            // Try rows\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    int cost = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[r][(c + k) % N];\n                        if (cur != '.' && cur != s[k]) {\n                            possible = false;\n                            break;\n                        }\n                        if (cur == '.') cost++;\n                    }\n                    if (possible && cost < min_cost) {\n                        min_cost = cost;\n                        best_r = r;\n                        best_c = c;\n                        is_row = true;\n                    }\n                }\n            }\n\n            // Try cols\n            for (int c = 0; c < N; c++) {\n                for (int r = 0; r < N; r++) {\n                    int cost = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[(r + k) % N][c];\n                        if (cur != '.' && cur != s[k]) {\n                            possible = false;\n                            break;\n                        }\n                        if (cur == '.') cost++;\n                    }\n                    if (possible && cost < min_cost) {\n                        min_cost = cost;\n                        best_r = r;\n                        best_c = c;\n                        is_row = false;\n                    }\n                }\n            }\n\n            // Place if found\n            // Threshold: Don't place if it requires overwriting too many chars (unless it's long)\n            if (best_r != -1 && min_cost <= 2) {\n                if (is_row) {\n                    for (int k = 0; k < len; k++) grid[best_r][(best_c + k) % N] = s[k];\n                } else {\n                    for (int k = 0; k < len; k++) grid[(best_r + k) % N][best_c] = s[k];\n                }\n            }\n        }\n\n        // Fill remaining '.' with random chars\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == '.') {\n                    grid[i][j] = 'A' + (rng() % 8);\n                }\n            }\n        }\n        return grid;\n    }\n\n    // -----------------------------------------------------\n    // Main Solver\n    // -----------------------------------------------------\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        vector<string> grid = greedy_init();\n        \n        // Map to store count of each substring hash currently in grid\n        unordered_map<uint64_t, int> substr_count;\n        \n        // Helper to update hash map for a line (row or col)\n        // line_str: the string representing the row or col\n        // delta: +1 to add, -1 to remove\n        auto process_line = [&](const string& line_str, int delta) {\n            // To handle wrap-around efficiently, we create s = line_str + line_str\n            // Then any substring of length L starting at pos (0..N-1) corresponds to s[pos..pos+L)\n            string s2 = line_str + line_str;\n            auto pref = rh.get_prefix(s2);\n            \n            for (int L = 2; L <= 12; L++) {\n                for (int start = 0; start < N; start++) {\n                    uint64_t h = rh.get_sub(pref, start, start + L);\n                    substr_count[h] += delta;\n                    if (substr_count[h] == 0) substr_count.erase(h);\n                }\n            }\n        };\n\n        // Initial map population\n        for (int i = 0; i < N; i++) {\n            process_line(grid[i], 1);\n            string col_str;\n            for (int j = 0; j < N; j++) col_str += grid[j][i];\n            process_line(col_str, 1);\n        }\n\n        // Calculate initial score\n        auto calc_score = [&]() {\n            int cnt = 0;\n            for (int i = 0; i < M; i++) {\n                if (substr_count.count(S_hashes[i])) cnt++;\n            }\n            return cnt;\n        };\n\n        int current_score = calc_score();\n        int best_score = current_score;\n        vector<string> best_grid = grid;\n\n        // SA Parameters\n        double temp_start = 100.0;\n        double temp_end = 0.01;\n        int iter = 0;\n        int max_iter = 60000;\n\n        while (iter < max_iter) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > 2800) break; // Stop early to ensure output\n\n            double temp = temp_start + (temp_end - temp_start) * (iter / max_iter);\n            iter++;\n\n            // Pick random cell\n            int r = rng() % N;\n            int c = rng() % N;\n            \n            // Extract affected lines\n            string old_row = grid[r];\n            string old_col;\n            for (int i = 0; i < N; i++) old_col += grid[i][c];\n\n            // Remove contributions\n            process_line(old_row, -1);\n            process_line(old_col, -1);\n\n            // Propose change\n            char old_char = grid[r][c];\n            char new_char = 'A' + (rng() % 8);\n            if (new_char == old_char) {\n                // Revert immediately if no change\n                process_line(old_row, 1);\n                process_line(old_col, 1);\n                continue;\n            }\n\n            grid[r][c] = new_char;\n\n            // Add new contributions\n            string new_row = grid[r];\n            string new_col;\n            for (int i = 0; i < N; i++) new_col += grid[i][c];\n\n            process_line(new_row, 1);\n            process_line(new_col, 1);\n\n            // Evaluate\n            int new_score = calc_score();\n            int delta = new_score - current_score;\n\n            // Acceptance\n            if (delta > 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_grid = grid;\n                }\n            } else {\n                // Revert\n                // Remove new\n                process_line(new_row, -1);\n                process_line(new_col, -1);\n                \n                // Restore grid\n                grid[r][c] = old_char;\n                \n                // Restore old\n                process_line(old_row, 1);\n                process_line(old_col, 1);\n            }\n        }\n        \n        // Output best grid found\n        for (const auto& row : best_grid) cout << row << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; i++) cin >> S[i];\n\n    Solver solver(N, M, S);\n    solver.solve();\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/scc>\n#include <atcoder/modint>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\nusing point = bg::model::point<int, 2, bg::cs::cartesian>;\nusing value = std::pair<point, size_t>; // point, index in nodes\n\nusing namespace std;\n\n// Global Constants\nconst int INF = 1e9;\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\nconst char dc[4] = {'R', 'L', 'D', 'U'};\n\nstruct Input {\n    int N;\n    int si, sj;\n    vector<string> grid;\n    int total_road;\n};\n\nInput read_input() {\n    Input in;\n    cin >> in.N >> in.si >> in.sj;\n    in.grid.resize(in.N);\n    in.total_road = 0;\n    for (int i = 0; i < in.N; ++i) {\n        cin >> in.grid[i];\n        for (int j = 0; j < in.N; ++j) {\n            if (in.grid[i][j] != '#') in.total_road++;\n        }\n    }\n    return in;\n}\n\n// Hopcroft-Karp for Maximum Bipartite Matching\nclass HopcroftKarp {\npublic:\n    int n_left, n_right;\n    vector<vector<int>> adj;\n    vector<int> pair_u, pair_v, dist;\n\n    HopcroftKarp(int n_left, int n_right) : n_left(n_left), n_right(n_right), adj(n_left) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        for (int u = 0; u < n_left; ++u) {\n            if (pair_u[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = INF;\n            }\n        }\n        dist[n_left] = INF; // Dummy node for right side check\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (dist[u] < dist[n_left]) {\n                for (int v : adj[u]) {\n                    if (pair_v[v] == -1) {\n                        dist[n_left] = dist[u] + 1;\n                    } else if (dist[pair_v[v]] == INF) {\n                        dist[pair_v[v]] = dist[u] + 1;\n                        q.push(pair_v[v]);\n                    }\n                }\n            }\n        }\n        return dist[n_left] != INF;\n    }\n\n    bool dfs(int u) {\n        if (u != n_left) {\n            for (int v : adj[u]) {\n                if (pair_v[v] == -1 || (dist[pair_v[v]] == dist[u] + 1 && dfs(pair_v[v]))) {\n                    pair_u[u] = v;\n                    pair_v[v] = u;\n                    return true;\n                }\n            }\n            dist[u] = INF;\n            return false;\n        }\n        return true;\n    }\n\n    int max_matching() {\n        pair_u.assign(n_left, -1);\n        pair_v.assign(n_right, -1);\n        dist.assign(n_left + 1, 0);\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < n_left; ++u) {\n                if (pair_u[u] == -1) {\n                    if (dfs(u)) {\n                        matching++;\n                    }\n                }\n            }\n        }\n        return matching;\n    }\n    \n    // Get Minimum Vertex Cover from Maximum Matching\n    // Returns a bitset or boolean vector for left and right nodes respectively\n    pair<vector<bool>, vector<bool>> get_min_vertex_cover() {\n        vector<bool> in_cover_left(n_left, false);\n        vector<bool> in_cover_right(n_right, false);\n        \n        // Standard Konig's theorem construction:\n        // Z = { unmatched L } U { reachable from unmatched L via alternating paths }\n        // Min VC = (L \\ Z) U (R n Z)\n        // Here dist[] is used. In BFS layering, nodes with dist[] < INF are in Z (L side)\n        // But we need to re-run or use the state from the last BFS? \n        // Let's just use the pairings to find Z.\n        // Z starts with unmatched U.\n        // Then alternating paths: U -> V (not paired) -> U (paired) ...\n        \n        queue<int> q;\n        vector<bool> visited_L(n_left, false);\n        vector<bool> visited_R(n_right, false);\n        \n        for(int u=0; u<n_left; ++u) {\n            if(pair_u[u] == -1) {\n                q.push(u);\n                visited_L[u] = true;\n            }\n        }\n        \n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            for(int v : adj[u]) {\n                if(!visited_R[v]) {\n                    visited_R[v] = true;\n                    int paired_u = pair_v[v];\n                    if(paired_u != -1 && !visited_L[paired_u]) {\n                        visited_L[paired_u] = true;\n                        q.push(paired_u);\n                    }\n                }\n            }\n        }\n        \n        for(int u=0; u<n_left; ++u) {\n            if(!visited_L[u]) in_cover_left[u] = true;\n        }\n        for(int v=0; v<n_right; ++v) {\n            if(visited_R[v]) in_cover_right[v] = true;\n        }\n        \n        return {in_cover_left, in_cover_right};\n    }\n};\n\n// Dijkstra\nvector<int> dijkstra(const Input& in, pair<int, int> start, const vector<pair<int,int>>& targets) {\n    int N = in.N;\n    int s_dist = start.first * N + start.second;\n    vector<int> dist(N*N, INF);\n    dist[s_dist] = 0;\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, s_dist});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    return dist;\n}\n\nstring get_path(const Input& in, pair<int,int> s, pair<int,int> t) {\n    // Reconstruct path using simplified Dijkstra or A* since we just need one path\n    // Given N is small, Dijkstra with prev pointer is fine.\n    int N = in.N;\n    int s_idx = s.first * N + s.second;\n    int t_idx = t.first * N + t.second;\n    \n    vector<int> dist(N*N, INF);\n    vector<int> prev(N*N, -1);\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    dist[s_idx] = 0;\n    pq.push({0, s_idx});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (idx == t_idx) break;\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                prev[nidx] = k; // store direction\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    \n    string path = \"\";\n    int curr = t_idx;\n    while(curr != s_idx) {\n        int dir = prev[curr];\n        path += dc[dir];\n        // reverse direction to go back\n        int rdir;\n        if(dir==0) rdir=1; if(dir==1) rdir=0; if(dir==2) rdir=3; if(dir==3) rdir=2;\n        \n        int ci = curr / N;\n        int cj = curr % N;\n        ci += dx[rdir];\n        cj += dy[rdir];\n        curr = ci * N + cj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid solve() {\n    Input in = read_input();\n    int N = in.N;\n    \n    // 1. Identify Segments\n    vector<vector<int>> h_id(N, vector<int>(N, -1));\n    vector<vector<int>> v_id(N, vector<int>(N, -1));\n    int h_cnt = 0, v_cnt = 0;\n    \n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                if(j>0 && in.grid[i][j-1] != '#' && h_id[i][j-1] != -1) {\n                    h_id[i][j] = h_id[i][j-1];\n                } else {\n                    h_id[i][j] = h_cnt++;\n                }\n            }\n        }\n    }\n    \n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        for(int i=0; i<N; ++i) {\n            if(in.grid[i][j] != '#') {\n                if(i>0 && in.grid[i-1][j] != '#' && v_id[i-1][j] != -1) {\n                    v_id[i][j] = v_id[i-1][j];\n                } else {\n                    v_id[i][j] = v_cnt++;\n                }\n            }\n        }\n    }\n    \n    // 2. Build Bipartite Graph\n    HopcroftKarp hk(h_cnt, v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                hk.add_edge(h_id[i][j], v_id[i][j]);\n            }\n        }\n    }\n    \n    // 3. Solve Min Vertex Cover\n    hk.max_matching();\n    auto [cover_h, cover_v] = hk.get_min_vertex_cover();\n    \n    // Set of covered segments\n    vector<bool> covered_h_seg = cover_h; // rename for clarity\n    vector<bool> covered_v_seg = cover_v;\n    \n    // 4. Select Key Points\n    // We need to visit points such that every segment in the cover is visited.\n    // Strategy: Collect all intersection points of segments in the cover.\n    // Also add representative points for segments in cover that might be isolated.\n    \n    set<pair<int, int>> key_points_set;\n    vector<pair<int, int>> key_points;\n    \n    auto add_point = [&](int i, int j) {\n        if(key_points_set.count({i,j}) == 0) {\n            key_points_set.insert({i,j});\n            key_points.push_back({i,j});\n        }\n    };\n\n    // Add intersections of covered segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                int hid = h_id[i][j];\n                int vid = v_id[i][j];\n                if(covered_h_seg[hid] && covered_v_seg[vid]) {\n                    add_point(i, j);\n                }\n            }\n        }\n    }\n    \n    // Add representative points for segments that are not \"covered\" by the intersections logic\n    // (i.e., segments in cover that don't intersect any other segment in cover)\n    // A segment is satisfied if we visit at least one point on it.\n    // So we ensure for each segment in cover, there is a key point on it.\n    \n    // Find segments without intersection\n    vector<bool> h_has_intersect(h_cnt, false);\n    vector<bool> v_has_intersect(v_cnt, false);\n    for(auto p : key_points) {\n        int i = p.first, j = p.second;\n        h_has_intersect[h_id[i][j]] = true;\n        v_has_intersect[v_id[i][j]] = true;\n    }\n    \n    // For segments in cover without intersection, add their point closest to Start\n    // Or just middle point. Middle point is safer and faster.\n    vector<vector<pair<int,int>>> h_cells(h_cnt);\n    vector<vector<pair<int,int>>> v_cells(v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                h_cells[h_id[i][j]].push_back({i,j});\n                v_cells[v_id[i][j]].push_back({i,j});\n            }\n        }\n    }\n    \n    for(int i=0; i<h_cnt; ++i) {\n        if(covered_h_seg[i] && !h_has_intersect[i]) {\n            // Add middle cell\n            int mid = h_cells[i].size() / 2;\n            add_point(h_cells[i][mid].first, h_cells[i][mid].second);\n        }\n    }\n    for(int i=0; i<v_cnt; ++i) {\n        if(covered_v_seg[i] && !v_has_intersect[i]) {\n            int mid = v_cells[i].size() / 2;\n            add_point(v_cells[i][mid].first, v_cells[i][mid].second);\n        }\n    }\n    \n    // Make sure start point is in key points to build the cycle\n    add_point(in.si, in.sj);\n    \n    // 5. Compute Distances between Key Points\n    int K = key_points.size();\n    vector<vector<int>> dist(K, vector<int>(K, INF));\n    \n    // Optimization: Only run Dijkstra from each point. K should be small.\n    // Map point to index\n    map<pair<int,int>, int> pt_to_idx;\n    for(int i=0; i<K; ++i) pt_to_idx[key_points[i]] = i;\n    \n    for(int i=0; i<K; ++i) {\n        auto ds = dijkstra(in, key_points[i], key_points);\n        for(int j=0; j<K; ++j) {\n            int idx = key_points[j].first * N + key_points[j].second;\n            dist[i][j] = ds[idx];\n        }\n    }\n    \n    // 6. Construct Path\n    // Greedy insertion to ensure coverage, then 2-opt\n    \n    int start_idx = pt_to_idx[{in.si, in.sj}];\n    \n    // Current Path: [start_idx]\n    vector<int> path = {start_idx};\n    // Current coverage: segments containing S\n    vector<bool> visited_h(h_cnt, false);\n    vector<bool> visited_v(v_cnt, false);\n    \n    auto visit_pt = [&](int idx) {\n        int i = key_points[idx].first;\n        int j = key_points[idx].second;\n        visited_h[h_id[i][j]] = true;\n        visited_v[v_id[i][j]] = true;\n    };\n    visit_pt(start_idx);\n    \n    // Check if all covered segments are satisfied\n    auto all_covered = [&]() {\n        for(int i=0; i<h_cnt; ++i) if(covered_h_seg[i] && !visited_h[i]) return false;\n        for(int i=0; i<v_cnt; ++i) if(covered_v_seg[i] && !visited_v[i]) return false;\n        return true;\n    };\n    \n    // Greedy Insertion\n    while(!all_covered()) {\n        int best_k = -1;\n        int best_pos = -1;\n        int best_gain = -INF;\n        int best_cost = INF;\n        \n        for(int k=0; k<K; ++k) {\n            if(find(path.begin(), path.end(), k) != path.end()) continue;\n            \n            // Gain: number of newly covered segments\n            int i = key_points[k].first;\n            int j = key_points[k].second;\n            int gain = 0;\n            if(covered_h_seg[h_id[i][j]] && !visited_h[h_id[i][j]]) gain++;\n            if(covered_v_seg[v_id[i][j]] && !visited_v[v_id[i][j]]) gain++;\n            \n            if(gain == 0) continue;\n            \n            // Find best insertion position\n            for(int pos=0; pos<=path.size(); ++pos) {\n                int u = (pos==0) ? path.back() : path[pos-1];\n                int v = (pos==path.size()) ? path[0] : path[pos];\n                \n                // Cost change: dist[u][k] + dist[k][v] - dist[u][v]\n                int delta = dist[u][k] + dist[k][v] - dist[u][v];\n                \n                if(gain * best_cost > best_gain * delta) {\n                    best_gain = gain;\n                    best_cost = delta;\n                    best_k = k;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if(best_k == -1) {\n            // Should not happen if graph is connected and cover is valid\n            // Fallback: add any unvisited point on required segments\n            // (omitted for brevity, break to prevent infinite loop)\n            break; \n        }\n        \n        path.insert(path.begin() + best_pos, best_k);\n        visit_pt(best_k);\n    }\n    \n    // 2-opt Optimization\n    // Simple 2-opt loop\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int n = path.size();\n        for(int i=0; i<n; ++i) {\n            for(int j=i+2; j<n + (i>0 ? 1 : 0); ++j) {\n                // Edge (i, i+1) and (j, j+1) become (i, j) and (i+1, j+1)\n                int u = path[i];\n                int v = path[(i+1)%n];\n                int x = path[j%n];\n                int y = path[(j+1)%n];\n                \n                int current = dist[u][v] + dist[x][y];\n                int proposal = dist[u][x] + dist[v][y];\n                \n                if(proposal < current) {\n                    // Reverse path between i+1 and j\n                    reverse(path.begin() + (i+1)%n, path.begin() + (j%n) + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Generate Output String\n    string full_path = \"\";\n    int p_sz = path.size();\n    for(int i=0; i<p_sz; ++i) {\n        int u = path[i];\n        int v = path[(i+1)%p_sz];\n        string sub = get_path(in, key_points[u], key_points[v]);\n        full_path += sub;\n    }\n    \n    cout << full_path << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <functional>\n\nusing namespace std;\n\n// Global problem parameters\nint N, M, K, R;\nvector<vector<int>> d; // Task requirements\nvector<vector<int>> adj; // Adjacency list: u -> v\nvector<int> in_degree; \n\n// Task states: 0 = locked, 1 = available, 2 = assigned\nvector<int> task_state;\nvector<int> start_day;\n\n// Skill estimation\nvector<vector<double>> s;\n\n// Tracking member assignments\nvector<int> member_task;\n\n// Pre-calculated priorities\nvector<int> num_successors; \nvector<int> visited_dfs; // For DFS\n\n// Heuristic Constants\nconst double LEARNING_RATE = 0.5; \nconst double T1_BOOST = 0.5;      \n\n// Comparator for task priority (Higher successors first)\nstruct TaskPriority {\n    bool operator()(int t1, int t2) const {\n        if (num_successors[t1] != num_successors[t2]) {\n            return num_successors[t1] < num_successors[t2];\n        }\n        return t1 < t2; // Tie-breaker\n    }\n};\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // --- Input Reading ---\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n        }\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    // --- Pre-processing: Task Priorities (Successor Count) ---\n    num_successors.resize(N, 0);\n    visited_dfs.assign(N, 0);\n    \n    function<int(int)> count_descendants = [&](int u) {\n        if (visited_dfs[u]) return num_successors[u];\n        visited_dfs[u] = 1;\n        int cnt = 0;\n        for (int v : adj[u]) {\n            cnt += 1 + count_descendants(v);\n        }\n        num_successors[u] = cnt;\n        return cnt;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        if (!visited_dfs[i]) count_descendants(i);\n    }\n\n    // --- Initialization ---\n    task_state.resize(N, 0);\n    start_day.resize(N, -1);\n    \n    priority_queue<int, vector<int>, TaskPriority> available_tasks;\n\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            task_state[i] = 1;\n            available_tasks.push(i);\n        }\n    }\n\n    s.resize(M, vector<double>(K, 25.0));\n    member_task.resize(M, -1);\n\n    // --- Main Loop ---\n    int day = 0;\n    while (true) {\n        day++;\n\n        // 1. Identify idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n\n        // 2. Greedy Assignment\n        vector<pair<int, int>> assignments; \n        \n        while (!idle_members.empty() && !available_tasks.empty()) {\n            // Get highest priority task that is currently available (state 1)\n            int best_task = -1;\n            while (!available_tasks.empty()) {\n                int t = available_tasks.top();\n                if (task_state[t] == 1) {\n                    best_task = t;\n                    break;\n                }\n                available_tasks.pop();\n            }\n\n            if (best_task == -1) break;\n\n            // Find best member for this task (min estimated cost)\n            int best_member_idx = -1;\n            double min_cost = 1e9;\n\n            for (int idx = 0; idx < static_cast<int>(idle_members.size()); ++idx) {\n                int j = idle_members[idx];\n                double cost = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = d[best_task][k] - s[j][k];\n                    if (diff > 0) cost += diff;\n                }\n                \n                if (cost < min_cost) {\n                    min_cost = cost;\n                    best_member_idx = idx;\n                }\n            }\n\n            if (best_member_idx != -1) {\n                int j = idle_members[best_member_idx];\n                assignments.push_back({j + 1, best_task + 1});\n                \n                member_task[j] = best_task;\n                task_state[best_task] = 2; // Mark as assigned\n                start_day[best_task] = day;\n\n                idle_members[best_member_idx] = idle_members.back();\n                idle_members.pop_back();\n            } else {\n                // No member found (should be rare), skip this task for now\n                available_tasks.pop();\n                available_tasks.push(best_task); \n            }\n        }\n\n        // 3. Output\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n\n        // 4. Input & Update\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break;\n\n        vector<int> finished_members(n_finished);\n        for (int i = 0; i < n_finished; ++i) {\n            cin >> finished_members[i];\n            finished_members[i]--;\n        }\n\n        for (int member_idx : finished_members) {\n            int task_idx = member_task[member_idx];\n            if (task_idx == -1) continue;\n\n            int t = day - start_day[task_idx] + 1;\n\n            // --- SKILL UPDATE ---\n            double w_est = 0.0;\n            vector<int> deficit_dims;\n            for (int k = 0; k < K; ++k) {\n                double diff = d[task_idx][k] - s[member_idx][k];\n                if (diff > 0) {\n                    w_est += diff;\n                    deficit_dims.push_back(k);\n                }\n            }\n\n            if (t == 1) {\n                // t=1 implies w was likely 0.\n                // If we estimated deficit, pull skills up to meet requirements.\n                for (int k : deficit_dims) {\n                    s[member_idx][k] += T1_BOOST * (d[task_idx][k] - s[member_idx][k]);\n                }\n            } else {\n                // t > 1. We want w_est to match t.\n                // Gradient Descent: s += lr * (w_est - t)\n                double error = w_est - t;\n                double update = LEARNING_RATE * error;\n                \n                if (!deficit_dims.empty()) {\n                    double per_dim_update = update / deficit_dims.size();\n                    for (int k : deficit_dims) {\n                        s[member_idx][k] += per_dim_update;\n                        if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                    }\n                } else {\n                    // w_est = 0 but t > 1. Skills are overestimated.\n                    // Decrease all relevant dimensions.\n                    vector<int> non_zero_dims;\n                    for(int k=0; k<K; ++k) {\n                        if(d[task_idx][k] > 0) non_zero_dims.push_back(k);\n                    }\n                    \n                    if (!non_zero_dims.empty()) {\n                        double per_dim_update = update / non_zero_dims.size();\n                        for (int k : non_zero_dims) {\n                            s[member_idx][k] += per_dim_update;\n                            if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                        }\n                    }\n                }\n            }\n\n            // --- Unlock Dependencies ---\n            member_task[member_idx] = -1;\n            \n            for (int dependent_task : adj[task_idx]) {\n                in_degree[dependent_task]--;\n                if (in_degree[dependent_task] == 0) {\n                    task_state[dependent_task] = 1;\n                    available_tasks.push(dependent_task);\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Order {\n    int id;\n    int a, b, c, d;\n};\n\nconst int CENTER = 1000; // Special index for Center\n\nint dist(const vector<pair<int, int>>& points, int i, int j) {\n    if (i == CENTER) return 400 - points[j].first + 400 - points[j].second; // dist from Center\n    if (j == CENTER) return points[i].first - 400 + points[i].second - 400; // dist to Center\n    return abs(points[i].first - points[j].first) + abs(points[i].second - points[j].second);\n}\n\nint dist_center(int x, int y) {\n    return abs(400 - x) + abs(400 - y);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    int N = 1000;\n    vector<Order> orders(N);\n    // We will use points index: 0..999 for Pickup, 1000..1999 for Delivery\n    // Center is 2000 (or handled separately)\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n        orders[i].id = i + 1;\n    }\n    \n    // Best solution found\n    int best_score = -1;\n    vector<int> best_route_indices;\n    vector<int> best_order_ids;\n    long long best_len = 1e18;\n    \n    // We have time limit 2.0s. Let's run a few iterations of the heuristic with different random seeds or perturbations.\n    // Given the complexity, a single good run with local search might be sufficient, but multiple restarts helps escape local optima.\n    int NUM_ITERATIONS = 5;\n    \n    for (int iter = 0; iter < NUM_ITERATIONS; ++iter) {\n        // --- 1. Construction Phase (Greedy Insertion) ---\n        vector<int> used(N, 0);\n        vector<int> route_indices; // Stores point indices (0-999 for P, 1000-1999 for D)\n        route_indices.push_back(CENTER); // Start at center\n        \n        // Shuffle orders for randomness in selection if costs are equal, or just to explore different construction paths\n        // Actually, to make the greedy deterministic but good, we shouldn't shuffle for evaluation.\n        // We iterate all orders and pick the best.\n        \n        for (int step = 0; step < 50; ++step) {\n            int best_order = -1;\n            int best_delta = 1e9;\n            int best_u = -1;\n            int best_v = -1;\n            \n            // Pre-calculate coordinates for current route to speed up dist queries\n            // But constructing points vector on the fly is easy.\n            vector<pair<int, int>> current_points;\n            for (int idx : route_indices) {\n                if (idx == CENTER) current_points.push_back({400, 400});\n                else if (idx < 1000) current_points.push_back({orders[idx].a, orders[idx].b});\n                else current_points.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            \n            // Candidate selection (top-K)\n            // To avoid O(1000 * L^2) every step, we do a coarse filter.\n            vector<pair<int, int>> candidates; // {cost, order_id}\n            \n            for (int i = 0; i < N; ++i) {\n                if (used[i]) continue;\n                \n                // Est cost: dist(Route, P_i) + dist(P_i, D_i) + dist(D_i, Route)\n                int min_dist_P = 1e9;\n                int min_pos_P = -1;\n                int min_dist_D = 1e9;\n                int min_pos_D = -1;\n\n                // Find closest point in route to P_i and D_i\n                for (size_t k = 0; k < current_points.size(); ++k) {\n                    int dP = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    if (dP < min_dist_P) {\n                        min_dist_P = dP;\n                        min_pos_P = k;\n                    }\n                    int dD = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                    if (dD < min_dist_D) {\n                        min_dist_D = dD;\n                        min_pos_D = k;\n                    }\n                }\n                \n                // internal dist\n                int d_internal = abs(orders[i].a - orders[i].c) + abs(orders[i].b - orders[i].d);\n                int est_cost = min_dist_P + d_internal + min_dist_D;\n                \n                candidates.push_back({est_cost, i});\n            }\n            \n            // Sort by estimated cost and take top 30\n            sort(candidates.begin(), candidates.end());\n            if (candidates.size() > 30) candidates.resize(30);\n            \n            // Detailed check for top candidates\n            for (auto& cand : candidates) {\n                int i = cand.second;\n                \n                // Find exact best insertion for P_i\n                // Route has L points. Indices 0 to L-1.\n                // Insert P_i at u (between u-1 and u)\n                // Insert D_i at v (between v-1 and v), where v > u+1 (since P_i takes a spot)\n                \n                int L = route_indices.size();\n                \n                // Optimize: We can precompute distances to all nodes for P_i and D_i\n                vector<int> dists_P(L), dists_D(L);\n                for (int k = 0; k < L; ++k) {\n                    dists_P[k] = abs(current_points[k].first - orders[i].a) + abs(current_points[k].second - orders[i].b);\n                    dists_D[k] = abs(current_points[k].first - orders[i].c) + abs(current_points[k].second - orders[i].d);\n                }\n                \n                // Current route edges distances (sum of edges)\n                // We compute delta added - delta removed\n                \n                for (int u = 1; u < L; ++u) {\n                    // Insert P_i between u-1 and u\n                    // Removed edge: (u-1, u). Added edges: (u-1, P_i), (P_i, u)\n                    // Note: route is path, not cycle. Center is at 0.\n                    // Edge indices: (0,1), (1,2), ..., (L-2, L-1)\n                    // But we treat insert positions as 'slots' between points.\n                    // Insert at pos u means after point u-1, before point u.\n                    // Valid u: 1 to L-1. (After Center is 1, After last is L-1)\n                    // Actually, we can append? No, route must end at Center eventually?\n                    // Greedy construction builds a path that starts at Center. \n                    // The final step will add dist(last, center).\n                    // So yes, we can insert at the end (u = L).\n                    \n                    // Cost to insert P at u\n                    int edge_old_u = (u < L) ? dists_P[u-1] + dists_P[u] - (abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second)) : dists_P[u-1];\n                    // Wait, calculating delta properly:\n                    // Base edge cost E_u = dist(route[u-1], route[u]) for u < L. \n                    // For u = L, E_L = 0 (virtual edge to nothing? no, last point connects to nothing yet)\n                    \n                    int delta_P = 0;\n                    int old_u = 0;\n                    if (u < L) {\n                         old_u = abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                         delta_P = dists_P[u-1] + dists_P[u] - old_u;\n                    } else {\n                        delta_P = dists_P[u-1];\n                    }\n                    \n                    // For D_i, insert at v > u. \n                    // Since P_i is inserted, the indices shift. \n                    // Let's say we insert P at u. The new length is L+1.\n                    // D can be inserted at v from u+1 to L.\n                    // The points involved: \n                    // segment (u-1) -> P -> (u) -> ... -> (v-1) -> (v)\n                    // New: (u-1) -> P -> (u) ... -> (v-1) -> D -> (v)\n                    \n                    // Distance from P_i to next point (original u) is dists_P[u].\n                    // Distance from prev point (original v-1) to D_i is dists_D[v-1].\n                    // Distance from D_i to next point (original v) is dists_D[v].\n                    \n                    for (int v = u + 1; v <= L; ++v) {\n                        int delta_D = 0;\n                        if (v < L) {\n                            int old_v = abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            // P_i is at index u (0-based in new array, but original indices...)\n                            // Current points array indices: 0 to L-1.\n                            // P is inserted at index u-1 in the \"gap\" sense?\n                            // Let's stick to \"insert before old index k\" logic.\n                            // u is index in OLD route. P inserted before route[u].\n                            // v is index in OLD route. D inserted before route[v].\n                            // Condition: u < v.\n                            // If v == u+1, sequence is ..., route[u-1], P, D, route[u], ...\n                            // If v == L, sequence is ..., route[u-1], P, ..., route[L-1], D.\n                            \n                            int dist_P_next = (u < L) ? dists_P[u] : 0; // dist(P, route[u])\n                            \n                            // dist(route[v-1], D)\n                            int dist_prev_D = dists_D[v-1]; \n                            // dist(D, route[v])\n                            int dist_D_next = dists_D[v];\n                            \n                            // Edge broken: (route[u-1], route[u]) and (route[v-1], route[v])\n                            // Wait, if u and v are far apart, edges between u and v-1 are shifted but not broken?\n                            // The segment route[u] ... route[v-1] shifts right by 2. No internal distance change.\n                            // Only edges at insertion points change.\n                            // 1. Edge (route[u-1], route[u]) becomes (route[u-1], P) and (P, route[u]) ?\n                            // No, route[u] moves to u+1. P is at u.\n                            // So we replace (u-1, u) with (u-1, P) and (P, u).\n                            // Wait, if v = u+1. Then (u-1, u) -> (i-1, P), (P, u). \n                            // And (u, u+1) -> (D, u+1)?\n                            // Actually, simpler:\n                            // Old edges: (u-1, u) and (v-1, v).\n                            // New edges: (u-1, P), (P, v-1) -- NO.\n                            // The path is ... -> u-1 -> P -> u -> ... -> v-1 -> D -> v -> ...\n                            // Old edges broken: (u-1, u), (v-1, v).\n                            // New edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Note: if u == v-1, then (u-1, u) broken, (u, u+1) broken. \n                            // Path ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Broken: (u-1, u), (u, u+1).\n                            // New: (u-1, P), (P, D), (D, u+1).\n                            \n                            // General case:\n                            // Removed: dist(u-1, u) + dist(v-1, v).\n                            // Added: dist(u-1, P) + dist(P, u) + dist(v-1, D) + dist(D, v).\n                            \n                            int removed = 0;\n                            if (u < L) removed += abs(current_points[u-1].first-current_points[u].first) + abs(current_points[u-1].second-current_points[u].second);\n                            else removed = 0; // u == L\n                            \n                            if (v < L) removed += abs(current_points[v-1].first-current_points[v].first) + abs(current_points[v-1].second-current_points[v].second);\n                            else removed += 0; // v == L\n\n                            int added = dists_P[u-1];\n                            if (u < L) added += dists_P[u];\n                            else added += 0;\n                            \n                            added += dists_D[v-1];\n                            if (v < L) added += dists_D[v];\n                            else added += 0;\n                            \n                            // If u == v-1 (consecutive insertions), P connects to D?\n                            // Logic: ... -> u-1 -> P -> u -> ...\n                            // If v = u+1: ... -> u-1 -> P -> D -> u+1 -> ...\n                            // Edges added: (u-1, P), (P, D), (D, u+1).\n                            // dists_P[u] is dist(P, route[u]). \n                            // dists_D[u] is dist(D, route[u]).\n                            // My logic above:\n                            // Added: dist(u-1, P) + dist(P, u) + dist(u, D) + dist(D, u+1).\n                            // Wait, v-1 = u. So dists_D[v-1] = dist(D, route[u]).\n                            // Correct.\n                            // What if u and v are not consecutive?\n                            // ... -> u-1 -> P -> u -> u+1 -> ... -> v-1 -> D -> v -> ...\n                            // Edges added: (u-1, P), (P, u), (v-1, D), (D, v).\n                            // Correct.\n                            \n                            // Wait, there is a case where u > v?\n                            // We loop u from 1 to L. v from u+1 to L. So u < v always.\n                            // This ensures P is before D.\n                            \n                            int delta = added - removed;\n                            if (delta < best_delta) {\n                                best_delta = delta;\n                                best_order = i;\n                                best_u = u;\n                                best_v = v;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (best_order != -1) {\n                used[best_order] = 1;\n                // Insert P\n                route_indices.insert(route_indices.begin() + best_u, best_order);\n                // Insert D (index shifted by 1 because P was inserted)\n                route_indices.insert(route_indices.begin() + best_v, best_order + 1000);\n            }\n        }\n        \n        // Add final return to center\n        // Route construction logic didn't account for return to center yet, \n        // but since we always start at Center (index 0), and we never insert before it,\n        // and we only append/insert after, the route is valid path.\n        // Total length will be calculated later.\n        \n        // --- 2. Optimization Phase (2-opt + Order Swap) ---\n        \n        // Helper to calculate total length\n        auto calc_len = [&](const vector<int>& route) -> long long {\n            long long len = 0;\n            vector<pair<int, int>> coords;\n            for (int idx : route) {\n                if (idx == CENTER) coords.push_back({400, 400});\n                else if (idx < 1000) coords.push_back({orders[idx].a, orders[idx].b});\n                else coords.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            for (size_t i = 0; i < coords.size() - 1; ++i) {\n                len += abs(coords[i].first - coords[i+1].first) + abs(coords[i].second - coords[i+1].second);\n            }\n            len += abs(coords.back().first - 400) + abs(coords.back().second - 400); // Return to center\n            return len;\n        };\n        \n        // 2-opt\n        // Route: Center, ..., last\n        // Cycle is Center -> ... -> last -> Center.\n        // Indices in `route_indices` vector: 0, 1, ..., M.\n        // 2-opt swaps edges (i, i+1) and (j, j+1) for 0 <= i < j < M.\n        // Segment [i+1, j] is reversed.\n        // Note: Center (index 0) is fixed? \n        // Actually, standard 2-opt on the cycle.\n        // The cycle is nodes 0..M where 0 is Center.\n        // Edge (M, 0) exists (return to center).\n        // If we include edge (M, 0) in swaps, we might move Center? No, Center is fixed node 0.\n        // But the edge (M, 0) can be swapped with (i, i+1).\n        // That would mean segment [i+1, M] is reversed, and 0 connects to M, i connects to 0?\n        // Standard 2-opt logic on array `route`:\n        // Edges are (0,1), (1,2), ..., (M-1, M), (M, 0).\n        // We fix node 0 (Center) at position 0.\n        // Edges (k, k+1) for k=0..M-1.\n        // Edge (M, 0) is special.\n        \n        // Let's treat the route as Center fixed at start.\n        // We can swap edges (u, u+1) and (v, v+1) where 0 <= u < v < M.\n        // New path: 0 -> ... -> u -> v -> v-1 -> ... -> u+1 -> v+1 -> ... -> M -> 0.\n        // Constraint: For every order k, P_k before D_k.\n        // Reversing segment [u+1, v].\n        \n        // Validity check:\n        // Map order id -> indices of P and D in route.\n        \n        bool improved = true;\n        while (improved && (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800)) {\n            improved = false;\n            int M = route_indices.size();\n            \n            // Precompute positions for validity check\n            // This changes every swap, so recomputing is slow.\n            // Check validity of swap locally.\n            // Segment [u+1, v] reversed.\n            // For an order with nodes at p, q:\n            // If p and q are both in [u+1, v], their relative order reverses -> INVALID (unless we check specific case, but generally P before D fails).\n            //   Wait, if P is before D in original, after reversal P is after D. So INVALID.\n            //   Exception: If we reverse a segment containing P and D, it becomes invalid.\n            //   So swap is valid ONLY IF for every order, it has 0 or 1 nodes in the segment.\n            //   If it has 1 node, the node moves, but P is still before D relative to outside nodes?\n            //   Consider P inside, D outside (after segment). Original: ... P ... D. After rev: ... (rev) ... D. P moves to end of segment. Still before D. OK.\n            //   Consider P outside (before segment), D inside. Original: P ... D. After rev: P ... (rev) ... D. D moves to start of segment. Still after P. OK.\n            //   So condition: No order has BOTH P and D in the segment.\n            \n            for (int u = 0; u < M - 1; ++u) {\n                // Optimization: only iterate v reasonably far? Standard 2-opt is O(N^2).\n                for (int v = u + 1; v < M; ++v) {\n                    // Check validity\n                    bool valid = true;\n                    // Scan segment [u+1, v]\n                    // Use a frequency array for current segment scan?\n                    // N=50, so 100 nodes. Scanning 100 orders for each pair is 10,000 checks per pair.\n                    // Pairs 5000. Total 50M. A bit high but doable in C++.\n                    // Faster: count P and D in segment.\n                    vector<char> in_segment(N, 0);\n                    for (int k = u + 1; k <= v; ++k) {\n                        int idx = route_indices[k];\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (idx < 1000) in_segment[oid] |= 1; // P\n                        else in_segment[oid] |= 2; // D\n                        if (in_segment[oid] == 3) {\n                            valid = false;\n                            break;\n                        }\n                    }\n                    if (!valid) continue;\n                    \n                    // Calculate delta\n                    // Edges removed: (u, u+1) and (v, v+1)\n                    // Edges added: (u, v) and (u+1, v+1)\n                    // Note: v < M, so v+1 exists.\n                    // Coordinates\n                    auto get_pt = [&](int idx) -> pair<int,int> {\n                        if (idx == CENTER) return {400, 400};\n                        if (idx < 1000) return {orders[idx].a, orders[idx].b};\n                        return {orders[idx-1000].c, orders[idx-1000].d};\n                    };\n\n                    auto p_u = get_pt(route_indices[u]);\n                    auto p_u1 = get_pt(route_indices[u+1]);\n                    auto p_v = get_pt(route_indices[v]);\n                    auto p_v1 = get_pt(route_indices[v+1]);\n                    \n                    long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                      + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                    long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                     + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                    \n                    if (added < removed) {\n                        // Perform swap\n                        reverse(route_indices.begin() + u + 1, route_indices.begin() + v + 1);\n                        improved = true;\n                        // Reset search? Or continue?\n                        // With found improvement, resetting loops is safer to find new structure.\n                        // But breaking and restarting outer loop is standard.\n                        goto next_opt_pass; \n                    }\n                }\n            }\n            next_opt_pass:;\n        }\n        \n        // Local Search: Swap one order\n        // Try removing an order and inserting another\n        for (int step = 0; step < 5; ++step) {\n            if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 1900) break;\n            \n            // Current route length\n            long long current_len = calc_len(route_indices);\n            \n            // Try remove each order\n            for (int i = 0; i < N; ++i) {\n                if (!used[i]) continue;\n                \n                // Remove order i\n                auto it_p = find(route_indices.begin(), route_indices.end(), i);\n                auto it_d = find(route_indices.begin(), route_indices.end(), i + 1000);\n                if (it_p == route_indices.end() || it_d == route_indices.end()) continue;\n                \n                int pos_p = distance(route_indices.begin(), it_p);\n                int pos_d = distance(route_indices.begin(), it_d);\n                \n                // Indices: pos_p < pos_d\n                // Remove D then P to keep indices correct\n                route_indices.erase(it_d);\n                route_indices.erase(route_indices.begin() + pos_p);\n                \n                // Try insert all j not used\n                bool found_better = false;\n                for (int j = 0; j < N; ++j) {\n                    if (used[j] || j == i) continue;\n                    \n                    // Try insert P_j and D_j optimally\n                    // Similar to construction but smaller\n                    int L = route_indices.size();\n                    \n                    // We need to calculate insertion cost\n                    // This is O(L^2) per j. N ~ 1000. L ~ 100. 1000 * 10000 = 10M.\n                    // Plus the loop over i (50). Total 500M. Too slow.\n                    // Optimization: Only try a subset of j?\n                    // Or only try replacing with \"good\" candidates?\n                    // Or break early.\n                    \n                    // Just pick the best j to insert.\n                    // We can check the \"approximate\" cost of j first.\n                    // dist(route, P_j) + dist(P_j, D_j) + dist(D_j, route)\n                    \n                    // Let's limit this local search.\n                    // Instead of iterating all i, iterate random i.\n                    // Instead of iterating all j, iterate top 50 candidates.\n                }\n                \n                // Revert if not better\n                route_indices.insert(route_indices.begin() + pos_p, i);\n                route_indices.insert(route_indices.begin() + pos_d, i + 1000);\n            }\n        }\n\n        // Calculate final length for this iteration\n        long long current_len = calc_len(route_indices);\n        if (current_len < best_len) {\n            best_len = current_len;\n            best_route_indices = route_indices;\n            // best_order_ids not needed if we reconstruct from route_indices\n        }\n    }\n    \n    // --- Output ---\n    // Extract order IDs from best_route_indices\n    vector<int> final_orders;\n    set<int> seen;\n    for (int idx : best_route_indices) {\n        if (idx == CENTER) continue;\n        int oid = (idx < 1000) ? idx : idx - 1000;\n        if (seen.find(oid) == seen.end()) {\n            final_orders.push_back(oid + 1);\n            seen.insert(oid);\n        }\n    }\n    // final_orders should be 50.\n    // Ensure exactly 50? My logic inserts exactly 50.\n    \n    // Output format\n    // m r1 ... rm\n    // n x1 y1 ... xn yn\n    \n    cout << 50;\n    for (int oid : final_orders) cout << \" \" << oid;\n    cout << \"\\n\";\n    \n    cout << best_route_indices.size() + 1; // +1 for final Center\n    for (int idx : best_route_indices) {\n        int x, y;\n        if (idx == CENTER) { x = 400; y = 400; }\n        else if (idx < 1000) { x = orders[idx].a; y = orders[idx].b; }\n        else { x = orders[idx-1000].c; y = orders[idx-1000].d; }\n        cout << \" \" << x << \" \" << y;\n    }\n    // Final center\n    cout << \" \" << 400 << \" \" << 400 << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct DSU {\n    vector<int> parent;\n    int components;\n\n    DSU(int n) : parent(n), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        components--;\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N = 400;\n    int M = 1995;\n\n    vector<pair<int, int>> points(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = points[edges[i].u].first - points[edges[i].v].first;\n        int dy = points[edges[i].u].second - points[edges[i].v].second;\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        edges[i].d = (int)round(dist);\n    }\n\n    DSU dsu(N);\n    int taken = 0;\n\n    // Heuristic threshold: Accept if l <= 2.2 * d.\n    // Expected value of l is 2.0 * d. \n    // 2.2 is slightly more lenient to ensure we gather enough edges.\n    const double COST_THRESHOLD = 2.2;\n    \n    // Safety buffer: If we have at most 'need + 50' edges left, we MUST take the current useful edge.\n    // This large buffer prevents disconnection even if we hit a streak of bad edges at the end.\n    const int SAFETY_BUFFER = 50;\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        if (taken == N - 1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int need = dsu.components - 1;\n        \n        // Count useful edges remaining in the future\n        int available = 0;\n        for (int j = i + 1; j < M; ++j) {\n            if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                available++;\n            }\n        }\n\n        // \"Must Take\" Logic with Large Buffer\n        if (available <= need + SAFETY_BUFFER) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n            continue;\n        }\n\n        // Heuristic: Accept if cost is reasonably low\n        if (l <= COST_THRESHOLD * d) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multi_array.hpp>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int TURNS = 300;\nconstexpr int DX[4] = {0, 0, 1, -1};\nconstexpr int DY[4] = {1, -1, 0, 0};\nconstexpr char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\nconstexpr char BLOCK_CHAR[4] = {'r', 'l', 'd', 'u'}; // Action to block (x+dx, y+dy)\n\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int x, int y) : x(x), y(y) {}\n    bool operator==(const Point& p) const { return x == p.x && y == p.y; }\n    int dist(const Point& p) const { return abs(x - p.x) + abs(y - p.y); }\n};\n\n// Global State\nint N, M;\nvector<Point> pets;\nvector<Point> humans;\nvector<int> pet_types; \n// grid[x][y] : true if impassable (wall)\n// Note: walls are built on squares. Humans/Pets can be on squares that are passable.\n// Once a wall is built on (x,y), it becomes impassable.\n// Humans and Pets can be on the same square? \"each square can contain any number of humans and pets.\"\n// So grid state is independent of entity positions, except for the \"cannot build adjacent to pet\" rule.\nvector<vector<bool>> grid; \n\n// Input parsing\nvoid read_init() {\n    cin >> N;\n    pets.resize(N);\n    pet_types.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> pet_types[i];\n        // Convert to 0-based for internal logic if needed, but problem is 1-based\n        pets[i].x--; pets[i].y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    grid.assign(H, vector<bool>(W, false));\n}\n\n// Read pet movements for one turn\n// pet_moves[i] is a string of characters like \"U\", \"R.\", etc.\nvoid read_turn(vector<string>& pet_moves) {\n    pet_moves.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_moves[i];\n    }\n}\n\n// Apply pet movements\nvoid apply_moves(const vector<string>& pet_moves) {\n    for (int i = 0; i < N; ++i) {\n        int cx = pets[i].x;\n        int cy = pets[i].y;\n        for (char c : pet_moves[i]) {\n            int dir = -1;\n            if (c == 'U') dir = 3;\n            else if (c == 'D') dir = 2;\n            else if (c == 'L') dir = 1;\n            else if (c == 'R') dir = 0;\n            \n            if (dir != -1) {\n                int nx = cx + DX[dir];\n                int ny = cy + DY[dir];\n                // Pets move randomly but logically. \n                // The problem says they move to passable squares chosen randomly.\n                // Assuming the server provides valid moves that respect grid bounds and walls.\n                // We just update coordinates.\n                cx = nx;\n                cy = ny;\n            }\n        }\n        pets[i].x = cx;\n        pets[i].y = cy;\n    }\n}\n\n// Helper to check bounds\nbool inside(int x, int y) {\n    return 0 <= x && x < H && 0 <= y && y < W;\n}\n\n// Helper to check if a cell is buildable (wall action)\n// Cannot build if:\n// 1. The cell contains a pet or human at the START of the turn.\n// 2. The cell is already a wall.\n// 3. An adjacent cell contains a pet.\nbool is_buildable(int x, int y, const vector<Point>& current_pets, const vector<Point>& current_humans) {\n    if (!inside(x, y)) return false;\n    if (grid[x][y]) return false; // Already impassable\n    \n    // Check if pet or human is on (x, y)\n    for (const auto& p : current_pets) {\n        if (p.x == x && p.y == y) return false;\n    }\n    for (const auto& h : current_humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    \n    // Check if adjacent cell contains a pet\n    for (int i = 0; i < 4; ++i) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (!inside(nx, ny)) continue;\n        for (const auto& p : current_pets) {\n            if (p.x == nx && p.y == ny) return false;\n        }\n    }\n    return true;\n}\n\n// Strategy: Secure a large rectangle with 0 pets.\nstruct Rect {\n    int r1, r2, c1, c2;\n    int area;\n};\n\n// Find best rectangle to secure\n// Criteria: \n// 1. Contains 0 pets currently.\n// 2. Maximize Area.\n// 3. Minimize Wall Length (perimeter).\n// 4. Maximize distance from pets to wall (safety).\nRect find_best_rectangle() {\n    // 2D prefix sum for pet counts\n    vector<vector<int>> ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int cnt = 0;\n            for (const auto& p : pets) {\n                if (p.x == i && p.y == j) cnt++;\n            }\n            ps[i+1][j+1] = ps[i][j+1] + ps[i+1][j] - ps[i][j] + cnt;\n        }\n    }\n    \n    auto get_pet_count = [&](int r1, int c1, int r2, int c2) {\n        return ps[r2+1][c2+1] - ps[r1][c2+1] - ps[r2+1][c1] + ps[r1][c1];\n    };\n\n    double best_score = -1e9;\n    Rect best_r = {0, H-1, 0, W-1, 0};\n\n    // Iterate over all rectangles\n    // To limit search, maybe only consider those touching boundary? \n    // No, a central island is also valid, though walls are expensive.\n    // Let's iterate all.\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (get_pet_count(r1, c1, r2, c2) > 0) continue;\n                    \n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    \n                    // Calculate required wall length\n                    // Walls needed on sides that are not touching map boundary\n                    int wall_len = 0;\n                    if (r1 > 0) wall_len += (c2 - c1 + 1);\n                    if (r2 < H - 1) wall_len += (c2 - c1 + 1);\n                    if (c1 > 0) wall_len += (r2 - r1 + 1);\n                    if (c2 < W - 1) wall_len += (r2 - r1 + 1);\n                    \n                    // Safety: min distance of any pet to the rectangle boundary\n                    // If a pet is very close, we can't build there easily.\n                    // This is a heuristic.\n                    int min_dist = H + W;\n                    for (const auto& p : pets) {\n                        // If inside, skip (already filtered)\n                        // Distance to rectangle\n                        int dx = max({r1 - p.x, 0, p.x - r2});\n                        int dy = max({c1 - p.y, 0, p.y - c2});\n                        int d = dx + dy;\n                        // If pet is outside, d >= 1\n                        if (d < min_dist) min_dist = d;\n                    }\n                    \n                    // We cannot build adjacent to pet. So we need buffer of 1.\n                    // If min_dist < 2, the wall is adjacent to pet.\n                    // Actually, if min_dist == 1, pet is adjacent to rect. \n                    // We need to build wall outside rect. So dist to wall is min_dist - 1.\n                    // If dist_to_wall == 0 (pet touching rect), we CANNOT build the wall on that side.\n                    // So such rectangles are dangerous.\n                    \n                    // Score: Area - Cost\n                    // Cost = Wall_Length * K1 + (if unsafe) * LargePenalty\n                    double score = (double)area;\n                    \n                    // Penalty for walls\n                    score -= wall_len * 0.5; // Tunable factor\n                    \n                    // Penalty for low safety margin\n                    // Buffer needed is 1.\n                    // If pet is touching boundary (min_dist=1), we are blocked.\n                    if (min_dist == 0) { /* Should not happen since count=0 */ }\n                    else if (min_dist == 1) {\n                        score -= 100; // Heavily penalize touching pets\n                    } else {\n                        // Slight penalty for being close\n                        score -= (5.0 / min_dist);\n                    }\n                    \n                    // Bonus for containing humans? No, we can move them in.\n                    // Penalty for humans being far away?\n                    // Sum of distances from humans to rect.\n                    int total_dist = 0;\n                    for (const auto& h : humans) {\n                        // Closest point in rect\n                        int cx = max(r1, min(h.x, r2));\n                        int cy = max(c1, min(h.y, c2));\n                        total_dist += abs(h.x - cx) + abs(h.y - cy);\n                    }\n                    score -= total_dist * 0.05;\n\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = {r1, r2, c1, c2, area};\n                    }\n                }\n            }\n        }\n    }\n    return best_r;\n}\n\n// Action Generation\nvector<char> generate_actions(Rect& target_rect, vector<Point>& current_humans, int& phase, vector<Point>& wall_tasks, int turn_cnt) {\n    vector<char> actions(M, '.');\n    \n    // Wall cells needed to seal the rectangle\n    vector<Point> needed_walls;\n    // r1-1, r2+1, c1-1, c2+1\n    if (target_rect.r1 > 0) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r1 - 1, c);\n    if (target_rect.r2 < H - 1) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r2 + 1, c);\n    if (target_rect.c1 > 0) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c1 - 1);\n    if (target_rect.c2 < W - 1) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c2 + 1);\n    \n    // Remove already built walls\n    needed_walls.erase(remove_if(needed_walls.begin(), needed_walls.end(), \n        [&](const Point& p){ return grid[p.x][p.y]; }), \n        needed_walls.end());\n        \n    // Phase 1: Move humans into the rectangle\n    if (phase == 1) {\n        bool all_in = true;\n        for (int i = 0; i < M; ++i) {\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            if (target_rect.r1 <= hx && hx <= target_rect.r2 && target_rect.c1 <= hy && hy <= target_rect.c2) {\n                actions[i] = '.';\n                continue;\n            }\n            all_in = false;\n            \n            // Move towards closest point in rect\n            int tx = max(target_rect.r1, min(hx, target_rect.r2));\n            int ty = max(target_rect.c1, min(hy, target_rect.c2));\n            \n            // BFS to find shortest path to (tx, ty) or any cell in rect?\n            // Simple greedy: reduce Manhattan distance\n            int best_d = abs(hx - tx) + abs(hy - ty);\n            int best_dir = -1;\n            \n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + DX[d];\n                int ny = hy + DY[d];\n                if (!inside(nx, ny)) continue;\n                if (grid[nx][ny]) continue; // Can't move into wall\n                \n                // Check if (nx, ny) is in rect (good)\n                bool in_rect = (target_rect.r1 <= nx && nx <= target_rect.r2 && target_rect.c1 <= ny && ny <= target_rect.c2);\n                int d_score = abs(nx - tx) + abs(ny - ty);\n                if (in_rect) d_score = -1000; // Priority to enter\n                \n                if (d_score < best_d) {\n                    best_d = d_score;\n                    best_dir = d;\n                }\n            }\n            if (best_dir != -1) {\n                actions[i] = DIR_CHAR[best_dir];\n                current_humans[i].x += DX[best_dir];\n                current_humans[i].y += DY[best_dir];\n            }\n        }\n        \n        if (all_in) {\n            phase = 2;\n            // Assign wall tasks\n            wall_tasks = needed_walls;\n            // Shuffle to distribute work randomly? Or keep sorted?\n            // Keep simple.\n        }\n    } \n    // Phase 2: Build walls\n    else if (phase == 2) {\n        if (wall_tasks.empty()) {\n            phase = 3;\n            return actions;\n        }\n        \n        // Greedy assignment: each human picks closest task\n        // To avoid conflict, we process humans in order of distance to tasks? \n        // Or simply assign static chunks? \n        // Static chunks are better for consistency.\n        \n        // Let's use a persistent assignment.\n        // If no assignment yet, create one.\n        static vector<int> assignment(M, -1);\n        static bool assigned = false;\n        \n        if (!assigned || wall_tasks.size() != (unsigned)(assignment.size())) {\n             // Simple Round Robin assignment based on human index\n             assignment.clear();\n             assignment.resize(M, -1);\n             for (size_t i = 0; i < wall_tasks.size(); ++i) {\n                 assignment[i % M] = i;\n             }\n             assigned = true;\n        }\n        \n        // Execute\n        for (int i = 0; i < M; ++i) {\n            int task_idx = assignment[i];\n            if (task_idx == -1 || task_idx >= (int)wall_tasks.size()) {\n                actions[i] = '.';\n                continue;\n            }\n            \n            Point target = wall_tasks[task_idx];\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            // If adjacent, try build\n            bool adj = false;\n            int build_dir = -1;\n            for (int d = 0; d < 4; ++d) {\n                if (hx + DX[d] == target.x && hy + DY[d] == target.y) {\n                    adj = true;\n                    build_dir = d;\n                    break;\n                }\n            }\n            \n            if (adj) {\n                // Check if buildable\n                // Need to check adjacency to pets at the START of this turn\n                // We have `pets` vector which is already updated for this turn?\n                // No, `pets` in global state is updated at the START of the loop in main.\n                // So `pets` holds positions at the START of the turn.\n                // We check buildability against `pets`.\n                \n                // is_buildable checks `grid` and `pets` and `current_humans`\n                // But `current_humans` is being modified. We should use previous pos? \n                // Rule: \"cannot choose a square that contains pets or humans at the start of this turn\"\n                // So we check against `humans` (initial state of turn).\n                // `current_humans` is a copy we modify to simulate moves. \n                // We need the actual start positions.\n                // Let's pass `humans` (the vector holding start-of-turn pos) to is_buildable?\n                // Or just check `current_humans[i]` before moving? No, that's wrong for other humans.\n                // Let's assume `humans` is not modified yet.\n                // Wait, I modify `current_humans` in place.\n                // So at the start of generate_actions, `current_humans` IS the start position.\n                // Good.\n                \n                if (is_buildable(target.x, target.y, pets, current_humans)) {\n                    actions[i] = BLOCK_CHAR[build_dir];\n                    grid[target.x][target.y] = true; // Mark as built immediately for logic?\n                    // Note: The problem says \"perform each action simultaneously\".\n                    // However, for our planning in the next turn, we update grid.\n                    // If two humans build the same wall, the second one does nothing (rule: \"If you choose a square that is already impassable, nothing happens\").\n                    // But we shouldn't assign two humans to the same task ideally.\n                    // With round robin, tasks are distinct.\n                    \n                    // Remove task\n                    wall_tasks.erase(wall_tasks.begin() + task_idx);\n                    // Update assignments?\n                    // Shift indices down for those > task_idx\n                    for (int k = 0; k < M; ++k) {\n                        if (assignment[k] > task_idx) assignment[k]--;\n                    }\n                } else {\n                    actions[i] = '.'; // Cannot build now\n                }\n            } else {\n                // Move towards target\n                // BFS or simple Manhattan\n                int best_d = abs(hx - target.x) + abs(hy - target.y);\n                int best_dir = -1;\n                \n                for (int d = 0; d < 4; ++d) {\n                    int nx = hx + DX[d];\n                    int ny = hy + DY[d];\n                    if (!inside(nx, ny)) continue;\n                    if (grid[nx][ny]) continue;\n                    if (nx == target.x && ny == target.y) continue; // Moving onto the wall square? No, can only build adjacent. \n                    // Actually, can we move onto a square that will be a wall? \n                    // \"It is not possible to move to a square that becomes impassable by another person's action in this turn.\"\n                    // We are the person. If we move to target, we can't build it (must be adjacent).\n                    // So we shouldn't move onto target.\n                    \n                    int d_score = abs(nx - target.x) + abs(ny - target.y);\n                    if (d_score < best_d) {\n                        best_d = d_score;\n                        best_dir = d;\n                    }\n                }\n                if (best_dir != -1) {\n                    actions[i] = DIR_CHAR[best_dir];\n                    current_humans[i].x += DX[best_dir];\n                    current_humans[i].y += DY[best_dir];\n                } else {\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        if (wall_tasks.empty()) phase = 3;\n    }\n    // Phase 3: Done\n    else {\n        for (int i = 0; i < M; ++i) actions[i] = '.';\n    }\n    \n    return actions;\n}\n\nvoid solve() {\n    read_init();\n    \n    Rect target_rect;\n    int phase = 1; // 1: Enter, 2: Build, 3: Done\n    vector<Point> wall_tasks;\n    \n    for (int t = 0; t < TURNS; ++t) {\n        // Read Pet Moves\n        vector<string> pet_moves;\n        read_turn(pet_moves);\n        \n        // Update Pet Positions\n        apply_moves(pet_moves);\n        \n        // Check if plan is still valid\n        bool valid = true;\n        if (phase == 3) {\n            // Just stay put\n            cout << string(M, '.') << endl;\n            continue;\n        }\n        \n        // Check if pets entered target rect\n        for (const auto& p : pets) {\n            if (target_rect.r1 <= p.x && p.x <= target_rect.r2 &&\n                target_rect.c1 <= p.y && p.y <= target_rect.c2) {\n                valid = false;\n                break;\n            }\n        }\n        \n        if (!valid || phase == 0) {\n            // Re-plan\n            target_rect = find_best_rectangle();\n            phase = 1;\n            wall_tasks.clear();\n            // cout << \"# Turn \" << t << \" Replanning. Rect: \" \n            //      << target_rect.r1 << \" \" << target_rect.r2 << \" \"\n            //      << target_rect.c1 << \" \" << target_rect.c2 << \" Area: \" << target_rect.area << endl;\n        }\n        \n        // Generate Actions\n        // We need a copy of human positions to simulate moves for next turn logic?\n        // No, the problem state updates based on our output.\n        // We just need to update our internal `humans` state for the next iteration's `is_buildable` check.\n        // So `generate_actions` should update `humans`.\n        // But `is_buildable` needs \"start of turn\" positions.\n        // So we pass `humans` (which holds start pos) and update it at the end.\n        \n        vector<char> actions = generate_actions(target_rect, humans, phase, wall_tasks, t);\n        \n        // Output\n        string s(actions.begin(), actions.end());\n        cout << s << endl;\n        cout.flush();\n    }\n}\n\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n    solve();\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Global configuration\nconst int H = 20;\nconst int W = 20;\nconst int MAX_LEN = 200;\nconst double INF = 1e9;\n\n// Directions\nconst int DY[4] = {-1, 1, 0, 0};\nconst int DX[4] = {0, 0, -1, 1};\nconst char DC[4] = {'U', 'D', 'L', 'R'};\n\n// Input\nint si, sj, ti, tj;\ndouble p;\nvector<string> h_grid(H);\nvector<string> v_grid(H-1);\n\n// Helper to check wall\n// dir: 0=U, 1=D, 2=L, 3=R\ninline bool is_wall(int y, int x, int dir) {\n    if (dir == 0) { // U\n        if (y == 0) return true;\n        return v_grid[y-1][x] == '1';\n    } else if (dir == 1) { // D\n        if (y == H-1) return true;\n        return v_grid[y][x] == '1';\n    } else if (dir == 2) { // L\n        if (x == 0) return true;\n        return h_grid[y][x-1] == '1';\n    } else { // R\n        if (x == W-1) return true;\n        return h_grid[y][x] == '1';\n    }\n    return false;\n}\n\n// Buffers for calculation to avoid allocation overhead\nvector<vector<double>> prob_buff1(H, vector<double>(W, 0.0));\nvector<vector<double>> prob_buff2(H, vector<double>(W, 0.0));\n\n// Function to calculate expected score of a sequence\n// Uses DP on probability distribution\ndouble calculate_score(const string& s) {\n    // Initialize buffers\n    for(int i=0; i<H; ++i) fill(prob_buff1[i].begin(), prob_buff1[i].end(), 0.0);\n    \n    prob_buff1[si][sj] = 1.0;\n    double expected_score = 0.0;\n    int L = s.length();\n\n    auto& curr_prob = prob_buff1;\n    auto& next_prob = prob_buff2;\n\n    for (int t = 0; t < L; ++t) {\n        // Reset next_prob\n        for(int i=0; i<H; ++i) fill(next_prob[i].begin(), next_prob[i].end(), 0.0);\n\n        int dir_idx = -1;\n        if (s[t] == 'U') dir_idx = 0;\n        else if (s[t] == 'D') dir_idx = 1;\n        else if (s[t] == 'L') dir_idx = 2;\n        else if (s[t] == 'R') dir_idx = 3;\n\n        // If invalid char (should not happen), just stay\n        if (dir_idx == -1) {\n            // Treat as staying, effectively just p stays, 1-p stays (if wall) or moves\n            // but since char is invalid, we assume it maps to nothing or self-loop? \n            // Problem guarantees UDLR.\n        }\n\n        double ny_off = DY[dir_idx];\n        double nx_off = DX[dir_idx];\n\n        for (int y = 0; y < H; ++y) {\n            for (int x = 0; x < W; ++x) {\n                double cur_p = curr_prob[y][x];\n                if (cur_p == 0.0) continue;\n\n                // Probability of forgetting: stay in place\n                double p_forget = cur_p * p;\n                next_prob[y][x] += p_forget;\n\n                // Probability of trying to move\n                double p_move = cur_p * (1.0 - p);\n                \n                int nx = x + (int)nx_off;\n                int ny = y + (int)ny_off;\n\n                // Check wall collision\n                if (is_wall(y, x, dir_idx)) {\n                    next_prob[y][x] += p_move;\n                } else {\n                    if (ny == ti && nx == tj) {\n                        // Reached goal\n                        expected_score += p_move * (401.0 - (t + 1));\n                        // Mass absorbed into score, not propagated to next state\n                    } else {\n                        next_prob[ny][nx] += p_move;\n                    }\n                }\n            }\n        }\n        swap(curr_prob, next_prob);\n    }\n    return expected_score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < H; ++i) cin >> h_grid[i];\n    for (int i = 0; i < H-1; ++i) cin >> v_grid[i];\n\n    // 1. Find shortest path (A*)\n    // priority_queue: (estimated_cost, y, x)\n    using Node = pair<int, pair<int, int>>;\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    vector<vector<int>> dist(H, vector<int>(W, INF));\n    vector<vector<int>> parent(H, vector<int>(W, -1));\n    \n    auto heuristic = [&](int y, int x) {\n        return abs(y - ti) + abs(x - tj);\n    };\n\n    dist[si][sj] = 0;\n    pq.push({heuristic(si, sj), {si, sj}});\n\n    while (!pq.empty()) {\n        auto curr = pq.top();\n        pq.pop();\n        int y = curr.second.first;\n        int x = curr.second.second;\n        int cost = dist[y][x];\n\n        if (y == ti && x == tj) break;\n        if (cost > dist[y][x]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int ny = y + DY[i];\n            int nx = x + DX[i];\n            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;\n            if (is_wall(y, x, i)) continue;\n            \n            if (dist[ny][nx] > cost + 1) {\n                dist[ny][nx] = cost + 1;\n                parent[ny][nx] = i;\n                pq.push({dist[ny][nx] + heuristic(ny, nx), {ny, nx}});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cy = ti, cx = tj;\n    while (cy != si || cx != sj) {\n        int dir = parent[cy][cx];\n        path.push_back(DC[dir]);\n        cy -= DY[dir];\n        cx -= DX[dir];\n    }\n    reverse(path.begin(), path.end());\n    \n    // 2. Build initial robust string\n    // Strategy: Repeat each character in the path K times\n    // K depends on p. Higher p -> Higher K.\n    int path_len = path.length();\n    string ans = \"\";\n    \n    // Calculate optimal K\n    // Empirically chosen thresholds\n    int K = 1;\n    if (p > 0.15) K = 2;\n    if (p > 0.35) K = 3;\n    if (p > 0.45) K = 4;\n    \n    // Ensure K * path_len fits reasonably, or reduce K if too long\n    // We want to repeat the sequence to allow multiple attempts.\n    // A single run of robust path should consume most of the length or leave room for repeats.\n    // If K*path_len is very small, we can repeat it many times.\n    // If K*path_len is close to 200, we run it once.\n    \n    // Cap K such that we can at least run the path once\n    while (K > 1 && K * path_len > 200) {\n        K--;\n    }\n\n    string robust_seg = \"\";\n    for (char c : path) {\n        robust_seg += string(K, c);\n    }\n    \n    // Fill ans by repeating the robust segment\n    while ((int)ans.size() < 200) {\n        ans += robust_seg;\n    }\n    ans.resize(200);\n\n    // 3. Local Search (Hill Climbing)\n    auto start_time = chrono::high_resolution_clock::now();\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis_idx(0, 199);\n    uniform_int_distribution<> dis_dir(0, 3);\n\n    double current_score = calculate_score(ans);\n    string best_ans = ans;\n    double best_score = current_score;\n    \n    const int time_limit_ms = 1900;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > time_limit_ms) break;\n\n        // Mutation 1: Change a random character\n        int idx = dis_idx(gen);\n        int new_dir = dis_dir(gen);\n        char original = ans[idx];\n        char new_char = DC[new_dir];\n        \n        if (original != new_char) {\n            ans[idx] = new_char;\n            double new_score = calculate_score(ans);\n            \n            if (new_score > current_score) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_ans = ans;\n                }\n            } else {\n                ans[idx] = original; // Revert\n            }\n        }\n\n        // Mutation 2: Swap two random characters (less frequent or just mixed in)\n        // To keep it fast, we can just do change mutations mostly.\n        // Let's try a swap occasionally\n        if (dis_idx(gen) % 10 == 0) {\n             int idx2 = dis_idx(gen);\n             if (idx != idx2) {\n                 swap(ans[idx], ans[idx2]);\n                 double new_score = calculate_score(ans);\n                 if (new_score > current_score) {\n                     current_score = new_score;\n                     if (new_score > best_score) {\n                         best_score = new_score;\n                         best_ans = ans;\n                     }\n                 } else {\n                     swap(ans[idx], ans[idx2]); // Revert\n                 }\n             }\n        }\n    }\n\n    cout << best_ans << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <ctime>\n#include <set>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0:Left, 1:Up, 2:Right, 3:Down\nint dr[4] = {0, -1, 0, 1};\nint dc[4] = {-1, 0, 1, 0};\n\n// to[type][in_dir] = out_dir\nint to[8][4] = {\n    {1, 0, -1, -1}, // 0: LU\n    {3, -1, -1, 0}, // 1: LD\n    {-1, -1, 3, 2}, // 2: RD\n    {-1, 2, 1, -1}, // 3: RU\n    {1, 0, 3, 2},   // 4: Cross 1 (LU-RD)\n    {3, 2, 1, 0},   // 5: Cross 2 (LD-RU)\n    {2, -1, 0, -1}, // 6: Vert\n    {-1, 3, -1, 1}  // 7: Horz\n};\n\nint grid[H][W];\nint state[H][W]; // Current effective types\nint rotations[H][W]; // Current rotation counts\n\nmt19937 rng(time(0));\n\n// Returns effective type based on base type and rotation\nint get_type(int base, int r) {\n    if (base <= 3) return (base + r) % 4;\n    if (base == 4 || base == 5) return ((base + r) % 2 == 0) ? 4 : 5;\n    return ((base + r) % 2 == 0) ? 6 : 7;\n}\n\n// Trace loop starting at (r,c) entering from 'in_d'.\n// Returns length of loop.\nint trace_loop(int r, int c, int in_d) {\n    int cr = r, cc = c, cd = in_d;\n    int len = 0;\n    // Safety limit\n    for (int steps = 0; steps < 1000; ++steps) {\n        int t = state[cr][cc];\n        int out_d = to[t][cd];\n        if (out_d == -1) return 0;\n        \n        int nr = cr + dr[out_d];\n        int nc = cc + dc[out_d];\n        \n        if (nr < 0 || nr >= H || nc < 0 || nc >= W) return 0;\n        \n        int next_in_d = (out_d + 2) % 4;\n        len++;\n        \n        if (nr == r && nc == c && next_in_d == in_d) {\n            return len;\n        }\n        \n        cr = nr;\n        cc = nc;\n        cd = next_in_d;\n    }\n    return 0;\n}\n\n// Multiset of all loop lengths in the current state\nmultiset<int> loops;\nlong long current_score = 0;\n\n// Helper to update global score and loops multiset\nvoid update_score_and_loops(const vector<int>& to_remove, const vector<int>& to_add) {\n    for (int l : to_remove) {\n        auto it = loops.find(l);\n        if (it != loops.end()) loops.erase(it);\n    }\n    for (int l : to_add) {\n        loops.insert(l);\n    }\n    \n    if (loops.size() >= 2) {\n        auto it = loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        current_score = (long long)L1 * L2;\n    } else {\n        current_score = 0;\n    }\n}\n\n// Try flipping (r,c) to new_rot. Returns new score. Reverts state.\nlong long try_flip(int r, int c, int new_rot) {\n    int old_rot = rotations[r][c];\n    if (new_rot == old_rot) return current_score;\n\n    // 1. Identify old loops at (r,c)\n    vector<int> old_lengths;\n    bool processed[4] = {false};\n    int old_type = state[r][c];\n    \n    for (int d = 0; d < 4; ++d) {\n        if (to[old_type][d] != -1 && !processed[d]) {\n            int out_d = to[old_type][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) old_lengths.push_back(len);\n            \n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    // 2. Apply temporary flip\n    state[r][c] = get_type(grid[r][c], new_rot);\n    \n    // 3. Identify new loops at (r,c)\n    vector<int> new_lengths;\n    fill(processed, processed+4, false);\n    int new_type = state[r][c];\n    \n    for (int d = 0; d < 4; ++d) {\n        if (to[new_type][d] != -1 && !processed[d]) {\n            int out_d = to[new_type][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) new_lengths.push_back(len);\n            \n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    // 4. Calculate hypothetical score\n    multiset<int> temp_loops = loops;\n    for (int l : old_lengths) {\n        auto it = temp_loops.find(l);\n        if (it != temp_loops.end()) temp_loops.erase(it);\n    }\n    for (int l : new_lengths) {\n        temp_loops.insert(l);\n    }\n    \n    long long score = 0;\n    if (temp_loops.size() >= 2) {\n        auto it = temp_loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        score = (long long)L1 * L2;\n    }\n    \n    // 5. Revert state\n    state[r][c] = get_type(grid[r][c], old_rot);\n    return score;\n}\n\n// Permanently apply the flip\nvoid apply_flip(int r, int c, int new_rot) {\n    int old_rot = rotations[r][c];\n    \n    vector<int> old_lengths;\n    bool processed[4] = {false};\n    int old_type = state[r][c];\n    \n    for (int d = 0; d < 4; ++d) {\n        if (to[old_type][d] != -1 && !processed[d]) {\n            int out_d = to[old_type][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) old_lengths.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    rotations[r][c] = new_rot;\n    state[r][c] = get_type(grid[r][c], new_rot);\n    \n    vector<int> new_lengths;\n    fill(processed, processed+4, false);\n    int new_type = state[r][c];\n    \n    for (int d = 0; d < 4; ++d) {\n        if (to[new_type][d] != -1 && !processed[d]) {\n            int out_d = to[new_type][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) new_lengths.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    update_score_and_loops(old_lengths, new_lengths);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < H; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < W; ++j) {\n            grid[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Greedy Initialization\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int best_r = rng() % 4;\n            int best_conn = -1;\n            for (int r = 0; r < 4; ++r) {\n                int t_eff = get_type(grid[i][j], r);\n                int conn = 0;\n                // Connect to Top\n                if (i > 0) {\n                    int t_top = state[i-1][j];\n                    // Top exits Down(3), Current enters Up(1)\n                    if (to[t_top][3] != -1 && to[t_eff][1] != -1 && \n                        to[t_top][3] == 3 && to[t_eff][1] == 1) conn++;\n                }\n                // Connect to Left\n                if (j > 0) {\n                    int t_left = state[i][j-1];\n                    // Left exits Right(2), Current enters Left(0)\n                    if (to[t_left][2] != -1 && to[t_eff][0] != -1 && \n                        to[t_left][2] == 2 && to[t_eff][0] == 0) conn++;\n                }\n                if (conn > best_conn || (conn == best_conn && rng() % 2)) {\n                    best_conn = conn;\n                    best_r = r;\n                }\n            }\n            rotations[i][j] = best_r;\n            state[i][j] = get_type(grid[i][j], best_r);\n        }\n    }\n    \n    // Initial Calculation of Loops\n    bool visited[H][W][4];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) for(int d=0; d<4; ++d) visited[i][j][d] = false;\n    \n    loops.clear();\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (visited[i][j][d]) continue;\n                int t = state[i][j];\n                if (to[t][d] == -1) continue;\n                \n                int len = trace_loop(i, j, d);\n                if (len > 0) {\n                    loops.insert(len);\n                    // Mark all ports on this loop as visited\n                    int cr=i, cc=j, cd=d;\n                    while(true) {\n                        visited[cr][cc][cd] = true;\n                        int out = to[state[cr][cc]][cd];\n                        int nr = cr + dr[out], nc = cc + dc[out];\n                        int nd = (out + 2) % 4;\n                        if (nr==i && nc==j && nd==d) break;\n                        cr=nr; cc=nc; cd=nd;\n                    }\n                }\n            }\n        }\n    }\n    \n    if (loops.size() >= 2) {\n        auto it = loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        current_score = (long long)L1 * L2;\n    } else {\n        current_score = 0;\n    }\n    \n    long long best_score = current_score;\n    int best_rotations[H][W];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_rotations[i][j] = rotations[i][j];\n    \n    // Simulated Annealing\n    auto start_time = clock();\n    double TIME_LIMIT = 1.9 * CLOCKS_PER_SEC;\n    \n    while ((double)(clock() - start_time) < TIME_LIMIT) {\n        double progress = (double)(clock() - start_time) / TIME_LIMIT;\n        double T = 1000.0 * (1.0 - progress);\n        if (T < 0.1) T = 0.1;\n        \n        int r = rng() % H;\n        int c = rng() % W;\n        int old_rot = rotations[r][c];\n        int new_rot = rng() % 4;\n        \n        if (new_rot == old_rot) continue;\n        \n        long long new_score = try_flip(r, c, new_rot);\n        \n        long long diff = new_score - current_score;\n        if (diff > 0 || (rng() % 100000 < 100000 * exp(diff / T))) {\n            apply_flip(r, c, new_rot);\n            if (current_score > best_score) {\n                best_score = current_score;\n                for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_rotations[i][j] = rotations[i][j];\n            }\n        }\n    }\n    \n    string ans = \"\";\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ans += (char)('0' + best_rotations[i][j]);\n        }\n    }\n    cout << ans << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <array>\n\nusing namespace std;\n\nconst int LEFT = 1;\nconst int UP = 2;\nconst int RIGHT = 4;\nconst int DOWN = 8;\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n    bool operator==(const Point& p) const { return r == p.r && c == p.c; }\n    bool operator!=(const Point& p) const { return !(*this == p); }\n};\n\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char MOVE_CHARS[4] = {'U', 'D', 'L', 'R'};\n\nclass Solver {\npublic:\n    int N;\n    int T_limit;\n    vector<vector<int>> board;\n    Point empty_pos;\n    string moves;\n    mt19937 rng;\n\n    Solver(int n, int t_limit) : N(n), T_limit(t_limit), rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void set_board(const vector<vector<int>>& b, Point ep) {\n        board = b;\n        empty_pos = ep;\n        moves = \"\";\n    }\n\n    bool is_valid(int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    }\n\n    vector<Point> get_largest_component() {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<Point> largest;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] != 0 && !visited[i][j]) {\n                    vector<Point> comp;\n                    queue<Point> q;\n                    q.push(Point(i, j));\n                    visited[i][j] = true;\n                    comp.push_back(Point(i, j));\n\n                    while (!q.empty()) {\n                        Point cur = q.front(); q.pop();\n                        int cr = cur.r, cc = cur.c;\n                        int tile = board[cr][cc];\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (is_valid(nr, nc) && board[nr][nc] != 0 && !visited[nr][nc]) {\n                                int neighbor = board[nr][nc];\n                                bool connects = false;\n                                if (d == 0 && (tile & UP) && (neighbor & DOWN)) connects = true;\n                                if (d == 1 && (tile & DOWN) && (neighbor & UP)) connects = true;\n                                if (d == 2 && (tile & LEFT) && (neighbor & RIGHT)) connects = true;\n                                if (d == 3 && (tile & RIGHT) && (neighbor & LEFT)) connects = true;\n                                \n                                if (connects) {\n                                    visited[nr][nc] = true;\n                                    comp.push_back(Point(nr, nc));\n                                    q.push(Point(nr, nc));\n                                }\n                            }\n                        }\n                    }\n                    if (comp.size() > largest.size()) largest = comp;\n                }\n            }\n        }\n        return largest;\n    }\n\n    Point find_closest_tile(Point p, int bitmask) {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        queue<pair<Point, int>> q; \n        q.push({p, 0});\n        visited[p.r][p.c] = true;\n        \n        while (!q.empty()) {\n            auto curr = q.front(); q.pop();\n            Point pt = curr.first;\n            int dist = curr.second;\n            \n            if (pt != p) {\n                if (board[pt.r][pt.c] != 0 && (board[pt.r][pt.c] & bitmask)) {\n                    return pt;\n                }\n            }\n            \n            for (int d = 0; d < 4; ++d) {\n                int nr = pt.r + DR[d];\n                int nc = pt.c + DC[d];\n                if (is_valid(nr, nc) && !visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({Point(nr, nc), dist + 1});\n                }\n            }\n        }\n        return Point(-1, -1);\n    }\n\n    vector<Point> get_path_for_empty(Point target, Point forbidden = Point(-1, -1)) {\n        if (empty_pos == target) return {};\n        queue<Point> q;\n        vector<vector<Point>> parent(N, vector<Point>(N, Point(-1, -1)));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        q.push(empty_pos);\n        visited[empty_pos.r][empty_pos.c] = true;\n        bool found = false;\n        while(!q.empty()) {\n            Point p = q.front(); q.pop();\n            if(p == target) { found = true; break; }\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) && !visited[nr][nc]) {\n                    if (Point(nr, nc) == forbidden) continue; \n                    visited[nr][nc] = true;\n                    parent[nr][nc] = p;\n                    q.push(Point(nr, nc));\n                }\n            }\n        }\n        vector<Point> path;\n        if(found) {\n            Point curr = target;\n            while(curr != empty_pos) {\n                path.push_back(curr);\n                curr = parent[curr.r][curr.c];\n            }\n            reverse(path.begin(), path.end());\n        }\n        return path;\n    }\n\n    void execute_empty_path(const vector<Point>& path) {\n        for (Point p : path) {\n            if (moves.size() >= T_limit) return;\n            int dr = p.r - empty_pos.r;\n            int dc = p.c - empty_pos.c;\n            int d = -1;\n            if (dr == -1) d = 0; else if (dr == 1) d = 1;\n            else if (dc == -1) d = 2; else if (dc == 1) d = 3;\n            \n            moves += MOVE_CHARS[d];\n            board[empty_pos.r][empty_pos.c] = board[p.r][p.c];\n            board[p.r][p.c] = 0;\n            empty_pos = p;\n        }\n    }\n\n    void move_tile(Point from, Point to) {\n        if (from == to) return;\n        Point cur = from;\n        while (cur != to) {\n            if (moves.size() >= T_limit) return;\n            \n            Point diff = Point(to.r - cur.r, to.c - cur.c);\n            vector<int> dirs;\n            if (diff.r > 0) dirs.push_back(1);\n            else if (diff.r < 0) dirs.push_back(0);\n            if (diff.c > 0) dirs.push_back(3);\n            else if (diff.c < 0) dirs.push_back(2);\n            \n            // Shuffle dirs to avoid getting stuck in local patterns when blocked\n            shuffle(dirs.begin(), dirs.end(), rng);\n\n            bool moved = false;\n            for (int d : dirs) {\n                int nr = cur.r + DR[d];\n                int nc = cur.c + DC[d];\n                Point next_target(nr, nc);\n\n                vector<Point> path = get_path_for_empty(next_target, cur);\n                if (path.empty()) continue; \n\n                execute_empty_path(path);\n                if (moves.size() >= T_limit) return;\n\n                int er = cur.r - empty_pos.r; \n                int ec = cur.c - empty_pos.c;\n                int ed = -1;\n                if (er == -1) ed = 0; else if (er == 1) ed = 1;\n                else if (ec == -1) ed = 2; else if (ec == 1) ed = 3;\n                \n                moves += MOVE_CHARS[ed];\n                board[empty_pos.r][empty_pos.c] = board[cur.r][cur.c];\n                board[cur.r][cur.c] = 0;\n                empty_pos = cur;\n                \n                cur = next_target;\n                moved = true;\n                break;\n            }\n            if (!moved) {\n                break; \n            }\n        }\n    }\n\n    void solve() {\n        while ((int)moves.size() < T_limit) {\n            vector<Point> cc = get_largest_component();\n            if (cc.size() == N * N - 1) break;\n\n            vector<bool> in_cc(N*N, false);\n            for (auto& p : cc) in_cc[p.r * N + p.c] = true;\n\n            vector<Point> boundary;\n            for (auto& p : cc) {\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) && !in_cc[nr * N + nc] && board[nr][nc] != 0) {\n                        boundary.push_back(Point(nr, nc));\n                    }\n                }\n            }\n            shuffle(boundary.begin(), boundary.end(), rng);\n\n            Point best_hole = Point(-1, -1);\n            Point best_filler = Point(-1, -1);\n            int best_dist = 1000;\n\n            // Greedy search for the closest fix\n            for (Point v : boundary) {\n                for (int d = 0; d < 4; ++d) {\n                    int ur = v.r + DR[d];\n                    int uc = v.c + DC[d];\n                    if (is_valid(ur, uc) && in_cc[ur*N + uc]) {\n                        int tile_u = board[ur][uc];\n                        int tile_v = board[v.r][v.c];\n                        \n                        int du = DR[d], dv = DC[d];\n                        int bit_u = 0, bit_v = 0;\n                        if (du == 1) { bit_u = 8; bit_v = 2; } \n                        else if (du == -1) { bit_u = 2; bit_v = 8; } \n                        else if (dv == 1) { bit_u = 4; bit_v = 1; } \n                        else if (dv == -1) { bit_u = 1; bit_v = 4; } \n                        \n                        bool u_has = (tile_u & bit_u);\n                        bool v_has = (tile_v & bit_v);\n\n                        if (u_has && !v_has) {\n                            Point filler = find_closest_tile(v, bit_v);\n                            if (filler.r != -1) {\n                                int dist = abs(filler.r - v.r) + abs(filler.c - v.c);\n                                if (dist < best_dist) {\n                                    best_dist = dist;\n                                    best_hole = v;\n                                    best_filler = filler;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (best_hole.r != -1) {\n                move_tile(best_filler, best_hole);\n            } else {\n                break; \n            }\n        }\n        cout << moves << endl;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    \n    vector<vector<int>> board(N, vector<int>(N));\n    Point empty_pos;\n    \n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) {\n            char c = line[j];\n            if (c == '0') {\n                board[i][j] = 0;\n                empty_pos = Point(i, j);\n            } else {\n                if (c >= 'a') board[i][j] = 10 + (c - 'a');\n                else board[i][j] = c - '0';\n            }\n        }\n    }\n\n    Solver solver(N, T);\n    solver.set_board(board, empty_pos);\n    solver.solve();\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <cmath>\n#include <chrono>\n#include <cassert>\n\nusing namespace std;\n\ntypedef long long ll;\n\nconst int K_MAX = 100;\n\nstruct Point {\n    ll x, y;\n};\n\nstruct Line {\n    ll x1, y1, x2, y2;\n};\n\n// Signature to uniquely identify a region (bitmask of side of each line)\nstruct Signature {\n    unsigned long long p1; // bits 0-63\n    unsigned long long p2; // bits 64-99 (since K_MAX is 100)\n\n    bool operator<(const Signature& other) const {\n        if (p1 != other.p1) return p1 < other.p1;\n        return p2 < other.p2;\n    }\n    \n    bool operator==(const Signature& other) const {\n        return p1 == other.p1 && p2 == other.p2;\n    }\n};\n\n// Global inputs\nint N, K;\nvector<int> a(11);\nvector<Point> points;\n\n// Random generator\nmt19937 rng(1337);\n\nll rand_ll(ll l, ll r) {\n    uniform_int_distribution<ll> dist(l, r);\n    return dist(rng);\n}\n\nll cross_product(const Point& a, const Point& b, const Point& c) {\n    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n// Generate a random line that does not pass through any point\nLine generate_random_line() {\n    while (true) {\n        ll x1 = rand_ll(-10000, 10000);\n        ll y1 = rand_ll(-10000, 10000);\n        ll x2 = rand_ll(-10000, 10000);\n        ll y2 = rand_ll(-10000, 10000);\n\n        if (x1 == x2 && y1 == y2) continue;\n\n        Line l{x1, y1, x2, y2};\n        \n        bool hits_point = false;\n        for (const auto& p : points) {\n            if (cross_product({x1, y1}, {x2, y2}, p) == 0) {\n                hits_point = true;\n                break;\n            }\n        }\n        if (!hits_point) {\n            return l;\n        }\n    }\n}\n\n// State of the solver\nstruct State {\n    int k;\n    vector<Line> lines;\n    vector<Signature> signatures; // signature for each point\n    vector<bool> is_dead;\n    \n    map<Signature, int> region_counts; // maps signature -> number of points in that region\n    vector<int> b_counts; // b_counts[d] = number of regions with exactly d points (d=1..10)\n    int score;\n\n    void init(int init_k) {\n        k = init_k;\n        lines.clear();\n        lines.reserve(k);\n        for(int i=0; i<k; ++i) lines.push_back(generate_random_line());\n        \n        is_dead.assign(N, false);\n        signatures.assign(N, {0, 0});\n        region_counts.clear();\n        b_counts.assign(11, 0);\n\n        for (int i = 0; i < N; ++i) {\n            Signature sig{0, 0};\n            bool dead = false;\n            for (int j = 0; j < k; ++j) {\n                ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                if (val == 0) {\n                    dead = true;\n                    break;\n                }\n                if (val > 0) {\n                    if (j < 64) sig.p1 |= (1ULL << j);\n                    else sig.p2 |= (1ULL << (j - 64));\n                }\n            }\n            is_dead[i] = dead;\n            signatures[i] = sig;\n            if (!dead) {\n                region_counts[sig]++;\n            }\n        }\n\n        for (auto& p : region_counts) {\n            int cnt = p.second;\n            if (1 <= cnt && cnt <= 10) {\n                b_counts[cnt]++;\n            }\n        }\n        compute_score();\n    }\n\n    void compute_score() {\n        score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min(a[d], b_counts[d]);\n        }\n    }\n\n    // Replace line at index idx with a new random line\n    void replace(int idx) {\n        Line old_line = lines[idx];\n        Line new_line = generate_random_line();\n        lines[idx] = new_line;\n\n        for (int i = 0; i < N; ++i) {\n            ll old_val = cross_product({old_line.x1, old_line.y1}, {old_line.x2, old_line.y2}, points[i]);\n            ll new_val = cross_product({new_line.x1, new_line.y1}, {new_line.x2, new_line.y2}, points[i]);\n\n            // Since new_line is guaranteed not to pass through points, new_val != 0\n            \n            if (is_dead[i]) {\n                // Point was dead. It becomes alive if the old line was the one killing it.\n                if (old_val == 0) {\n                    // Recalculate signature from scratch\n                    Signature sig{0, 0};\n                    bool still_dead = false;\n                    for (int j = 0; j < k; ++j) {\n                        ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                        if (val == 0) {\n                            still_dead = true;\n                            break;\n                        }\n                        if (val > 0) {\n                            if (j < 64) sig.p1 |= (1ULL << j);\n                            else sig.p2 |= (1ULL << (j - 64));\n                        }\n                    }\n                    \n                    is_dead[i] = still_dead;\n                    if (!still_dead) {\n                        // Point came alive\n                        int cnt = region_counts[sig]++;\n                        // b_counts update: added 1 to region with (cnt-1) points -> now cnt points\n                        int prev_cnt = cnt - 1;\n                        if (1 <= prev_cnt && prev_cnt <= 10) b_counts[prev_cnt]--;\n                        if (1 <= cnt && cnt <= 10) b_counts[cnt]++;\n                        \n                        signatures[i] = sig;\n                    }\n                }\n                // If dead due to another line, stays dead. No change.\n            } else {\n                // Point was alive. Since new_val != 0, it stays alive.\n                // Check if side changed\n                bool old_pos = (old_val > 0);\n                bool new_pos = (new_val > 0);\n                \n                if (old_pos != new_pos) {\n                    Signature old_sig = signatures[i];\n                    Signature new_sig = old_sig;\n                    // Toggle bit at idx\n                    if (idx < 64) new_sig.p1 ^= (1ULL << idx);\n                    else new_sig.p2 ^= (1ULL << (idx - 64));\n\n                    // Remove from old region\n                    int cnt_old = region_counts[old_sig]--;\n                    // b_counts update: removed 1 from region with cnt_old points -> now cnt_old-1 points\n                    if (1 <= cnt_old && cnt_old <= 10) b_counts[cnt_old]--;\n                    if (1 <= cnt_old - 1 && cnt_old - 1 <= 10) b_counts[cnt_old - 1]++;\n\n                    // Add to new region\n                    int cnt_new = region_counts[new_sig]++;\n                    // b_counts update: added 1 to region with cnt_new-1 points -> now cnt_new points\n                    if (1 <= cnt_new - 1 && cnt_new - 1 <= 10) b_counts[cnt_new - 1]--;\n                    if (1 <= cnt_new && cnt_new <= 10) b_counts[cnt_new]++;\n\n                    signatures[i] = new_sig;\n                }\n            }\n        }\n        compute_score();\n    }\n};\n\nvoid solve() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> K;\n    for (int i = 1; i <= 10; ++i) cin >> a[i];\n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 2.8; // seconds\n\n    State best_state;\n    best_state.init(0); \n\n    // Try various K values\n    vector<int> k_candidates = {0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100};\n    \n    for (int try_k : k_candidates) {\n        if (try_k > K) continue;\n\n        // Check time\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        if (elapsed.count() > time_limit) break;\n\n        State current_state;\n        current_state.init(try_k);\n        if (current_state.score > best_state.score) {\n            best_state = current_state;\n        }\n\n        // Adjust iterations based on N (complexity O(N))\n        // N is roughly sum of d*a[d]. Max ~5000.\n        // 3000 points -> 4000 iterations is safe. \n        // We can afford more if N is smaller.\n        int base_iters = 3000;\n        int max_iters = base_iters; \n        \n        // SA params\n        double start_temp = 50.0;\n        double end_temp = 1.0;\n\n        for (int iter = 0; iter < max_iters; ++iter) {\n            now = chrono::high_resolution_clock::now();\n            elapsed = now - start_time;\n            if (elapsed.count() > time_limit) break;\n\n            double temp = start_temp + (end_temp - start_temp) * iter / max_iters;\n\n            State next_state = current_state;\n            \n            // Move: Replace\n            if (try_k > 0) {\n                int idx = rand_ll(0, try_k - 1);\n                next_state.replace(idx);\n            }\n\n            int delta = next_state.score - current_state.score;\n            \n            // Maximize score\n            if (delta > 0 || exp((double)delta / temp) > (double)rand_ll(0, 10000) / 10000.0) {\n                current_state = next_state;\n                if (current_state.score > best_state.score) {\n                    best_state = current_state;\n                }\n            }\n        }\n    }\n\n    // Output best solution found\n    cout << best_state.lines.size() << endl;\n    for (const auto& l : best_state.lines) {\n        cout << l.x1 << \" \" << l.y1 << \" \" << l.x2 << \" \" << l.y2 << endl;\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <tuple>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst int MAX_N = 61;\nint N, M;\nint center;\nbool grid[MAX_N][MAX_N];\n\n// Directions: 8 vectors\nconst int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};\nconst int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};\n\n// Helper to check perpendicularity (dot product 0)\n// dir 0 (1,0) perp to 1,3\n// dir 1 (0,1) perp to 0,2\n// dir 2 (-1,0) perp to 1,3\n// dir 3 (0,-1) perp to 0,2\n// dir 4 (1,1) perp to 5,6\n// dir 5 (1,-1) perp to 4,7\n// dir 6 (-1,1) perp to 4,7\n// dir 7 (-1,-1) perp to 5,6\nconst vector<vector<int>> perp_dirs = {\n    {1, 3}, {0, 2}, {1, 3}, {0, 2}, // Axis\n    {5, 6}, {4, 7}, {4, 7}, {5, 6}  // Diagonal\n};\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\nbool time_limit_exceeded = false;\n\nvoid check_time() {\n    auto now = chrono::high_resolution_clock::now();\n    auto duration = chrono::duration_cast<chrono::milliseconds>(now - start_time);\n    if (duration.count() > 4800) { // 4.8s limit\n        time_limit_exceeded = true;\n    }\n}\n\n// Data structures for 1D prefix sums\n// We need to manage sums for Grid Points and Segments along 4 directions\n// H, V, D1 (\\), D2 (/)\n\ntemplate <int SIZE>\nstruct PrefixManager {\n    int sums[SIZE][MAX_N + 2]; // 1-based prefix sums. sums[k][i] is sum up to i (exclusive of i if using typical logic, but we can do inclusive).\n    // Let's use: sums[k][i] is sum of elements from 0 to i-1. Range [l, r) is sums[k][r] - sums[k][l].\n    // For segments: sums[k][i] is sum of segments starting at indices < i.\n    \n    void init() {\n        for(int i=0; i<SIZE; ++i) {\n            for(int j=0; j<=N+1; ++j) sums[i][j] = 0;\n        }\n    }\n\n    // Update: add 1 to all indices >= idx on line k\n    void update_line(int k, int idx) {\n        // idx is the index of the modified element (point or segment)\n        // Prefix sums logic: sums[i] stores sum of elements [0, i).\n        // If we add 1 to element at idx, we add 1 to sums[k][idx+1 ... N]\n        for (int i = idx + 1; i <= N + 1; ++i) {\n            sums[k][i]++;\n        }\n    }\n    \n    // Query range [l, r) (points at l, l+1, ..., r-1)\n    int query(int k, int l, int r) {\n        if (l >= r) return 0;\n        return sums[k][r] - sums[k][l];\n    }\n};\n\n// We have 2 sets: Grid Points, Segments\n// For each set, 4 directions.\n// Grid Points:\n// H Rows: N rows, each length N.\n// V Cols: N cols, each length N.\n// D1 Diagonals: 2N-1 diagonals. Length varies. Max length N. Array size 2N-1.\n// D2 Diagonals: 2N-1 diagonals.\n// Segments:\n// H: N rows, N-1 segments.\n// V: N cols, N-1 segments.\n// D1: 2N-2 diagonals (main diagonals of unit squares). Max length N-1.\n// D2: 2N-2 diagonals.\n\nPrefixManager<MAX_N> grid_rows;\nPrefixManager<MAX_N> grid_cols;\nPrefixManager<2 * MAX_N> grid_d1; // y - x + (N-1)\nPrefixManager<2 * MAX_N> grid_d2; // y + x\n\nPrefixManager<MAX_N> seg_rows;\nPrefixManager<MAX_N> seg_cols;\nPrefixManager<2 * MAX_N> seg_d1;\nPrefixManager<2 * MAX_N> seg_d2;\n\n// Indices mapping for diagonals\n// For Grid D1 (y-x = const): k = y - x + (N-1). Index along diagonal: \n// Top-left start: x from max(0, k - (N-1)) to min(N-1, k). \n// Let's define index `i` along diagonal starting from the top-most or left-most point.\n// Simple mapping: `idx` = x (or y). We need a consistent way to query range sum.\n// Let's say we map point (x,y) to `x` coordinate on the diagonal `k=y-x+N-1`.\n// Then points on same diagonal have increasing x.\n// Range [x1, x2] on diagonal k corresponds to points (x, y) where x in [x1, x2].\n// Update: update_line(k, x).\n// Query: query(k, x1, x2+1).\n\n// For Grid D2 (y+x = const): k = y + x. \n// Map (x,y) to `x`.\n// Points on same diagonal have increasing x (and decreasing y).\n// Update: update_line(k, x).\n// Query: query(k, x1, x2+1).\n\n// For Seg D1 (\\): Segment connecting (x,y) and (x+1,y+1).\n// This segment lies on the same diagonal line as grid points, but \"between\" them.\n// The diagonal index is `k = y - x + (N-1)`.\n// We can map this segment to the `x` coordinate of the left/top point.\n// Valid x: 0..N-2.\n// Update: update_line(k, x).\n\n// For Seg D2 (/): Segment connecting (x+1,y) and (x,y+1).\n// Diagonal index `k = y + x`.\n// Map to `x` coordinate of the left point (the one with smaller x).\n// Valid x: 0..N-2.\n// Update: update_line(k, x).\n\n\nvoid init_prefix_structures() {\n    grid_rows.init();\n    grid_cols.init();\n    grid_d1.init();\n    grid_d2.init();\n    \n    seg_rows.init();\n    seg_cols.init();\n    seg_d1.init();\n    seg_d2.init();\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (grid[x][y]) {\n                grid_rows.update_line(y, x);\n                grid_cols.update_line(x, y);\n                int k1 = y - x + (N - 1);\n                grid_d1.update_line(k1, x);\n                int k2 = y + x;\n                grid_d2.update_line(k2, x);\n            }\n        }\n    }\n}\n\nbool is_segment_free(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    \n    // Length\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return true;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    \n    // Check bounds for segment existence\n    // Segment exists between (x1, y1) and (x2, y2) inclusive of intermediate points?\n    // A segment is a set of unit segments.\n    // e.g. (0,0) to (0,2) has segments (0,0)-(0,1) and (0,1)-(0,2).\n    \n    if (sx == 1 && sy == 0) { // Right\n        // Check horizontal segments on row y1, from x1 to x1+len-1\n        // seg_rows[k] sum of segments starting at x < idx.\n        // Segments involved: indices x1, x1+1, ..., x1+len-1.\n        // Query sum [x1, x1+len)\n        return seg_rows.query(y1, x1, x1 + len) == 0;\n    } else if (sx == -1 && sy == 0) { // Left\n        // Same, symmetry handled by x1 < x2 in query?\n        // No, x1 is start, x2 is end. We assume x1 < x2 for internal logic usually,\n        // but here x1 might be > x2.\n        // Let's normalize: lx = min(x1, x2), rx = max(x1, x2). ly = min(y1, y2)...\n        // But simpler: just use the direction.\n        // Segments are at x1, x1-1, ...\n        // Better to normalize to range [lx, rx).\n        int lx = min(x1, x2);\n        int ly = y1; // same row\n        return seg_rows.query(ly, lx, lx + len) == 0;\n    } else if (sx == 0 && sy == 1) { // Up\n        int lx = x1; // same col\n        int ly = min(y1, y2);\n        return seg_cols.query(lx, ly, ly + len) == 0;\n    } else if (sx == 0 && sy == -1) { // Down\n        int lx = x1;\n        int ly = min(y1, y2);\n        return seg_cols.query(lx, ly, ly + len) == 0;\n    } else if (sx == 1 && sy == 1) { // Up-Right (D1)\n        // Diagonal segments. k = y - x + (N-1).\n        // Index mapped to x of top-left point.\n        // Start (x1, y1), End (x2, y2). x2 = x1+len.\n        // Segments indices: x1, x1+1, ...\n        int lx = min(x1, x2);\n        int ly = min(y1, y2);\n        int k = ly - lx + (N - 1); // Same k for all\n        return seg_d1.query(k, lx, lx + len) == 0;\n    } else if (sx == -1 && sy == -1) { // Down-Left (D1 reverse)\n        int lx = min(x1, x2);\n        int ly = min(y1, y2);\n        int k = ly - lx + (N - 1);\n        return seg_d1.query(k, lx, lx + len) == 0;\n    } else if (sx == -1 && sy == 1) { // Up-Left (D2)\n        // k = y + x.\n        // Index mapped to x of left point (smaller x).\n        // Start (x1, y1). x1 > x2.\n        // Segments at x2, x2+1, ..., x1-1.\n        // Indices x in [x2, x1).\n        int lx = min(x1, x2);\n        int ly = max(y1, y2); // Top-left point\n        int k = ly + lx;\n        // Segment index corresponds to x (smaller x).\n        return seg_d2.query(k, lx, lx + len) == 0;\n    } else if (sx == 1 && sy == -1) { // Down-Right (D2 reverse)\n        int lx = min(x1, x2);\n        int ly = max(y1, y2); // Top-left\n        int k = ly + lx;\n        return seg_d2.query(k, lx, lx + len) == 0;\n    }\n    return false;\n}\n\nbool is_perimeter_clean(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len <= 1) return true; // Adjacent points, nothing in between\n    \n    int lx = min(x1, x2);\n    int rx = max(x1, x2);\n    int ly = min(y1, y2);\n    int ry = max(y1, y2);\n\n    if (y1 == y2) { // Horizontal\n        // Points at lx+1 ... rx-1 on row y1\n        return grid_rows.query(y1, lx + 1, rx) == 0;\n    } else if (x1 == x2) { // Vertical\n        return grid_cols.query(x1, ly + 1, ry) == 0;\n    } else if (x2 - x1 == y2 - y1) { // D1\n        int k = ly - lx + (N - 1);\n        // Points strictly between. x from lx+1 to rx-1.\n        return grid_d1.query(k, lx + 1, rx) == 0;\n    } else { // D2\n        int k = ry + lx; // y + x is constant. Using top-left (lx, ry)\n        // Points x from lx+1 to rx-1.\n        return grid_d2.query(k, lx + 1, rx) == 0;\n    }\n}\n\nvoid update_segment(int x1, int y1, int x2, int y2) {\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    int cx = x1, cy = y1;\n    for (int i = 0; i < len; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        \n        // Mark segment (cx, cy)-(nx, ny)\n        // Update corresponding prefix sum array\n        // Horizontal\n        if (cy == ny) {\n            int lx = min(cx, nx);\n            seg_rows.update_line(cy, lx);\n        } \n        // Vertical\n        else if (cx == nx) {\n            int ly = min(cy, ny);\n            seg_cols.update_line(cx, ly);\n        }\n        // D1\n        else if (nx == cx + 1 && ny == cy + 1) {\n            int lx = min(cx, nx);\n            int k = min(cy, ny) - lx + (N - 1);\n            seg_d1.update_line(k, lx);\n        }\n        // D1 reverse\n        else if (nx == cx - 1 && ny == cy - 1) {\n            int lx = min(cx, nx);\n            int k = min(cy, ny) - lx + (N - 1);\n            seg_d1.update_line(k, lx);\n        }\n        // D2\n        else if (nx == cx - 1 && ny == cy + 1) {\n            int lx = min(cx, nx);\n            int ly = max(cy, ny); // Top-left\n            int k = ly + lx;\n            seg_d2.update_line(k, lx);\n        }\n        // D2 reverse\n        else if (nx == cx + 1 && ny == cy - 1) {\n            int lx = min(cx, nx);\n            int ly = max(cy, ny);\n            int k = ly + lx;\n            seg_d2.update_line(k, lx);\n        }\n        \n        cx = nx; cy = ny;\n    }\n}\n\nstruct Point {\n    int x, y;\n    int weight;\n};\n\nstruct ComparePoint {\n    bool operator()(const Point& a, const Point& b) {\n        return a.weight < b.weight; // Min-heap behavior, but we want max weight.\n        // Wait, priority_queue puts largest element at top if we use less.\n        // To get largest weight at top: return a.weight < b.weight.\n    }\n};\n\nvector<tuple<int, int, int, int, int, int, int, int>> ops;\n\n// Try to place a dot at (x, y).\n// Returns true if successful.\nbool try_place(int x, int y) {\n    if (grid[x][y]) return false;\n\n    // Iterate u directions\n    for (int du = 0; du < 8; ++du) {\n        // Iterate v directions (perpendicular)\n        for (int dv : perp_dirs[du]) {\n            // Iterate lengths (try small rectangles first)\n            // Limit length search? N is small enough (60).\n            // Maybe try length 1..10 first? Then extend?\n            // For robustness, try all, but start small.\n            for (int len_u = 1; len_u < N; ++len_u) {\n                int bx = x + dx[du] * len_u;\n                int by = y + dy[du] * len_u;\n                if (bx < 0 || bx >= N || by < 0 || by >= N) break; // Out of bounds\n                if (!grid[bx][by]) continue; // Not a dot\n\n                for (int len_v = 1; len_v < N; ++len_v) {\n                    int cx_coord = x + dx[dv] * len_v; // Actually this is D (p4) based on problem description order?\n                    // Let's map:\n                    // p1 = (x,y)\n                    // u = p1 -> p2. p2 = (bx, by).\n                    // v = p1 -> p4. p4 = (dx_coord, dy_coord).\n                    // p3 = p2 + v = p4 + u = (bx, by) + (dx[dv]*len_v, dy[dv]*len_v).\n                    \n                    int dx_coord = x + dx[dv] * len_v;\n                    int dy_coord = y + dy[dv] * len_v;\n                    \n                    int cx = bx + dx[dv] * len_v;\n                    int cy = by + dy[dv] * len_v;\n\n                    if (dx_coord < 0 || dx_coord >= N || dy_coord < 0 || dy_coord >= N) break;\n                    if (cx < 0 || cx >= N || cy < 0 || cy >= N) break;\n\n                    if (!grid[dx_coord][dy_coord]) continue;\n                    if (!grid[cx][cy]) continue;\n\n                    // Check segments\n                    // p1-p2, p2-p3, p3-p4, p4-p1\n                    if (!is_segment_free(x, y, bx, by)) continue;\n                    if (!is_segment_free(bx, by, cx, cy)) continue;\n                    if (!is_segment_free(cx, cy, dx_coord, dy_coord)) continue;\n                    if (!is_segment_free(dx_coord, dy_coord, x, y)) continue;\n\n                    // Check clean perimeter\n                    // No dots on perimeter except vertices\n                    if (!is_perimeter_clean(x, y, bx, by)) continue;\n                    if (!is_perimeter_clean(bx, by, cx, cy)) continue;\n                    if (!is_perimeter_clean(cx, cy, dx_coord, dy_coord)) continue;\n                    if (!is_perimeter_clean(dx_coord, dy_coord, x, y)) continue;\n\n                    // Found!\n                    \n                    // Apply updates\n                    grid[x][y] = true;\n                    grid_rows.update_line(y, x);\n                    grid_cols.update_line(x, y);\n                    grid_d1.update_line(y - x + (N - 1), x);\n                    grid_d2.update_line(y + x, x);\n\n                    update_segment(x, y, bx, by);\n                    update_segment(bx, by, cx, cy);\n                    update_segment(cx, cy, dx_coord, dy_coord);\n                    update_segment(dx_coord, dy_coord, x, y);\n\n                    ops.emplace_back(x, y, bx, by, cx, cy, dx_coord, dy_coord);\n                    return true;\n                }\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    center = (N - 1) / 2;\n    \n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = false;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        grid[x][y] = true;\n    }\n    \n    init_prefix_structures();\n    \n    priority_queue<Point, vector<Point>, ComparePoint> pq;\n    \n    // Push all empty points\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!grid[i][j]) {\n                int dist_sq = (i - center) * (i - center) + (j - center) * (j - center);\n                pq.push({i, j, dist_sq});\n            }\n        }\n    }\n    \n    int total_processed = 0;\n    \n    while (!pq.empty() && !time_limit_exceeded) {\n        check_time();\n        \n        Point p = pq.top();\n        pq.pop();\n        \n        // If already filled (by previous operation), skip\n        if (grid[p.x][p.y]) continue;\n        \n        if (try_place(p.x, p.y)) {\n            // Success! Push neighbors back to PQ to handle dependencies\n            // Neighbors are points that might be unblocked by this new dot.\n            // Range: +/- 10\n            int R = 10;\n            int x_min = max(0, p.x - R);\n            int x_max = min(N - 1, p.x + R);\n            int y_min = max(0, p.y - R);\n            int y_max = min(N - 1, p.y + R);\n            \n            for (int nx = x_min; nx <= x_max; ++nx) {\n                for (int ny = y_min; ny <= y_max; ++ny) {\n                    if (!grid[nx][ny]) {\n                        int dist_sq = (nx - center) * (nx - center) + (ny - center) * (ny - center);\n                        pq.push({nx, ny, dist_sq});\n                    }\n                }\n            }\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \" \"\n             << get<4>(op) << \" \" << get<5>(op) << \" \"\n             << get<6>(op) << \" \" << get<7>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int H = 10;\nconst int W = 10;\n\nstruct Solver {\n    vector<vector<int>> board;\n    vector<int> flavors;\n    int step;\n    // Fixed potential targets (gravity centers)\n    // T_BC: Bottom Center (Easy to reach, wide area)\n    // T_TL: Top Left\n    // T_TR: Top Right\n    pair<int, int> T_BC = {9, 4};\n    pair<int, int> T_TL = {0, 0};\n    pair<int, int> T_TR = {0, 9};\n    \n    // Actual targets for flavors 1, 2, 3 (0-indexed in vector)\n    vector<pair<int, int>> targets;\n    \n    // Weight for the distance penalty\n    const double W_PENALTY = 3.0;\n\n    Solver(vector<int> f) : flavors(f), step(0) {\n        board.assign(H, vector<int>(W, 0));\n        \n        // Calculate counts of each flavor\n        vector<int> counts(3, 0);\n        for (int x : f) counts[x-1]++;\n        \n        // Create list of (flavor_index, count) and sort by count descending\n        vector<pair<int, int>> flavor_counts = {{0, counts[0]}, {1, counts[1]}, {2, counts[2]}};\n        sort(flavor_counts.begin(), flavor_counts.end(), [](const auto& a, const auto& b) {\n            return a.second > b.second;\n        });\n        \n        // Assign targets adaptively:\n        // Largest flavor gets Bottom Center (spacious, easy to reach)\n        // Other flavors get Top corners\n        targets.resize(3);\n        targets[flavor_counts[0].first] = T_BC;\n        targets[flavor_counts[1].first] = T_TL;\n        targets[flavor_counts[2].first] = T_TR;\n    }\n\n    // Maps 1-based empty cell index to 0-based coordinates\n    pair<int, int> get_pos(int p) {\n        int cnt = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (board[i][j] == 0) {\n                    cnt++;\n                    if (cnt == p) return {i, j};\n                }\n            }\n        }\n        return {-1, -1}; \n    }\n\n    // Simulates the tilting operation\n    vector<vector<int>> tilt(vector<vector<int>> b, int dir) {\n        if (dir == 0) { // Forward (Up)\n            for (int j = 0; j < W; ++j) {\n                int wi = 0;\n                for (int i = 0; i < H; ++i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // Backward (Down)\n            for (int j = 0; j < W; ++j) {\n                int wi = H - 1;\n                for (int i = H - 1; i >= 0; --i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // Left\n            for (int i = 0; i < H; ++i) {\n                int wj = 0;\n                for (int j = 0; j < W; ++j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < H; ++i) {\n                int wj = W - 1;\n                for (int j = W - 1; j >= 0; --j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj--;\n                    }\n                }\n            }\n        }\n        return b;\n    }\n\n    // Evaluation function\n    double evaluate(const vector<vector<int>>& b) {\n        // Component Score: Sum of squares of connected component sizes\n        int sum_sq = 0;\n        vector<vector<bool>> visited(H, vector<bool>(W, false));\n        \n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0 && !visited[i][j]) {\n                    queue<pair<int,int>> q;\n                    q.push({i,j});\n                    visited[i][j] = true;\n                    int size = 0;\n                    while (!q.empty()) {\n                        auto [r, c] = q.front(); q.pop();\n                        size++;\n                        int dr[] = {0, 0, 1, -1};\n                        int dc[] = {1, -1, 0, 0};\n                        for (int k = 0; k < 4; ++k) {\n                            int nr = r + dr[k];\n                            int nc = c + dc[k];\n                            if (nr >= 0 && nr < H && nc >= 0 && nc < W && !visited[nr][nc] && b[nr][nc] == b[r][c]) {\n                                visited[nr][nc] = true;\n                                q.push({nr,nc});\n                            }\n                        }\n                    }\n                    sum_sq += size * size;\n                }\n            }\n        }\n\n        // Distance Penalty: Pull candies towards their assigned targets\n        double penalty = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0) {\n                    int flavor_idx = b[i][j] - 1;\n                    penalty += abs(i - targets[flavor_idx].first) + abs(j - targets[flavor_idx].second);\n                }\n            }\n        }\n        \n        return (double)sum_sq - W_PENALTY * penalty;\n    }\n\n    char solve(int p) {\n        // Place the new candy\n        auto [r, c] = get_pos(p);\n        board[r][c] = flavors[step];\n        \n        double best_score = -1e18;\n        int best_dir = -1;\n        \n        // Greedy search: try all 4 moves\n        for (int d = 0; d < 4; ++d) {\n            auto next_board = tilt(board, d);\n            double score = evaluate(next_board);\n            if (score > best_score) {\n                best_score = score;\n                best_dir = d;\n            }\n        }\n        \n        // Apply the chosen move\n        board = tilt(board, best_dir);\n        step++;\n        \n        if (best_dir == 0) return 'F';\n        if (best_dir == 1) return 'B';\n        if (best_dir == 2) return 'L';\n        return 'R';\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) cin >> f[i];\n    \n    Solver solver(f);\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        if (t < 99) {\n            char out = solver.solve(p);\n            cout << out << endl;\n            cout.flush();\n        } else {\n            solver.solve(p);\n        }\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nmt19937 rng(42); \n\n// Estimate expected errors E for given N\ndouble estimate_expected_errors(int M, double eps, int N) {\n    int P = N * (N - 1) / 2;\n    if (P < M) return 100.0; \n\n    double step = (double)P / (M - 1);\n    double gap_observed = step * (1.0 - 2.0 * eps);\n    double sigma = sqrt((double)P * eps * (1.0 - eps));\n    \n    if (sigma < 1e-9) return 0.0;\n    \n    double z = (gap_observed / 2.0) / sigma;\n    double p_err = 0.5 * erfc(z / sqrt(2.0));\n    return (M - 1) * p_err * 100.0;\n}\n\n// Choose N to maximize Score = 0.9^E / N\nint choose_N(int M, double eps) {\n    int best_N = 100;\n    double best_score = -1.0;\n    \n    int min_N = (int)ceil((1.0 + sqrt(1.0 + 8.0 * M)) / 2.0);\n    if (min_N < 4) min_N = 4;\n\n    for (int N = min_N; N <= 100; ++N) {\n        double E = estimate_expected_errors(M, eps, N);\n        double score = pow(0.9, E) / (double)N;\n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n        }\n    }\n    return best_N;\n}\n\nstring generate_graph(int N, int target_edges) {\n    int P = N * (N - 1) / 2;\n    string graph(P, '0');\n    vector<int> indices(P);\n    iota(indices.begin(), indices.end(), 0);\n    shuffle(indices.begin(), indices.end(), rng);\n    for (int i = 0; i < target_edges; ++i) {\n        graph[indices[i]] = '1';\n    }\n    return graph;\n}\n\n// Extract degree sequence\nvector<int> get_degrees(int N, const string& s) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    int N = choose_N(M, eps);\n    int P = N * (N - 1) / 2;\n    \n    // Precompute data for generated graphs\n    vector<string> graphs(M);\n    // Expected degree sequence for each graph\n    vector<vector<double>> exp_deg_seq(M); \n    // Expected wedge count for each graph\n    vector<double> exp_wedge_count(M); \n\n    // Common terms for expectation calculation\n    // E[d_H | d_G] = d_G * (1-2*eps) + (N-1)*eps\n    double slope = (1.0 - 2.0 * eps);\n    double intercept = (N - 1) * eps;\n    \n    // Var[d_H] = (N-1) * eps * (1-eps) (constant for all vertices)\n    double var_deg = (N - 1) * eps * (1.0 - eps);\n    \n    // E[Wedge_H | d_G] = Sum_v E[C(d_H(v), 2)]\n    // E[C(d, 2)] = 0.5 * (E[d^2] - E[d]) = 0.5 * (Var(d) + E[d]^2 - E[d])\n    // Term: 0.5 * (var_deg + (slope*d + intercept)^2 - (slope*d + intercept))\n\n    for (int i = 0; i < M; ++i) {\n        int target_edges = (int)round((double)i * P / (M - 1));\n        graphs[i] = generate_graph(N, target_edges);\n        \n        vector<int> deg = get_degrees(N, graphs[i]);\n        \n        exp_deg_seq[i].resize(N);\n        exp_wedge_count[i] = 0.0;\n        \n        for (int j = 0; j < N; ++j) {\n            int d = deg[j];\n            double mu = d * slope + intercept;\n            exp_deg_seq[i][j] = mu;\n            \n            // Accumulate expected wedge contribution\n            // 0.5 * (var_deg + mu*mu - mu)\n            exp_wedge_count[i] += 0.5 * (var_deg + mu * mu - mu);\n        }\n    }\n    \n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    cout << flush;\n    \n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        \n        vector<int> deg_H = get_degrees(N, H);\n        \n        // Calculate observed wedge count for H\n        // Wedge = sum C(d, 2)\n        long long wedge_H = 0;\n        for (int d : deg_H) {\n            wedge_H += (long long)d * (d - 1) / 2;\n        }\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            // Primary metric: L2 distance on expected degree sequences\n            double dist_deg = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - exp_deg_seq[k][j];\n                dist_deg += diff * diff;\n            }\n            \n            // Secondary metric: Absolute difference in expected wedge count\n            // We combine them. Wedge count is O(N^2), degree distance is O(N).\n            // To balance, we scale wedge distance down or rely on it for tie-breaking.\n            // Given N~50, wedge~1000. Dist_deg ~ 100. \n            // So squared wedge diff would be huge if we just added them.\n            // Let's use a small weight for wedge distance.\n            \n            double wedge_diff = wedge_H - exp_wedge_count[k];\n            double dist_total = dist_deg + 0.001 * wedge_diff * wedge_diff; // 0.001 is an arbitrary heuristic weight\n            \n            if (dist_total < min_dist) {\n                min_dist = dist_total;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <climits>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\n// Global variables for efficient access\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<pair<int, int>>> adj; // (neighbor, edge_id)\nvector<int> edge_day; // -1 if not assigned, otherwise day index (0-based)\nvector<long long> load; // Sum of usage of edges assigned to each day\nvector<int> day_size; // Number of edges assigned to each day\nvector<int> visited; // For connectivity check\nint iter_id = 0;\n\n// Check if graph remains connected after removing edges assigned to day_k\n// and the hypothetically removed edge 'check_eid'.\n// Using BFS from node 0.\nbool is_connected(int day_k, int check_eid) {\n    iter_id++;\n    queue<int> q;\n    q.push(0);\n    visited[0] = iter_id;\n    int count = 1;\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n\n        // Early exit if we have visited all nodes\n        if (count == N) return true;\n\n        for (auto& [v, eid] : adj[u]) {\n            if (visited[v] == iter_id) continue;\n\n            // Check if this edge is effectively removed\n            // It is removed if it's scheduled for day_k, or if it's the edge we are currently checking\n            if (edge_day[eid] == day_k || eid == check_eid) continue;\n\n            visited[v] = iter_id;\n            count++;\n            q.push(v);\n        }\n    }\n    return count == N;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> D >> K;\n\n    edges.resize(M);\n    adj.resize(N);\n\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        adj[edges[i].u].emplace_back(edges[i].v, i);\n        adj[edges[i].v].emplace_back(edges[i].u, i);\n    }\n\n    // Consume coordinates (not needed for algorithm)\n    for (int i = 0; i < N; ++i) {\n        double x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Calculate Edge Usage (Centrality)\n    // Usage = number of times edge appears in any shortest path\n    vector<long long> usage(M, 0);\n\n    for (int s = 0; s < N; ++s) {\n        vector<long long> dist(N, INF);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                long long w = edges[eid].w;\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n\n        // Count contributions to usage\n        for (int i = 0; i < M; ++i) {\n            int u = edges[i].u;\n            int v = edges[i].v;\n            long long w = edges[i].w;\n            if (dist[u] + w == dist[v]) usage[i]++;\n            if (dist[v] + w == dist[u]) usage[i]++;\n        }\n    }\n\n    // 2. Sort edges by usage (descending) to handle critical edges first\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return usage[a] > usage[b];\n    });\n\n    // 3. Initialize State\n    edge_day.assign(M, -1);\n    load.assign(D, 0);\n    day_size.assign(D, 0);\n    visited.assign(N, 0);\n\n    // 4. Greedy Assignment\n    for (int i = 0; i < M; ++i) {\n        int eid = edge_order[i];\n        long long e_usage = usage[eid];\n\n        // Create a list of days sorted by current load (ascending)\n        // We want to assign this edge to the day that causes the least \"frustration\" so far\n        vector<int> day_indices(D);\n        iota(day_indices.begin(), day_indices.end(), 0);\n        sort(day_indices.begin(), day_indices.end(), [&](int a, int b) {\n            if (load[a] != load[b]) return load[a] < load[b];\n            return day_size[a] < day_size[b]; // Tie-breaker: size\n        });\n\n        bool assigned = false;\n        for (int d : day_indices) {\n            if (day_size[d] >= K) continue;\n\n            // Check if adding this edge to day 'd' disconnects the graph\n            if (is_connected(d, eid)) {\n                edge_day[eid] = d;\n                load[d] += e_usage;\n                day_size[d]++;\n                assigned = true;\n                break;\n            }\n        }\n\n        // Fallback: If no day maintains connectivity (e.g., strict constraints),\n        // we must assign it to a valid day anyway to satisfy output format and constraints.\n        // We choose the day with minimum load that has space.\n        if (!assigned) {\n            int best_d = -1;\n            long long min_load = LLONG_MAX;\n            \n            for (int d = 0; d < D; ++d) {\n                if (day_size[d] < K) {\n                    if (load[d] < min_load) {\n                        min_load = load[d];\n                        best_d = d;\n                    }\n                }\n            }\n\n            // Assign to the best found day\n            if (best_d != -1) {\n                edge_day[eid] = best_d;\n                load[best_d] += e_usage;\n                day_size[best_d]++;\n            } else {\n                // This should theoretically not happen given problem constraints (slack),\n                // but as a last resort, assign to day 0 (or first available) ignoring K? \n                // No, we MUST respect K. If all full, input is invalid or logic error.\n                // Given constraints ceil(M/D) < K, there will always be space.\n            }\n        }\n    }\n\n    // 5. Output\n    for (int i = 0; i < M; ++i) {\n        if (i > 0) cout << \" \";\n        cout << edge_day[i] + 1; // Convert to 1-based index\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n#include <set>\n#include <map>\n\nusing namespace std;\n\nconst int D_MAX = 14;\nconst int XY_MAX = 14;\n\n// Timer for managing execution time\nclass Timer {\n    chrono::system_clock::time_point start;\npublic:\n    Timer() : start(chrono::system_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::system_clock::now() - start).count();\n    }\n};\n\n// Global state\nint D;\nbool f[2][D_MAX][D_MAX]; // Front silhouette: z, x\nbool r[2][D_MAX][D_MAX]; // Right silhouette: z, y\n\n// Grid representation of the two objects\n// grid[id][z][x][y] = 1 if occupied\n// Using bitset for efficiency and easy copy/overlap\nbitset<XY_MAX * XY_MAX> grid[2][D_MAX]; // Flattened x,y for z layer. Index = x*D + y\n\n// Helper structures for fast operations during SA\nvector<int> active_x[2][D_MAX];\nvector<int> active_y[2][D_MAX];\nint y_of_x[2][D_MAX][D_MAX]; // Mapping x -> y for active cells in a layer\nint cnt_of_y[2][D_MAX][D_MAX]; // Count of x mapped to y\n\nint current_overlap = 0;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Coordinates structure\nstruct Point {\n    int x, y, z;\n};\n\nint get_idx(int x, int y) {\n    return x * D + y;\n}\n\nvoid init() {\n    // Read D\n    cin >> D;\n    \n    // Read silhouettes\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int x = 0; x < D; ++x) {\n                f[i][z][x] = (s[x] == '1');\n                if (f[i][z][x]) active_x[i][z].push_back(x);\n            }\n        }\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int y = 0; y < D; ++y) {\n                r[i][z][y] = (s[y] == '1');\n                if (r[i][z][y]) active_y[i][z].push_back(y);\n            }\n        }\n    }\n}\n\nvoid construct_initial(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        \n        int kx = xs.size();\n        int ky = ys.size();\n        \n        // Reset mappings\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n        \n        if (kx == 0 || ky == 0) continue;\n        \n        // Greedy matching to maximize initial overlap potential\n        // If kx >= ky, match first ky xs to all ys, remaining xs to first y\n        // If kx < ky, match all xs to first ky ys. But remaining ys must be covered.\n        // Wait, if kx < ky, we must cover all ys.\n        // Basic logic: create a set of pairs (x, y) such that all x in xs, all y in ys are covered.\n        \n        // Simplified logic for minimal volume intersection\n        // We just need a valid configuration. SA will optimize it.\n        \n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            for (int i = ky; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[0]; // Map to first y\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                int x = xs[i];\n                int y = ys[i];\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n                grid[obj_id][z].set(get_idx(x, y));\n            }\n            // Cover remaining ys. Reuse the first x (index 0)\n            for (int i = kx; i < ky; ++i) {\n                int x = xs[0];\n                int y = ys[i];\n                // Add pair (x, y)\n                // Note: x=0 might already have a pair.\n                y_of_x[obj_id][z][x] = y; // Overwrite? No, we just add to grid and counts.\n                // y_of_x only stores ONE y for x, but an x can map to multiple y if needed?\n                // Our structure assumes 1-to-1 or 1-to-many.\n                // In this case, x=0 maps to many y.\n                // y_of_x needs to support list of y, or we just iterate to find neighbors.\n                // For SA, we used y_of_x to find current y. If x maps to multiple, this fails.\n                // So we should stick to matchings or near-matchings.\n                // Since kx < ky, we have fewer columns than rows. Some columns MUST cover multiple rows.\n                // Let's change logic: use a matching where possible, then add extra edges.\n                // Since k is small, let's just make sure every x maps to at least 1 y, and every y is mapped by some x.\n                // This is a bipartite graph cover.\n                // Minimal edges = max(kx, ky).\n                // Structure: A spanning tree structure on the bipartite graph of xs and ys.\n                // Since xs and ys are sets of integers, we can sort them and try to match proximity.\n            }\n        }\n        \n        // Re-doing the construction more robustly for the kx < ky case\n        // and handling the \"multiple y per x\" issue.\n        // Let's store edges explicitly?\n        // Given D=14, we can just store a vector of pairs per layer.\n        // But SA needs O(1) modification.\n        // Let's allow \"y_of_x\" to be just one representative y, but counts to be correct.\n        // Actually, if x maps to multiple y, which one do we move?\n        // We can restrict to matchings (kx=ky) or star graphs (one central x or one central y).\n        // Let's use the star graph approach which covers all minimal volumes.\n        \n        // Clear again\n        for(int x : xs) y_of_x[obj_id][z][x] = -1;\n        for(int y : ys) cnt_of_y[obj_id][z][y] = 0;\n        grid[obj_id][z].reset();\n\n        if (kx >= ky) {\n            // Star centered at ys.\n            // Each y gets at least one distinct x.\n            // Remaining x connect to y[0].\n            for(int i=0; i<ky; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            for(int i=ky; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y; \n                // If y_of_x already had this y from previous loop, it's fine.\n                // It just means x maps to y.\n                cnt_of_y[obj_id][z][y]++;\n            }\n        } else {\n            // Star centered at xs.\n            // Each x gets at least one distinct y.\n            // Remaining y connect to x[0].\n            for(int i=0; i<kx; i++) {\n                int x = xs[i];\n                int y = ys[i];\n                grid[obj_id][z].set(get_idx(x,y));\n                y_of_x[obj_id][z][x] = y;\n                cnt_of_y[obj_id][z][y]++;\n            }\n            // Remaining ys\n            for(int i=kx; i<ky; i++) {\n                int y = ys[i];\n                int x = xs[0];\n                grid[obj_id][z].set(get_idx(x,y));\n                // x[0] already maps to some y. We add another edge.\n                // y_of_x[x[0]] points to ys[0]. It doesn't capture this new edge.\n                // So y_of_x is insufficient for \"many y per x\".\n                // We need a list of edges.\n                // But D=14. Max edges per layer ~14.\n                // Let's store vector<pair<int,int>> cells[obj][z].\n                // SA moves:\n                // Pick an edge (x,y). Change to (x, y_new).\n                // If cnt[y] > 1, valid.\n                // If cnt[y] == 1, must swap with (x2, y_new).\n                // This works with edge lists.\n                \n                // Let's switch to edge lists representation.\n            }\n        }\n    }\n}\n\n// Let's use a unified representation that supports the move logic perfectly.\n// We will maintain:\n// - vector<pair<int, int>> cells[2][D_MAX];  List of active cells (x,y) at layer z.\n// - This is sufficient to reconstruct the grid.\n// - Counts are derived.\n// - \"Pick x, move y\" logic:\n//   We need to find if there is an edge (x, y_curr).\n//   With vector, searching is O(N).\n//   N is small (<=14). O(14) is fine.\n//   Swapping is also O(N).\n\nvector<pair<int, int>> layer_cells[2][D_MAX];\n\nvoid build_initial_with_edge_list(int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        layer_cells[obj_id][z].clear();\n        vector<int>& xs = active_x[obj_id][z];\n        vector<int>& ys = active_y[obj_id][z];\n        int kx = xs.size();\n        int ky = ys.size();\n        \n        if (kx == 0 || ky == 0) continue;\n\n        if (kx >= ky) {\n            for (int i = 0; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = ky; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[0]});\n            }\n        } else {\n            for (int i = 0; i < kx; ++i) {\n                layer_cells[obj_id][z].push_back({xs[i], ys[i]});\n            }\n            for (int i = kx; i < ky; ++i) {\n                layer_cells[obj_id][z].push_back({xs[0], ys[i]});\n            }\n        }\n        \n        // Update bitset\n        grid[obj_id][z].reset();\n        for (auto& p : layer_cells[obj_id][z]) {\n            grid[obj_id][z].set(get_idx(p.first, p.second));\n        }\n    }\n}\n\nvoid solve() {\n    init();\n    \n    // Construct initial states\n    build_initial_with_edge_list(0);\n    build_initial_with_edge_list(1);\n    \n    // Calculate initial overlap\n    current_overlap = 0;\n    for (int z = 0; z < D; ++z) {\n        current_overlap += (grid[0][z] & grid[1][z]).count();\n    }\n    \n    // Simulated Annealing\n    double start_time = Timer().elapsed();\n    double time_limit = 5.8; // leave margin\n    double temp_start = 100.0;\n    double temp_end = 1e-4;\n    int iter = 0;\n    \n    // Helper to calculate counts from cells\n    auto get_counts = [&](int obj, int z) {\n        vector<int> cnt(D, 0);\n        for (auto& p : layer_cells[obj][z]) cnt[p.second]++;\n        return cnt;\n    };\n    \n    while (true) {\n        double now = Timer().elapsed();\n        if (now - start_time > time_limit) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, (now - start_time) / time_limit);\n        \n        // Pick operation\n        // 0: modify obj 0, 1: modify obj 1\n        int obj = (rng() % 2);\n        int z = rng() % D;\n        \n        vector<pair<int,int>>& cells = layer_cells[obj][z];\n        if (cells.empty()) continue;\n        \n        // Select a random edge to modify\n        int idx = rng() % cells.size();\n        int x_a = cells[idx].first;\n        int y_curr = cells[idx].second;\n        \n        // Pick target y\n        // Must be active y in silhouettes\n        vector<int>& active_ys = active_y[obj][z];\n        if (active_ys.empty()) continue;\n        int y_new = active_ys[rng() % active_ys.size()];\n        \n        if (y_new == y_curr) continue;\n        \n        // Check feasibility\n        auto counts = get_counts(obj, z);\n        \n        // Proposed change: move (x_a, y_curr) to (x_a, y_new)\n        // Valid if counts[y_curr] > 1 OR we swap with another edge ending at y_new\n        \n        bool valid = false;\n        int idx_swap = -1;\n        \n        if (counts[y_curr] > 1) {\n            valid = true;\n        } else {\n            // Must swap\n            // Find edge (x_b, y_new)\n            for (int i = 0; i < cells.size(); ++i) {\n                if (cells[i].second == y_new) {\n                    idx_swap = i;\n                    break;\n                }\n            }\n            if (idx_swap != -1) valid = true;\n        }\n        \n        if (!valid) continue;\n        \n        // Calculate Delta Overlap\n        int delta = 0;\n        int other = 1 - obj;\n        \n        // Remove (x_a, y_curr)\n        int pos1 = get_idx(x_a, y_curr);\n        if (grid[other][z].test(pos1)) delta--;\n        \n        // Add (x_a, y_new)\n        int pos2 = get_idx(x_a, y_new);\n        if (grid[other][z].test(pos2)) delta++;\n        \n        if (idx_swap != -1) {\n            // Remove (x_b, y_new)\n            int x_b = cells[idx_swap].first;\n            int pos3 = get_idx(x_b, y_new);\n            if (grid[other][z].test(pos3)) delta--;\n            \n            // Add (x_b, y_curr)\n            int pos4 = get_idx(x_b, y_curr);\n            if (grid[other][z].test(pos4)) delta++;\n        }\n        \n        // Acceptance\n        if (delta >= 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n            // Apply change\n            if (idx_swap == -1) {\n                // Simple move\n                cells[idx].second = y_new;\n            } else {\n                // Swap\n                int x_b = cells[idx_swap].first;\n                cells[idx].second = y_new;\n                cells[idx_swap].second = y_curr;\n            }\n            \n            // Update grid bitset\n            grid[obj][z].reset();\n            for (auto& p : cells) {\n                grid[obj][z].set(get_idx(p.first, p.second));\n            }\n            \n            current_overlap += delta;\n        }\n    }\n    \n    // Final block construction\n    // We need to assign Block IDs.\n    \n    // 1. Identify shared cells\n    vector<int> b1(D*D*D, 0);\n    vector<int> b2(D*D*D, 0);\n    \n    // Helper to convert x,y,z to linear index\n    auto lin = [&](int x, int y, int z) { return x * D * D + y * D + z; };\n    \n    // Map to store block IDs\n    // We will perform BFS to find connected components\n    int current_id = 0;\n    \n    // Visited arrays\n    int visited[2][D_MAX][D_MAX][D_MAX]; // 0=unvisited, 1=visited\n    for(int i=0; i<2; ++i) for(int z=0; z<D; ++z) for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) visited[i][z][x][y] = 0;\n\n    // First process Shared Components\n    // Cells that are in both grid[0] and grid[1]\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && grid[1][z].test(get_idx(x,y))) {\n                    if (visited[0][z][x][y] == 0) { // Not yet assigned\n                        // Start BFS for shared component\n                        current_id++;\n                        queue<Point> q;\n                        q.push({x,y,z});\n                        visited[0][z][x][y] = current_id;\n                        visited[1][z][x][y] = current_id; // Mark visited in both\n                        \n                        while (!q.empty()) {\n                            Point p = q.front(); q.pop();\n                            int idx = lin(p.x, p.y, p.z);\n                            b1[idx] = current_id;\n                            b2[idx] = current_id;\n                            \n                            // Neighbors: 6 directions\n                            int dx[6] = {1, -1, 0, 0, 0, 0};\n                            int dy[6] = {0, 0, 1, -1, 0, 0};\n                            int dz[6] = {0, 0, 0, 0, 1, -1};\n                            \n                            for (int k = 0; k < 6; ++k) {\n                                int nx = p.x + dx[k];\n                                int ny = p.y + dy[k];\n                                int nz = p.z + dz[k];\n                                \n                                if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                    // Check if cell is shared and unvisited\n                                    if (visited[0][nz][nx][ny] == 0 && \n                                        grid[0][nz].test(get_idx(nx, ny)) && \n                                        grid[1][nz].test(get_idx(nx, ny))) {\n                                        visited[0][nz][nx][ny] = current_id;\n                                        visited[1][nz][nx][ny] = current_id;\n                                        q.push({nx, ny, nz});\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Second process Unique Components for Object 1\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[0][z].test(get_idx(x,y)) && visited[0][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b1[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[0][nz][nx][ny] == 0 && grid[0][nz].test(get_idx(nx, ny))) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Third process Unique Components for Object 2\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (grid[1][z].test(get_idx(x,y)) && visited[1][z][x][y] == 0) {\n                    current_id++;\n                    queue<Point> q;\n                    q.push({x,y,z});\n                    visited[1][z][x][y] = current_id;\n                    \n                    while (!q.empty()) {\n                        Point p = q.front(); q.pop();\n                        int idx = lin(p.x, p.y, p.z);\n                        b2[idx] = current_id;\n                        \n                        int dx[6] = {1, -1, 0, 0, 0, 0};\n                        int dy[6] = {0, 0, 1, -1, 0, 0};\n                        int dz[6] = {0, 0, 0, 0, 1, -1};\n                        \n                        for (int k = 0; k < 6; ++k) {\n                            int nx = p.x + dx[k];\n                            int ny = p.y + dy[k];\n                            int nz = p.z + dz[k];\n                            \n                            if (0 <= nx && nx < D && 0 <= ny && ny < D && 0 <= nz && nz < D) {\n                                if (visited[1][nz][nx][ny] == 0 && grid[1][nz].test(get_idx(nx, ny))) {\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx, ny, nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    int n = current_id;\n    \n    // Output\n    cout << n << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b1[i];\n    }\n    cout << endl;\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i > 0) cout << \" \";\n        cout << b2[i];\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <tuple>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Solver {\n    int N, M, K;\n    vector<pair<int, int>> coords;\n    vector<tuple<int, int, long long>> edges;\n    vector<pair<int, int>> residents;\n    vector<vector<long long>> dist_nodes; \n    vector<vector<int>> dist_res; \n    vector<int> P;\n    vector<int> B;\n    \n    // Heuristic data\n    vector<vector<int>> resident_order; // Sorted vertices by distance for each resident\n    vector<int> assign; // Assign resident k to vertex assign[k]\n    vector<bool> active;\n\n    Solver(int n, int m, int k) : N(n), M(m), K(k) {\n        coords.resize(N);\n        edges.resize(M);\n        residents.resize(K);\n        dist_nodes.assign(N, vector<long long>(N, 1e18));\n        dist_res.assign(N, vector<int>(K));\n        P.assign(N, 0);\n        B.assign(M, 0);\n        resident_order.assign(K, vector<int>(N));\n        assign.assign(K, -1);\n        active.assign(N, false);\n    }\n\n    void solve() {\n        // 1. Floyd-Warshall\n        for (int i = 0; i < N; ++i) dist_nodes[i][i] = 0;\n        for (auto& e : edges) {\n            int u, v;\n            long long w;\n            tie(u, v, w) = e;\n            u--; v--;\n            if (w < dist_nodes[u][v]) {\n                dist_nodes[u][v] = w;\n                dist_nodes[v][u] = w;\n            }\n        }\n        for (int k = 0; k < N; ++k) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (dist_nodes[i][k] + dist_nodes[k][j] < dist_nodes[i][j]) {\n                        dist_nodes[i][j] = dist_nodes[i][k] + dist_nodes[k][j];\n                    }\n                }\n            }\n        }\n\n        // 2. Precompute resident distances and sort\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < K; ++k) {\n                long long dx = (long long)coords[i].first - residents[k].first;\n                long long dy = (long long)coords[i].second - residents[k].second;\n                dist_res[i][k] = (int)round(sqrt((double)dx*dx + dy*dy));\n            }\n        }\n        \n        vector<int> temp_nodes(N);\n        iota(temp_nodes.begin(), temp_nodes.end(), 0);\n        for (int k = 0; k < K; ++k) {\n            sort(temp_nodes.begin(), temp_nodes.end(), [&](int a, int b) {\n                return dist_res[a][k] < dist_res[b][k];\n            });\n            resident_order[k] = temp_nodes;\n        }\n\n        // 3. Helper functions\n        auto calc_mst_cost = [&]() {\n            long long cost = 0;\n            vector<bool> in_mst(N, false);\n            vector<long long> min_dist(N, 1e18);\n            min_dist[0] = 0;\n            for (int i = 0; i < N; ++i) {\n                int u = -1;\n                for (int j = 0; j < N; ++j) {\n                    if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                        u = j;\n                    }\n                }\n                if (u == -1) break;\n                in_mst[u] = true;\n                cost += min_dist[u];\n                for (int v = 0; v < N; ++v) {\n                    if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                        min_dist[v] = dist_nodes[u][v];\n                    }\n                }\n            }\n            return cost;\n        };\n\n        auto calc_node_cost = [&]() {\n            long long cost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (active[i]) {\n                    cost += (long long)P[i] * P[i];\n                }\n            }\n            return cost;\n        };\n\n        auto reassign = [&]() {\n            // Assign residents to nearest active vertex\n            // Also calculate P\n            // Returns true if any resident is uncovered (>5000)\n            bool uncovered = false;\n            fill(P.begin(), P.end(), 0);\n            for (int k = 0; k < K; ++k) {\n                for (int v : resident_order[k]) {\n                    if (active[v]) {\n                        assign[k] = v;\n                        int d = dist_res[v][k];\n                        if (d > P[v]) P[v] = d;\n                        if (d > 5000) uncovered = true;\n                        break;\n                    }\n                }\n            }\n            return uncovered;\n        };\n\n        // 4. Initial Solution (Greedy Coverage)\n        active[0] = true;\n        bool valid = reassign();\n        \n        // Add vertices until valid\n        while (valid) {\n            int best_u = -1;\n            int best_k = -1;\n            int max_dist = -1;\n            \n            // Find the resident with max distance to nearest active\n            for (int k = 0; k < K; ++k) {\n                int d = dist_res[assign[k]][k];\n                if (d > max_dist) {\n                    max_dist = d;\n                    best_k = k;\n                }\n            }\n            \n            // Find vertex u that covers best_k best\n            for (int u : resident_order[best_k]) {\n                if (!active[u]) {\n                    best_u = u;\n                    break;\n                }\n            }\n            \n            if (best_u != -1) {\n                active[best_u] = true;\n                valid = reassign();\n            } else {\n                // Should not happen given problem constraints\n                break; \n            }\n        }\n\n        long long current_edge_cost = calc_mst_cost();\n        long long current_node_cost = calc_node_cost();\n        long long total_cost = current_edge_cost + current_node_cost;\n\n        // 5. Optimization Loop\n        mt19937 rng(20240520);\n        \n        // Run multiple passes of Add/Remove\n        for (int iter = 0; iter < 10; ++iter) {\n            vector<int> indices(N);\n            iota(indices.begin(), indices.end(), 0);\n            \n            // Greedy Remove\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (u == 0 || !active[u]) continue;\n                \n                // Check if we can remove u\n                // We need to reassign residents of u to other active vertices\n                // And check if cost decreases\n                \n                vector<int> saved_P_u(N, 0); // Only need to track changes for modified P\n                vector<int> modified_nodes;\n                \n                // Tentative removal\n                active[u] = false;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost - (long long)P[u] * P[u];\n                \n                // For residents assigned to u, find new owner\n                for (int k = 0; k < K; ++k) {\n                    if (assign[k] == u) {\n                        int new_v = -1;\n                        for (int v : resident_order[k]) {\n                            if (active[v]) {\n                                new_v = v;\n                                break;\n                            }\n                        }\n                        if (new_v == -1) {\n                            invalid = true;\n                            break;\n                        }\n                        int d = dist_res[new_v][k];\n                        if (d > 5000) {\n                            invalid = true;\n                            break;\n                        }\n                        \n                        // Update tentative P for new_v\n                        if (d > P[new_v]) {\n                            if (saved_P_u[new_v] == 0) saved_P_u[new_v] = P[new_v];\n                            P[new_v] = d;\n                        }\n                    }\n                }\n                \n                if (!invalid) {\n                    // Calculate new node cost based on changes\n                    for (int v = 0; v < N; ++v) {\n                        if (v != u && saved_P_u[v] != 0) {\n                            tentative_node_cost += (long long)P[v] * P[v];\n                            tentative_node_cost -= (long long)saved_P_u[v] * saved_P_u[v];\n                        }\n                    }\n                    \n                    long long new_edge_cost = calc_mst_cost();\n                    if (tentative_node_cost + new_edge_cost < total_cost) {\n                        // Accept removal\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = tentative_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        // Reassign permanently\n                        reassign(); \n                        // P is updated by reassign\n                        continue; \n                    }\n                }\n                \n                // Reject: Revert\n                active[u] = true;\n                for (int v = 0; v < N; ++v) {\n                    if (saved_P_u[v] != 0) P[v] = saved_P_u[v];\n                }\n            }\n\n            // Greedy Add\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (active[u]) continue;\n                \n                // Try add u\n                active[u] = true;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost; // P[u] starts at 0, might increase\n                \n                // Check residents who might move to u\n                vector<int> saved_P(N, 0);\n                \n                // We only care if cost decreases.\n                // Simply run reassign to get new P.\n                // But reassign is O(KN). Since N=100, K=5000, O(5e5) per check is okay.\n                // 200 checks -> 1e8 ops. A bit slow but acceptable in C++.\n                \n                // Optimization: only check residents where u is closer than current owner\n                // Or just run reassign on a copy? No, just run reassign and revert.\n                \n                // Let's do fast check first: if dist(u, any resident in C_v) < P_v, potential gain.\n                // This is heuristic. For safety, let's just use reassign.\n                \n                reassign(); \n                \n                // Check validity\n                valid = true;\n                for (int i=0; i<N; ++i) if (active[i] && P[i] > 5000) valid = false;\n                \n                if (valid) {\n                    long long new_node_cost = calc_node_cost();\n                    long long new_edge_cost = calc_mst_cost();\n                    if (new_node_cost + new_edge_cost < total_cost) {\n                        // Accept\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = new_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        continue;\n                    }\n                }\n                \n                // Reject\n                active[u] = false;\n                // Revert P and assign\n                reassign();\n            }\n        }\n\n        // 6. Construct Output Edges\n        // Prim's MST on active vertices, then expand to shortest paths\n        vector<vector<int>> mst_adj(N, vector<int>(N, 0));\n        vector<bool> in_mst(N, false);\n        vector<int> parent(N, -1);\n        vector<long long> min_dist(N, 1e18);\n        min_dist[0] = 0;\n\n        for (int i = 0; i < N; ++i) {\n            int u = -1;\n            for (int j = 0; j < N; ++j) {\n                if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                    u = j;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (parent[u] != -1) {\n                // Find path between parent[u] and u\n                int s = parent[u];\n                int t = u;\n                \n                // Dijkstra\n                vector<long long> d(N, 1e18);\n                vector<int> prev(N, -1);\n                d[s] = 0;\n                priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n                pq.push({0, s});\n                \n                while(!pq.empty()){\n                    auto [dist, v] = pq.top(); pq.pop();\n                    if(dist > d[v]) continue;\n                    if(v == t) break;\n                    for(auto& edge : edges){\n                        int a, b; long long w;\n                        tie(a, b, w) = edge;\n                        a--; b--;\n                        if(v == a && d[a] + w < d[b]){\n                            d[b] = d[a] + w;\n                            prev[b] = a;\n                            pq.push({d[b], b});\n                        } else if (v == b && d[b] + w < d[a]){\n                            d[a] = d[b] + w;\n                            prev[a] = b;\n                            pq.push({d[a], a});\n                        }\n                    }\n                }\n                \n                int curr = t;\n                while(curr != s && curr != -1) {\n                    int p = prev[curr];\n                    if (p == -1) break;\n                    for (int j = 0; j < M; ++j) {\n                        int uj, vj; long long wj;\n                        tie(uj, vj, wj) = edges[j];\n                        uj--; vj--;\n                        if ((uj == p && vj == curr) || (uj == curr && vj == p)) {\n                            B[j] = 1;\n                            break;\n                        }\n                    }\n                    curr = p;\n                }\n            }\n            \n            for (int v = 0; v < N; ++v) {\n                if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                    min_dist[v] = dist_nodes[u][v];\n                    parent[v] = u;\n                }\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if (i > 0) cout << \" \";\n            cout << P[i];\n        }\n        cout << \"\\n\";\n        for (int j = 0; j < M; ++j) {\n            if (j > 0) cout << \" \";\n            cout << B[j];\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    \n    Solver solver(N, M, K);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        solver.edges[i] = {u, v, w};\n    }\n    for (int i = 0; i < K; ++i) {\n        cin >> solver.residents[i].first >> solver.residents[i].second;\n    }\n    \n    solver.solve();\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> all_vals;\n    map<int, pair<int, int>> pos;\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            grid[x][y] = v;\n            pos[v] = {x, y};\n            all_vals.push_back(v);\n        }\n    }\n\n    sort(all_vals.begin(), all_vals.end());\n    map<int, int> rank_of_val;\n    for (int i = 0; i < (int)all_vals.size(); ++i) {\n        rank_of_val[all_vals[i]] = i;\n    }\n\n    auto get_tier = [&](int rank) -> int {\n        int t = (int)((-1 + sqrt(1 + 8.0 * rank)) / 2);\n        while ((t + 1) * (t + 2) / 2 <= rank) t++;\n        while (t * (t + 1) / 2 > rank) t--;\n        return t;\n    };\n\n    vector<int> target_tier(465);\n    for (int i = 0; i < 465; ++i) {\n        target_tier[i] = get_tier(i);\n    }\n\n    vector<tuple<int, int, int, int>> operations;\n\n    auto dist = [](int x1, int y1, int x2, int y2) -> int {\n        return max(abs(x1 - x2), abs(y1 - y2));\n    };\n\n    vector<pair<int, int>> directions = {\n        {0, -1}, {0, 1}, {-1, 0}, {-1, -1}, {1, 0}, {1, 1}\n    };\n\n    for (int t = N - 1; t >= 0; --t) {\n        int start_rank = t * (t + 1) / 2;\n        int count = t + 1;\n        \n        vector<int> balls_in_tier;\n        for (int i = 0; i < count; ++i) {\n            balls_in_tier.push_back(all_vals[start_rank + i]);\n        }\n\n        int node_offset = t + 1;\n        int SRC = (t + 1) * 2;\n        int SNK = (t + 1) * 2 + 1;\n        \n        mcf_graph<int, int> g(SNK + 1);\n\n        for (int i = 0; i < count; ++i) {\n            int val = balls_in_tier[i];\n            auto [cx, cy] = pos[val];\n            g.add_edge(SRC, i, 1, 0); \n            \n            for (int j = 0; j < count; ++j) {\n                int d = dist(cx, cy, t, j);\n                // Cost function: Primary objective is distance.\n                // Tie-breaker: Minimize vertical displacement |cy - j|.\n                // Weight 50 is sufficient since max distance is 30, \n                // so reducing distance by 1 is always better than any vertical optimization.\n                int cost = d * 50 + abs(cy - j);\n                g.add_edge(i, node_offset + j, 1, cost);\n            }\n        }\n        \n        for (int j = 0; j < count; ++j) {\n             g.add_edge(node_offset + j, SNK, 1, 0);\n        }\n\n        auto flow_res = g.flow(SRC, SNK);\n        \n        map<int, pair<int, int>> final_targets; \n        \n        auto edges = g.edges();\n        for (auto &e : edges) {\n            if (e.from >= SRC || e.to >= SNK || e.to == SRC || e.from == SNK) continue;\n            if (e.from < t + 1 && e.to >= node_offset && e.to < (t + 1) * 2 && e.flow > 0) {\n                int ball_idx = e.from;\n                int target_y = e.to - node_offset;\n                int val = balls_in_tier[ball_idx];\n                final_targets[val] = {t, target_y};\n            }\n        }\n\n        struct Assignment {\n            int val;\n            int tx;\n            int ty;\n        };\n        vector<Assignment> assigns;\n        for (auto& p : final_targets) {\n            assigns.push_back({p.first, p.second.first, p.second.second});\n        }\n\n        // Placement order: Place balls at the edges of the row first (indices 0 and t),\n        // moving towards the center. This keeps the middle of the row open for longer,\n        // reducing detours for balls that need to cross from one side to the other.\n        sort(assigns.begin(), assigns.end(), [&](const Assignment& a, const Assignment& b) {\n            int dist_a = min(a.ty, t - a.ty);\n            int dist_b = min(b.ty, t - b.ty);\n            if (dist_a != dist_b) return dist_a < dist_b;\n            return a.ty < b.ty;\n        });\n\n        for (auto& item : assigns) {\n            int val = item.val;\n            int tx = item.tx;\n            int ty = item.ty;\n            auto [sx, sy] = pos[val];\n\n            if (sx == tx && sy == ty) continue;\n\n            queue<pair<int, int>> q;\n            map<pair<int, int>, pair<int, int>> parent;\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            \n            q.push({sx, sy});\n            visited[sx][sy] = true;\n            \n            bool found = false;\n            \n            while (!q.empty() && !found) {\n                auto [cx, cy] = q.front();\n                q.pop();\n                \n                for (auto [dx, dy] : directions) {\n                    int nx = cx + dx;\n                    int ny = cy + dy;\n                    \n                    if (nx < 0 || nx >= N || ny < 0 || ny > nx) continue;\n                    if (visited[nx][ny]) continue;\n                    \n                    int ball_at_nx = grid[nx][ny];\n                    int b_tier = target_tier[rank_of_val[ball_at_nx]];\n                    \n                    bool is_obstacle = false;\n                    if (b_tier > t) is_obstacle = true;\n                    else if (b_tier == t) {\n                        if (final_targets.count(ball_at_nx)) {\n                             auto [b_tx, b_ty] = final_targets[ball_at_nx];\n                             if (nx == b_tx && ny == b_ty) is_obstacle = true;\n                        }\n                    }\n                    \n                    if (!is_obstacle) {\n                        visited[nx][ny] = true;\n                        parent[{nx, ny}] = {cx, cy};\n                        q.push({nx, ny});\n                        if (nx == tx && ny == ty) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            vector<pair<int, int>> path;\n            {\n                auto curr = make_pair(tx, ty);\n                while (curr != make_pair(sx, sy)) {\n                    path.push_back(curr);\n                    curr = parent[curr];\n                }\n                path.push_back({sx, sy});\n                reverse(path.begin(), path.end());\n            }\n\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                auto [u1, v1] = path[i];\n                auto [u2, v2] = path[i+1];\n                \n                int val1 = grid[u1][v1];\n                int val2 = grid[u2][v2];\n                \n                swap(grid[u1][v1], grid[u2][v2]);\n                \n                pos[val1] = {u2, v2};\n                pos[val2] = {u1, v1};\n                \n                operations.push_back({u1, v1, u2, v2});\n            }\n        }\n    }\n\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <numeric>\n\nusing namespace std;\n\n// Grid configuration\nconst int D = 9;\nconst int INF = 1e9;\n// Entrance\nconst int ER = 0;\nconst int EC = 4;\n\nstruct State {\n    vector<vector<bool>> obstacle;\n    vector<vector<int>> dist;\n    vector<vector<bool>> occupied;\n    int total_containers;\n\n    State(int n, const vector<pair<int, int>>& obs_coords) {\n        obstacle.assign(D, vector<bool>(D, false));\n        occupied.assign(D, vector<bool>(D, false));\n        dist.assign(D, vector<int>(D, -1));\n        \n        // Mark entrance and adjacent as not obstacles (problem guarantee)\n        // But we also treat them as not storage space.\n        \n        // Mark obstacles\n        for (auto p : obs_coords) {\n            obstacle[p.first][p.second] = true;\n        }\n\n        // Calculate distances from entrance\n        queue<pair<int, int>> q;\n        q.push({ER, EC});\n        dist[ER][EC] = 0;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (dist[nr][nc] == -1 && !obstacle[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + 1;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Count available spots\n        total_containers = 0;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                // Entrance and obstacles are not for storage\n                if ((i == ER && j == EC) || obstacle[i][j]) continue;\n                // Problem statement says entrance and its 3 adjacent are not obstacles\n                // But they are valid storage spots? \n                // \"Each D x D - 1 - N square other than the entrance and obstacles can hold at most 1 container.\"\n                // So adjacent squares (0,3), (0,5), (1,4) ARE valid storage spots.\n                total_containers++;\n            }\n        }\n    }\n    \n    // Find empty cells reachable from entrance via empty cells\n    vector<pair<int, int>> get_reachable_empty() {\n        vector<pair<int, int>> reachable;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        \n        // Start from entrance\n        q.push({ER, EC});\n        visited[ER][EC] = true;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (!visited[nr][nc] && !obstacle[nr][nc] && !occupied[nr][nc]) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                        reachable.push_back({nr, nc});\n                    }\n                }\n            }\n        }\n        return reachable;\n    }\n\n    // Check if placing a container at (tr, tc) blocks other empty cells from entrance\n    // It blocks if, after marking (tr, tc) occupied, some previously reachable empty cell becomes unreachable.\n    bool is_safe_placement(int tr, int tc) {\n        // Temporarily mark as occupied\n        occupied[tr][tc] = true;\n        \n        vector<pair<int, int>> new_reachable = get_reachable_empty();\n        \n        // Restore\n        occupied[tr][tc] = false;\n\n        // Count previously reachable (excluding the cell itself)\n        auto prev_reachable = get_reachable_empty();\n        \n        // Actually, we can just compare counts of reachable nodes (excluding the one we are filling)\n        // Since we are adding an obstacle, the set of reachable empty cells can only shrink.\n        // We want it to NOT shrink (except for the cell itself).\n        // Note: get_reachable_empty returns EMPTY cells.\n        // (tr, tc) is empty before placement. It is in prev_reachable.\n        // After placement, it is not in new_reachable.\n        // So we expect |new_reachable| == |prev_reachable| - 1.\n        \n        if (new_reachable.size() == prev_reachable.size() - 1) return true;\n        return false;\n    }\n\n    // Choose best cell for container t\n    pair<int, int> choose_placement(int t) {\n        auto reachable = get_reachable_empty();\n        \n        if (reachable.empty()) {\n            // Should not happen\n            return {-1, -1};\n        }\n\n        // Target distance\n        // Map t from [0, M-1] to a distance range\n        // Max distance is around 15.\n        double ratio = (double)t / total_containers;\n        \n        // We want to sort candidates.\n        // Heuristic: \n        // 1. Is safe (doesn't block).\n        // 2. Distance is close to target.\n        // 3. (Optional) Prefer low degree or corners?\n        \n        vector<tuple<int, int, double>> candidates; // score, r, c\n        // Score > 0 means safe, < 0 unsafe.\n        \n        int max_dist = 0;\n        for(auto& p : reachable) max_dist = max(max_dist, dist[p.first][p.second]);\n        \n        for (auto& p : reachable) {\n            int r = p.first;\n            int c = p.second;\n            int d = dist[r][c];\n            \n            double ideal_d = ratio * max_dist;\n            double dist_error = abs(d - ideal_d);\n            \n            int safe_score = is_safe_placement(r, c) ? 1000 : 0;\n            \n            // Combine: safety is most important. Then distance match.\n            // We maximize score.\n            double final_score = safe_score - dist_error;\n            \n            // If unsafe, we might still want to place it if we have no other choice,\n            // but we pick the one with max_dist_error (least bad? or best distance?).\n            // Let's say if unsafe, score is just -dist_error.\n            // If safe, score is 1000 - dist_error.\n            \n            candidates.push_back({final_score, r, c});\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<tuple<double, int, int>>());\n        \n        // Pick the best one\n        return {get<1>(candidates[0]), get<2>(candidates[0])};\n    }\n\n    void place(int t, int r, int c) {\n        occupied[r][c] = true;\n        cout << r << \" \" << c << endl;\n        // cout << \"# Placed \" << t << \" at \" << r << \" \" << c << endl;\n    }\n\n    // Retrieve phase\n    void retrieve_all(const map<int, pair<int, int>>& id_to_coord) {\n        vector<pair<int, int>> retrieval_order;\n        \n        // Set of remaining IDs\n        set<int> remaining;\n        for (auto p : id_to_coord) remaining.insert(p.first);\n        \n        // While there are containers\n        while (!remaining.empty()) {\n            // Find reachable occupied cells\n            queue<pair<int, int>> q;\n            vector<vector<bool>> visited(D, vector<bool>(D, false));\n            q.push({ER, EC});\n            visited[ER][EC] = true;\n            \n            vector<int> reachable_ids;\n            \n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n\n            while (!q.empty()) {\n                auto curr = q.front(); 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                    if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                        if (!visited[nr][nc] && !obstacle[nr][nc]) {\n                            // Check if occupied\n                            bool is_occupied = false;\n                            int id_at = -1;\n                            // We need to check if this coordinate has a container that is still in 'remaining'\n                            // We can look up in id_to_coord map (inverse map needed?)\n                            // Actually we have id_to_coord. We need coord_to_id.\n                            // Or just iterate remaining? remaining size is up to 80. O(80*80) is fine.\n                            for (int rid : remaining) {\n                                if (id_to_coord.at(rid) == make_pair(nr, nc)) {\n                                    is_occupied = true;\n                                    id_at = rid;\n                                    break;\n                                }\n                            }\n\n                            if (is_occupied) {\n                                visited[nr][nc] = true; // Can reach this square (but stop here?)\n                                // Actually we pass through it? No.\n                                // Rule: \"passing through adjacent empty squares\".\n                                // Occupied squares are NOT empty.\n                                // So we CANNOT pass through occupied squares.\n                                // We can only reach the occupied square itself if we are adjacent to an empty square.\n                                // But we CANNOT go THROUGH an occupied square.\n                                // However, the square containing the container is the target.\n                                // The rule says: \"The square containing the container to be transported out must be reachable... by passing through adjacent empty squares.\"\n                                // This means the path ends at the square. The square itself is occupied.\n                                // So we just check connectivity via EMPTY squares.\n                                // If (nr, nc) is occupied, we don't push it to queue.\n                                // But we record it as a retrievable target.\n                                reachable_ids.push_back(id_at);\n                            } else {\n                                // Empty, traverse\n                                visited[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (reachable_ids.empty()) {\n                // Should not happen\n                break;\n            }\n            \n            // Pick smallest ID\n            sort(reachable_ids.begin(), reachable_ids.end());\n            int to_retrieve = reachable_ids[0];\n            \n            retrieval_order.push_back(id_to_coord.at(to_retrieve));\n            remaining.erase(to_retrieve);\n        }\n        \n        // Output\n        for (auto p : retrieval_order) {\n            cout << p.first << \" \" << p.second << endl;\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N;\n    cin >> N;\n    \n    vector<pair<int, int>> obstacles(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    State solver(N, obstacles);\n    \n    map<int, pair<int, int>> id_to_coord;\n    \n    for (int i = 0; i < solver.total_containers; ++i) {\n        int t;\n        cin >> t;\n        \n        auto p = solver.choose_placement(t);\n        solver.place(t, p.first, p.second);\n        id_to_coord[t] = p;\n    }\n    \n    solver.retrieve_all(id_to_coord);\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Constants\nconst int N = 50;\nconst int M = 100;\n\n// Global variables\nint n, m;\nint grid[N][N];\nint color_cnt[M + 1];       // Count of kept cells for each color\nbool is_boundary_color[M + 1]; // True if color touches grid boundary\nbool is_fixed[N][N];        // True if cell cannot be removed\n\nint dx[4] = {0, 1, 0, -1};\nint dy[4] = {1, 0, -1, 0};\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < n && 0 <= y && y < n;\n}\n\nvoid solve() {\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n            color_cnt[grid[i][j]]++;\n        }\n    }\n\n    // 1. Identify boundary colors\n    for (int c = 1; c <= m; ++c) is_boundary_color[c] = false;\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                is_boundary_color[c] = true;\n            }\n        }\n    }\n\n    // 2. Mark fixed cells\n    // A cell is fixed if:\n    // a) It is an internal color (must not touch 0).\n    // b) It is a boundary color cell but touches an internal color (removing it would expose internal to 0).\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            if (!is_boundary_color[c]) {\n                // Internal colors are completely fixed\n                is_fixed[i][j] = true;\n            } else {\n                // Check neighbors for internal colors\n                bool touches_internal = false;\n                for (int k = 0; k < 4; ++k) {\n                    int nx = i + dx[k];\n                    int ny = j + dy[k];\n                    if (in_grid(nx, ny)) {\n                        int nc = grid[nx][ny];\n                        if (!is_boundary_color[nc]) {\n                            touches_internal = true;\n                            break;\n                        }\n                    }\n                }\n                is_fixed[i][j] = touches_internal;\n            }\n        }\n    }\n\n    // 3. Initialize Queue with non-fixed cells on the grid boundary\n    // These are adjacent to \"outside\" (color 0)\n    queue<pair<int, int>> q;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !is_fixed[i][j]) {\n                q.push({i, j});\n            }\n        }\n    }\n\n    // 4. Greedy Removal\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        \n        // If already removed or became fixed (fixed is static, but safe to check)\n        if (grid[x][y] == 0) continue;\n        if (is_fixed[x][y]) continue;\n\n        int c = grid[x][y];\n\n        // Must keep at least 1 cell of this color\n        if (color_cnt[c] <= 1) continue;\n\n        // A. Connectivity Check for color c\n        // Check if removing (x,y) disconnects the kept cells of c\n        bool connectivity_ok = true;\n        int start_x = -1, start_y = -1;\n        \n        // Find a start node\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == c && (i != x || j != y)) {\n                    start_x = i; start_y = j;\n                    break;\n                }\n            }\n            if (start_x != -1) break;\n        }\n\n        if (start_x != -1) {\n            queue<pair<int, int>> bq;\n            bq.push({start_x, start_y});\n            vector<vector<bool>> visited(n, vector<bool>(n, false));\n            visited[start_x][start_y] = true;\n            int visited_count = 0;\n\n            while (!bq.empty()) {\n                auto [cx, cy] = bq.front(); bq.pop();\n                visited_count++;\n                for (int k = 0; k < 4; ++k) {\n                    int nx = cx + dx[k];\n                    int ny = cy + dy[k];\n                    if (in_grid(nx, ny) && !visited[nx][ny] && grid[nx][ny] == c && (nx != x || ny != y)) {\n                        visited[nx][ny] = true;\n                        bq.push({nx, ny});\n                    }\n                }\n            }\n\n            if (visited_count != color_cnt[c] - 1) {\n                connectivity_ok = false;\n            }\n        } else {\n            // Should not happen if cnt > 1, but if no other cell found, can't remove\n            connectivity_ok = false;\n        }\n\n        if (!connectivity_ok) continue;\n\n        // B. Witness Check\n        // Check adjacencies provided by (x,y) that must be preserved\n        bool witness_ok = true;\n\n        // Check adjacency to 0\n        // Since is_boundary_color[c] is true, (c, 0) is an original edge.\n        // If we remove (x,y), we must ensure there is still a path from c to 0.\n        // (x,y) is currently adjacent to 0 (it was in queue, so adjacent to boundary/existing 0).\n        // We need to ensure some OTHER kept cell of c is adjacent to 0 or boundary.\n        // Note: Checking \"adjacent to boundary\" is sufficient for adjacency to 0 because outside is 0.\n        bool has_other_0_contact = false;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] == c && (i != x || j != y)) {\n                    if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                        has_other_0_contact = true;\n                        break;\n                    }\n                    // Also check adjacent to existing 0 cells\n                    for (int k = 0; k < 4; ++k) {\n                        int nx = i + dx[k];\n                        int ny = j + dy[k];\n                        if (in_grid(nx, ny) && grid[nx][ny] == 0) {\n                            has_other_0_contact = true;\n                            break;\n                        }\n                    }\n                }\n                if (has_other_0_contact) break;\n            }\n            if (has_other_0_contact) break;\n        }\n\n        if (!has_other_0_contact) {\n            witness_ok = false;\n        }\n\n        if (witness_ok) {\n            // Check adjacencies to other colors\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny)) {\n                    int d = grid[nx][ny];\n                    if (d == 0 || d == c) continue;\n\n                    // Need another witness for (c, d)\n                    bool found_witness = false;\n                    for (int i = 0; i < n; ++i) {\n                        for (int j = 0; j < n; ++j) {\n                            if (grid[i][j] == c && (i != x || j != y)) {\n                                for (int kk = 0; kk < 4; ++kk) {\n                                    int nnx = i + dx[kk];\n                                    int nny = j + dy[kk];\n                                    if (in_grid(nnx, nny) && grid[nnx][nny] == d) {\n                                        found_witness = true;\n                                        break;\n                                    }\n                                }\n                            }\n                            if (found_witness) break;\n                        }\n                        if (found_witness) break;\n                    }\n                    if (!found_witness) {\n                        witness_ok = false;\n                        break;\n                    }\n                }\n            }\n        }\n\n        // C. Perform Removal\n        if (witness_ok) {\n            grid[x][y] = 0;\n            color_cnt[c]--;\n\n            // Add neighbors to queue\n            // Only add neighbors that are not fixed.\n            // This ensures we grow 0 region contiguously.\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny) && !is_fixed[nx][ny]) {\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <random>\n#include <iomanip>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\n\n// Structure to represent a node in the tournament tree\n// We only need to store the winner index at each node for the standard logic,\n// but to recover the \"depth\" or status of losers for weight estimation, we might need more.\n// However, standard tournament sort only maintains the path of winners.\n// To estimate weights of losers, we can just look at the remaining tree.\n// Items that are closer to the root in the remaining tree are \"winners\" of sub-tournaments, hence heavier.\n// Items that are leaves are losers of the first round, hence lighter.\n// So we can assign weights by traversing the remaining tree in level order.\n\nstruct Node {\n    int winner = -1;\n    int left = -1;\n    int right = -1;\n    int depth = 0; // Distance from root (0 is root)\n};\n\nvector<Node> tree;\nvector<int> extracted_indices; // Stores the indices of items in sorted order (heaviest first)\nvector<int> item_to_weight_est; // Estimated weight for each item\n\nint ask(int l, int r) {\n    cout << 1 << \" \" << 1 << \" \" << l << \" \" << r << endl;\n    cout.flush();\n    query_count++;\n    string res;\n    cin >> res;\n    if (res == \"<\") return -1;\n    if (res == \">\") return 1;\n    return 0;\n}\n\n// Build tournament tree.\n// Returns the index of the root node in the 'tree' vector.\nint build_tournament(const vector<int>& items, int depth) {\n    int node_idx = tree.size();\n    tree.emplace_back();\n    tree[node_idx].depth = depth;\n\n    if (items.size() == 1) {\n        tree[node_idx].winner = items[0];\n        return node_idx;\n    }\n\n    int mid = items.size() / 2;\n    vector<int> left_items(items.begin(), items.begin() + mid);\n    vector<int> right_items(items.begin() + mid, items.end());\n\n    int left_idx = build_tournament(left_items, depth + 1);\n    int right_idx = build_tournament(right_items, depth + 1);\n\n    tree[node_idx].left = left_idx;\n    tree[node_idx].right = right_idx;\n\n    int w_left = tree[left_idx].winner;\n    int w_right = tree[right_idx].winner;\n\n    // If one side is empty (shouldn't happen with split logic but good for safety)\n    if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n    return node_idx;\n}\n\n// Re-evaluate the node based on its children.\n// Used after a winner is extracted and removed.\nvoid update_node(int node_idx) {\n    if (tree[node_idx].left == -1 && tree[node_idx].right == -1) {\n        // Leaf\n        tree[node_idx].winner = -1;\n        return;\n    }\n\n    int w_left = -1;\n    int w_right = -1;\n    \n    if (tree[node_idx].left != -1) w_left = tree[tree[node_idx].left].winner;\n    if (tree[node_idx].right != -1) w_right = tree[tree[node_idx].right].winner;\n\n    if (w_left == -1 && w_right == -1) {\n        tree[node_idx].winner = -1;\n    } else if (w_left == -1) {\n        tree[node_idx].winner = w_right;\n    } else if (w_right == -1) {\n        tree[node_idx].winner = w_left;\n    } else {\n        int res = ask(w_left, w_right);\n        if (res >= 0) tree[node_idx].winner = w_left;\n        else tree[node_idx].winner = w_right;\n    }\n}\n\n// Extract the winner from the tree and update the structure.\n// Returns the index of the extracted item.\nint extract_max(int root_idx) {\n    int winner_idx = tree[root_idx].winner;\n    \n    // Trace down to the leaf\n    int curr = root_idx;\n    while (curr != -1) {\n        int left_child = tree[curr].left;\n        int right_child = tree[curr].right;\n        \n        // If leaf, winner is removed\n        if (left_child == -1 && right_child == -1) {\n            tree[curr].winner = -1;\n            break;\n        }\n\n        int w_left = (left_child != -1) ? tree[left_child].winner : -1;\n        int w_right = (right_child != -1) ? tree[right_child].winner : -1;\n\n        // Determine which child contains the current winner\n        if (w_left == winner_idx) {\n            curr = left_child;\n        } else {\n            curr = right_child;\n        }\n    }\n\n    // Propagate changes back up to root\n    // We need to reconstruct the path. We didn't store parents.\n    // Alternative: simply traverse down again? No, we need to update ancestors.\n    // Let's just rebuild winners along the path from root to where winner was found?\n    // Better approach for small N (100): Just re-update everything bottom-up? No.\n    // We can do a recursive update.\n    // Or simply: when we removed the leaf, we can walk back up? We don't have parent pointers.\n    \n    // Let's modify extraction: we know the winner. We search for it in the tree? No, structure is fixed.\n    // We can implement a recursive function `remove(node, target_winner)`\n    \n    return winner_idx;\n}\n\n// Helper to recursively remove and update\nbool remove_winner(int node_idx, int target_winner) {\n    if (node_idx == -1) return false;\n    \n    int left = tree[node_idx].left;\n    int right = tree[node_idx].right;\n    \n    // If this is the leaf node holding the winner\n    if (left == -1 && right == -1) {\n        if (tree[node_idx].winner == target_winner) {\n            tree[node_idx].winner = -1; // Mark as empty\n            return true;\n        }\n        return false;\n    }\n\n    // Recurse\n    int next_child = -1;\n    int w_left = (left != -1) ? tree[left].winner : -1;\n    \n    if (w_left == target_winner) {\n        if (remove_winner(left, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    } else {\n        if (remove_winner(right, target_winner)) {\n            update_node(node_idx);\n            return true;\n        }\n    }\n    return false;\n}\n\n// Assign weights to items remaining in the tree\nvoid estimate_weights_from_tree(int node_idx, int base_weight) {\n    if (node_idx == -1) return;\n    \n    int winner = tree[node_idx].winner;\n    if (winner != -1) {\n        // If this item hasn't been assigned a weight yet (not in extracted list)\n        // Since we process extracted items first, we only assign to unassigned ones.\n        if (item_to_weight_est[winner] == -1) {\n            // Heuristic: The winner of a subtree is heavier than items in sub-subtrees.\n            // We traverse down, so we give larger weight to higher nodes?\n            // Actually, DFS pre-order visits root, then children.\n            // Root is max. Children are smaller.\n            // So assign current base_weight to winner, then smaller to children.\n            item_to_weight_est[winner] = base_weight;\n        }\n    }\n\n    // Recurse to children with smaller weight\n    // We want to maintain order. We don't know order of left/right children without querying.\n    // But we can just average the weight or decrement by a small amount.\n    // Since N is small, we can just spread the remaining weights.\n    \n    estimate_weights_from_tree(tree[node_idx].left, base_weight - 2); // Arbitrary decrement\n    estimate_weights_from_tree(tree[node_idx].right, base_weight - 2);\n}\n\nvoid solve() {\n    cin >> N >> D >> Q;\n    \n    // Initialize indices\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    // Shuffle indices? \n    // For tournament sort, initial order affects which items meet in early rounds.\n    // It doesn't change the set of Top K found.\n    // Random shuffle might help if we were approximating, but exact Top K is exact.\n    // Shuffle might be useful to randomize which \"branch\" heavy items fall into, \n    // but strictly speaking not necessary for correctness of top K.\n    // However, for the \"remaining\" items, if we assume distribution, random order is fine.\n    // Let's shuffle to ensure no bias in early rounds for equal weights (though unlikely).\n    mt19937 rng(0); // Fixed seed for reproducibility or random?\n    // Problem says \"seed\" for input generation, but we can use random for our logic.\n    // Actually, usually deterministic is better for debugging, but random helps break patterns.\n    // Let's use default random_device or fixed seed.\n    shuffle(indices.begin(), indices.end(), rng);\n\n    tree.clear();\n    int root = build_tournament(indices, 0);\n\n    item_to_weight_est.assign(N, -1);\n    extracted_indices.clear();\n\n    // We used N-1 queries to build. Remaining Q - (N-1).\n    // We want to extract top K.\n    // Each extraction takes approx log2(N) queries.\n    // But update_node might ask queries again.\n    // In worst case, update_node asks 1 query per level.\n    // So extraction costs O(log N).\n    \n    // Reserve 5 queries for safety/flushing\n    int limit = Q - 5;\n    \n    while (query_count < limit) {\n        int winner = tree[root].winner;\n        if (winner == -1) break; // No items left\n        \n        extracted_indices.push_back(winner);\n        \n        // Remove this winner from the tree\n        remove_winner(root, winner);\n        \n        // Check if we exceeded limit during removal (query inside update_node)\n        if (query_count > limit) {\n            // Revert? No, just stop. \n            // The last extraction might be incomplete if update stopped early?\n            // remove_winner calls update_node recursively. \n            // If a query pushes us over, the update is done but we should stop.\n            break;\n        }\n    }\n\n    int K = extracted_indices.size();\n    \n    // Assign weights to extracted items\n    // Heaviest gets N, then N-1, etc.\n    for (int i = 0; i < K; ++i) {\n        item_to_weight_est[extracted_indices[i]] = N - i;\n    }\n    \n    // Assign weights to remaining items\n    // Use a DFS/BFS traversal. \n    // We want to assign weights smaller than N-K.\n    // The root of the current tree holds the max of remaining.\n    // We can give it N-K-1.\n    // We need to traverse.\n    // Since we don't know the exact order of remaining, we just give them weights\n    // based on depth or random values in the range [1, N-K].\n    \n    // Let's assign based on BFS order.\n    // Root gets next largest weight. Children get smaller.\n    if (tree[root].winner != -1) {\n       queue<int> q;\n       q.push(root);\n       int next_w = N - K;\n       \n       while(!q.empty()) {\n           int node = q.front();\n           q.pop();\n           \n           int winner = tree[node].winner;\n           if (winner != -1 && item_to_weight_est[winner] == -1) {\n               item_to_weight_est[winner] = next_w;\n               next_w = max(1, next_w - 1); // Decrement weight\n           }\n           \n           if (tree[node].left != -1) q.push(tree[node].left);\n           if (tree[node].right != -1) q.push(tree[node].right);\n       }\n    }\n\n    // Fill any unassigned items (shouldn't happen if tree covers all)\n    for (int i = 0; i < N; ++i) {\n        if (item_to_weight_est[i] == -1) {\n            item_to_weight_est[i] = 1;\n        }\n    }\n\n    // Now partition using LPT (Longest Processing Time) heuristic\n    // Create pairs of (estimated weight, original index)\n    vector<pair<int, int>> items_with_est;\n    for (int i = 0; i < N; ++i) {\n        items_with_est.push_back({item_to_weight_est[i], i});\n    }\n    \n    // Sort by estimated weight descending\n    sort(items_with_est.begin(), items_with_est.end(), greater<pair<int, int>>());\n\n    // Maintain D bins with their current sums\n    // Since we need to assign indices to bins, we can just store the sum\n    // and a reference to the bin assignments.\n    \n    // For small N and D, simple linear scan for min bin is fine.\n    // Optimization: priority_queue.\n    \n    // We need to output d_i for each item 0..N-1\n    vector<int> assignment(N);\n    vector<long long> bin_sums(D, 0); // Use long long to avoid overflow (though weights are small)\n    \n    // Min-heap to find the bin with smallest sum\n    // pair<sum, bin_index>\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n    for (int i = 0; i < D; ++i) {\n        pq.push({0, i});\n    }\n    \n    for (auto& p : items_with_est) {\n        int w = p.first;\n        int idx = p.second;\n        \n        auto top = pq.top();\n        pq.pop();\n        \n        int bin_idx = top.second;\n        bin_sums[bin_idx] += w;\n        assignment[idx] = bin_idx;\n        \n        pq.push({bin_sums[bin_idx], bin_idx});\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for state and parameters\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // 0-indexed stack and height\nvector<pair<int, int>> operations;\n\n// Structure to hold heuristic evaluation results\nstruct DestInfo {\n    int id;\n    long long score;\n    int min_val; // Smallest element in the stack (used for tie-breaking)\n};\n\n// Helper to get the top element of a stack, return large number if empty\nint get_top(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return stacks[stack_id].back();\n}\n\n// Helper to get the minimum element in a stack\nint get_min(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return *min_element(stacks[stack_id].begin(), stacks[stack_id].end());\n}\n\n// Evaluate the cost of moving a segment 'seg' to stack 'dest'\n// Score represents the \"badness\", lower is better.\n// Badness is defined as the number of inversions created.\n// An inversion is a pair (t, s) where t is in destination, s is in segment, and t > s.\n// We also want to prefer keeping segments intact if they are sorted,\n// but the split logic handles that before calling this.\nlong long evaluate_move(int dest, const vector<int>& seg) {\n    if (stacks[dest].empty()) return 0; // No inversions possible with empty stack\n\n    long long inv_count = 0;\n    \n    // Optimization: Since we sum counts of t > s for all s in seg\n    // We can iterate through t in destination and count how many s it is greater than.\n    // Complexity: O(Size(D) * Size(S)). Max 20 * 200 = 4000. Negligible.\n    \n    const vector<int>& dest_stack = stacks[dest];\n    \n    // Pre-calculate prefix sums? Not necessary for N=200.\n    // Just brute force double loop.\n    for (int t : dest_stack) {\n        for (int s : seg) {\n            if (t > s) {\n                inv_count++;\n            }\n        }\n    }\n    return inv_count;\n}\n\n// Execute operation type 1: Move box 'v' (and above it) to stack 'dest'\nvoid move_box(int v, int dest) {\n    // Find current stack\n    int s = pos[v].first;\n    int h = pos[v].second;\n    \n    if (s == dest) return; // Should not happen based on logic\n\n    // Identify segment to move\n    vector<int> boxes_to_move;\n    // stacks[s] has boxes from bottom (0) to top (size-1)\n    // v is at index h. We move h to size-1.\n    for (int i = h; i < stacks[s].size(); ++i) {\n        boxes_to_move.push_back(stacks[s][i]);\n    }\n    \n    // Update Source Stack\n    stacks[s].resize(h);\n    \n    // Update Destination Stack\n    for (int box : boxes_to_move) {\n        stacks[dest].push_back(box);\n    }\n    \n    // Update Positions\n    int new_h = stacks[dest].size() - boxes_to_move.size();\n    for (int i = 0; i < boxes_to_move.size(); ++i) {\n        int box = boxes_to_move[i];\n        pos[box] = {dest, new_h + i};\n    }\n    \n    operations.push_back({v, dest});\n}\n\n// Execute operation type 2: Carry out box 'v'\nvoid carry_out(int v) {\n    int s = pos[v].first;\n    // Check if v is at top (should be guaranteed by caller)\n    if (stacks[s].back() != v) {\n        // Error or should not happen\n        return;\n    }\n    \n    stacks[s].pop_back();\n    // pos[v] is no longer valid, but we won't query v again\n    operations.push_back({v, 0});\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M;\n    stacks.resize(M);\n    pos.resize(N + 1);\n    \n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Process boxes 1 to N\n    for (int v = 1; v <= N; ++v) {\n        // While v is not at top of its stack\n        while (true) {\n            int s = pos[v].first;\n            int h = pos[v].second;\n            \n            // If stack has been emptied or v is at top (h == size-1)\n            if (stacks[s].size() == h + 1) {\n                break;\n            }\n            \n            // Identify the top box of the stack containing v\n            int top_box = stacks[s].back();\n            \n            // We want to move segments that are \"inverted\" or simply move the blocking segment.\n            // Strategy:\n            // Look at the box immediately above v. Let's call it 'blocker'.\n            // Or look at the top of the stack.\n            // If the top of the stack is larger than the box below it, it creates an inversion.\n            // Moving just the top box resolves that inversion for the pair (top, below).\n            // Recursively doing this sorts the stack.\n            // Once the stack above v is sorted (small on top), we move the whole block.\n            \n            bool moved = false;\n            \n            // Check for shallow inversion at the top of the current stack\n            if (stacks[s].size() >= 2) {\n                int top = stacks[s].back();\n                int below = stacks[s][stacks[s].size() - 2];\n                \n                // If top > below, moving top alone is usually beneficial to fix the inversion.\n                // However, if 'below' is v, and top is v+1, moving top is bad.\n                // But if top > below, they are not consecutive (unless v, v+1 is inverted which is impossible in sorted 1..N).\n                // So top > below implies they are not in order.\n                if (top > below) {\n                    // Find best destination for 'top_box'\n                    // We want to minimize inversions created by adding 'top_box' to dest.\n                    \n                    vector<DestInfo> candidates;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == s) continue;\n                        \n                        // Segment is just {top_box}\n                        long long inv = evaluate_move(i, {top_box});\n                        candidates.push_back({i, inv, get_min(i)});\n                    }\n                    \n                    // Sort by score (inversions), then by min_val (larger is better buffer)\n                    sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                        if (a.score != b.score) return a.score < b.score;\n                        return a.min_val > b.min_val;\n                    });\n                    \n                    int best_dest = candidates[0].id;\n                    move_box(top_box, best_dest);\n                    moved = true;\n                }\n            }\n            \n            if (!moved) {\n                // No shallow inversion at the top, or we decided not to split.\n                // Move the entire segment above v.\n                // Segment starts at index h+1.\n                vector<int> seg;\n                for (int i = h + 1; i < stacks[s].size(); ++i) {\n                    seg.push_back(stacks[s][i]);\n                }\n                \n                // Find best destination for the whole segment\n                vector<DestInfo> candidates;\n                for (int i = 0; i < M; ++i) {\n                    if (i == s) continue;\n                    \n                    long long inv = evaluate_move(i, seg);\n                    candidates.push_back({i, inv, get_min(i)});\n                }\n                \n                sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.min_val > b.min_val;\n                });\n                \n                int best_dest = candidates[0].id;\n                \n                // The segment starts at seg[0], which is the box just above v.\n                move_box(seg[0], best_dest);\n            }\n        }\n        \n        // v is now at top. Carry out.\n        carry_out(v);\n    }\n\n    // Output\n    cout << operations.size() << endl;\n    for (auto op : operations) {\n        cout << op.first << \" \" << op.second << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <array>\n#include <numeric>\n\nusing namespace std;\n\nconst int MAX_N = 40;\nconst int MAX_NODES = MAX_N * MAX_N;\nconst int MAX_MOVES = 100000;\nconst double INF = 1e18;\n\nint N;\nint d[MAX_NODES];\nvector<int> adj[MAX_NODES];\nint cnt[MAX_NODES][MAX_NODES]; // Traversal counts for edges\nlong long k[MAX_NODES]; // Visit counts\nlong long total_len = 0;\n\nint dir_map[4] = {1, 0, -1, 0};\nint dj_map[4] = {0, 1, 0, -1};\nchar char_map[4] = {'D', 'R', 'U', 'L'};\n\nint to_idx(int i, int j) {\n    return i * N + j;\n}\n\nvoid from_idx(int idx, int& i, int& j) {\n    i = idx / N;\n    j = idx % N;\n}\n\nvoid dfs_init(int u, int p, vector<string>& h, vector<string>& v) {\n    // For constructing the initial spanning tree path\n    // We will just build the adjacency list and run a DFS to find a path that visits all nodes\n    // Then we set cnt[u][v] = 2 for tree edges.\n    // Wait, the problem says \"cleaning route\".\n    // A simple DFS that returns to start visits each edge twice.\n    // Let's store the DFS traversal to build the initial cnt.\n}\n\nstruct State {\n    int u;\n    int v;\n    double score;\n    State(int _u, int _v, double _score) : u(_u), v(_v), score(_score) {}\n    bool operator>(const State& other) const {\n        return score > other.score; // Min-heap based on score? No, we want max score.\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N;\n    vector<string> h(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[to_idx(i, j)];\n            k[to_idx(i, j)] = 0;\n        }\n    }\n\n    // Build adjacency list\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = to_idx(i, j);\n            if (i < N-1 && h[i][j] == '0') {\n                int v_idx = to_idx(i+1, j);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n            if (j < N-1 && v[i][j] == '0') {\n                int v_idx = to_idx(i, j+1);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n                cnt[u][v_idx] = 0;\n                cnt[v_idx][u] = 0;\n            }\n        }\n    }\n\n    // Initial DFS to ensure connectivity and set baseline k\n    // We don't need the string, just the edge counts and k\n    // Run DFS from 0\n    vector<bool> visited(N*N, false);\n    vector<pair<int, int>> stack; // parent, current\n    stack.push_back({-1, 0});\n    \n    // We perform a DFS and record the path as edges\n    // Actually, we just need to traverse edges.\n    // Standard DFS iterative\n    stack.push_back({-1, 0});\n    visited[0] = true;\n    \n    // We need to actually construct a cycle.\n    // Simple recursive DFS is easier to implement for logic.\n    // Since N is small, recursion depth is fine.\n    // We just need to modify 'cnt' and 'k'.\n    \n    // Use a lambda for DFS\n    // To compute 'k', we need to know how many times we \"arrive\" at a node.\n    // Start at 0. Go to neighbor...\n    // DFS traversal visits each node deg times (except root).\n    // Let's implement a DFS that returns to parent.\n    \n    vector<int> parent(N*N, -1);\n    // Re-usable stack for DFS\n    vector<int> dfs_stack;\n    dfs_stack.push_back(0);\n    vector<int> order;\n    \n    // To count k properly:\n    // A DFS tour: start at root.\n    // For each neighbor not visited: \n    //   go to neighbor (move 1), visit neighbor subtree\n    //   return to parent (move 1)\n    // This visits each edge twice.\n    // k[u] is the number of times we arrive at u.\n    // In a tree, arrival at root happens at the end (1 time).\n    // Arrival at internal node happens when returning from children + coming from parent.\n    // Effectively, for a tree, k[u] is the degree in the tree, except root is 1.\n    // But we don't have a tree, we have a grid.\n    // Let's just perform a standard DFS on the grid graph.\n    \n    fill(visited.begin(), visited.end(), false);\n    \n    // Recursive DFS function\n    // We need to pass `adj` and `cnt`, `k`, `visited`\n    // We can capture by reference\n    std::function<void(int, int)> dfs = [&](int u, int p) {\n        visited[u] = true;\n        for (int v : adj[u]) {\n            if (!visited[v]) {\n                // Go u -> v\n                cnt[u][v]++;\n                k[v]++; // Arrive at v\n                dfs(v, u);\n                // Return v -> u\n                cnt[v][u]++;\n                k[u]++; // Arrive at u (return)\n            }\n        }\n    };\n    \n    // The root is 0. k[0] starts at 0.\n    // We arrive at 0 at the end?\n    // In DFS above, we don't explicitly return to root at the very top level.\n    // So k[0] will be equal to the number of children (returns from children).\n    // The problem requires a cycle starting and ending at (0,0).\n    // The DFS path starts at 0 and ends at 0.\n    // So we arrive at 0 at the end.\n    // My DFS logic: `dfs(0, -1)`\n    // Inside, for each child `c`:\n    //   0->c (cnt++, k[c]++)\n    //   dfs(c)\n    //   c->0 (cnt++, k[0]++)\n    // So k[0] is incremented for each child.\n    // This matches the number of times we visit 0 (except start? No, start is 0).\n    // The definition of k is number of visits.\n    // In sequence p0, p1, ..., pL. p0=0, pL=0.\n    // k[0] is number of times 0 appears in p1..pL.\n    // In DFS, we visit 0 at the end. That's 1 visit?\n    // Wait. If we have children, we return from each child to 0.\n    // So we visit 0 multiple times.\n    // Is this a cycle?\n    // Sequence: 0 -> c1 -> ... -> c1 -> 0 -> c2 -> ... -> c2 -> 0.\n    // This is a valid cycle.\n    // k[0] is equal to number of children in DFS tree.\n    // Correct.\n    \n    dfs(0, -1);\n    \n    // Calculate total length\n    total_len = 0;\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            total_len += cnt[u][v];\n        }\n    }\n    // Divide by 2 because we counted u->v and v->u\n    total_len /= 2;\n    \n    // Greedy additions\n    // Priority queue: (score, u, v)\n    // score = d_u/k_u^2 + d_v/k_v^2\n    // Note: k can be 0 initially?\n    // DFS ensures all visited, so k >= 1 for all nodes except maybe root if isolated? \n    // Graph is connected. Root visited.\n    // k[u] > 0 for all u reachable from 0. Since all reachable, k[u] > 0.\n    \n    priority_queue<pair<double, pair<int, int>>> pq;\n    \n    // Initialize PQ\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            if (u < v) { // Add each edge once\n                double val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n                pq.push({val, {u, v}});\n            }\n        }\n    }\n    \n    // Loop\n    while (total_len < MAX_MOVES) {\n        if (pq.empty()) break;\n        \n        auto item = pq.top();\n        pq.pop();\n        double score = item.first;\n        int u = item.second.first;\n        int v = item.second.second;\n        \n        // Re-evaluate score lazily or just assume it's ok?\n        // Since scores decrease as k increases, the top is likely the best.\n        // But we should check.\n        double current_val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n        if (current_val < score - 1e-9) {\n            pq.push({current_val, {u, v}});\n            continue;\n        }\n        \n        // Add detour\n        if (total_len + 2 > MAX_MOVES) break;\n        \n        cnt[u][v]++;\n        cnt[v][u]++;\n        k[u]++;\n        k[v]++;\n        total_len += 2;\n        \n        // Push updates for neighbors of u and v\n        for (int w : adj[u]) {\n            int a = min(u, w);\n            int b = max(u, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n        for (int w : adj[v]) {\n            int a = min(v, w);\n            int b = max(v, w);\n            double val = (double)d[a] / (k[a] * k[a]) + (double)d[b] / (k[b] * k[b]);\n            pq.push({val, {a, b}});\n        }\n    }\n    \n    // Hierholzer's Algorithm\n    // We need to construct the path string.\n    // Start at 0.\n    \n    // We need a mutable copy of adj with edge counts to remove edges.\n    // Or just use cnt array and decrement.\n    // Since max moves is 100k, recursion is safe? 100k depth might be too much for stack.\n    // Use iterative stack or manual stack.\n    \n    vector<char> path;\n    vector<int> stack_path;\n    stack_path.push_back(0);\n    \n    // To optimize neighbor iteration in Hierholzer, we can store current edge index?\n    // Or just loop.\n    \n    while (!stack_path.empty()) {\n        int u = stack_path.back();\n        bool found = false;\n        for (int v : adj[u]) {\n            if (cnt[u][v] > 0) {\n                // Take this edge\n                cnt[u][v]--;\n                \n                // Find direction char\n                int i1, j1, i2, j2;\n                from_idx(u, i1, j1);\n                from_idx(v, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                \n                stack_path.push_back(v);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) {\n            stack_path.pop_back();\n            if (!stack_path.empty()) {\n                int prev = stack_path.back();\n                // Find direction from prev to u\n                int i1, j1, i2, j2;\n                from_idx(prev, i1, j1);\n                from_idx(u, i2, j2);\n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                path.push_back(c);\n            }\n        }\n    }\n    \n    // Path is constructed backwards\n    reverse(path.begin(), path.end());\n    \n    // Output\n    for (char c : path) {\n        cout << c;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconstexpr int M_MAX = 200;\nconstexpr int MAX_N = 15;\nconstexpr int INF = 1e9;\n\nint N = 15;\nint M = 0;\nint N2 = 225;\n\nint grid[MAX_N][MAX_N];\nvector<int> char_pos[26];\nint start_pos;\nvector<string> targets(M_MAX);\n\nint dist[MAX_N * MAX_N][MAX_N * MAX_N];\n\n// Timer\nstd::chrono::system_clock::time_point start_time;\n\nint get_elapsed_ms() {\n    auto now = std::chrono::system_clock::now();\n    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n}\n\nvoid precompute() {\n    N2 = N * N;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            for (int k = 0; k < N; ++k) {\n                for (int l = 0; l < N; ++l) {\n                    int v = k * N + l;\n                    dist[u][v] = abs(i - k) + abs(j - l);\n                }\n            }\n        }\n    }\n}\n\nint calc_overlap(const string& A, const string& B) {\n    int max_ov = 0;\n    int len_A = A.size();\n    int len_B = B.size();\n    int limit = min(len_A, len_B);\n    if (limit > 4) limit = 4;\n    for (int k = 1; k <= limit; ++k) {\n        if (A.compare(len_A - k, k, B, 0, k) == 0) {\n            max_ov = k;\n        }\n    }\n    return max_ov;\n}\n\nint overlap_mat[M_MAX][M_MAX];\n\nvoid build_overlap_matrix() {\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                overlap_mat[i][j] = 0;\n                continue;\n            }\n            overlap_mat[i][j] = calc_overlap(targets[i], targets[j]);\n        }\n    }\n}\n\nstring build_string(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5);\n    s.append(targets[order[0]]);\n    for (size_t i = 1; i < order.size(); ++i) {\n        int u = order[i-1];\n        int v = order[i];\n        int ov = overlap_mat[u][v];\n        const string& t = targets[v];\n        s.append(t.c_str() + ov, t.size() - ov);\n    }\n    return s;\n}\n\nvector<int> dp_buf;\nvector<int> next_dp_buf;\nvector<int> prev_step_buf; \n\npair<int, vector<pair<int, int>>> solve_grid(const string& s, bool store_path = false) {\n    if (s.empty()) return {0, {}};\n\n    int len = s.size();\n\n    // Resize buffers\n    if (dp_buf.size() != N2) dp_buf.resize(N2);\n    if (next_dp_buf.size() != N2) next_dp_buf.resize(N2);\n    \n    size_t required_prev_size = (size_t)len * N2;\n    if (prev_step_buf.size() < required_prev_size) {\n        prev_step_buf.resize(required_prev_size);\n    }\n\n    fill(dp_buf.begin(), dp_buf.end(), INF);\n    dp_buf[start_pos] = 0;\n    \n    // IMPORTANT: Reset prev_step_buf to -1 to prevent reading garbage from previous calls\n    fill(prev_step_buf.begin(), prev_step_buf.begin() + required_prev_size, -1);\n\n    auto get_prev = [&](int step, int u) -> int& {\n        return prev_step_buf[step * N2 + u];\n    };\n\n    for (size_t i = 0; i < len; ++i) {\n        char c = s[i];\n        fill(next_dp_buf.begin(), next_dp_buf.end(), INF);\n        \n        int c_idx = c - 'A';\n        \n        // Safety check for character index\n        if (c_idx < 0 || c_idx >= 26) continue; \n\n        for (int v : char_pos[c_idx]) {\n            int best_cost = INF;\n            int best_prev = -1;\n            \n            for (int u = 0; u < N2; ++u) {\n                if (dp_buf[u] == INF) continue;\n                int cost = dp_buf[u] + dist[u][v] + 1;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_prev = u;\n                }\n            }\n            \n            if (best_cost < INF) {\n                next_dp_buf[v] = best_cost;\n                if (store_path) {\n                    get_prev(i, v) = best_prev;\n                }\n            }\n        }\n        swap(dp_buf, next_dp_buf);\n    }\n\n    int min_cost = *min_element(dp_buf.begin(), dp_buf.end());\n    vector<pair<int, int>> path;\n\n    if (store_path && min_cost < INF) {\n        path.resize(len);\n        int end_pos = -1;\n        for (int i = 0; i < N2; ++i) {\n            if (dp_buf[i] == min_cost) {\n                end_pos = i;\n                break;\n            }\n        }\n        \n        if (end_pos != -1) {\n            int curr = end_pos;\n            bool valid_path = true;\n            for (int i = len - 1; i >= 0; --i) {\n                if (curr < 0 || curr >= N2) {\n                    valid_path = false;\n                    break;\n                }\n                path[i] = {curr / N, curr % N};\n                curr = get_prev(i, curr);\n            }\n            if (!valid_path) {\n                path.clear();\n            }\n        }\n    }\n\n    return {min_cost, path};\n}\n\nvector<int> initial_order_greedy() {\n    vector<int> order;\n    vector<bool> used(M, false);\n    \n    std::random_device rd;\n    std::mt19937 gen(rd());\n    uniform_int_distribution<> dis(0, M-1);\n    int first = dis(gen);\n    \n    order.push_back(first);\n    used[first] = true;\n    \n    for (int count = 1; count < M; ++count) {\n        int last = order.back();\n        int best_next = -1;\n        int max_ov = -1;\n        vector<int> candidates;\n        \n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlap_mat[last][i];\n            if (ov > max_ov) {\n                max_ov = ov;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (ov == max_ov) {\n                candidates.push_back(i);\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        uniform_int_distribution<> cand_dis(0, (int)candidates.size()-1);\n        best_next = candidates[cand_dis(gen)];\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\nvoid solve() {\n    // Read N and M from input\n    int read_N, read_M;\n    cin >> read_N >> read_M;\n    N = read_N;\n    M = read_M;\n    \n    int si, sj;\n    cin >> si >> sj;\n    start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = row[j];\n            char_pos[row[j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i];\n    }\n    \n    precompute();\n    build_overlap_matrix();\n\n    vector<int> current_order = initial_order_greedy();\n    string current_s = build_string(current_order);\n    auto [current_cost, _] = solve_grid(current_s);\n    \n    vector<int> best_order = current_order;\n    int best_cost = current_cost;\n    \n    double time_limit = 1900.0; \n    \n    std::random_device rd;\n    std::mt19937 gen(rd());\n    uniform_int_distribution<> idx_dist(0, M-1);\n    uniform_real_distribution<> prob_dist(0.0, 1.0);\n\n    double start_temp = 1000.0; \n    double end_temp = 10.0;\n\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        int idx1 = idx_dist(gen);\n        int idx2 = idx_dist(gen);\n        while(idx1 == idx2) idx2 = idx_dist(gen);\n        \n        swap(current_order[idx1], current_order[idx2]);\n        \n        string new_s = build_string(current_order);\n        auto [new_cost, _] = solve_grid(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            swap(current_order[idx1], current_order[idx2]);\n        }\n    }\n    \n    string final_s = build_string(best_order);\n    auto [final_cost, path] = solve_grid(final_s, true);\n    \n    if (!path.empty()) {\n        for (auto p : path) {\n            cout << p.first << \" \" << p.second << \"\\n\";\n        }\n    } else {\n        // Fallback: output start position if path reconstruction fails\n        cout << (start_pos / N) << \" \" << (start_pos % N) << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = std::chrono::system_clock::now();\n    \n    solve();\n    \n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\n#include <atcoder/random>\nusing namespace std;\nusing namespace atcoder;\n\nconst double INF = 1e9;\nconst int MAX_N = 20;\nconst int MAX_M = 20;\n\n// Global variables\nint N, M;\ndouble eps;\nvector<vector<pair<int, int>>> shapes; // Relative coordinates of each shape\nvector<pair<int, int>> shape_sizes;   // (height, width) of each shape\nmap<pair<int, int>, int> fixed_cells; // Known values: (r,c) -> value\n\n// Estimated sums from divination\nvector<double> est_row_sums;\nvector<double> est_col_sums;\n\n// Inverse variances for chi-squared\ndouble inv_var_row;\ndouble inv_var_col;\n\n// Random number generator\nrandom_device rd;\nmt19937 gen(rd());\n\n// Operation cost tracking\ndouble total_cost = 0.0;\n\n// Helper to output and flush\nvoid flush_output() {\n    cout << flush;\n}\n\n// Divination operation\ndouble divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto [r, c] : cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0 / sqrt(k);\n    \n    // Invert the noise model\n    // y ~ round(max(0, x)), x ~ N(k*eps + T(1-2*eps), k*eps(1-eps))\n    // Estimate T\n    double T_est = (res - k * eps) / (1.0 - 2.0 * eps);\n    if (T_est < 0) T_est = 0; // T must be non-negative\n    return T_est;\n}\n\n// Drilling operation\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0;\n    fixed_cells[{r, c}] = res;\n    return res;\n}\n\n// Answer operation\nbool answer(const vector<pair<int, int>>& pos_cells) {\n    cout << \"a \" << pos_cells.size();\n    for (auto [r, c] : pos_cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    return res == 1;\n}\n\n// State representation for SA\nstruct State {\n    vector<pair<int, int>> pos; // (r, c) for each field\n    int grid[MAX_N][MAX_N];\n    double energy;\n\n    void compute_grid_and_energy() {\n        // Reset grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = 0;\n            }\n        }\n\n        // Place fields\n        for (int k = 0; k < M; ++k) {\n            auto [pr, pc] = pos[k];\n            for (auto [dr, dc] : shapes[k]) {\n                int r = pr + dr;\n                int c = pc + dc;\n                grid[r][c]++;\n            }\n        }\n\n        // Check fixed cells constraint\n        for (auto [p, val] : fixed_cells) {\n            if (grid[p.first][p.second] != val) {\n                energy = INF;\n                return;\n            }\n        }\n\n        // Calculate chi-squared distance to observed row/col sums\n        double err = 0.0;\n        \n        // Row sums\n        for (int i = 0; i < N; ++i) {\n            int sum = 0;\n            for (int j = 0; j < N; ++j) sum += grid[i][j];\n            double diff = sum - est_row_sums[i];\n            err += diff * diff * inv_var_row;\n        }\n\n        // Column sums\n        for (int j = 0; j < N; ++j) {\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += grid[i][j];\n            double diff = sum - est_col_sums[j];\n            err += diff * diff * inv_var_col;\n        }\n\n        energy = err;\n    }\n};\n\n// Simulated Annealing\nState run_sa(int iterations) {\n    State cur, best;\n    cur.pos.resize(M);\n    best.pos.resize(M);\n\n    // Initialize random valid positions\n    for (int k = 0; k < M; ++k) {\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        cur.pos[k] = {dist_r(gen), dist_c(gen)};\n    }\n    cur.compute_grid_and_energy();\n    best = cur;\n\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        State nxt = cur;\n        \n        // Pick a field to move\n        int k = uniform_int_distribution<>(0, M - 1)(gen);\n        \n        // Generate new position\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        \n        if (uniform_real_distribution<>(0, 1)(gen) < 0.1) {\n            // Jump\n            nxt.pos[k] = {dist_r(gen), dist_c(gen)};\n        } else {\n            // Small step\n            int dr = uniform_int_distribution<>(-2, 2)(gen);\n            int dc = uniform_int_distribution<>(-2, 2)(gen);\n            int nr = nxt.pos[k].first + dr;\n            int nc = nxt.pos[k].second + dc;\n            \n            // Clamp to valid range\n            nr = max(0, min(N - h, nr));\n            nc = max(0, min(N - w, nc));\n            nxt.pos[k] = {nr, nc};\n        }\n\n        nxt.compute_grid_and_energy();\n\n        if (nxt.energy < cur.energy || uniform_real_distribution<>(0, 1)(gen) < exp((cur.energy - nxt.energy) / max(temp, 0.1))) {\n            cur = nxt;\n        }\n\n        if (cur.energy < best.energy) {\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M >> eps;\n    shapes.resize(M);\n    shape_sizes.resize(M);\n\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n            shapes[k].emplace_back(r, c);\n            max_r = max(max_r, r);\n            max_c = max(max_c, c);\n        }\n        shape_sizes[k] = {max_r, max_c};\n    }\n\n    // Precompute inverse variances\n    // Variance = k * eps * (1 - eps)\n    inv_var_row = 1.0 / (N * eps * (1.0 - eps));\n    inv_var_col = 1.0 / (N * eps * (1.0 - eps));\n    est_row_sums.resize(N);\n    est_col_sums.resize(N);\n\n    // Initial Probing: Rows and Columns\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_cells;\n        for (int j = 0; j < N; ++j) row_cells.emplace_back(i, j);\n        est_row_sums[i] = divine(row_cells);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_cells;\n        for (int i = 0; i < N; ++i) col_cells.emplace_back(i, j);\n        est_col_sums[j] = divine(col_cells);\n    }\n\n    // Main search loop\n    int max_ops = 2 * N * N;\n    int sa_iters = 3000; // Per iteration\n    \n    // We want to leave some buffer for the answer query\n    while (total_cost < max_ops - 1) {\n        // Run SA\n        State best_state = run_sa(sa_iters);\n\n        // If energy is very low, we might be done\n        // Heuristic: if energy < 10 (which is small for 40 degrees of freedom)\n        if (best_state.energy < 5.0) {\n            // Verify a few random cells or just submit?\n            // Let's try to submit if we are very confident\n            // Or drill one last cell to be safe\n            \n            // Construct answer\n            vector<pair<int, int>> ans;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0) {\n                        ans.emplace_back(i, j);\n                    }\n                }\n            }\n            \n            // Check if we have budget for another drill\n            if (total_cost + 1 + 0.01 > max_ops) {\n                 // Submit\n                if (answer(ans)) return;\n                else {\n                    // If wrong, we shouldn't really get here often if energy is low.\n                    // If we do, we break loop because we can't afford more ops?\n                    // Actually, we just continue if we have time.\n                    // But answer costs 1. So we lost 1 op.\n                }\n            } else {\n                // Try to verify a high-value cell\n                // Find a cell with max v that is not fixed\n                pair<int, int> target = {-1, -1};\n                int max_v = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                            if (best_state.grid[i][j] > max_v) {\n                                max_v = best_state.grid[i][j];\n                                target = {i, j};\n                            }\n                        }\n                    }\n                }\n\n                if (target.first != -1) {\n                    drill(target.first, target.second);\n                } else {\n                    // All positive cells fixed. Submit.\n                    if (answer(ans)) return;\n                }\n            }\n        } else {\n            // Energy is not low enough. Drill a cell to improve.\n            // Strategy: Drill a cell that is positive in the best model\n            pair<int, int> target = {-1, -1};\n            int max_v = -1;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                        if (best_state.grid[i][j] > max_v) {\n                            max_v = best_state.grid[i][j];\n                            target = {i, j};\n                        }\n                    }\n                }\n            }\n\n            // If no positive cell found (all fixed?), check empty?\n            // Or just pick a cell with v=0 that is surrounded by v>0?\n            if (target.first == -1) {\n                 // This case implies model says no undrilled positive cells.\n                 // But energy is high. Means model is wrong (missed some oil).\n                 // We should drill somewhere to find the missing oil.\n                 // Pick a random undrilled cell with v=0 in model.\n                 vector<pair<int,int>> candidates;\n                 for (int i=0; i<N; ++i) {\n                     for (int j=0; j<N; ++j) {\n                         if (best_state.grid[i][j] == 0 && fixed_cells.count({i,j}) == 0) {\n                             candidates.emplace_back(i,j);\n                         }\n                     }\n                 }\n                 if (!candidates.empty()) {\n                     target = candidates[uniform_int_distribution<>(0, candidates.size()-1)(gen)];\n                 } else {\n                     // All cells fixed? Just submit.\n                     vector<pair<int, int>> ans;\n                     for (int i = 0; i < N; ++i) {\n                        for (int j = 0; j < N; ++j) {\n                            if (best_state.grid[i][j] > 0) ans.emplace_back(i, j);\n                        }\n                    }\n                    if (answer(ans)) return;\n                 }\n            }\n            \n            if (target.first != -1) drill(target.first, target.second);\n        }\n    }\n    \n    // Fallback / Time up: Submit current best guess\n    State final_state = run_sa(1000); // Quick last run\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (final_state.grid[i][j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    answer(ans);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <deque>\n\nusing namespace std;\n\nconst int W = 1000;\nconst long long INF = 1e18;\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_input, D, N;\n    cin >> W_input >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // prev_cuts[k] stores the y-coordinate of the k-th cut (0-indexed) from the previous day.\n    // Initially, we can assume cuts are at 0 (or any value, as L_0=0).\n    vector<int> prev_cuts(N - 1, 0);\n\n    for (int d = 0; d < D; ++d) {\n        // dp_prev[v] = min cost to place the first (k-1) cuts, with the (k-1)-th cut at y=v.\n        // We start with k=1 (placing the 0th cut).\n        // Initial state: 0 cuts placed, virtual cut at y=0, cost 0.\n        vector<long long> dp_prev(W + 1, INF);\n        dp_prev[0] = 0;\n        \n        // choice[k][v] stores the position of the previous cut 'u' that led to cut 'k' being at 'v'.\n        // k is 1-indexed for cuts (1 to N-1).\n        vector<vector<int>> choice(N, vector<int>(W + 1, -1));\n\n        // Iterate to place the k-th cut (1-indexed)\n        for (int k = 1; k < N; ++k) {\n            // The rectangle to the left of this cut is rectangle (k-1) (0-indexed).\n            int A = a[d][k-1];\n            int min_h = (A + W - 1) / W; // Minimum height to avoid deficit\n            if (min_h == 0) min_h = 1;\n\n            // Precompute B[u] = dp_prev[u] + 100 * W * u\n            // Used for calculating cost when deficit occurs.\n            vector<long long> B(W + 1);\n            for (int i = 0; i <= W; ++i) {\n                B[i] = dp_prev[i] + (long long)100 * W * i;\n            }\n\n            vector<long long> dp_curr(W + 1, INF);\n            \n            // Prefix minima for dp_prev (Case 1: No deficit)\n            // pmin[i] = min(dp_prev[0...i-1])\n            vector<long long> pmin(W + 2, INF);\n            vector<int> parg(W + 2, -1);\n            for (int i = 0; i <= W; ++i) {\n                if (dp_prev[i] < pmin[i]) {\n                    pmin[i+1] = dp_prev[i];\n                    parg[i+1] = i;\n                } else {\n                    pmin[i+1] = pmin[i];\n                    parg[i+1] = parg[i];\n                }\n            }\n            \n            // Sliding window minimum for B[u] (Case 2: Deficit)\n            // We need min(B[u]) for u in [v - min_h + 1, v - 1]\n            deque<int> dq;\n\n            for (int v = 1; v <= W; ++v) {\n                // Update deque for the current window ending at v-1\n                // 1. Add u = v - 1\n                while (!dq.empty() && B[dq.back()] >= B[v - 1]) {\n                    dq.pop_back();\n                }\n                dq.push_back(v - 1);\n                \n                // 2. Remove indices < v - min_h + 1\n                while (!dq.empty() && dq.front() < v - min_h + 1) {\n                    dq.pop_front();\n                }\n\n                // Calculate costs\n                long long best_inner_cost = INF;\n                int best_u = -1;\n\n                // Case 1: u <= v - min_h (No deficit)\n                // Cost is dp_prev[u]. We want min over u in [0, v - min_h]\n                if (v - min_h >= 0) {\n                    long long c1 = pmin[v - min_h + 1];\n                    if (c1 < best_inner_cost) {\n                        best_inner_cost = c1;\n                        best_u = parg[v - min_h + 1];\n                    }\n                }\n\n                // Case 2: u in [v - min_h + 1, v - 1] (Deficit)\n                // Cost is 100*A - 100*W*v + min(B[u])\n                if (!dq.empty()) {\n                    int idx = dq.front();\n                    long long c2 = B[idx] + (long long)100 * A - (long long)100 * W * v;\n                    if (c2 < best_inner_cost) {\n                        best_inner_cost = c2;\n                        best_u = idx;\n                    }\n                }\n\n                if (best_inner_cost < INF) {\n                    // Add move cost.\n                    // On Day 0 (d==0), L_0=0, so move cost is 0.\n                    // For d > 0, cost is 2 * W * |v - prev_cuts[k-1]|\n                    long long move_cost = (d == 0) ? 0 : 2000 * abs(v - prev_cuts[k-1]);\n                    dp_curr[v] = best_inner_cost + move_cost;\n                    choice[k][v] = best_u;\n                } else {\n                    dp_curr[v] = INF;\n                }\n            }\n            \n            dp_prev = dp_curr;\n        }\n\n        // Determine the optimal position for the last cut (N-1)\n        // And account for the last rectangle (N-1)\n        int last_min_h = (a[d][N-1] + W - 1) / W;\n        int best_v = -1;\n        long long min_total_cost = INF;\n\n        for (int v = 0; v <= W; ++v) {\n            if (dp_prev[v] >= INF) continue;\n            \n            long long cost = dp_prev[v];\n            int h_last = W - v;\n            if (h_last < last_min_h) {\n                cost += (long long)100 * (a[d][N-1] - (long long)W * h_last);\n            }\n            \n            if (cost < min_total_cost) {\n                min_total_cost = cost;\n                best_v = v;\n            }\n        }\n\n        // Fallback in case no valid configuration found (should not happen with correct constraints)\n        if (best_v == -1) {\n            best_v = W / 2; // Just a fallback to avoid crash\n        }\n\n        // Reconstruct cuts\n        vector<int> new_cuts(N - 1);\n        int curr_v = best_v;\n        bool valid_reconstruction = true;\n        \n        for (int k = N - 1; k >= 1; --k) {\n            new_cuts[k-1] = curr_v;\n            if (curr_v < 0 || curr_v > W || choice[k][curr_v] == -1) {\n                // Fallback to equal partition if reconstruction fails\n                valid_reconstruction = false;\n                break;\n            }\n            curr_v = choice[k][curr_v];\n        }\n\n        if (!valid_reconstruction) {\n            // Fallback strategy: Divide equally\n            int step = W / N;\n            for (int i = 0; i < N - 1; ++i) {\n                new_cuts[i] = step * (i + 1);\n            }\n        }\n\n        // Output\n        int y_prev = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            int y_curr = new_cuts[k];\n            // Ensure strictly increasing coordinates\n            if (y_curr <= y_prev) y_curr = y_prev + 1; \n            if (y_curr > W) y_curr = W;\n            \n            cout << y_prev << \" \" << 0 << \" \" << y_curr << \" \" << W << \"\\n\";\n            y_prev = y_curr;\n        }\n        // Last rectangle\n        if (y_prev >= W) y_prev = W - 1; // Safety\n        cout << y_prev << \" \" << 0 << \" \" << W << \" \" << W << \"\\n\";\n\n        // Update previous cuts for next day\n        prev_cuts = new_cuts;\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <tuple>\n#include <queue>\n\nusing namespace std;\n\nconst int MOD = 998244353;\n\n// --- Common Structures ---\n\nstruct Board {\n    array<long long, 81> data; // Flattened 9x9\n\n    long long get_score() const {\n        long long s = 0;\n        for (int i = 0; i < 81; ++i) {\n            s += data[i] % MOD;\n        }\n        return s;\n    }\n};\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Greedy Solver ---\n\nvector<Operation> solve_greedy(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    Board board = initial_board;\n    \n    // Gains cache\n    array<array<array<long long, 7>, 7>, 20> gains{};\n    \n    auto calc_gain = [&](int m, int p, int q) {\n        long long diff = 0;\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int idx = (p+i)*9 + (q+j);\n                long long old_v = board.data[idx];\n                long long new_v = old_v + stamps[m][i*3+j];\n                diff += (new_v % MOD) - (old_v % MOD);\n            }\n        }\n        return diff;\n    };\n\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < 7; ++p) {\n            for (int q = 0; q < 7; ++q) {\n                gains[m][p][q] = calc_gain(m, p, q);\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(K);\n\n    for (int turn = 0; turn < K; ++turn) {\n        long long best_gain = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < 7; ++p) {\n                for (int q = 0; q < 7; ++q) {\n                    if (gains[m][p][q] > best_gain) {\n                        best_gain = gains[m][p][q];\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_gain <= 0) break;\n\n        ops.push_back({best_m, best_p, best_q});\n\n        // Apply\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                board.data[(best_p+i)*9 + (best_q+j)] += stamps[best_m][i*3+j];\n            }\n        }\n\n        // Update gains\n        int p_min = max(0, best_p - 2);\n        int p_max = min(6, best_p + 2);\n        int q_min = max(0, best_q - 2);\n        int q_max = min(6, best_q + 2);\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = p_min; p <= p_max; ++p) {\n                for (int q = q_min; q <= q_max; ++q) {\n                    gains[m][p][q] = calc_gain(m, p, q);\n                }\n            }\n        }\n    }\n    return ops;\n}\n\n// --- Beam Search Solver (Memory Efficient) ---\n\nstruct HistoryNode {\n    int parent;\n    char m, p, q; // Operation to reach this state. -1 for initial or do-nothing\n};\n\nstruct BeamState {\n    Board board;\n    long long score;\n    int history_idx; // Index in global history\n};\n\nvector<Operation> solve_beam(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    // Parameters\n    const int BEAM_WIDTH = 400;\n    const int BRANCH_FACTOR = 120; \n    const int GREEDY_INIT_DEPTH = 10;\n\n    vector<HistoryNode> history;\n    vector<BeamState> current_beam;\n\n    // 1. Initialize with root state\n    HistoryNode root_node{-1, -1, -1, -1};\n    history.push_back(root_node);\n    current_beam.push_back({initial_board, initial_board.get_score(), 0});\n\n    // 2. Seed with Greedy path\n    Board temp_board = initial_board;\n    vector<Operation> greedy_ops = solve_greedy(initial_board, stamps, M, min(K, GREEDY_INIT_DEPTH));\n    \n    int h_idx = 0;\n    for (auto op : greedy_ops) {\n        h_idx++;\n        HistoryNode node{(int)history.size() - 1, (char)op.m, (char)op.p, (char)op.q};\n        history.push_back(node);\n        \n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                temp_board.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n            }\n        }\n        current_beam.push_back({temp_board, temp_board.get_score(), (int)history.size() - 1});\n    }\n\n    // Beam Search Loop\n    for (int step = 0; step < K; ++step) {\n        vector<BeamState> candidates;\n        // Reserving space helps performance significantly\n        candidates.reserve(current_beam.size() * (BRANCH_FACTOR + 1));\n\n        for (const auto& state : current_beam) {\n            // A. \"Do Nothing\" move\n            // Gain is 0. \n            HistoryNode noop_node{state.history_idx, -1, -1, -1};\n            history.push_back(noop_node);\n            candidates.push_back({state.board, state.score, (int)history.size() - 1});\n\n            // B. Generate Moves\n            // Instead of creating a huge vector, we can process and keep top N?\n            // But sorting requires vector. Given the scale (400 * 1000), creating vector of tuples is fine.\n            // Optimization: Precompute stamp contributions? No, dynamic board.\n            \n            vector<tuple<long long, int, int, int>> potential_moves;\n            potential_moves.reserve(M * 49);\n\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < 7; ++p) {\n                    for (int q = 0; q < 7; ++q) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                long long old_v = state.board.data[(p+i)*9 + (q+j)];\n                                long long new_v = old_v + stamps[m][i*3+j];\n                                gain += (new_v % MOD) - (old_v % MOD);\n                            }\n                        }\n                        potential_moves.emplace_back(gain, m, p, q);\n                    }\n                }\n            }\n\n            // Select top BRANCH_FACTOR\n            int limit = min((int)potential_moves.size(), BRANCH_FACTOR);\n            if (limit > 0) {\n                nth_element(potential_moves.begin(), potential_moves.begin() + limit, potential_moves.end(), \n                    [](const auto& a, const auto& b){ return get<0>(a) > get<0>(b); });\n                \n                // No need to fully sort strictly, but nth_element guarantees first 'limit' are the top ones.\n                // We iterate over them.\n                for (int i = 0; i < limit; ++i) {\n                    auto [gain, m, p, q] = potential_moves[i];\n                    \n                    // Create new state\n                    Board next_board = state.board;\n                    for (int di = 0; di < 3; ++di) {\n                        for (int dj = 0; dj < 3; ++dj) {\n                            next_board.data[(p+di)*9 + (q+dj)] += stamps[m][di*3+dj];\n                        }\n                    }\n                    long long next_score = state.score + gain;\n                    \n                    HistoryNode node{state.history_idx, (char)m, (char)p, (char)q};\n                    history.push_back(node);\n                    candidates.push_back({next_board, next_score, (int)history.size() - 1});\n                }\n            }\n        }\n\n        // Selection\n        int next_limit = min((int)candidates.size(), BEAM_WIDTH);\n        if (next_limit == 0) break;\n\n        auto mid = candidates.begin() + next_limit;\n        nth_element(candidates.begin(), mid, candidates.end(), \n            [](const BeamState& a, const BeamState& b){ return a.score > b.score; });\n\n        current_beam.assign(candidates.begin(), candidates.begin() + next_limit);\n    }\n\n    // Find best state in final beam\n    long long best_score = -1;\n    int best_history_idx = -1;\n    for (const auto& state : current_beam) {\n        if (state.score > best_score) {\n            best_score = state.score;\n            best_history_idx = state.history_idx;\n        }\n    }\n\n    // Reconstruct\n    vector<Operation> ops;\n    int curr = best_history_idx;\n    while (curr != 0) {\n        const HistoryNode& node = history[curr];\n        if (node.m != -1) {\n            ops.emplace_back(node.m, node.p, node.q);\n        }\n        curr = node.parent;\n    }\n    // Reverse\n    reverse(ops.begin(), ops.end());\n    return ops;\n}\n\n// --- Main ---\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    Board initial_board;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> initial_board.data[i * 9 + j];\n        }\n    }\n\n    // Read stamps\n    vector<vector<long long>> stamps(M, vector<long long>(9));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i * 3 + j];\n            }\n        }\n    }\n\n    // 1. Solve Greedy\n    auto ops_greedy = solve_greedy(initial_board, stamps, M, K);\n    \n    // Score Greedy\n    Board b_greedy = initial_board;\n    long long score_greedy = 0;\n    for(auto op : ops_greedy) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_greedy.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_greedy = b_greedy.get_score();\n\n    // 2. Solve Beam Search\n    auto ops_beam = solve_beam(initial_board, stamps, M, K);\n    \n    // Score Beam\n    Board b_beam = initial_board;\n    long long score_beam = 0;\n    for(auto op : ops_beam) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_beam.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_beam = b_beam.get_score();\n\n    // 3. Output Best\n    if (score_beam > score_greedy) {\n        cout << ops_beam.size() << \"\\n\";\n        for (auto op : ops_beam) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    } else {\n        cout << ops_greedy.size() << \"\\n\";\n        for (auto op : ops_greedy) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    vector<vector<int>> A(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> A[i][j];\n        }\n    }\n    \n    vector<int> target_row(N * N);\n    for (int c = 0; c < N * N; c++) target_row[c] = c / N;\n    \n    vector<vector<int>> arrival(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) arrival[i][j] = A[i][j];\n    \n    vector<int> arrived(N, 0);\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_x(N), crane_y(N);\n    vector<int> carrying(N, -1);\n    \n    for (int i = 0; i < N; i++) {\n        crane_x[i] = i;\n        crane_y[i] = 0;\n    }\n    \n    vector<string> actions(N);\n    vector<bool> dispatched(N * N, false);\n    \n    for (int t = 0; t < MAX_TURNS; t++) {\n        // Step 1: Container arrivals\n        for (int i = 0; i < N; i++) {\n            // A container appears if:\n            // 1. There is no container at the gate.\n            // 2. There is no crane *holding a container* at the gate.\n            // (Note: A crane standing there empty-handed does NOT block arrival).\n            \n            bool blocked_by_carrying = false;\n            for (int c = 0; c < N; c++) {\n                if (crane_x[c] == i && crane_y[c] == 0 && carrying[c] != -1) {\n                    blocked_by_carrying = true;\n                }\n            }\n            \n            if (grid[i][0] == -1 && !blocked_by_carrying && arrived[i] < N) {\n                grid[i][0] = arrival[i][arrived[i]++];\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        vector<char> act(N, '.');\n        vector<int> nx = crane_x, ny = crane_y;\n        vector<int> ncarry = carrying;\n        \n        for (int c = 0; c < N; c++) {\n            if (c == 0) {\n                // Large Crane\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (crane_x[c] < tr) { act[c] = 'D'; nx[c]++; }\n                    else if (crane_x[c] > tr) { act[c] = 'U'; nx[c]--; }\n                    else if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                    else { act[c] = 'Q'; ncarry[c] = -1; }\n                } else {\n                    int best_i = -1, best_j = -1, best_score = -1e9;\n                    \n                    // Check if container under crane\n                    int under = grid[crane_x[c]][crane_y[c]];\n                    if (under != -1 && !dispatched[under]) {\n                        int tr = target_row[under];\n                        int score = 10000 - abs(tr - crane_x[c]); \n                        if (score > best_score) {\n                            best_score = score; best_i = crane_x[c]; best_j = crane_y[c];\n                        }\n                    }\n                    \n                    // Search for best container\n                    for (int i = 0; i < N; i++) {\n                        for (int j = 0; j < N; j++) {\n                            int cont = grid[i][j];\n                            if (cont != -1 && !dispatched[cont]) {\n                                int tr = target_row[cont];\n                                int wrong = (i != tr);\n                                int dist = abs(i - crane_x[c]) + abs(j - crane_y[c]);\n                                int score = wrong * 1000 - dist;\n                                if (score > best_score) {\n                                    best_score = score; best_i = i; best_j = j;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (best_i != -1) {\n                        if (crane_x[c] < best_i) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > best_i) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < best_j) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > best_j) { act[c] = 'L'; ny[c]--; }\n                        else { act[c] = 'P'; ncarry[c] = grid[best_i][best_j]; }\n                    } else {\n                        // Idle behavior: Move right to free gate\n                        if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                    }\n                }\n            } else {\n                // Small Cranes\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    if (tr == c) {\n                        // In correct row, go right\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c] + 1] == -1) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] == N - 1) { act[c] = 'Q'; ncarry[c] = -1; }\n                    } else {\n                        act[c] = 'Q'; ncarry[c] = -1;\n                    }\n                } else {\n                    // Not carrying\n                    int cont = grid[c][crane_y[c]];\n                    if (cont != -1 && target_row[cont] == c) {\n                        act[c] = 'P'; ncarry[c] = cont;\n                    } else {\n                        // Idle behavior: Look for container in row c\n                        bool found_cont = false;\n                        // Check right\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) {\n                             for (int k = crane_y[c] + 1; k < N; k++) if (grid[c][k] != -1) found_cont = true;\n                             if (found_cont) { act[c] = 'R'; ny[c]++; }\n                        } \n                        // Check left\n                        else if (crane_y[c] > 0 && grid[c][crane_y[c]-1] == -1) {\n                            for (int k = 0; k < crane_y[c]; k++) if (grid[c][k] != -1) found_cont = true;\n                            if (found_cont) { act[c] = 'L'; ny[c]--; }\n                        }\n                        // Try moving right regardless to make room if blocked by wall/crane logic?\n                        // Basic fallback: move right if empty to free gate\n                        if (act[c] == '.' && crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) {\n                             act[c] = 'R'; ny[c]++;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Step 3: Resolve collisions\n        for (int p = 0; p < N; p++) {\n            bool collision = false;\n            \n            // Check against all other cranes\n            for (int i = 0; i < N; i++) {\n                if (i == p) continue;\n                \n                // Position of the other crane (target if resolved, start if unresolved)\n                int other_x = (i < p) ? nx[i] : crane_x[i];\n                int other_y = (i < p) ? ny[i] : crane_y[i];\n                \n                // Check if my target conflicts with the other crane's location\n                if (nx[p] == other_x && ny[p] == other_y) {\n                    collision = true;\n                    break;\n                }\n            }\n            \n            // Small crane carrying cannot move to occupied by container\n            if (!collision && p != 0 && carrying[p] != -1 && act[p] != 'P' && act[p] != 'Q' && act[p] != '.') {\n                if (grid[nx[p]][ny[p]] != -1) {\n                    collision = true;\n                }\n            }\n            \n            if (collision) {\n                act[p] = '.';\n                nx[p] = crane_x[p];\n                ny[p] = crane_y[p];\n            }\n        }\n        \n        // Step 4: Execute\n        for (int c = 0; c < N; c++) {\n            actions[c] += act[c];\n            if (act[c] == 'P') grid[crane_x[c]][crane_y[c]] = -1;\n            else if (act[c] == 'Q') grid[crane_x[c]][crane_y[c]] = carrying[c];\n            crane_x[c] = nx[c]; crane_y[c] = ny[c]; carrying[c] = ncarry[c];\n        }\n        \n        // Step 5: Dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N - 1] != -1) {\n                dispatched[grid[i][N - 1]] = true;\n                grid[i][N - 1] = -1;\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)actions[i].size() < max_len) actions[i] += '.';\n        cout << actions[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Grid dimensions\nconst int N = 20;\nconst int INF = 1e9;\nconst int DX[4] = {0, 0, 1, -1};\nconst int DY[4] = {1, -1, 0, 0};\nconst char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n;\n    // N is always 20, but we read it just in case\n    if (!(cin >> n)) return 0; \n    \n    vector<int> h(n * n);\n    for (int i = 0; i < n * n; ++i) {\n        cin >> h[i];\n    }\n\n    // 1. Construct Min-Cost Flow Graph\n    // Nodes: 0 to n*n-1 are grid cells.\n    // Source S = n*n, Sink T = n*n + 1.\n    int S = n * n;\n    int T = n * n + 1;\n    mcf_graph<int, long long> graph(n * n + 2);\n    \n    long long total_supply = 0;\n\n    for (int i = 0; i < n * n; ++i) {\n        if (h[i] > 0) {\n            graph.add_edge(S, i, h[i], 0);\n            total_supply += h[i];\n        } else if (h[i] < 0) {\n            graph.add_edge(i, T, -h[i], 0);\n        }\n    }\n\n    // Add grid edges (undirected)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int u = i * n + j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + DX[k];\n                int nj = j + DY[k];\n                if (0 <= ni && ni < n && 0 <= nj && nj < n) {\n                    int v = ni * n + nj;\n                    // Cost is 1 per unit distance\n                    graph.add_edge(u, v, INF, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min-Cost Flow\n    auto result = graph.flow(S, T, total_supply);\n    // result.second is the min cost (sum of amount * distance)\n    // We don't strictly need the value, just the flow distribution.\n\n    // 3. Extract Flow Graph\n    // adj[u] stores (v, flow) pairs for flow > 0\n    vector<vector<pair<int, int>>> adj(n * n);\n    auto edges = graph.edges();\n    for (const auto& e : edges) {\n        if (e.from < S && e.to < S && e.flow > 0) {\n            adj[e.from].emplace_back(e.to, e.flow);\n        }\n    }\n\n    // 4. Construct Path using DFS simulation\n    vector<string> ops;\n    int current_pos = 0; // Start at (0,0)\n    int current_load = 0;\n    \n    // Helper to perform moves\n    auto move_to = [&](int target_pos) {\n        int cx = current_pos / n;\n        int cy = current_pos % n;\n        int tx = target_pos / n;\n        int ty = target_pos % n;\n        \n        // Simple BFS to find path (since we just need a path, but shortest is best)\n        // For simplicity, just move greedily or BFS.\n        // Given the constraints and the fact that we mostly follow flow edges,\n        // we might just need to connect components. \n        // But here we implement BFS for shortest path.\n        \n        vector<int> prev(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        prev[current_pos] = current_pos;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_pos) break;\n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        // Reconstruct path\n        vector<int> path;\n        int curr = target_pos;\n        while (curr != current_pos) {\n            path.push_back(curr);\n            curr = prev[curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        for (int next_pos : path) {\n            int dx = (next_pos / n) - (current_pos / n);\n            int dy = (next_pos % n) - (current_pos % n);\n            for (int k = 0; k < 4; ++k) {\n                if (DX[k] == dx && DY[k] == dy) {\n                    ops.push_back(string(1, DIR_CHAR[k]));\n                    break;\n                }\n            }\n            current_pos = next_pos;\n            // We assume move_to is called with 0 load or correct load.\n            // The cost update is implicit in the operations.\n        }\n    };\n\n    // Helper to load/unload\n    auto check_height = [&]() {\n        if (h[current_pos] > 0) {\n            ops.push_back(\"+\" + to_string(h[current_pos]));\n            current_load += h[current_pos];\n            h[current_pos] = 0;\n        } else if (h[current_pos] < 0) {\n            // We need to unload.\n            // However, we might not have exactly -h[current_pos] available if flow is split weirdly?\n            // In theory, inflow should cover it.\n            int needed = -h[current_pos];\n            if (current_load >= needed) {\n                ops.push_back(\"-\" + to_string(needed));\n                current_load -= needed;\n                h[current_pos] = 0;\n            } else {\n                // Should not happen in optimal flow, but just in case:\n                // This implies we need to carry more soil here.\n                // Or we are processing in a weird order.\n                // With the tree traversal, we should arrive with sufficient load.\n                // If not, it's a logic error in flow construction or traversal.\n                // We will assume it holds.\n            }\n        }\n    };\n\n    // Recursive DFS to cover flow tree\n    // Returns true if we don't need to backtrack (optimized path end)\n    function<bool(int)> dfs = [&](int u) {\n        // 1. Satisfy height at u\n        check_height();\n        \n        // 2. Process children\n        if (adj[u].empty()) {\n            return true; // Leaf\n        }\n        \n        // Optimization: Find the child with the deepest/longest path to process last (to avoid backtrack)\n        // Simple heuristic: just iterate.\n        // To avoid backtrack on the last child:\n        for (size_t i = 0; i < adj[u].size(); ++i) {\n            int v = adj[u][i].first;\n            int flow_amt = adj[u][i].second;\n            \n            // We need to carry `flow_amt` from u to v.\n            // The rest of current_load (if any) should stay at u.\n            // We unload the rest, reload later.\n            int load_to_keep = current_load - flow_amt;\n            \n            if (load_to_keep > 0) {\n                ops.push_back(\"-\" + to_string(load_to_keep));\n                current_load -= load_to_keep;\n                // Height of u increases temporarily. This is fine, we fix it later.\n                h[u] += load_to_keep; \n            }\n            \n            // Move to v\n            move_to(v);\n            // current_load should be flow_amt now\n            if (current_load != flow_amt) {\n                // Logic error\n            }\n            \n            bool should_return = true;\n            if (i == adj[u].size() - 1) {\n                should_return = false; // Last child, don't return\n            }\n            \n            bool child_is_leaf = dfs(v);\n            \n            if (!should_return) {\n                return false; // Propagate \"don't return\" up\n            }\n            \n            // Return from v\n            // At v, we should have 0 load (all deposited at its children/height)\n            // Move back to u\n            move_to(u);\n            \n            // Reload the soil we left at u\n            if (load_to_keep > 0) {\n                ops.push_back(\"+\" + to_string(load_to_keep));\n                current_load += load_to_keep;\n                h[u] -= load_to_keep;\n            }\n            // Now current_load is restored for next child\n        }\n        return true;\n    };\n\n    // Main loop to handle disconnected components\n    while (true) {\n        // Check if any flow remains\n        bool has_flow = false;\n        int best_u = -1;\n        int best_dist = INF;\n        \n        // Find closest node with remaining outflow\n        // Simple BFS from current_pos\n        vector<int> dist(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        dist[current_pos] = 0;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            \n            if (!adj[u].empty()) {\n                if (dist[u] < best_dist) {\n                    best_dist = dist[u];\n                    best_u = u;\n                }\n            }\n            \n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (dist[v] == -1) {\n                        dist[v] = dist[u] + 1;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        if (best_u == -1) break; // Done\n        \n        if (best_u != current_pos) {\n            // Move to best_u with 0 load (we assume we can reach with 0 load)\n            // We need to ensure we have 0 load to move optimally?\n            // Actually, we might have load if we are in a middle of something.\n            // But this loop handles disconnected components.\n            // So we should be at load 0 when jumping.\n            move_to(best_u);\n        }\n        \n        // Process component starting at best_u\n        dfs(best_u);\n    }\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// MT19937 for random number generation\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    int grid_size = N * N;\n\n    // Precompute neighbor offsets for grid indices\n    // 0..(N-1) is row 0, N..(2N-1) is row 1, etc.\n    vector<vector<int>> neighbors(grid_size);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int idx = r * N + c;\n            if (r > 0) neighbors[idx].push_back(idx - N);     // Up\n            if (r < N - 1) neighbors[idx].push_back(idx + N); // Down\n            if (c > 0) neighbors[idx].push_back(idx - 1);     // Left\n            if (c < N - 1) neighbors[idx].push_back(idx + 1); // Right\n        }\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // 1. Read Input\n        vector<vector<int>> X(seed_count, vector<int>(M));\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n\n        // 2. Calculate Total Value V for each seed\n        vector<int> V(seed_count);\n        for (int i = 0; i < seed_count; ++i) {\n            V[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // 3. Seed Selection\n        set<int> specialists;\n        for (int l = 0; l < M; ++l) {\n            int max_val = -1;\n            int best_idx = -1;\n            for (int i = 0; i < seed_count; ++i) {\n                if (X[i][l] > max_val) {\n                    max_val = X[i][l];\n                    best_idx = i;\n                }\n            }\n            if (best_idx != -1) {\n                specialists.insert(best_idx);\n            }\n        }\n\n        vector<int> pool_indices;\n        vector<bool> used(seed_count, false);\n        \n        for (int idx : specialists) {\n            if (!used[idx]) {\n                pool_indices.push_back(idx);\n                used[idx] = true;\n            }\n        }\n\n        vector<int> sorted_by_V(seed_count);\n        iota(sorted_by_V.begin(), sorted_by_V.end(), 0);\n        sort(sorted_by_V.begin(), sorted_by_V.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        for (int idx : sorted_by_V) {\n            if (!used[idx]) {\n                pool_indices.push_back(idx);\n                used[idx] = true;\n                if ((int)pool_indices.size() >= grid_size) break;\n            }\n        }\n\n        while ((int)pool_indices.size() > grid_size) pool_indices.pop_back();\n        // Pad if needed (shouldn't happen given constraints but safe coding)\n        while ((int)pool_indices.size() < grid_size) {\n             for (int idx = 0; idx < seed_count; ++idx) {\n                 if (!used[idx]) {\n                     pool_indices.push_back(idx);\n                     used[idx] = true;\n                     if ((int)pool_indices.size() >= grid_size) break;\n                 }\n             }\n        }\n\n        // Map pool_indices (real seed IDs) to 0..35 for local search\n        // We will modify the order of these 0..35 IDs in the grid\n        \n        // 4. Precompute Score Matrix for the selected pool\n        // Score(i, j) = sum(max(X[i][l], X[j][l]))\n        vector<vector<int>> S(grid_size, vector<int>(grid_size, 0));\n        for (int i = 0; i < grid_size; ++i) {\n            for (int j = i + 1; j < grid_size; ++j) {\n                int score = 0;\n                int real_i = pool_indices[i];\n                int real_j = pool_indices[j];\n                for (int l = 0; l < M; ++l) {\n                    score += max(X[real_i][l], X[real_j][l]);\n                }\n                S[i][j] = score;\n                S[j][i] = score;\n            }\n        }\n\n        // 5. Initial Placement (Greedy Path on Grid + Hill Climbing)\n        // Use the greedy path logic to generate a good initial permutation of 0..35\n        vector<int> perm(grid_size);\n        iota(perm.begin(), perm.end(), 0);\n        \n        // Greedy Path construction to sort `perm`\n        // Start with highest V (index 0 in pool_indices is usually sorted by V)\n        // Actually pool_indices has specialists first, then V.\n        // Let's sort `perm` based on V of the corresponding real seed.\n        sort(perm.begin(), perm.end(), [&](int a, int b) {\n            return V[pool_indices[a]] > V[pool_indices[b]];\n        });\n\n        // Optimize this permutation using a path-based heuristic (1D TSP approximation)\n        vector<int> path;\n        path.push_back(perm[0]);\n        vector<bool> in_path(grid_size, false);\n        in_path[perm[0]] = true;\n\n        for (int step = 1; step < grid_size; ++step) {\n            int last = path.back();\n            int best_next = -1;\n            int best_score = -1;\n            for (int i = 0; i < grid_size; ++i) {\n                if (!in_path[i]) {\n                    if (S[last][i] > best_score) {\n                        best_score = S[last][i];\n                        best_next = i;\n                    }\n                }\n            }\n            if (best_next != -1) {\n                path.push_back(best_next);\n                in_path[best_next] = true;\n            } else {\n                // Should not happen if connected\n                for (int i = 0; i < grid_size; ++i) {\n                    if (!in_path[i]) { path.push_back(i); in_path[i]=true; break; }\n                }\n            }\n        }\n        \n        // Map path to Grid (Snake pattern)\n        vector<int> grid(grid_size);\n        for (int i = 0; i < grid_size; ++i) {\n            int r = i / N;\n            int c = (r % 2 == 0) ? (i % N) : (N - 1 - (i % N));\n            grid[r * N + c] = path[i];\n        }\n\n        // 6. Grid Local Search (2-opt swap)\n        // Calculate current total score\n        auto calculate_total_score = [&](const vector<int>& g) {\n            int total = 0;\n            for (int i = 0; i < grid_size; ++i) {\n                for (int nb : neighbors[i]) {\n                    if (i < nb) { // count each edge once\n                        total += S[g[i]][g[nb]];\n                    }\n                }\n            }\n            return total;\n        };\n\n        int current_total_score = calculate_total_score(grid);\n        \n        // Random swaps\n        // Iterations: 80,000 is a good balance for 6ms\n        int iterations = 80000;\n        for (int it = 0; it < iterations; ++it) {\n            int p1 = rng() % grid_size;\n            int p2 = rng() % grid_size;\n            while (p1 == p2) p2 = rng() % grid_size;\n\n            int u = grid[p1];\n            int v = grid[p2];\n\n            // Calculate current contribution of u at p1 and v at p2\n            int current_contrib = 0;\n            for (int nb : neighbors[p1]) {\n                current_contrib += S[u][grid[nb]];\n            }\n            for (int nb : neighbors[p2]) {\n                if (nb != p1) current_contrib += S[v][grid[nb]];\n            }\n\n            // Swap tentatively\n            grid[p1] = v;\n            grid[p2] = u;\n\n            // Calculate new contribution\n            int new_contrib = 0;\n            for (int nb : neighbors[p1]) {\n                new_contrib += S[v][grid[nb]];\n            }\n            for (int nb : neighbors[p2]) {\n                if (nb != p1) new_contrib += S[u][grid[nb]];\n            }\n\n            if (new_contrib > current_contrib) {\n                current_total_score += (new_contrib - current_contrib);\n            } else {\n                // Revert\n                grid[p1] = u;\n                grid[p2] = v;\n            }\n        }\n\n        // 7. Output\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int idx = grid[r * N + c];\n                cout << pool_indices[idx] << (c < N - 1 ? \" \" : \"\\n\");\n            }\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    // Grid state\n    vector<vector<int>> grid(N, vector<int>(N, 0)); // 0: empty, 1: item present\n    vector<vector<int>> target(N, vector<int>(N, 0));\n\n    string s_row, t_row;\n    for (int i = 0; i < N; ++i) {\n        cin >> s_row;\n        for (int j = 0; j < N; ++j) grid[i][j] = s_row[j] - '0';\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> t_row;\n        for (int j = 0; j < N; ++j) target[i][j] = t_row[j] - '0';\n    }\n\n    // --- 1. Design Robotic Arm ---\n    // Star topology: Root 0, children 1..V-1.\n    // Lengths: 1, 2, ..., V-1.\n    // This provides distinct reach for each arm.\n    cout << V << \"\\n\";\n    vector<int> lengths(V);\n    for (int i = 1; i < V; ++i) {\n        lengths[i] = i;\n        cout << 0 << \" \" << i << \"\\n\";\n    }\n\n    // Initial position: (0, 0)\n    int rx = 0, ry = 0;\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // --- 2. Operate ---\n    vector<int> arm_dirs(V, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(V, 0);  // 0 or 1, whether fingertip i holds an item\n\n    int total_steps = 0;\n    const int MAX_STEPS = 100000;\n\n    // Snake movement state\n    int move_dir = 0; // 0: Right\n    int current_row = 0;\n\n    auto is_finished = [&]() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] != target[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    while (total_steps < MAX_STEPS && !is_finished()) {\n        string S(2 * V, '.');\n\n        // --- A. Determine Movement (Snake) ---\n        if (move_dir == 0) { // Moving Right\n            if (ry + 1 < N) {\n                S[0] = 'R';\n                ry++;\n            } else {\n                // Reached right end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 2; // Switch to Left\n                } else {\n                    S[0] = '.'; // End of grid\n                }\n            }\n        } else if (move_dir == 2) { // Moving Left\n            if (ry - 1 >= 0) {\n                S[0] = 'L';\n                ry--;\n            } else {\n                // Reached left end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 0; // Switch to Right\n                } else {\n                    S[0] = '.';\n                }\n            }\n        }\n\n        // --- B. Determine Rotations (Greedy) ---\n        // For each arm (excluding root), evaluate which direction points to the most valuable square.\n        for (int i = 1; i < V; ++i) {\n            int best_dir = arm_dirs[i];\n            int best_score = -1;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                int tx = rx + DX[d] * lengths[i];\n                int ty = ry + DY[d] * lengths[i];\n                int score = 0;\n\n                if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                    // Logic: High value if:\n                    // 1. It's a source (grid=1, target=0) and we can pick it.\n                    // 2. It's a target (grid=0, target=1) and we are holding an item to place.\n                    if (grid[tx][ty] == 1 && target[tx][ty] == 0) {\n                        score += 10; // Prioritize picking up sources\n                    } else if (grid[tx][ty] == 0 && target[tx][ty] == 1) {\n                        score += 5;  // Next prioritize filling targets\n                    } else if (grid[tx][ty] == 1 && target[tx][ty] == 1) {\n                        score += 1;   // Already correct\n                    }\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_dir = d;\n                }\n            }\n\n            // Set rotation command\n            if (best_dir != arm_dirs[i]) {\n                int diff = (best_dir - arm_dirs[i] + 4) % 4;\n                if (diff == 1) S[i] = 'R';\n                else if (diff == 3) S[i] = 'L';\n                else if (diff == 2) {\n                    // 180 degree turn, choose L (arbitrary, or shortest path)\n                    S[i] = 'L'; \n                    best_dir = (arm_dirs[i] + 3) % 4; // Update to intermediate state\n                }\n            }\n            \n            // Update internal state for this step (so Action phase uses correct coords)\n            arm_dirs[i] = best_dir;\n        }\n\n        // --- C. Determine Actions (Pick/Put) ---\n        // Loop from 1 to V-1 (Vertex 0 is root/internal, cannot act).\n        for (int i = 1; i < V; ++i) {\n            int cx = rx + DX[arm_dirs[i]] * lengths[i];\n            int cy = ry + DY[arm_dirs[i]] * lengths[i];\n\n            char action_cmd = '.';\n            if (cx >= 0 && cx < N && cy >= 0 && cy < N) {\n                if (holding[i] == 1) {\n                    // Try to Place\n                    if (grid[cx][cy] == 0 && target[cx][cy] == 1) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 1;\n                        holding[i] = 0;\n                    }\n                } else {\n                    // Try to Pick\n                    if (grid[cx][cy] == 1 && target[cx][cy] == 0) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 0;\n                        holding[i] = 1;\n                    }\n                }\n            }\n            S[V + i] = action_cmd;\n        }\n\n        cout << S << \"\\n\";\n        total_steps++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <unordered_set>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int TYPE_MACKEREL = 1;\nconst int TYPE_SARDINE = -1;\n\n// Parameters tuned for balance between speed and quality\nconst int MAX_GREEDY_RESTARTS = 1000; \nconst int MAX_GREEDY_STEPS = 40;\nconst int TOP_CANDIDATES = 5;        // Number of seeds for SA\nconst int SA_ITERATIONS = 60000;    // Iterations per SA run\nconst double START_TEMP = 10.0;      // High enough to jump over small barriers\nconst double END_TEMP = 0.1;         // Low enough to converge\n\nstruct Rect {\n    int x1, x2, y1, y2;\n    int score;\n};\n\nvector<vector<pair<int, int>>> cols(MAX_COORD + 1);\nvector<vector<pair<int, int>>> rows(MAX_COORD + 1);\nvector<int> next_x(MAX_COORD + 2, -1);\nvector<int> prev_x(MAX_COORD + 2, -1);\nvector<int> next_y(MAX_COORD + 2, -1);\nvector<int> prev_y(MAX_COORD + 2, -1);\n\nint best_global_score = -1;\nRect best_global_rect;\n\n// Random Generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> dist_double(0.0, 1.0);\nuniform_int_distribution<int> dist_int(0, 7);\n\n// Helper to get sum of points in a column segment [y1, y2]\ninline int get_col_sum(int x, int y1, int y2) {\n    if (y1 > y2) return 0;\n    const auto& col = cols[x];\n    auto start = lower_bound(col.begin(), col.end(), make_pair(y1, -2));\n    auto end = upper_bound(col.begin(), col.end(), make_pair(y2, 2));\n    int sum = 0;\n    for (auto it = start; it != end; ++it) sum += it->second;\n    return sum;\n}\n\n// Helper to get sum of points in a row segment [x1, x2]\ninline int get_row_sum(int y, int x1, int x2) {\n    if (x1 > x2) return 0;\n    const auto& row = rows[y];\n    auto start = lower_bound(row.begin(), row.end(), make_pair(x1, -2));\n    auto end = upper_bound(row.begin(), row.end(), make_pair(x2, 2));\n    int sum = 0;\n    for (auto it = start; it != end; ++it) sum += it->second;\n    return sum;\n}\n\n// Calculate exact score for a rectangle (used to correct drift)\ninline int calculate_score(const Rect& r) {\n    int total = 0;\n    int x = r.x1;\n    while (true) {\n        total += get_col_sum(x, r.y1, r.y2);\n        if (x == r.x2) break;\n        x = next_x[x];\n        if (x == -1) break; \n    }\n    return total;\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return;\n\n    vector<pair<int, int>> mackerels;\n    mackerels.reserve(N);\n\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        mackerels.push_back({x, y});\n        cols[x].emplace_back(y, TYPE_MACKEREL);\n        rows[y].emplace_back(x, TYPE_MACKEREL);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        cols[x].emplace_back(y, TYPE_SARDINE);\n        rows[y].emplace_back(x, TYPE_SARDINE);\n    }\n\n    // Sort cols and rows for binary search\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        if (!cols[i].empty()) sort(cols[i].begin(), cols[i].end());\n        if (!rows[i].empty()) sort(rows[i].begin(), rows[i].end());\n    }\n\n    // Precompute next/prev populated indices\n    int last_x = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_x[i] = last_x;\n        if (!cols[i].empty()) last_x = i;\n    }\n    int next_x_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_x[i] = next_x_val;\n        if (!cols[i].empty()) next_x_val = i;\n    }\n\n    int last_y = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_y[i] = last_y;\n        if (!rows[i].empty()) last_y = i;\n    }\n    int next_y_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_y[i] = next_y_val;\n        if (!rows[i].empty()) next_y_val = i;\n    }\n\n    // Phase 1: Fast Greedy Search to generate candidate seeds\n    vector<Rect> candidates;\n    shuffle(mackerels.begin(), mackerels.end(), rng);\n    \n    int restarts = min((int)mackerels.size(), MAX_GREEDY_RESTARTS);\n\n    for (int r = 0; r < restarts; ++r) {\n        const auto& start_pt = mackerels[r];\n        Rect cur;\n        cur.x1 = cur.x2 = start_pt.first;\n        cur.y1 = cur.y2 = start_pt.second;\n        cur.score = 1; // Start with the mackerel itself\n\n        unordered_set<long long> visited;\n        auto encode = [](int x1, int x2, int y1, int y2) {\n            return ((long long)x1 << 48) | ((long long)x2 << 32) | ((long long)y1 << 16) | y2;\n        };\n        visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n        Rect best_local = cur;\n\n        for (int step = 0; step < MAX_GREEDY_STEPS; ++step) {\n            int best_delta = -2;\n            int best_dir = -1;\n            Rect next_rect;\n\n            // Try 4 expansion directions\n            // Right (x2 -> next_x[x2])\n            if (next_x[cur.x2] != -1) {\n                Rect n = cur; n.x2 = next_x[cur.x2];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x2, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 0; next_rect = n; }\n                }\n            }\n            // Left (x1 -> prev_x[x1])\n            if (prev_x[cur.x1] != -1) {\n                Rect n = cur; n.x1 = prev_x[cur.x1];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x1, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 1; next_rect = n; }\n                }\n            }\n            // Up (y2 -> next_y[y2])\n            if (next_y[cur.y2] != -1) {\n                Rect n = cur; n.y2 = next_y[cur.y2];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y2, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 2; next_rect = n; }\n                }\n            }\n            // Down (y1 -> prev_y[y1])\n            if (prev_y[cur.y1] != -1) {\n                Rect n = cur; n.y1 = prev_y[cur.y1];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y1, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 3; next_rect = n; }\n                }\n            }\n\n            if (best_dir == -1) break;\n            if (best_delta < 0) break; // Stop if no positive gain\n            if (best_delta == 0 && visited.count(encode(next_rect.x1, next_rect.x2, next_rect.y1, next_rect.y2))) break;\n\n            cur = next_rect;\n            cur.score += best_delta;\n            visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n            if (cur.score > best_local.score) {\n                best_local = cur;\n            }\n        }\n        candidates.push_back(best_local);\n    }\n\n    // Phase 2: Simulated Annealing on top candidates\n    sort(candidates.begin(), candidates.end(), [](const Rect& a, const Rect& b) {\n        return a.score > b.score;\n    });\n\n    int num_candidates = min((int)candidates.size(), TOP_CANDIDATES);\n\n    for (int i = 0; i < num_candidates; ++i) {\n        Rect cur = candidates[i];\n        // Recalculate exact score to be safe\n        cur.score = calculate_score(cur);\n        \n        Rect best_sa = cur;\n        \n        // Temperature schedule\n        double temp = START_TEMP;\n        double cooling_rate = pow(END_TEMP / START_TEMP, 1.0 / SA_ITERATIONS);\n\n        for (int iter = 0; iter < SA_ITERATIONS; ++iter) {\n            temp *= cooling_rate;\n\n            // Pick a random move (0-7)\n            // 0: Expand L, 1: Shrink L, 2: Expand R, 3: Shrink R, 4: Expand D, 5: Shrink D, 6: Expand U, 7: Shrink U\n            int dir = dist_int(rng);\n            Rect next = cur;\n            int delta = 0;\n            bool valid = true;\n\n            // Apply move and check validity\n            if (dir == 0) { // Expand Left\n                if (prev_x[next.x1] != -1) {\n                    int tx = prev_x[next.x1];\n                    if (tx < next.x2 && 2LL * (next.x2 - tx + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x1 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 1) { // Shrink Left\n                if (next_x[next.x1] != -1 && next_x[next.x1] < next.x2) {\n                    int tx = next_x[next.x1]; // New x1 is to the right\n                    // We lose column old x1\n                    delta = -get_col_sum(next.x1, next.y1, next.y2);\n                    next.x1 = tx;\n                } else valid = false;\n            } else if (dir == 2) { // Expand Right\n                if (next_x[next.x2] != -1) {\n                    int tx = next_x[next.x2];\n                    if (tx > next.x1 && 2LL * (tx - next.x1 + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x2 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 3) { // Shrink Right\n                if (prev_x[next.x2] != -1 && prev_x[next.x2] > next.x1) {\n                    int tx = prev_x[next.x2];\n                    delta = -get_col_sum(next.x2, next.y1, next.y2);\n                    next.x2 = tx;\n                } else valid = false;\n            } else if (dir == 4) { // Expand Down\n                if (prev_y[next.y1] != -1) {\n                    int ty = prev_y[next.y1];\n                    if (ty < next.y2 && 2LL * (next.x2 - next.x1 + next.y2 - ty) <= MAX_PERIMETER) {\n                        next.y1 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 5) { // Shrink Down\n                if (next_y[next.y1] != -1 && next_y[next.y1] < next.y2) {\n                    int ty = next_y[next.y1];\n                    delta = -get_row_sum(next.y1, next.x1, next.x2);\n                    next.y1 = ty;\n                } else valid = false;\n            } else if (dir == 6) { // Expand Up\n                if (next_y[next.y2] != -1) {\n                    int ty = next_y[next.y2];\n                    if (ty > next.y1 && 2LL * (next.x2 - next.x1 + ty - next.y1) <= MAX_PERIMETER) {\n                        next.y2 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 7) { // Shrink Up\n                if (prev_y[next.y2] != -1 && prev_y[next.y2] > next.y1) {\n                    int ty = prev_y[next.y2];\n                    delta = -get_row_sum(next.y2, next.x1, next.x2);\n                    next.y2 = ty;\n                } else valid = false;\n            }\n\n            if (valid) {\n                next.score = cur.score + delta;\n                // Metropolis criterion\n                if (delta > 0 || dist_double(rng) < exp((double)delta / temp)) {\n                    cur = next;\n                    if (cur.score > best_sa.score) {\n                        best_sa = cur;\n                    }\n                }\n            }\n        }\n\n        if (best_sa.score > best_global_score) {\n            best_global_score = best_sa.score;\n            best_global_rect = best_sa;\n        }\n    }\n\n    // Output Phase\n    // Handle degenerate rectangles (score 0 or bad luck)\n    if (best_global_rect.x1 == best_global_rect.x2) {\n        if (best_global_rect.x1 > 0) best_global_rect.x1--;\n        else best_global_rect.x2++;\n    }\n    if (best_global_rect.y1 == best_global_rect.y2) {\n        if (best_global_rect.y1 > 0) best_global_rect.y1--;\n        else best_global_rect.y2++;\n    }\n\n    cout << 4 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y2 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y2 << endl;\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nusing ll = long long;\n\n// Structure for operations\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\n// Structure for placed rectangles\nstruct Rect {\n    ll w, h;\n    ll x, y;\n    int id;\n};\n\n// Global inputs\nint N, T;\nll sigma;\nvector<pair<ll, ll>> dims;\n\n// Best solution\nvector<Op> best_ops;\nll best_score = 1e18;\n\n// Random number generator\nmt19937 rng(1234);\n\n// Check if two intervals [l1, r1) and [l2, r2) overlap\ninline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n// Structure to hold a placement candidate\nstruct Candidate {\n    ll score;\n    int r;\n    char d;\n    int b;\n    ll x;\n    ll y;\n};\n\nvoid solve_one() {\n    vector<Rect> placed;\n    placed.reserve(N);\n    vector<Op> current_ops;\n    current_ops.reserve(N);\n    \n    ll W = 0, H = 0;\n    ll skipped_sum = 0;\n    \n    for (int i = 0; i < N; ++i) {\n        ll w_i = dims[i].first;\n        ll h_i = dims[i].second;\n        \n        // Maintain top 3 candidates to avoid sorting overhead\n        const ll INF = 1e18;\n        Candidate best[3] = {\n            {INF, 0, 'U', -1, 0, 0},\n            {INF, 0, 'U', -1, 0, 0},\n            {INF, 0, 'U', -1, 0, 0}\n        };\n        \n        auto update_best = [&](const Candidate& c) {\n            if (c.score < best[0].score) {\n                best[2] = best[1];\n                best[1] = best[0];\n                best[0] = c;\n            } else if (c.score < best[1].score) {\n                best[2] = best[1];\n                best[1] = c;\n            } else if (c.score < best[2].score) {\n                best[2] = c;\n            }\n        };\n        \n        // Option 1: Skip\n        update_best({w_i + h_i, -1, 'X', -1, 0, 0});\n        \n        // Option 2: Place\n        // Try all possible references: -1 and all placed rectangles\n        for (int k = -1; k < (int)placed.size(); ++k) {\n            for (int r = 0; r < 2; ++r) {\n                ll cw = (r == 0 ? w_i : h_i);\n                ll ch = (r == 1 ? w_i : h_i);\n                \n                int b_id = (k == -1 ? -1 : placed[k].id);\n                \n                // Direction U: Align x, slide up\n                {\n                    ll x = (k == -1 ? 0 : placed[k].x + placed[k].w);\n                    ll max_bot = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                            max_bot = max(max_bot, p.y + p.h);\n                        }\n                    }\n                    ll y = max_bot - ch;\n                    if (y < 0) y = 0;\n                    \n                    ll new_W = max(W, x + cw);\n                    ll new_H = max(H, y + ch);\n                    update_best({(new_W - W) + (new_H - H), r, 'U', b_id, x, y});\n                }\n                \n                // Direction L: Align y, slide left\n                {\n                    ll y = (k == -1 ? 0 : placed[k].y + placed[k].h);\n                    ll max_right = 0;\n                    for (const auto& p : placed) {\n                        if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                            max_right = max(max_right, p.x + p.w);\n                        }\n                    }\n                    ll x = max_right - cw;\n                    if (x < 0) x = 0;\n                    \n                    ll new_W = max(W, x + cw);\n                    ll new_H = max(H, y + ch);\n                    update_best({(new_W - W) + (new_H - H), r, 'L', b_id, x, y});\n                }\n            }\n        }\n        \n        // Select one of the top 3 candidates randomly\n        int idx = rng() % 3;\n        const auto& chosen = best[idx];\n        \n        if (chosen.r == -1) {\n            skipped_sum += w_i + h_i;\n        } else {\n            ll final_w = (chosen.r == 0 ? w_i : h_i);\n            ll final_h = (chosen.r == 1 ? w_i : h_i);\n            \n            placed.push_back({final_w, final_h, chosen.x, chosen.y, i});\n            W = max(W, chosen.x + final_w);\n            H = max(H, chosen.y + final_h);\n            \n            current_ops.push_back({i, chosen.r, chosen.b, chosen.d});\n        }\n    }\n    \n    ll total_score = W + H + skipped_sum;\n    if (total_score < best_score) {\n        best_score = total_score;\n        best_ops = current_ops;\n    }\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma)) return 0;\n    \n    dims.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> dims[i].first >> dims[i].second;\n    }\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    // Run as many iterations as possible within the time limit\n    // Using 2.8 seconds to leave a safe margin for I/O\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > 2800) break;\n        \n        solve_one();\n    }\n    \n    // Output the best sequence T times\n    for (int t = 0; t < T; ++t) {\n        cout << best_ops.size() << \"\\n\";\n        for (const auto& op : best_ops) {\n            cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read feedback (must read to keep sync)\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <sys/time.h>\n#include <queue>\n\nusing namespace std;\n\n// Timer for time limit management\ndouble get_time() {\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    return tv.tv_sec + tv.tv_usec * 1e-6;\n}\n\n// Global inputs\nint N, M, H;\nvector<int> A;\nvector<vector<int>> G;\n\n// Global best state\nlong long best_score = 0;\nvector<int> best_parent;\n\n// Greedy construction based on a specific processing order\npair<vector<int>, long long> greedy_construct(const vector<int>& order) {\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<bool> processed(N, false);\n    \n    for (int v : order) {\n        int best_u = -1;\n        int max_depth = -1;\n\n        // Find the best processed neighbor\n        for (int u : G[v]) {\n            if (processed[u] && depth[u] < H) {\n                if (depth[u] > max_depth) {\n                    max_depth = depth[u];\n                    best_u = u;\n                }\n            }\n        }\n\n        if (best_u != -1) {\n            parent[v] = best_u;\n            depth[v] = depth[best_u] + 1;\n        } else {\n            parent[v] = -1;\n            depth[v] = 0;\n        }\n        processed[v] = true;\n    }\n    \n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        score += (long long)(depth[i] + 1) * A[i];\n    }\n    return {parent, 1 + score};\n}\n\n// Hill Climbing optimization\nvoid hill_climb(vector<int>& parent, vector<int>& depth, long long current_score) {\n    // Build children list\n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) {\n        if (parent[i] != -1) {\n            children[parent[i]].push_back(i);\n        }\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        // Iterate through all nodes to try moving them\n        for (int v = 0; v < N; ++v) {\n            // Try all neighbors u as a new parent\n            for (int u : G[v]) {\n                // Skip if u is already the parent\n                if (u == parent[v]) continue;\n                \n                // Check if u is in the subtree of v (to avoid cycles)\n                int curr = u;\n                while (curr != -1 && curr != v) {\n                    curr = parent[curr];\n                }\n                if (curr == v) continue; // Cycle detected\n\n                int new_depth_v = depth[u] + 1;\n                if (new_depth_v > H) continue; \n\n                int diff = new_depth_v - depth[v];\n                \n                // We only consider moves that increase score (go deeper)\n                if (diff <= 0) continue;\n                \n                // Verify that all nodes in the subtree of v satisfy depth constraints after move\n                long long sum_A = 0;\n                vector<int> stack; \n                stack.push_back(v);\n                bool valid_move = true;\n                \n                while (!stack.empty()) {\n                    int curr_node = stack.back();\n                    stack.pop_back();\n                    \n                    if (depth[curr_node] + diff > H) {\n                        valid_move = false;\n                        break;\n                    }\n                    sum_A += A[curr_node];\n                    \n                    for (int c : children[curr_node]) {\n                        stack.push_back(c);\n                    }\n                }\n                \n                if (!valid_move) continue;\n                \n                // --- Apply the move ---\n                \n                // Update parent and depth of v\n                int old_parent = parent[v];\n                parent[v] = u;\n                depth[v] = new_depth_v;\n                \n                // Update children lists\n                if (old_parent != -1) {\n                    auto it = find(children[old_parent].begin(), children[old_parent].end(), v);\n                    if (it != children[old_parent].end()) children[old_parent].erase(it);\n                }\n                children[u].push_back(v);\n                \n                // Update depths of all nodes in the subtree of v\n                stack.push_back(v);\n                while (!stack.empty()) {\n                    int curr_node = stack.back();\n                    stack.pop_back();\n                    \n                    for (int c : children[curr_node]) {\n                        depth[c] += diff;\n                        stack.push_back(c);\n                    }\n                }\n                \n                // Update score\n                current_score += (long long)diff * sum_A;\n                improved = true;\n                \n                // Update global best\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_parent = parent;\n                }\n                \n                // Restart scan from beginning after an improvement\n                v = -1; \n                break; \n            }\n        }\n    }\n}\n\nint main() {\n    double start_time = get_time();\n\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> H)) return 0;\n\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    G.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n\n    // Read coordinates (ignored for logic)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Prepare indices 0 to N-1\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    // Random generator\n    random_device rd;\n    mt19937 g(rd());\n    \n    int num_trials = 15; \n    \n    for (int t = 0; t < num_trials; ++t) {\n        // Generate a randomized processing order\n        vector<int> order = indices;\n        shuffle(order.begin(), order.end(), g);\n        \n        // Apply sorting heuristics\n        if (t < 12) {\n            stable_sort(order.begin(), order.end(), [&](int u, int v) { return A[u] < A[v]; });\n        } else {\n            stable_sort(order.begin(), order.end(), [&](int u, int v) { return A[u] > A[v]; });\n        }\n        \n        // Phase 1: Greedy Construction\n        auto [parent, score] = greedy_construct(order);\n        \n        // FIX: Compute depth correctly using BFS\n        // The previous simple loop was incorrect because parent indices are not topologically sorted\n        vector<int> depth(N, 0);\n        vector<vector<int>> children_init(N);\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] != -1) {\n                children_init[parent[i]].push_back(i);\n            }\n        }\n        \n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        \n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int c : children_init[v]) {\n                depth[c] = depth[v] + 1;\n                q.push(c);\n            }\n        }\n        \n        // Update global best if initial solution is good\n        if (score > best_score) {\n            best_score = score;\n            best_parent = parent;\n        }\n\n        // Phase 2: Hill Climbing Optimization\n        hill_climb(parent, depth, score);\n        \n        // Check time limit\n        if (get_time() - start_time > 1.9) break;\n    }\n\n    // Output the best parent array found\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << best_parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <tuple>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n};\n\nint N;\nvector<string> grid;\nvector<Point> onis;\nvector<bool> removed; \n\nbool has_o_up(int r, int c) {\n    for (int i = 0; i < r; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_down(int r, int c) {\n    for (int i = r + 1; i < N; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\n\nbool can_remove_up(int r, int c) { return !has_o_up(r, c); }\nbool can_remove_down(int r, int c) { return !has_o_down(r, c); }\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 'x') {\n                onis.push_back({i, j});\n            }\n        }\n    }\n\n    removed.assign(onis.size(), false);\n    vector<pair<char, int>> moves;\n\n    // --- PHASE 1: ROW REMOVALS ---\n    for (int r = 0; r < N; ++r) {\n        // Identify segments separated by 'o'\n        vector<pair<int, int>> segments;\n        int l = 0;\n        while (l < N) {\n            while (l < N && grid[r][l] == 'o') l++;\n            if (l >= N) break;\n            int rend = l;\n            while (rend < N && grid[r][rend] != 'o') rend++;\n            segments.push_back({l, rend - 1});\n            l = rend;\n        }\n\n        for (auto seg : segments) {\n            // Collect indices of onis in this segment\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].r == r && onis[k].c >= seg.first && onis[k].c <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            \n            if (indices.empty()) continue;\n\n            // Sort by column\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].c < onis[b].c;\n            });\n\n            int K = indices.size();\n            vector<int> cols(K);\n            vector<int> savings(K, 0);\n            vector<bool> is_forced(K, false);\n\n            for (int i = 0; i < K; ++i) {\n                int c = onis[indices[i]].c;\n                cols[i] = c;\n                if (!can_remove_up(r, c) && !can_remove_down(r, c)) {\n                    is_forced[i] = true;\n                } else {\n                    // Savings is the cost we avoid paying if we remove this via row\n                    savings[i] = min(2 * (r + 1), 2 * (N - r));\n                }\n            }\n\n            // Prefix sum of savings for efficient range queries\n            vector<int> savings_prefix(K, 0);\n            for(int i=0; i<K; ++i) {\n                savings_prefix[i] = savings[i] + (i>0 ? savings_prefix[i-1] : 0);\n            }\n\n            // DP to find optimal cover\n            // dp[i] is min cost for first i points (1..i)\n            vector<int> dp(K + 1, 2000000000); \n            vector<pair<int, int>> parent(K + 1, {-1, -1}); // {prev_idx, type} -1=uncovered, 0=L, 1=R\n            dp[0] = 0;\n\n            for (int i = 1; i <= K; ++i) {\n                // Option 1: Leave point i for Phase 2 (only if optional)\n                if (!is_forced[i-1]) {\n                    if (dp[i-1] < dp[i]) {\n                        dp[i] = dp[i-1];\n                        parent[i] = {i-1, -1};\n                    }\n                }\n\n                // Option 2: Cover interval j..i with row operations\n                for (int j = 1; j <= i; ++j) {\n                    // Cost to cover cols[j-1] to cols[i-1] using Left shift\n                    int costL = 2 * (cols[i-1] + 1);\n                    // Cost using Right shift\n                    int costR = 2 * (N - cols[j-1]);\n                    \n                    // Total savings for points j..i\n                    int sum_savings = savings_prefix[i-1] - (j >= 2 ? savings_prefix[j-2] : 0);\n\n                    // Net cost = Move Cost - Savings\n                    int totalL = dp[j-1] + costL - sum_savings;\n                    if (totalL < dp[i]) {\n                        dp[i] = totalL;\n                        parent[i] = {j-1, 0};\n                    }\n                    \n                    int totalR = dp[j-1] + costR - sum_savings;\n                    if (totalR < dp[i]) {\n                        dp[i] = totalR;\n                        parent[i] = {j-1, 1};\n                    }\n                }\n            }\n\n            // Reconstruction\n            vector<tuple<int, int, int>> intervals; // {start_idx, end_idx, type} (indices in cols array, 0-based)\n            int curr = K;\n            while (curr > 0) {\n                int prev = parent[curr].first;\n                int type = parent[curr].second;\n                if (type == -1) {\n                    curr = prev;\n                } else {\n                    // We covered cols[prev] ... cols[curr-1]\n                    // DP index i maps to cols[i-1]. Transition j-1 -> i covers cols[j-1] to cols[i-1].\n                    // Here prev = j-1, curr = i. So range is prev to curr-1.\n                    intervals.push_back({prev, curr - 1, type});\n                    curr = prev;\n                }\n            }\n            reverse(intervals.begin(), intervals.end());\n\n            // Apply moves\n            for (auto iv : intervals) {\n                int s = get<0>(iv);\n                int e = get<1>(iv);\n                int type = get<2>(iv);\n                \n                if (type == 0) { // Left cover\n                    int bound = cols[e];\n                    for(int k=0; k<=bound; ++k) moves.push_back({'L', r});\n                    for(int k=0; k<=bound; ++k) moves.push_back({'R', r});\n                    \n                    for(int k=s; k<=e; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                } else { // Right cover\n                    int bound = cols[s];\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'R', r});\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'L', r});\n\n                    for(int k=s; k<=e; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // --- PHASE 2: COLUMN REMOVALS ---\n    for (int c = 0; c < N; ++c) {\n        vector<pair<int, int>> segments;\n        int u = 0;\n        while (u < N) {\n            while (u < N && grid[u][c] == 'o') u++;\n            if (u >= N) break;\n            int d = u;\n            while (d < N && grid[d][c] != 'o') d++;\n            segments.push_back({u, d - 1});\n            u = d;\n        }\n\n        for (auto seg : segments) {\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].c == c && onis[k].r >= seg.first && onis[k].r <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            if (indices.empty()) continue;\n\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].r < onis[b].r;\n            });\n\n            int K = indices.size();\n            vector<int> rows(K);\n            for (int i = 0; i < K; ++i) rows[i] = onis[indices[i]].r;\n\n            // Standard DP for interval cover (no savings here, just min moves)\n            vector<int> dp(K, 1e9);\n            vector<pair<int, int>> choice(K, {-1, 0}); \n\n            for (int i = 0; i < K; ++i) {\n                for (int j = 0; j <= i; ++j) {\n                    int prev_cost = (j == 0) ? 0 : dp[j-1];\n                    \n                    int costU = prev_cost + 2 * (rows[i] + 1);\n                    if (costU < dp[i]) {\n                        dp[i] = costU;\n                        choice[i] = {j - 1, 0};\n                    }\n\n                    int costD = prev_cost + 2 * (N - rows[j]);\n                    if (costD < dp[i]) {\n                        dp[i] = costD;\n                        choice[i] = {j - 1, 1};\n                    }\n                }\n            }\n\n            int curr = K - 1;\n            while (curr >= 0) {\n                int prev = choice[curr].first;\n                int type = choice[curr].second;\n\n                if (type == 0) {\n                    int r_end = rows[curr];\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'U', c});\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'D', c});\n                    \n                    for(int k=prev+1; k<=curr; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                } else {\n                    int r_start = rows[prev + 1];\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'D', c});\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'U', c});\n\n                    for(int k=prev+1; k<=curr; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                }\n                curr = prev;\n            }\n        }\n    }\n\n    for (auto m : moves) {\n        cout << m.first << \" \" << m.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <array>\n#include <random>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\n// Random number generator\nmt19937 rng(0); // Fixed seed for reproducibility in testing, use random_device for submission if allowed\n\n// Simulation function to calculate counts t_i and error\nlong long simulate(const vector<int>& a, const vector<int>& b, const vector<int>& T) {\n    vector<int> cnt(N, 0);\n    int cur = 0;\n    cnt[0] = 1;\n    for (int i = 1; i < L; ++i) {\n        if (cnt[cur] % 2 == 1) {\n            cur = a[cur];\n        } else {\n            cur = b[cur];\n        }\n        cnt[cur]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(cnt[i] - T[i]);\n    }\n    return error;\n}\n\n// Greedy construction of a and b based on target T\n// Randomize the order of processing nodes to explore different configurations\nvoid construct_greedy(const vector<int>& T, vector<int>& a, vector<int>& b) {\n    // Remaining demand for each node y\n    vector<long long> demand(N);\n    for (int i = 0; i < N; ++i) {\n        demand[i] = T[i];\n    }\n\n    // Process nodes in random order\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int x : order) {\n        long long tx = T[x];\n        if (tx == 0) {\n            // If target is 0, it doesn't matter much where we point, \n            // but pointing to a node with high demand might help satisfy it (if we ever visit x)\n            // However, we likely won't visit x. Just point randomly or to self.\n            a[x] = 0;\n            b[x] = 0;\n            continue;\n        }\n\n        // We split the outflow from x into two parts.\n        // Based on parity, we will use a_x roughly ceil(tx/2) times and b_x roughly floor(tx/2) times.\n        long long w1 = (tx + 1) / 2;\n        long long w2 = tx / 2;\n\n        // Find best y for w1\n        // We want to minimize |demand[y] - w1| ideally, but demand represents what we NEED.\n        // We are ADDING w1 to the inflow. So we want the new inflow (demand[y] + w1) to be close to target T[y].\n        // Wait, demand here is effectively \"remaining needed inflow\" or \"current balance\"?\n        // Let's define demand[y] as the current estimate of how much more inflow y needs.\n        // Initially demand[y] = T[y] (it needs T[y] inflow).\n        // When we send w to y, we reduce demand[y] by w?\n        // No, standard flow formulation: Sum of inflows = Sum of T. \n        // We want sum of inflows to be T. \n        // Let current_inflow[y] = 0. Target = T[y].\n        // We want to add w to current_inflow[y] such that current_inflow[y] is close to T[y].\n        // So we minimize | (current_inflow[y] + w) - T[y] |.\n        // This is equivalent to minimizing | -demand[y] + w | if demand[y] = T[y] - current_inflow[y].\n        // Let's stick to tracking \"current_inflow\".\n        \n        // Re-thinking the greedy logic for robustness:\n        // We have \"slots\" to fill. Total slots = L.\n        // We iterate x. x produces w1 and w2.\n        // We assign w1 to some y. We assign w2 to some z.\n        // We want the final distribution of assigned weights to match T.\n        \n        // Heuristic: Pick y that minimizes | (assigned_so_far[y] + w) - T[y] |.\n        // assigned_so_far is initially 0.\n        \n        // To implement this efficiently without scanning all N every time:\n        // We can just scan all N (N=100 is small).\n    }\n\n    // Let's redo the greedy logic cleanly here.\n    vector<long long> assigned(N, 0); // How much flow assigned to each node so far\n    \n    for (int x : order) {\n        long long w1 = (T[x] + 1) / 2;\n        long long w2 = T[x] / 2;\n\n        // Helper lambda to find best target\n        auto find_best_target = [&](long long w) -> int {\n            int best_y = 0;\n            long long best_diff = -1; \n            // We want to minimize overflow/underflow.\n            // Cost = |assigned[y] + w - T[y]|.\n            // We also want to slightly penalize staying on the same node to encourage mixing?\n            // Or maybe not. Let's stick to pure flow matching.\n            \n            for (int y = 0; y < N; ++y) {\n                long long diff = abs((assigned[y] + w) - T[y]);\n                // If diff is same, prefer random to break ties consistently but randomly\n                if (best_diff == -1 || diff < best_diff || (diff == best_diff && rng() % 2 == 0)) {\n                    best_diff = diff;\n                    best_y = y;\n                }\n            }\n            return best_y;\n        };\n\n        int y1 = find_best_target(w1);\n        assigned[y1] += w1;\n        a[x] = y1;\n\n        int y2 = find_best_target(w2);\n        assigned[y2] += w2;\n        b[x] = y2;\n    }\n}\n\nvoid solve() {\n    int n_input;\n    long long l_input;\n    cin >> n_input >> l_input;\n    N; // N is fixed 100\n    L; // L is fixed 500000\n\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    vector<int> best_a(N), best_b(N);\n    long long best_error = 1e18;\n\n    // We will perform multiple random restarts.\n    // Given 2 seconds and N=100, L=500k, we can fit maybe 500-1000 simulations.\n    // Let's try 500.\n    const int TRIES = 500;\n    \n    // Seed rng based on time for the submission\n    rng.seed(static_cast<unsigned int>(chrono::steady_clock::now().time_since_epoch().count()));\n\n    for (int t = 0; t < TRIES; ++t) {\n        vector<int> a(N), b(N);\n        construct_greedy(T, a, b);\n        \n        long long err = simulate(a, b, T);\n        if (err < best_error) {\n            best_error = err;\n            best_a = a;\n            best_b = b;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    solve();\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n\nusing namespace std;\n\n// DSU implementation\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        return true;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<double> cx, cy;\nvector<int> city_to_group; // Maps city index to group index\n\n// Function to estimate distance based on box centers\nint estimated_dist(int i, int j) {\n    double dx = cx[i] - cx[j];\n    double dy = cy[i] - cy[j];\n    return (int)floor(sqrt(dx*dx + dy*dy));\n}\n\n// Perform a query\nvector<pair<int, int>> ask_query(const vector<int>& cities) {\n    cout << \"? \" << cities.size();\n    for (int c : cities) cout << \" \" << c;\n    cout << endl;\n    cout.flush();\n    \n    vector<pair<int, int>> edges;\n    // We expect |C| - 1 edges\n    for (size_t i = 0; i < cities.size() - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.emplace_back(u, v);\n    }\n    return edges;\n}\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    cx.resize(N); cy.resize(N);\n    city_to_group.resize(N);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n    }\n\n    // 1. Assign cities to groups\n    // Sort all cities by their center coordinates\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n    \n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < G[k]; ++i) {\n            int city = order[idx++];\n            groups[k].push_back(city);\n            city_to_group[city] = k;\n        }\n    }\n\n    // 2. Global Scanning with Queries\n    // We scan the cities in the global order to capture local MST information\n    // without exceeding the query limit.\n    \n    // Sort cities again globally for the scanning phase.\n    // Using a simple X then Y sort.\n    vector<int> global_order(N);\n    iota(global_order.begin(), global_order.end(), 0);\n    sort(global_order.begin(), global_order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n\n    // Store known edges (u, v) where u < v\n    set<pair<int, int>> known_edges;\n    \n    int queries_used = 0;\n    // Stride of L/2 ensures overlap to catch edges that might cross window boundaries\n    int stride = max(1, L / 2);\n    \n    // Sliding window over globally sorted cities\n    for (int i = 0; i <= N - L; i += stride) {\n        if (queries_used >= Q) break;\n        \n        vector<int> subset(global_order.begin() + i, global_order.begin() + i + L);\n        auto res = ask_query(subset);\n        queries_used++;\n        \n        for (auto& e : res) {\n            known_edges.insert(e);\n        }\n    }\n\n    // 3. Construct Answer for each group\n    vector<vector<pair<int, int>>> answer_edges(M);\n    \n    for (int k = 0; k < M; ++k) {\n        auto& vec = groups[k];\n        int sz = vec.size();\n        \n        if (sz <= 1) continue;\n        \n        // Candidates: (priority, estimated_dist, u, v)\n        // Known edges get priority 0, Estimated get priority 1\n        // This ensures we use verified edges first, as estimates can be wrong\n        vector<tuple<int, int, int, int>> candidates;\n        \n        // Add known edges belonging to this group\n        for (auto& e : known_edges) {\n            if (city_to_group[e.first] == k && city_to_group[e.second] == k) {\n                int d = estimated_dist(e.first, e.second);\n                candidates.push_back({0, d, e.first, e.second});\n            }\n        }\n        \n        // Add estimated edges for all pairs in group\n        for (int i = 0; i < sz; ++i) {\n            for (int j = i + 1; j < sz; ++j) {\n                int u = vec[i];\n                int v = vec[j];\n                // Check if already in known_edges to avoid duplicates in candidates\n                // Although sorting handles duplicates, it saves work.\n                if (u > v) swap(u, v); // Ensure consistent order for lookup\n                if (known_edges.find({u, v}) != known_edges.end()) continue;\n                \n                int d = estimated_dist(u, v);\n                candidates.push_back({1, d, u, v});\n            }\n        }\n        \n        // Sort candidates\n        sort(candidates.begin(), candidates.end());\n        \n        // Run Kruskal\n        map<int, int> local_id;\n        for(int i=0; i<sz; ++i) local_id[vec[i]] = i;\n        \n        DSU dsu(sz);\n        int edges_needed = sz - 1;\n        \n        for (auto& item : candidates) {\n            int u = get<2>(item);\n            int v = get<3>(item);\n            int uid = local_id[u];\n            int vid = local_id[v];\n            \n            if (dsu.unite(uid, vid)) {\n                answer_edges[k].push_back({u, v});\n                if (answer_edges[k].size() == edges_needed) break;\n            }\n        }\n    }\n    \n    // Output\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        // Output cities\n        for (int city : groups[k]) {\n            cout << city << (city == groups[k].back() ? \"\" : \" \");\n        }\n        cout << endl;\n        \n        // Output edges\n        for (auto& e : answer_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    solve();\n    \n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nstruct Point {\n    int x;\n    int y;\n};\n\nint N, M;\nvector<Point> targets;\n\nvector<pair<char, char>> actions;\n\nvoid add_action(char a, char d) {\n    actions.push_back({a, d});\n}\n\nvoid add_move(char d, int steps) {\n    for (int i = 0; i < steps; ++i) {\n        add_action('M', d);\n    }\n}\n\nbool isCorner(Point p) {\n    return (p.x == 0 || p.x == N - 1) && (p.y == 0 || p.y == N - 1);\n}\n\nstruct Strategy {\n    int cost;\n    int type; // 0=Walk, 1=Slide U, 2=Slide D, 3=Slide L, 4=Slide R, 5=Corner 1-slide, 6=Corner 2-slide\n    char dir;\n    Point slide_dest; // Relevant for Corner 2-slide to know where to stop\n\n    bool operator<(const Strategy& other) const {\n        return cost < other.cost;\n    }\n};\n\nconst int INF = 1000000000;\n\nStrategy evaluate_strategy(Point cur, Point target, int type) {\n    int dx = abs(cur.x - target.x);\n    int dy = abs(cur.y - target.y);\n    \n    if (type == 0) { // Walk\n        return {dx + dy, 0, ' ', target};\n    }\n    else if (type == 1) { // Slide Up\n        if (cur.y <= target.y) return {INF, 1, 'U', target};\n        int cost = dx + 1 + target.y;\n        return {cost, 1, 'U', target};\n    }\n    else if (type == 2) { // Slide Down\n        if (cur.y >= target.y) return {INF, 2, 'D', target};\n        int cost = dx + 1 + (N - 1 - target.y);\n        return {cost, 2, 'D', target};\n    }\n    else if (type == 3) { // Slide Left\n        if (cur.x <= target.x) return {INF, 3, 'L', target};\n        int cost = dy + 1 + target.x;\n        return {cost, 3, 'L', target};\n    }\n    else if (type == 4) { // Slide Right\n        if (cur.x >= target.x) return {INF, 4, 'R', target};\n        int cost = dy + 1 + (N - 1 - target.x);\n        return {cost, 4, 'R', target};\n    }\n    return {INF, 0, ' ', target};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    targets.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int r, c;\n        cin >> r >> c;\n        targets[i].x = c;\n        targets[i].y = r;\n    }\n\n    Point cur = targets[0];\n\n    for (int k = 1; k < M; ++k) {\n        Point target = targets[k];\n        \n        Strategy best = {INF, 0, ' ', target};\n        \n        // Standard Strategies\n        best = min(best, evaluate_strategy(cur, target, 0));\n        best = min(best, evaluate_strategy(cur, target, 1));\n        best = min(best, evaluate_strategy(cur, target, 2));\n        best = min(best, evaluate_strategy(cur, target, 3));\n        best = min(best, evaluate_strategy(cur, target, 4));\n\n        // Corner Strategies\n        if (isCorner(target)) {\n            // Strategy: Single slide if aligned\n            if (cur.x == target.x) {\n                int cost = 1;\n                if (cur.y == target.y) cost = 0; // Already there\n                char d = (cur.y > target.y) ? 'U' : 'D';\n                best = min(best, {cost, 5, d, target});\n            } else if (cur.y == target.y) {\n                int cost = 1;\n                char d = (cur.x > target.x) ? 'L' : 'R';\n                best = min(best, {cost, 5, d, target});\n            } else {\n                // Strategy: 2-turn corner hop (e.g., Slide U then Slide R)\n                // Valid if we are not on the same row or col, and not already there.\n                // Cost is always 2.\n                best = min(best, {2, 6, ' ', target});\n            }\n        }\n\n        // Tie-breaking: Prefer Walk if costs equal\n        if (best.cost == evaluate_strategy(cur, target, 0).cost && best.type != 0) {\n            best.type = 0;\n        }\n\n        // Execution\n        int dx = target.x - cur.x;\n        int dy = target.y - cur.y;\n\n        if (best.type == 0) {\n            if (dx > 0) add_move('R', dx);\n            else if (dx < 0) add_move('L', -dx);\n            if (dy > 0) add_move('D', dy);\n            else if (dy < 0) add_move('U', -dy);\n        }\n        else if (best.type == 1) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'U');\n            add_move('D', target.y);\n        }\n        else if (best.type == 2) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'D');\n            add_move('U', N - 1 - target.y);\n        }\n        else if (best.type == 3) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'L');\n            add_move('R', target.x);\n        }\n        else if (best.type == 4) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'R');\n            add_move('L', N - 1 - target.x);\n        }\n        else if (best.type == 5) {\n            // Aligned corner slide\n            add_action('S', best.dir);\n        }\n        else if (best.type == 6) {\n            // 2-turn corner hop\n            // We need to slide to the adjacent edge, then slide to the corner.\n            // Order: Slide towards y=0 or y=N-1 (perpendicular to target's y-edge), then x.\n            // Or x then y.\n            // Let's align Y first.\n            char d1, d2;\n            if (target.y == 0) d1 = 'U';\n            else d1 = 'D'; // target.y == N-1\n            \n            if (target.x == N-1) d2 = 'R';\n            else d2 = 'L'; // target.x == 0\n\n            add_action('S', d1);\n            add_action('S', d2);\n        }\n\n        cur = target;\n    }\n\n    for (const auto& act : actions) {\n        cout << act.first << \" \" << act.second << \"\\n\";\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <limits>\n#include <numeric>\n\nusing namespace std;\n\n// Use long long for area and error calculations to avoid overflow\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n    int a, b, c, d; // Output rectangle coordinates\n};\n\nvector<Company> companies;\n\n// Recursive function to partition the space\n// (x1, y1) is the bottom-left of the current region, (x2, y2) is the top-right\n// ids contains the indices of companies that must be placed in this region\nvoid solve_recursive(int x1, int y1, int x2, int y2, vector<int> ids) {\n    int k = ids.size();\n    if (k == 0) return;\n    \n    // Base case: only one company, assign the whole region\n    if (k == 1) {\n        int id = ids[0];\n        companies[id].a = x1;\n        companies[id].b = y1;\n        companies[id].c = x2;\n        companies[id].d = y2;\n        return;\n    }\n\n    ll total_area = (ll)(x2 - x1) * (y2 - y1);\n    \n    // Find the best cut (vertical or horizontal)\n    // We minimize the squared error: sum((assigned_area - desired_area)^2)\n    \n    ll best_error = numeric_limits<ll>::max();\n    int best_split_axis = -1; // 0: vertical, 1: horizontal\n    int best_split_idx = -1; // Index in the sorted list to split at\n    int best_cut_pos = -1;   // Coordinate of the cut\n    \n    // --- Try Vertical Cut ---\n    // Sort companies by X coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].x < companies[j].x;\n    });\n    \n    // Calculate prefix sums of r to quickly get sum of desired areas for a split\n    vector<ll> prefix_sum(k);\n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int height = y2 - y1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        // Split between i and i+1\n        ll sum_r_left = prefix_sum[i];\n        ll sum_r_right = prefix_sum[k-1] - sum_r_left;\n        \n        // The cut position X must separate the points.\n        // Left points must have x < X, Right points must have x >= X.\n        // Since points are integers, X must be > max_x_left and <= min_x_right.\n        int max_x_left = companies[ids[i]].x;\n        int min_x_right = companies[ids[i+1]].x;\n        \n        // Also must be within the current rectangle bounds (x1, x2)\n        // Left rect: [x1, X), Right: [X, x2) -> x1 < X < x2\n        int low = max(x1 + 1, max_x_left + 1);\n        int high = min(x2 - 1, min_x_right);\n        \n        if (low > high) continue; // No valid cut position for this split\n        \n        // Calculate optimal cut position to match area\n        // We want (X - x1) * height approx sum_r_left\n        double target_x = x1 + (double)sum_r_left / height;\n        int cut_x = (int)round(target_x);\n        \n        // Clamp to valid range\n        if (cut_x < low) cut_x = low;\n        if (cut_x > high) cut_x = high;\n        \n        ll actual_area_left = (ll)(cut_x - x1) * height;\n        ll actual_area_right = total_area - actual_area_left;\n        \n        ll error = (actual_area_left - sum_r_left) * (actual_area_left - sum_r_left) \n                 + (actual_area_right - sum_r_right) * (actual_area_right - sum_r_right);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 0;\n            best_split_idx = i;\n            best_cut_pos = cut_x;\n        }\n    }\n    \n    // --- Try Horizontal Cut ---\n    // Sort companies by Y coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].y < companies[j].y;\n    });\n    \n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int width = x2 - x1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        ll sum_r_bottom = prefix_sum[i];\n        ll sum_r_top = prefix_sum[k-1] - sum_r_bottom;\n        \n        int max_y_bottom = companies[ids[i]].y;\n        int min_y_top = companies[ids[i+1]].y;\n        \n        int low = max(y1 + 1, max_y_bottom + 1);\n        int high = min(y2 - 1, min_y_top);\n        \n        if (low > high) continue;\n        \n        double target_y = y1 + (double)sum_r_bottom / width;\n        int cut_y = (int)round(target_y);\n        \n        if (cut_y < low) cut_y = low;\n        if (cut_y > high) cut_y = high;\n        \n        ll actual_area_bottom = (ll)(cut_y - y1) * width;\n        ll actual_area_top = total_area - actual_area_bottom;\n        \n        ll error = (actual_area_bottom - sum_r_bottom) * (actual_area_bottom - sum_r_bottom) \n                 + (actual_area_top - sum_r_top) * (actual_area_top - sum_r_top);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 1;\n            best_split_idx = i;\n            best_cut_pos = cut_y;\n        }\n    }\n    \n    // --- Perform the Split ---\n    vector<int> left_ids, right_ids;\n    \n    if (best_split_axis == 0) {\n        // Vertical split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].x < companies[j].x;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, best_cut_pos, y2, left_ids);\n        solve_recursive(best_cut_pos, y1, x2, y2, right_ids);\n    } else {\n        // Horizontal split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].y < companies[j].y;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, x2, best_cut_pos, left_ids);\n        solve_recursive(x1, best_cut_pos, x2, y2, right_ids);\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    companies.resize(n);\n    vector<int> all_ids(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        all_ids[i] = i;\n    }\n    \n    solve_recursive(0, 0, 10000, 10000, all_ids);\n    \n    for (int i = 0; i < n; ++i) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" << companies[i].c << \" \" << companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n#include <random>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\n// mt19937_64 for high quality random numbers\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n};\n\nstruct Tile {\n    int id;\n    int size;\n    Point cells[2];\n    int total_val;\n    bool visited;\n};\n\n// Global variables for grid\nint H = 50, W = 50;\nint si, sj;\nvector<vector<int>> tile_ids;\nvector<vector<int>> p_vals;\nvector<Tile> tiles;\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHARS[4] = {'U', 'D', 'L', 'R'};\n\n// Helper to check bounds\ninline bool inside(int r, int c) {\n    return 0 <= r && r < H && 0 <= c && c < W;\n}\n\n// Heuristic function to evaluate the \"future\" potential of a cell\n// It sums the values of unvisited neighbor tiles + a bonus for connectivity\nint get_future_potential(int r, int c, const vector<bool>& visited) {\n    int score = 0;\n    int connections = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + DR[d];\n        int nc = c + DC[d];\n        if (inside(nr, nc)) {\n            int tid = tile_ids[nr][nc];\n            if (!visited[tid]) {\n                score += tiles[tid].total_val;\n                connections++;\n            }\n        }\n    }\n    // Bonus for having multiple options (connectivity)\n    return score + connections * 10;\n}\n\n// Main solver function\nstring solve_single_run() {\n    int num_tiles = tiles.size();\n    vector<bool> visited(num_tiles, false);\n    string path = \"\";\n    int score = 0;\n    \n    // Initialize current position and tile\n    Point curr_pos(si, sj);\n    int curr_tile_id = tile_ids[si][sj];\n    \n    // Mark start tile as visited\n    visited[curr_tile_id] = true;\n    score += p_vals[si][sj]; // Add score of starting square\n    \n    // Handle start tile logic (if it's a 2-tile, we might want to move to the other cell)\n    if (tiles[curr_tile_id].size == 2) {\n        Point p0 = tiles[curr_tile_id].cells[0];\n        Point p1 = tiles[curr_tile_id].cells[1];\n        \n        Point other = (p0.r == si && p0.c == sj) ? p1 : p0;\n        \n        // Calculate heuristic for exiting from current pos vs exiting from other\n        // Note: We already 'visited' the start tile, so we can move freely within it.\n        // We haven't collected points from 'other' yet.\n        \n        int potential_curr = get_future_potential(si, sj, visited);\n        int potential_other = p_vals[other.r][other.c] + get_future_potential(other.r, other.c, visited);\n        \n        if (potential_other > potential_curr) {\n            // Move to the other cell\n            for (int d = 0; d < 4; ++d) {\n                if (si + DR[d] == other.r && sj + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    curr_pos = other;\n                    score += p_vals[other.r][other.c];\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Main greedy loop\n    while (true) {\n        Point best_next_pos(-1, -1);\n        int best_score_move = -1;\n        bool best_is_full_traverse = false; // True if we choose to visit both cells of a 2-tile\n        int best_dir_idx = -1;\n        \n        // Check neighbors\n        for (int d = 0; d < 4; ++d) {\n            int nr = curr_pos.r + DR[d];\n            int nc = curr_pos.c + DC[d];\n            \n            if (!inside(nr, nc)) continue;\n            \n            int nxt_tid = tile_ids[nr][nc];\n            if (visited[nxt_tid]) continue;\n            \n            // Evaluate moving to (nr, nc)\n            // We enter the tile at (nr, nc)\n            int gain = tiles[nxt_tid].total_val;\n            \n            // Strategy 1: Full traverse (visit all cells of the tile)\n            // We effectively collect `gain`, and end up at the \"best\" exit point of the tile\n            // But since we enter at (nr, nc), we must reach the exit point from there.\n            // For 1-tile, exit is (nr, nc).\n            // For 2-tile, we enter at (nr, nc) -> go to other -> exit. Or enter -> exit.\n            \n            int max_future = -1e9;\n            int best_exit_cell_idx = -1; // 0 or 1 relative to tile cells\n            int future_curr_entry = -1e9;\n            \n            // Evaluate exit points\n            // Entry point is always the cell adjacent to curr_pos\n            // We need to identify which cell of the target tile is (nr, nc)\n            Point entry_cell(nr, nc);\n            Point other_cell(-1, -1);\n            if (tiles[nxt_tid].size == 2) {\n                if (tiles[nxt_tid].cells[0].r == nr && tiles[nxt_tid].cells[0].c == nc) {\n                    other_cell = tiles[nxt_tid].cells[1];\n                } else {\n                    other_cell = tiles[nxt_tid].cells[0];\n                }\n            }\n\n            // Option A: Exit from entry_cell (Partial traverse if 2-tile)\n            // We only gain points of entry_cell? \n            // Wait, if we enter a 2-tile and don't visit the other cell, do we gain its points? No.\n            // But wait, problem statement: \"score... sum of values of visited squares\".\n            // So we must decide which squares to visit.\n            // If 1-tile: visit (nr, nc). Gain = p(nr, nc).\n            // If 2-tile: visit (nr, nc). Gain = p(nr, nc).\n            \n            // Let's calculate exact gain for each strategy.\n            \n            // Strat 1: Visit ONLY entry_cell\n            int gain_partial = p_vals[nr][nc];\n            int future_partial = get_future_potential(nr, nc, visited);\n            int score_partial = gain_partial + future_partial;\n            \n            int score_full = -1e9;\n            int future_full = -1;\n            \n            if (tiles[nxt_tid].size == 1) {\n                // Only one option\n                score_full = gain_partial; // gain_partial is total_val here\n                future_full = future_partial;\n            } else {\n                // Strat 2: Visit entry_cell AND other_cell\n                int gain_full = tiles[nxt_tid].total_val;\n                // We end up at other_cell. Can we exit from other_cell? Yes.\n                // Can we exit from entry_cell? No, we stepped on other_cell, we must be at other_cell.\n                // Wait, if we step on entry, then other. We are at other. We leave from other.\n                // So future depends on other_cell.\n                int future_other = get_future_potential(other_cell.r, other_cell.c, visited);\n                score_full = gain_full + future_other;\n                future_full = future_other;\n            }\n            \n            // Pick best strategy for this neighbor\n            int current_best_score = max(score_partial, score_full);\n            \n            // Add noise\n            int noise = rng() % 20;\n            current_best_score += noise;\n            \n            if (current_best_score > best_score_move) {\n                best_score_move = current_best_score;\n                best_next_pos = Point(nr, nc);\n                best_dir_idx = d;\n                \n                // Record which strategy was better to update path later\n                // If score_full > score_partial, we will traverse fully\n                // Note: For 1-tile, they are equal, doesn't matter.\n                best_is_full_traverse = (score_full > score_partial);\n            }\n        }\n        \n        if (best_score_move == -1) {\n            break; // No moves left\n        }\n        \n        // Execute best move\n        int nxt_tid = tile_ids[best_next_pos.r][best_next_pos.c];\n        visited[nxt_tid] = true;\n        \n        // Update path and score\n        path += DIR_CHARS[best_dir_idx];\n        curr_pos = best_next_pos;\n        score += p_vals[best_next_pos.r][best_next_pos.c];\n        \n        if (tiles[nxt_tid].size == 2 && best_is_full_traverse) {\n            // Find the other cell\n            Point p0 = tiles[nxt_tid].cells[0];\n            Point p1 = tiles[nxt_tid].cells[1];\n            Point other = (p0.r == best_next_pos.r && p0.c == best_next_pos.c) ? p1 : p0;\n            \n            // Move to other cell\n            // Find direction\n            for (int d = 0; d < 4; ++d) {\n                if (best_next_pos.r + DR[d] == other.r && best_next_pos.c + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    break;\n                }\n            }\n            curr_pos = other;\n            score += p_vals[other.r][other.c];\n        }\n    }\n    \n    return path;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    cin >> si >> sj;\n    \n    tile_ids.resize(H, vector<int>(W));\n    p_vals.resize(H, vector<int>(W));\n    \n    // Map tile ID to vector of cells to construct Tile objects\n    vector<vector<Point>> raw_tile_cells;\n    \n    // Temporary map to normalize tile IDs if needed (though problem says 0..M-1)\n    // Just read and store\n    \n    // First pass to find M and store points\n    int max_id = 0;\n    vector<vector<int>> temp_ids(H, vector<int>(W));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> temp_ids[i][j];\n            max_id = max(max_id, temp_ids[i][j]);\n        }\n    }\n    \n    raw_tile_cells.resize(max_id + 1);\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = temp_ids[i][j];\n            raw_tile_cells[id].push_back(Point(i, j));\n        }\n    }\n    \n    // Construct Tile objects\n    tiles.resize(raw_tile_cells.size());\n    for (int i = 0; i < raw_tile_cells.size(); ++i) {\n        tiles[i].id = i;\n        tiles[i].size = raw_tile_cells[i].size();\n        tiles[i].cells[0] = raw_tile_cells[i][0];\n        if (tiles[i].size == 2) {\n            tiles[i].cells[1] = raw_tile_cells[i][1];\n        }\n        // Will update total_val after reading p\n    }\n    \n    // Assign normalized IDs to grid (can reuse original if they are dense 0..M-1, they are)\n    tile_ids = temp_ids;\n    \n    // Read values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> p_vals[i][j];\n            tiles[tile_ids[i][j]].total_val += p_vals[i][j];\n        }\n    }\n    \n    // Run multiple trials with random variations\n    string best_path = \"\";\n    int best_score = -1;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Limit to 1.8 seconds to be safe\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800) {\n        string current_path = solve_single_run();\n        \n        // Calculate score of this path (re-simulate or just compute during solve?)\n        // Let's re-simulate to be sure and clean.\n        int score = 0;\n        int cr = si, cc = sj;\n        vector<bool> vis(tiles.size(), false);\n        vis[tile_ids[cr][cc]] = true;\n        score += p_vals[cr][cc];\n        \n        bool valid = true;\n        \n        for (char move : current_path) {\n            int d = -1;\n            if (move == 'U') d = 0;\n            else if (move == 'D') d = 1;\n            else if (move == 'L') d = 2;\n            else if (move == 'R') d = 3;\n            \n            int nr = cr + DR[d];\n            int nc = cc + DC[d];\n            \n            if (!inside(nr, nc)) { valid = false; break; }\n            \n            int tid = tile_ids[nr][nc];\n            if (vis[tid]) { valid = false; break; }\n            \n            vis[tid] = true;\n            cr = nr; cc = nc;\n            score += p_vals[cr][cc];\n        }\n        \n        if (valid && score > best_score) {\n            best_score = score;\n            best_path = current_path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <algorithm>\n\nusing namespace std;\n\n// Global parameters\nconst int N = 30; // Grid size\nconst int NUM_PARAMS = N * 2; // 30 row costs + 30 col costs\n\nstruct RLS_Estimator {\n    int n_params;\n    vector<double> theta; // Estimated parameters\n    vector<vector<double>> P; // Covariance matrix\n\n    RLS_Estimator(int n) : n_params(n) {\n        theta.assign(n, 5000.0); // Initial guess\n        P.assign(n, vector<double>(n, 0.0));\n        // Initialize P with large diagonal values for high initial uncertainty\n        for (int i = 0; i < n; ++i) {\n            P[i][i] = 1000.0;\n        }\n    }\n\n    void update(const vector<int>& counts, double measured_total) {\n        // Calculate predicted total\n        double predicted_total = 0.0;\n        for (int i = 0; i < n_params; ++i) {\n            predicted_total += theta[i] * counts[i];\n        }\n\n        double error = measured_total - predicted_total;\n\n        // Vector x = P * counts\n        vector<double> Px(n_params, 0.0);\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                Px[i] += P[i][j] * counts[j];\n            }\n        }\n\n        // Denominator: 1 + counts^T * P * counts = 1 + counts^T * Px\n        double denom = 1.0;\n        for (int i = 0; i < n_params; ++i) {\n            denom += counts[i] * Px[i];\n        }\n\n        // Kalman gain: K = Px / denom\n        vector<double> K(n_params);\n        for (int i = 0; i < n_params; ++i) {\n            K[i] = Px[i] / denom;\n        }\n\n        // Update theta: theta = theta + error * K\n        for (int i = 0; i < n_params; ++i) {\n            theta[i] += error * K[i];\n        }\n\n        // Update P: P = P - K * (Px)^T\n        // This is a rank-1 update\n        for (int i = 0; i < n_params; ++i) {\n            for (int j = 0; j < n_params; ++j) {\n                P[i][j] -= K[i] * Px[j];\n            }\n        }\n    }\n};\n\nstring find_path(int si, int sj, int ti, int tj, RLS_Estimator& estimator) {\n    // Dijkstra's algorithm\n    // Distances\n    vector<vector<double>> dist(N, vector<double>(N, 1e18));\n    vector<vector<pair<int, int>>> prev(N, vector<pair<int, int>>(N, {-1, -1}));\n    \n    priority_queue<tuple<double, int, int>, vector<tuple<double, int, int>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, si, sj});\n\n    int di[4] = {-1, 1, 0, 0};\n    int dj[4] = {0, 0, -1, 1};\n    string dirs = \"UDLR\";\n\n    while (!pq.empty()) {\n        auto [d, r, c] = pq.top();\n        pq.pop();\n\n        if (r == ti && c == tj) break;\n        if (d > dist[r][c]) continue;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + di[k];\n            int nc = c + dj[k];\n\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            double cost;\n            if (k < 2) { // Vertical move (U, D)\n                // Edge weight depends on column\n                cost = estimator.theta[N + nc];\n            } else { // Horizontal move (L, R)\n                // Edge weight depends on row\n                cost = estimator.theta[r];\n            }\n\n            if (dist[r][c] + cost < dist[nr][nc]) {\n                dist[nr][nc] = dist[r][c] + cost;\n                prev[nr][nc] = {r, c};\n                pq.push({dist[nr][nc], nr, nc});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cr = ti, cc = tj;\n    while (cr != si || cc != sj) {\n        int pr = prev[cr][cc].first;\n        int pc = prev[cr][cc].second;\n        \n        if (pr == -1 && pc == -1) break; // Should not happen\n\n        if (pr < cr) path += \"D\";\n        else if (pr > cr) path += \"U\";\n        else if (pc < cc) path += \"R\";\n        else if (pc > cc) path += \"L\";\n        \n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Helper to get feature counts from a path\nvector<int> get_feature_counts(const string& path, int si, int sj) {\n    vector<int> counts(NUM_PARAMS, 0);\n    int r = si, c = sj;\n    for (char dir : path) {\n        if (dir == 'L') {\n            counts[r]++;\n            c--;\n        } else if (dir == 'R') {\n            counts[r]++;\n            c++;\n        } else if (dir == 'U') {\n            counts[N + c]++;\n            r--;\n        } else if (dir == 'D') {\n            counts[N + c]++;\n            r++;\n        }\n    }\n    return counts;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    RLS_Estimator estimator(NUM_PARAMS);\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        string path = find_path(si, sj, ti, tj, estimator);\n        cout << path << endl;\n\n        // Read feedback\n        int measured;\n        cin >> measured;\n\n        vector<int> counts = get_feature_counts(path, si, sj);\n        estimator.update(counts, (double)measured);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <unordered_map>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Solver\n// ---------------------------------------------------------\nclass Solver {\npublic:\n    int N;\n    int M;\n    vector<string> S;\n    vector<uint64_t> S_hashes;\n    unordered_map<uint64_t, int> s_hash_set; \n    mt19937 rng;\n\n    static const uint64_t BASE = 127;\n    \n    Solver(int n, int m, const vector<string>& s) : N(n), M(m), S(s), rng(chrono::steady_clock::now().time_since_epoch().count()) {\n        for (const auto& t : S) {\n            uint64_t h = compute_hash(t);\n            S_hashes.push_back(h);\n            s_hash_set[h] = 1; \n        }\n    }\n\n    uint64_t compute_hash(const string& s) {\n        uint64_t h = 0;\n        for (char c : s) h = h * BASE + (c - 'A' + 1);\n        return h;\n    }\n\n    // -----------------------------------------------------\n    // Greedy Initialization\n    // -----------------------------------------------------\n    vector<string> greedy_init() {\n        vector<string> grid(N, string(N, '.'));\n        vector<int> indices(M);\n        iota(indices.begin(), indices.end(), 0);\n        shuffle(indices.begin(), indices.end(), rng);\n        stable_sort(indices.begin(), indices.end(), [&](int a, int b) {\n            return S[a].size() > S[b].size();\n        });\n\n        for (int idx : indices) {\n            const string& s = S[idx];\n            int len = s.size();\n            int best_r = -1, best_c = -1;\n            bool is_row = false;\n            int min_cost = len + 1;\n            \n            // Slightly more aggressive threshold to try to fill more data\n            int threshold = 2; \n            if (len >= 10) threshold = 4;\n            else if (len >= 8) threshold = 3;\n\n            // Try rows\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    int cost = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[r][(c + k) % N];\n                        if (cur != '.' && cur != s[k]) { possible = false; break; }\n                        if (cur == '.') cost++;\n                    }\n                    if (possible && cost < min_cost) {\n                        min_cost = cost; best_r = r; best_c = c; is_row = true;\n                    }\n                }\n            }\n\n            // Try cols\n            for (int c = 0; c < N; c++) {\n                for (int r = 0; r < N; r++) {\n                    int cost = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[(r + k) % N][c];\n                        if (cur != '.' && cur != s[k]) { possible = false; break; }\n                        if (cur == '.') cost++;\n                    }\n                    if (possible && cost < min_cost) {\n                        min_cost = cost; best_r = r; best_c = c; is_row = false;\n                    }\n                }\n            }\n\n            if (best_r != -1 && min_cost <= threshold) {\n                if (is_row) for (int k = 0; k < len; k++) grid[best_r][(best_c + k) % N] = s[k];\n                else for (int k = 0; k < len; k++) grid[(best_r + k) % N][best_c] = s[k];\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == '.') grid[i][j] = 'A' + (rng() % 8);\n            }\n        }\n        return grid;\n    }\n\n    // -----------------------------------------------------\n    // Optimized SA with Targeted Hash Updates\n    // -----------------------------------------------------\n    int run_sa(vector<string>& grid, double time_limit_ms) {\n        unordered_map<uint64_t, int> substr_count;\n        int current_score = 0;\n\n        auto update_line_counts = [&](int line_idx, int affected_idx, auto line_getter, int delta) {\n            int diff = 0;\n            for (int L = 2; L <= 12; L++) {\n                for (int offset = 0; offset < L; offset++) {\n                    int start = (affected_idx - offset + N) % N;\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) {\n                        h = h * BASE + (line_getter((start + k) % N) - 'A' + 1);\n                    }\n\n                    if (delta > 0) {\n                        substr_count[h]++;\n                        if (substr_count[h] == 1 && s_hash_set.count(h)) diff++;\n                    } else {\n                        if (substr_count[h] == 1 && s_hash_set.count(h)) diff--;\n                        substr_count[h]--;\n                        if (substr_count[h] == 0) substr_count.erase(h);\n                    }\n                }\n            }\n            return diff;\n        };\n\n        // Initialize\n        substr_count.clear();\n        for (int i = 0; i < N; i++) {\n            for (int L = 2; L <= 12; L++) {\n                for (int start = 0; start < N; start++) {\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) h = h * BASE + (grid[i][(start+k)%N] - 'A' + 1);\n                    substr_count[h]++;\n                }\n            }\n        }\n        for (int j = 0; j < N; j++) {\n            for (int L = 2; L <= 12; L++) {\n                for (int start = 0; start < N; start++) {\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) h = h * BASE + (grid[(start+k)%N][j] - 'A' + 1);\n                    substr_count[h]++;\n                }\n            }\n        }\n\n        for (auto& p : s_hash_set) {\n            if (substr_count.count(p.first)) current_score++;\n        }\n\n        int best_local_score = current_score;\n        vector<string> best_local_grid = grid;\n\n        auto sa_start = chrono::high_resolution_clock::now();\n        double temp_start = 50.0;\n        double temp_end = 0.01;\n\n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - sa_start).count();\n            if (elapsed > time_limit_ms) break;\n\n            double temp = temp_start + (temp_end - temp_start) * (elapsed / time_limit_ms);\n\n            int r = rng() % N;\n            int c = rng() % N;\n            char old_char = grid[r][c];\n            char new_char = 'A' + (rng() % 8);\n            if (new_char == old_char) continue;\n\n            int delta = 0;\n            \n            // Remove old\n            auto row_getter_old = [&](int idx) { return grid[r][idx]; };\n            delta += update_line_counts(r, c, row_getter_old, -1);\n            auto col_getter_old = [&](int idx) { return grid[idx][c]; };\n            delta += update_line_counts(c, r, col_getter_old, -1);\n\n            // Apply change\n            grid[r][c] = new_char;\n\n            // Add new\n            auto row_getter_new = [&](int idx) { return grid[r][idx]; };\n            delta += update_line_counts(r, c, row_getter_new, 1);\n            auto col_getter_new = [&](int idx) { return grid[idx][c]; };\n            delta += update_line_counts(c, r, col_getter_new, 1);\n\n            int new_score = current_score + delta;\n\n            if (delta > 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                current_score = new_score;\n                if (current_score > best_local_score) {\n                    best_local_score = current_score;\n                    best_local_grid = grid;\n                    if (current_score == M) break;\n                }\n            } else {\n                // Revert\n                delta -= update_line_counts(r, c, row_getter_new, 1);\n                delta -= update_line_counts(c, r, col_getter_new, 1);\n                grid[r][c] = old_char;\n                update_line_counts(r, c, row_getter_old, 1);\n                update_line_counts(c, r, col_getter_old, 1);\n            }\n        }\n\n        grid = best_local_grid;\n        return best_local_score;\n    }\n\n    void solve() {\n        auto global_start = chrono::high_resolution_clock::now();\n        int best_overall_score = -1;\n        vector<string> best_overall_grid;\n\n        // Strategy: Run a long first pass to find a good basin of attraction.\n        // If the score is high (> 85% of M), polish it with the remaining time.\n        // Otherwise, do short restarts.\n        \n        vector<string> grid = greedy_init();\n        double first_run_budget = 1000.0;\n        \n        int run_score = run_sa(grid, first_run_budget);\n        \n        if (run_score > best_overall_score) {\n            best_overall_score = run_score;\n            best_overall_grid = grid;\n        }\n\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed_total = chrono::duration<double, milli>(now - global_start).count();\n\n        // Threshold for \"very good\" score\n        if (run_score >= M * 0.85) {\n            // Polishing phase: Continue with the current best grid\n            double remaining = 2800.0 - elapsed_total;\n            if (remaining > 50) {\n                run_sa(best_overall_grid, remaining);\n                // Update best_overall_grid with the polished result\n                // (run_sa modifies grid in place and returns score, but we also need to check internal best)\n                // Actually run_sa returns best score found during that run.\n                // Let's just assume run_sa updated best_overall_grid correctly.\n                // The function returns the score, we can update.\n                // But wait, run_sa returns `best_local_score`.\n                int final_score = run_sa(best_overall_grid, remaining); // Run again on the best grid found\n                 if (final_score > best_overall_score) {\n                    // Note: run_sa sets grid to best_local_grid at the end.\n                    // So best_overall_grid is updated.\n                    best_overall_score = final_score;\n                }\n            }\n        } else {\n            // Restart phase\n            int restart_budget = 250;\n            while (true) {\n                auto now = chrono::high_resolution_clock::now();\n                double elapsed = chrono::duration<double, milli>(now - global_start).count();\n                if (elapsed > 2800) break;\n\n                double time_left = 2800 - elapsed;\n                double budget = (double)restart_budget;\n                if (time_left < budget * 1.5) budget = time_left;\n\n                vector<string> new_grid = greedy_init();\n                int new_score = run_sa(new_grid, budget);\n\n                if (new_score > best_overall_score) {\n                    best_overall_score = new_score;\n                    best_overall_grid = new_grid;\n                }\n            }\n        }\n        \n        for (const auto& row : best_overall_grid) cout << row << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; i++) cin >> S[i];\n\n    Solver solver(N, M, S);\n    solver.solve();\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/scc>\n#include <atcoder/modint>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\nusing point = bg::model::point<int, 2, bg::cs::cartesian>;\nusing value = std::pair<point, size_t>; // point, index in nodes\n\nusing namespace std;\n\n// Global Constants\nconst int INF = 1e9;\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\nconst char dc[4] = {'R', 'L', 'D', 'U'};\n\nstruct Input {\n    int N;\n    int si, sj;\n    vector<string> grid;\n    int total_road;\n};\n\nInput read_input() {\n    Input in;\n    cin >> in.N >> in.si >> in.sj;\n    in.grid.resize(in.N);\n    in.total_road = 0;\n    for (int i = 0; i < in.N; ++i) {\n        cin >> in.grid[i];\n        for (int j = 0; j < in.N; ++j) {\n            if (in.grid[i][j] != '#') in.total_road++;\n        }\n    }\n    return in;\n}\n\n// Hopcroft-Karp for Maximum Bipartite Matching\nclass HopcroftKarp {\npublic:\n    int n_left, n_right;\n    vector<vector<int>> adj;\n    vector<int> pair_u, pair_v, dist;\n\n    HopcroftKarp(int n_left, int n_right) : n_left(n_left), n_right(n_right), adj(n_left) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        for (int u = 0; u < n_left; ++u) {\n            if (pair_u[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = INF;\n            }\n        }\n        dist[n_left] = INF; // Dummy node for right side check\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (dist[u] < dist[n_left]) {\n                for (int v : adj[u]) {\n                    if (pair_v[v] == -1) {\n                        dist[n_left] = dist[u] + 1;\n                    } else if (dist[pair_v[v]] == INF) {\n                        dist[pair_v[v]] = dist[u] + 1;\n                        q.push(pair_v[v]);\n                    }\n                }\n            }\n        }\n        return dist[n_left] != INF;\n    }\n\n    bool dfs(int u) {\n        if (u != n_left) {\n            for (int v : adj[u]) {\n                if (pair_v[v] == -1 || (dist[pair_v[v]] == dist[u] + 1 && dfs(pair_v[v]))) {\n                    pair_u[u] = v;\n                    pair_v[v] = u;\n                    return true;\n                }\n            }\n            dist[u] = INF;\n            return false;\n        }\n        return true;\n    }\n\n    int max_matching() {\n        pair_u.assign(n_left, -1);\n        pair_v.assign(n_right, -1);\n        dist.assign(n_left + 1, 0);\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < n_left; ++u) {\n                if (pair_u[u] == -1) {\n                    if (dfs(u)) {\n                        matching++;\n                    }\n                }\n            }\n        }\n        return matching;\n    }\n    \n    // Get Minimum Vertex Cover from Maximum Matching\n    // Returns a bitset or boolean vector for left and right nodes respectively\n    pair<vector<bool>, vector<bool>> get_min_vertex_cover() {\n        vector<bool> in_cover_left(n_left, false);\n        vector<bool> in_cover_right(n_right, false);\n        \n        // Standard Konig's theorem construction:\n        // Z = { unmatched L } U { reachable from unmatched L via alternating paths }\n        // Min VC = (L \\ Z) U (R n Z)\n        // Here dist[] is used. In BFS layering, nodes with dist[] < INF are in Z (L side)\n        // But we need to re-run or use the state from the last BFS? \n        // Let's just use the pairings to find Z.\n        // Z starts with unmatched U.\n        // Then alternating paths: U -> V (not paired) -> U (paired) ...\n        \n        queue<int> q;\n        vector<bool> visited_L(n_left, false);\n        vector<bool> visited_R(n_right, false);\n        \n        for(int u=0; u<n_left; ++u) {\n            if(pair_u[u] == -1) {\n                q.push(u);\n                visited_L[u] = true;\n            }\n        }\n        \n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            for(int v : adj[u]) {\n                if(!visited_R[v]) {\n                    visited_R[v] = true;\n                    int paired_u = pair_v[v];\n                    if(paired_u != -1 && !visited_L[paired_u]) {\n                        visited_L[paired_u] = true;\n                        q.push(paired_u);\n                    }\n                }\n            }\n        }\n        \n        for(int u=0; u<n_left; ++u) {\n            if(!visited_L[u]) in_cover_left[u] = true;\n        }\n        for(int v=0; v<n_right; ++v) {\n            if(visited_R[v]) in_cover_right[v] = true;\n        }\n        \n        return {in_cover_left, in_cover_right};\n    }\n};\n\n// Dijkstra\nvector<int> dijkstra(const Input& in, pair<int, int> start, const vector<pair<int,int>>& targets) {\n    int N = in.N;\n    int s_dist = start.first * N + start.second;\n    vector<int> dist(N*N, INF);\n    dist[s_dist] = 0;\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, s_dist});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    return dist;\n}\n\nstring get_path(const Input& in, pair<int,int> s, pair<int,int> t) {\n    // Reconstruct path using simplified Dijkstra or A* since we just need one path\n    // Given N is small, Dijkstra with prev pointer is fine.\n    int N = in.N;\n    int s_idx = s.first * N + s.second;\n    int t_idx = t.first * N + t.second;\n    \n    vector<int> dist(N*N, INF);\n    vector<int> prev(N*N, -1);\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    dist[s_idx] = 0;\n    pq.push({0, s_idx});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (idx == t_idx) break;\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                prev[nidx] = k; // store direction\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    \n    string path = \"\";\n    int curr = t_idx;\n    while(curr != s_idx) {\n        int dir = prev[curr];\n        path += dc[dir];\n        // reverse direction to go back\n        int rdir;\n        if(dir==0) rdir=1; if(dir==1) rdir=0; if(dir==2) rdir=3; if(dir==3) rdir=2;\n        \n        int ci = curr / N;\n        int cj = curr % N;\n        ci += dx[rdir];\n        cj += dy[rdir];\n        curr = ci * N + cj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid solve() {\n    Input in = read_input();\n    int N = in.N;\n    \n    // 1. Identify Segments\n    vector<vector<int>> h_id(N, vector<int>(N, -1));\n    vector<vector<int>> v_id(N, vector<int>(N, -1));\n    int h_cnt = 0, v_cnt = 0;\n    \n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                if(j>0 && in.grid[i][j-1] != '#' && h_id[i][j-1] != -1) {\n                    h_id[i][j] = h_id[i][j-1];\n                } else {\n                    h_id[i][j] = h_cnt++;\n                }\n            }\n        }\n    }\n    \n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        for(int i=0; i<N; ++i) {\n            if(in.grid[i][j] != '#') {\n                if(i>0 && in.grid[i-1][j] != '#' && v_id[i-1][j] != -1) {\n                    v_id[i][j] = v_id[i-1][j];\n                } else {\n                    v_id[i][j] = v_cnt++;\n                }\n            }\n        }\n    }\n    \n    // 2. Build Bipartite Graph\n    HopcroftKarp hk(h_cnt, v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                hk.add_edge(h_id[i][j], v_id[i][j]);\n            }\n        }\n    }\n    \n    // 3. Solve Min Vertex Cover\n    hk.max_matching();\n    auto [cover_h, cover_v] = hk.get_min_vertex_cover();\n    \n    // Set of covered segments\n    vector<bool> covered_h_seg = cover_h; // rename for clarity\n    vector<bool> covered_v_seg = cover_v;\n    \n    // 4. Select Key Points\n    // We need to visit points such that every segment in the cover is visited.\n    // Strategy: Collect all intersection points of segments in the cover.\n    // Also add representative points for segments in cover that might be isolated.\n    \n    set<pair<int, int>> key_points_set;\n    vector<pair<int, int>> key_points;\n    \n    auto add_point = [&](int i, int j) {\n        if(key_points_set.count({i,j}) == 0) {\n            key_points_set.insert({i,j});\n            key_points.push_back({i,j});\n        }\n    };\n\n    // Add intersections of covered segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                int hid = h_id[i][j];\n                int vid = v_id[i][j];\n                if(covered_h_seg[hid] && covered_v_seg[vid]) {\n                    add_point(i, j);\n                }\n            }\n        }\n    }\n    \n    // Add representative points for segments that are not \"covered\" by the intersections logic\n    // (i.e., segments in cover that don't intersect any other segment in cover)\n    // A segment is satisfied if we visit at least one point on it.\n    // So we ensure for each segment in cover, there is a key point on it.\n    \n    // Find segments without intersection\n    vector<bool> h_has_intersect(h_cnt, false);\n    vector<bool> v_has_intersect(v_cnt, false);\n    for(auto p : key_points) {\n        int i = p.first, j = p.second;\n        h_has_intersect[h_id[i][j]] = true;\n        v_has_intersect[v_id[i][j]] = true;\n    }\n    \n    // For segments in cover without intersection, add their point closest to Start\n    // Or just middle point. Middle point is safer and faster.\n    vector<vector<pair<int,int>>> h_cells(h_cnt);\n    vector<vector<pair<int,int>>> v_cells(v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                h_cells[h_id[i][j]].push_back({i,j});\n                v_cells[v_id[i][j]].push_back({i,j});\n            }\n        }\n    }\n    \n    for(int i=0; i<h_cnt; ++i) {\n        if(covered_h_seg[i] && !h_has_intersect[i]) {\n            // Add middle cell\n            int mid = h_cells[i].size() / 2;\n            add_point(h_cells[i][mid].first, h_cells[i][mid].second);\n        }\n    }\n    for(int i=0; i<v_cnt; ++i) {\n        if(covered_v_seg[i] && !v_has_intersect[i]) {\n            int mid = v_cells[i].size() / 2;\n            add_point(v_cells[i][mid].first, v_cells[i][mid].second);\n        }\n    }\n    \n    // Make sure start point is in key points to build the cycle\n    add_point(in.si, in.sj);\n    \n    // 5. Compute Distances between Key Points\n    int K = key_points.size();\n    vector<vector<int>> dist(K, vector<int>(K, INF));\n    \n    // Optimization: Only run Dijkstra from each point. K should be small.\n    // Map point to index\n    map<pair<int,int>, int> pt_to_idx;\n    for(int i=0; i<K; ++i) pt_to_idx[key_points[i]] = i;\n    \n    for(int i=0; i<K; ++i) {\n        auto ds = dijkstra(in, key_points[i], key_points);\n        for(int j=0; j<K; ++j) {\n            int idx = key_points[j].first * N + key_points[j].second;\n            dist[i][j] = ds[idx];\n        }\n    }\n    \n    // 6. Construct Path\n    // Greedy insertion to ensure coverage, then 2-opt\n    \n    int start_idx = pt_to_idx[{in.si, in.sj}];\n    \n    // Current Path: [start_idx]\n    vector<int> path = {start_idx};\n    // Current coverage: segments containing S\n    vector<bool> visited_h(h_cnt, false);\n    vector<bool> visited_v(v_cnt, false);\n    \n    auto visit_pt = [&](int idx) {\n        int i = key_points[idx].first;\n        int j = key_points[idx].second;\n        visited_h[h_id[i][j]] = true;\n        visited_v[v_id[i][j]] = true;\n    };\n    visit_pt(start_idx);\n    \n    // Check if all covered segments are satisfied\n    auto all_covered = [&]() {\n        for(int i=0; i<h_cnt; ++i) if(covered_h_seg[i] && !visited_h[i]) return false;\n        for(int i=0; i<v_cnt; ++i) if(covered_v_seg[i] && !visited_v[i]) return false;\n        return true;\n    };\n    \n    // Greedy Insertion\n    while(!all_covered()) {\n        int best_k = -1;\n        int best_pos = -1;\n        int best_gain = -INF;\n        int best_cost = INF;\n        \n        for(int k=0; k<K; ++k) {\n            if(find(path.begin(), path.end(), k) != path.end()) continue;\n            \n            // Gain: number of newly covered segments\n            int i = key_points[k].first;\n            int j = key_points[k].second;\n            int gain = 0;\n            if(covered_h_seg[h_id[i][j]] && !visited_h[h_id[i][j]]) gain++;\n            if(covered_v_seg[v_id[i][j]] && !visited_v[v_id[i][j]]) gain++;\n            \n            if(gain == 0) continue;\n            \n            // Find best insertion position\n            for(int pos=0; pos<=path.size(); ++pos) {\n                int u = (pos==0) ? path.back() : path[pos-1];\n                int v = (pos==path.size()) ? path[0] : path[pos];\n                \n                // Cost change: dist[u][k] + dist[k][v] - dist[u][v]\n                int delta = dist[u][k] + dist[k][v] - dist[u][v];\n                \n                if(gain * best_cost > best_gain * delta) {\n                    best_gain = gain;\n                    best_cost = delta;\n                    best_k = k;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if(best_k == -1) {\n            // Should not happen if graph is connected and cover is valid\n            // Fallback: add any unvisited point on required segments\n            // (omitted for brevity, break to prevent infinite loop)\n            break; \n        }\n        \n        path.insert(path.begin() + best_pos, best_k);\n        visit_pt(best_k);\n    }\n    \n    // 2-opt Optimization\n    // Simple 2-opt loop\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int n = path.size();\n        for(int i=0; i<n; ++i) {\n            for(int j=i+2; j<n + (i>0 ? 1 : 0); ++j) {\n                // Edge (i, i+1) and (j, j+1) become (i, j) and (i+1, j+1)\n                int u = path[i];\n                int v = path[(i+1)%n];\n                int x = path[j%n];\n                int y = path[(j+1)%n];\n                \n                int current = dist[u][v] + dist[x][y];\n                int proposal = dist[u][x] + dist[v][y];\n                \n                if(proposal < current) {\n                    // Reverse path between i+1 and j\n                    reverse(path.begin() + (i+1)%n, path.begin() + (j%n) + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Generate Output String\n    string full_path = \"\";\n    int p_sz = path.size();\n    for(int i=0; i<p_sz; ++i) {\n        int u = path[i];\n        int v = path[(i+1)%p_sz];\n        string sub = get_path(in, key_points[u], key_points[v]);\n        full_path += sub;\n    }\n    \n    cout << full_path << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <queue>\n#include <cmath>\n#include <set>\n#include <functional>\n#include <random>\n\nusing namespace std;\n\n// Global problem parameters\nint N, M, K, R;\nvector<vector<int>> d; // Task requirements\nvector<vector<int>> adj; // Adjacency list: u -> v\nvector<int> in_degree; \n\n// Task states: 0 = locked, 1 = available, 2 = assigned\nvector<int> task_state;\nvector<int> start_day;\n\n// Skill estimation\nvector<vector<double>> s;\n\n// Tracking member assignments\nvector<int> member_task;\n\n// Pre-calculated priorities\nvector<int> num_successors; \nvector<int> max_depth; \n\n// Random device\nmt19937 rng(1337); \nconst double EXPLORATION_RATE = 0.02; // Reduced to 2%\n\n// Comparator: Highest depth first\nstruct TaskPriority {\n    bool operator()(int t1, int t2) const {\n        if (max_depth[t1] != max_depth[t2]) {\n            return max_depth[t1] < max_depth[t2];\n        }\n        // Tie-breaker: Most successors\n        if (num_successors[t1] != num_successors[t2]) {\n            return num_successors[t1] < num_successors[t2];\n        }\n        return t1 < t2;\n    }\n};\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // --- Input Reading ---\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n        }\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    // --- Pre-processing: Task Priorities ---\n    num_successors.resize(N, 0);\n    vector<int> visited_dfs(N, 0);\n    \n    function<int(int)> count_descendants = [&](int u) {\n        if (visited_dfs[u]) return num_successors[u];\n        visited_dfs[u] = 1;\n        int cnt = 0;\n        for (int v : adj[u]) {\n            cnt += 1 + count_descendants(v);\n        }\n        num_successors[u] = cnt;\n        return cnt;\n    };\n    for (int i = 0; i < N; ++i) {\n        if (!visited_dfs[i]) count_descendants(i);\n    }\n\n    max_depth.assign(N, 0);\n    function<int(int)> calc_depth = [&](int u) {\n        if (max_depth[u] != 0) return max_depth[u];\n        int best = 0;\n        for (int v : adj[u]) {\n            best = max(best, calc_depth(v));\n        }\n        max_depth[u] = best + 1;\n        return max_depth[u];\n    };\n    for (int i = N-1; i >= 0; --i) {\n        if (max_depth[i] == 0) calc_depth(i);\n    }\n\n    // --- Initialization ---\n    task_state.resize(N, 0);\n    start_day.resize(N, -1);\n    \n    priority_queue<int, vector<int>, TaskPriority> available_tasks_pq;\n\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            task_state[i] = 1;\n            available_tasks_pq.push(i);\n        }\n    }\n\n    s.resize(M, vector<double>(K, 25.0)); \n    member_task.resize(M, -1);\n\n    // --- Main Loop ---\n    int day = 0;\n    while (true) {\n        day++;\n\n        // 1. Identify idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n\n        // 2. Prepare list of currently available tasks\n        vector<int> current_available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 1) {\n                current_available_tasks.push_back(i);\n            }\n        }\n\n        // 3. Assignment Loop\n        vector<pair<int, int>> assignments; \n        \n        while (!idle_members.empty() && !current_available_tasks.empty()) {\n            \n            bool explore = (rng() % 1000) < (EXPLORATION_RATE * 1000);\n\n            int task_to_assign = -1;\n            int member_idx_to_assign = -1;\n\n            if (explore) {\n                int rand_idx = rng() % current_available_tasks.size();\n                task_to_assign = current_available_tasks[rand_idx];\n                int rand_member_idx = rng() % idle_members.size();\n                member_idx_to_assign = rand_member_idx;\n                current_available_tasks[rand_idx] = current_available_tasks.back();\n                current_available_tasks.pop_back();\n\n            } else {\n                while (!available_tasks_pq.empty()) {\n                    int candidate = available_tasks_pq.top();\n                    if (task_state[candidate] == 1) {\n                        task_to_assign = candidate;\n                        break;\n                    } else {\n                        available_tasks_pq.pop();\n                    }\n                }\n\n                if (task_to_assign == -1) break;\n\n                double min_cost = 1e9;\n                for (int idx = 0; idx < static_cast<int>(idle_members.size()); ++idx) {\n                    int j = idle_members[idx];\n                    double cost = 0.0;\n                    for (int k = 0; k < K; ++k) {\n                        double diff = d[task_to_assign][k] - s[j][k];\n                        if (diff > 0) cost += diff;\n                    }\n                    \n                    if (cost < min_cost) {\n                        min_cost = cost;\n                        member_idx_to_assign = idx;\n                    }\n                }\n\n                auto it = find(current_available_tasks.begin(), current_available_tasks.end(), task_to_assign);\n                if (it != current_available_tasks.end()) {\n                    *it = current_available_tasks.back();\n                    current_available_tasks.pop_back();\n                }\n                available_tasks_pq.pop();\n            }\n\n            if (task_to_assign != -1 && member_idx_to_assign != -1) {\n                int member_id = idle_members[member_idx_to_assign];\n                assignments.push_back({member_id + 1, task_to_assign + 1});\n                member_task[member_id] = task_to_assign;\n                task_state[task_to_assign] = 2; \n                start_day[task_to_assign] = day;\n                idle_members[member_idx_to_assign] = idle_members.back();\n                idle_members.pop_back();\n            }\n        }\n\n        // 4. Output\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n\n        // 5. Input & Update\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break;\n\n        vector<int> finished_members(n_finished);\n        for (int i = 0; i < n_finished; ++i) {\n            cin >> finished_members[i];\n            finished_members[i]--;\n        }\n\n        const double LEARNING_RATE_STD = 0.4; \n        const double T1_BOOST_RATE = 0.95;    // Aggressive convergence for perfect matches\n\n        for (int member_idx : finished_members) {\n            int task_idx = member_task[member_idx];\n            if (task_idx == -1) continue;\n\n            int t = day - start_day[task_idx] + 1;\n\n            // --- SKILL UPDATE ---\n            double w_est = 0.0;\n            vector<int> deficit_dims;\n            for (int k = 0; k < K; ++k) {\n                double diff = d[task_idx][k] - s[member_idx][k];\n                if (diff > 0) {\n                    w_est += diff;\n                    deficit_dims.push_back(k);\n                }\n            }\n\n            if (t == 1) {\n                // t=1 implies s is sufficient for d.\n                // Aggressively pull s up to d.\n                for (int k : deficit_dims) {\n                    s[member_idx][k] += T1_BOOST_RATE * (d[task_idx][k] - s[member_idx][k]);\n                }\n            } else {\n                // t > 1\n                if (!deficit_dims.empty()) {\n                    // We knew we were deficient.\n                    // Update logic: s += lr * (w_est - t)\n                    double error = w_est - t;\n                    double update = LEARNING_RATE_STD * error;\n                    double per_dim_update = update / deficit_dims.size();\n                    \n                    for (int k : deficit_dims) {\n                        s[member_idx][k] += per_dim_update;\n                        if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                    }\n                } else {\n                    // w_est = 0 but t > 1. We overestimated skills.\n                    // We need to decrease skills. Decrease most where d is high.\n                    double total_required = 0.0;\n                    for(int k=0; k<K; ++k) total_required += d[task_idx][k];\n                    \n                    if (total_required > 0) {\n                        double total_decrease = LEARNING_RATE_STD * t; // error = -t\n                        for (int k = 0; k < K; ++k) {\n                            if (d[task_idx][k] > 0) {\n                                // Decrease proportional to requirement\n                                double w_k = d[task_idx][k] / total_required;\n                                double dec = total_decrease * w_k;\n                                s[member_idx][k] -= dec;\n                                if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                            }\n                        }\n                    } else {\n                        // Task requires 0 in all skills, but took > 1 day.\n                        // Impossible according to problem statement (w=0 -> t=1).\n                        // Should not happen.\n                    }\n                }\n            }\n\n            // --- Unlock Dependencies ---\n            member_task[member_idx] = -1;\n            \n            for (int dependent_task : adj[task_idx]) {\n                in_degree[dependent_task]--;\n                if (in_degree[dependent_task] == 0) {\n                    task_state[dependent_task] = 1;\n                    available_tasks_pq.push(dependent_task);\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nconst int CENTER_IDX = 2000; \n\nint dist_center(int x, int y) {\n    return abs(400 - x) + abs(400 - y);\n}\n\nlong long calculate_total_distance(const vector<int>& route_indices, const vector<Order>& orders) {\n    long long len = 0;\n    vector<pair<int, int>> coords;\n    coords.reserve(route_indices.size() + 1);\n    \n    for (int idx : route_indices) {\n        if (idx == CENTER_IDX) coords.push_back({400, 400});\n        else if (idx < 1000) coords.push_back({orders[idx].a, orders[idx].b});\n        else coords.push_back({orders[idx-1000].c, orders[idx-1000].d});\n    }\n    coords.push_back({400, 400}); // Return to center\n    \n    for (size_t i = 0; i < coords.size() - 1; ++i) {\n        len += (long long)abs(coords[i].first - coords[i+1].first) + abs(coords[i].second - coords[i+1].second);\n    }\n    return len;\n}\n\n// Helper to get coordinates\npair<int, int> get_pt(int idx, const vector<Order>& orders) {\n    if (idx == CENTER_IDX) return {400, 400};\n    if (idx < 1000) return {orders[idx].a, orders[idx].b};\n    return {orders[idx-1000].c, orders[idx-1000].d};\n}\n\n// Global variables for random\nrandom_device rd;\nmt19937 gen(rd());\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    int N = 1000;\n    vector<Order> orders(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n    \n    long long global_best_len = 1e18;\n    vector<int> best_route_indices;\n    \n    int NUM_ITERATIONS = 12; \n    \n    for (int iter = 0; iter < NUM_ITERATIONS; ++iter) {\n        vector<int> used(N, 0);\n        vector<int> route_indices;\n        route_indices.push_back(CENTER_IDX); \n        \n        // --- Greedy Construction ---\n        for (int step = 0; step < 50; ++step) {\n            int best_order = -1;\n            long long best_delta = 1e18;\n            int best_u = -1;\n            int best_v = -1;\n            bool is_append_case = false;\n\n            vector<pair<int, int>> current_points;\n            for (int idx : route_indices) {\n                if (idx == CENTER_IDX) current_points.push_back({400, 400});\n                else if (idx < 1000) current_points.push_back({orders[idx].a, orders[idx].b});\n                else current_points.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            \n            // Candidate filtering with Randomness\n            vector<pair<long long, int>> candidates;\n            for (int i = 0; i < N; ++i) {\n                if (used[i]) continue;\n                int min_dist = 2e9;\n                for (auto& p : current_points) {\n                    int d = abs(p.first - orders[i].a) + abs(p.second - orders[i].b);\n                    if (d < min_dist) min_dist = d;\n                }\n                int internal = abs(orders[i].a - orders[i].c) + abs(orders[i].b - orders[i].d);\n                candidates.push_back({(long long)min_dist + internal, i});\n            }\n            \n            sort(candidates.begin(), candidates.end());\n            // Add randomness: pick from top 100\n            int limit = min((int)candidates.size(), 100);\n            if (candidates.size() > 100) {\n                shuffle(candidates.begin(), candidates.begin() + 100, gen);\n            } else {\n                shuffle(candidates.begin(), candidates.end(), gen);\n                limit = candidates.size();\n            }\n            \n            int L = route_indices.size();\n            \n            for (int k = 0; k < limit; ++k) {\n                int i = candidates[k].second;\n                int px = orders[i].a, py = orders[i].b;\n                int dx = orders[i].c, dy = orders[i].d;\n                \n                vector<int> dists_P(L), dists_D(L);\n                for (int m = 0; m < L; ++m) {\n                    dists_P[m] = abs(current_points[m].first - px) + abs(current_points[m].second - py);\n                    dists_D[m] = abs(current_points[m].first - dx) + abs(current_points[m].second - dy);\n                }\n\n                for (int u = 1; u < L; ++u) {\n                    for (int v = u + 1; v <= L; ++v) {\n                        long long removed = 0, added = 0;\n                        \n                        removed += abs(current_points[u-1].first - current_points[u].first) + abs(current_points[u-1].second - current_points[u].second);\n                        added += dists_P[u-1] + dists_P[u];\n                        \n                        if (v == L) {\n                            removed += dist_center(current_points[L-1].first, current_points[L-1].second);\n                            added += dists_D[L-1] + dist_center(dx, dy);\n                        } else {\n                            removed += abs(current_points[v-1].first - current_points[v].first) + abs(current_points[v-1].second - current_points[v].second);\n                            added += dists_D[v-1] + dists_D[v];\n                        }\n                        \n                        long long delta = added - removed;\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_order = i;\n                            best_u = u;\n                            best_v = v;\n                            is_append_case = false;\n                        }\n                    }\n                }\n                \n                {\n                    long long removed = dist_center(current_points[L-1].first, current_points[L-1].second);\n                    long long added = dists_P[L-1] + (long long)abs(px - dx) + abs(py - dy) + dist_center(dx, dy);\n                    long long delta = added - removed;\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_order = i;\n                        best_u = L; \n                        best_v = L+1; \n                        is_append_case = true;\n                    }\n                }\n            }\n            \n            if (best_order != -1) {\n                used[best_order] = 1;\n                if (is_append_case) {\n                    route_indices.push_back(best_order);\n                    route_indices.push_back(best_order + 1000);\n                } else {\n                    route_indices.insert(route_indices.begin() + best_u, best_order);\n                    route_indices.insert(route_indices.begin() + best_v + 1, best_order + 1000);\n                }\n            } else {\n                for (int k=0; k<N; ++k) if (!used[k]) { used[k]=1; route_indices.push_back(k); route_indices.push_back(k+1000); break; }\n            }\n        }\n        \n        // --- 2-opt Optimization ---\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            int M = route_indices.size();\n            for (int u = 0; u < M - 1; ++u) {\n                for (int v = u + 1; v < M; ++v) {\n                    // Validity check\n                    char in_segment[50] = {0};\n                    bool valid = true;\n                    // Re-map global IDs to local [0..49] for speed\n                    // We can build a map outside the while loop if we maintain active orders\n                    // But map is simple\n                    unordered_map<int, int> g2l;\n                    int lid = 0;\n                    for(int r_idx : route_indices) {\n                        if(r_idx == CENTER_IDX) continue;\n                        int oid = (r_idx < 1000) ? r_idx : r_idx - 1000;\n                        if(!g2l.count(oid)) g2l[oid] = lid++;\n                    }\n\n                    for (int k = u + 1; k <= v; ++k) {\n                        int idx = route_indices[k];\n                        if (idx == CENTER_IDX) continue;\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (in_segment[g2l[oid]]) { valid = false; break; }\n                        in_segment[g2l[oid]] = 1;\n                    }\n                    \n                    if (!valid) continue;\n                    \n                    auto p_u = get_pt(route_indices[u], orders);\n                    auto p_u1 = get_pt(route_indices[u+1], orders);\n                    auto p_v = get_pt(route_indices[v], orders);\n                    \n                    if (v == M - 1) continue; \n                    auto p_v1 = get_pt(route_indices[v+1], orders);\n                    \n                    long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                      + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                    long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                     + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                    \n                    if (added < removed) {\n                        reverse(route_indices.begin() + u + 1, route_indices.begin() + v + 1);\n                        improved = true;\n                        goto next_opt_pass; \n                    }\n                }\n            }\n            next_opt_pass:;\n            \n            auto curr_time = chrono::high_resolution_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(curr_time - start_time).count() > 1400) {\n                improved = false;\n            }\n        }\n        \n        // --- Order Swap (Kick) ---\n        bool swap_improved = true;\n        while (swap_improved) {\n            swap_improved = false;\n            // Try random 10 orders to kick\n            for (int k = 0; k < 10; ++k) {\n                // Get unique order IDs\n                vector<int> unique_oids;\n                {\n                    unordered_set<int> seen;\n                    for (int idx : route_indices) {\n                        if (idx == CENTER_IDX) continue;\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (!seen.count(oid)) {\n                            seen.insert(oid);\n                            unique_oids.push_back(oid);\n                        }\n                    }\n                }\n                \n                if (unique_oids.empty()) break;\n                \n                int rand_idx = gen() % unique_oids.size();\n                int oid_out = unique_oids[rand_idx];\n                \n                // Find P and D in route\n                int p_pos = -1, d_pos = -1;\n                for (size_t i = 0; i < route_indices.size(); ++i) {\n                    if (route_indices[i] == oid_out) p_pos = i;\n                    if (route_indices[i] == oid_out + 1000) d_pos = i;\n                }\n                \n                if (p_pos == -1 || d_pos == -1) continue;\n                \n                vector<pair<int, int>> current_points;\n                for (int idx : route_indices) {\n                    current_points.push_back(get_pt(idx, orders));\n                }\n                \n                int best_oid_in = -1;\n                int best_u_in = -1;\n                int best_v_in = -1;\n                long long best_delta_in = 0; \n                bool is_append_in = false;\n                \n                vector<pair<long long, int>> unused_candidates;\n                for (int i = 0; i < N; ++i) {\n                    if (used[i] && i != oid_out) continue; \n                    int min_dist = 2e9;\n                    for (auto& p : current_points) {\n                        int d = abs(p.first - orders[i].a) + abs(p.second - orders[i].b);\n                        if (d < min_dist) min_dist = d;\n                    }\n                    unused_candidates.push_back({(long long)min_dist, i});\n                }\n                sort(unused_candidates.begin(), unused_candidates.end());\n                if (unused_candidates.size() > 50) unused_candidates.resize(50);\n                \n                int L = route_indices.size();\n                \n                for (auto& cand : unused_candidates) {\n                    int i = cand.second;\n                    int px = orders[i].a, py = orders[i].b;\n                    int dx = orders[i].c, dy = orders[i].d;\n                    \n                    vector<int> dists_P(L), dists_D(L);\n                    for (int m = 0; m < L; ++m) {\n                        dists_P[m] = abs(current_points[m].first - px) + abs(current_points[m].second - py);\n                        dists_D[m] = abs(current_points[m].first - dx) + abs(current_points[m].second - dy);\n                    }\n                    \n                    long long local_best_delta = 1e18;\n                    int loc_u = -1, loc_v = -1;\n                    bool loc_app = false;\n                    \n                    for (int u = 1; u < L; ++u) {\n                        for (int v = u + 1; v <= L; ++v) {\n                            long long delta = 0;\n                            delta += dists_P[u-1] + dists_P[u] - (abs(current_points[u-1].first - current_points[u].first) + abs(current_points[u-1].second - current_points[u].second));\n                            if (v == L) {\n                                delta += dists_D[L-1] + dist_center(dx, dy) - dist_center(current_points[L-1].first, current_points[L-1].second);\n                            } else {\n                                delta += dists_D[v-1] + dists_D[v] - (abs(current_points[v-1].first - current_points[v].first) + abs(current_points[v-1].second - current_points[v].second));\n                            }\n                            \n                            if (delta < local_best_delta) {\n                                local_best_delta = delta;\n                                loc_u = u; loc_v = v; loc_app = false;\n                            }\n                        }\n                    }\n                    {\n                        long long delta = dists_P[L-1] + (long long)abs(px-dx) + abs(py-dy) + dist_center(dx, dy) - dist_center(current_points[L-1].first, current_points[L-1].second);\n                        if (delta < local_best_delta) {\n                            local_best_delta = delta;\n                            loc_u = L; loc_v = L+1; loc_app = true;\n                        }\n                    }\n                    \n                    if (local_best_delta < best_delta_in) {\n                        best_delta_in = local_best_delta;\n                        best_oid_in = i;\n                        best_u_in = loc_u;\n                        best_v_in = loc_v;\n                        is_append_in = loc_app;\n                    }\n                }\n                \n                if (best_oid_in != -1 && best_delta_in < 0) {\n                    used[oid_out] = 0;\n                    used[best_oid_in] = 1;\n                    \n                    if (is_append_in) {\n                        route_indices.push_back(best_oid_in);\n                        route_indices.push_back(best_oid_in + 1000);\n                    } else {\n                        route_indices.insert(route_indices.begin() + best_u_in, best_oid_in);\n                        route_indices.insert(route_indices.begin() + best_v_in + 1, best_oid_in + 1000);\n                    }\n                    \n                    swap_improved = true;\n                    break; \n                }\n            }\n             auto curr_time = chrono::high_resolution_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(curr_time - start_time).count() > 1950) {\n                swap_improved = false;\n            }\n        }\n\n        long long current_len = calculate_total_distance(route_indices, orders);\n        if (current_len < global_best_len) {\n            global_best_len = current_len;\n            best_route_indices = route_indices;\n        }\n    }\n    \n    // --- Output ---\n    vector<int> final_orders;\n    set<int> seen;\n    for (int idx : best_route_indices) {\n        if (idx == CENTER_IDX) continue;\n        int oid = (idx < 1000) ? idx : idx - 1000;\n        if (seen.find(oid) == seen.end()) {\n            final_orders.push_back(oid + 1);\n            seen.insert(oid);\n        }\n    }\n    \n    cout << 50;\n    for (int oid : final_orders) cout << \" \" << oid;\n    cout << \"\\n\";\n    \n    cout << best_route_indices.size() + 1;\n    for (int idx : best_route_indices) {\n        int x, y;\n        if (idx == CENTER_IDX) { x = 400; y = 400; }\n        else if (idx < 1000) { x = orders[idx].a; y = orders[idx].b; }\n        else { x = orders[idx-1000].c; y = orders[idx-1000].d; }\n        cout << \" \" << x << \" \" << y;\n    }\n    cout << \" \" << 400 << \" \" << 400 << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct DSU {\n    vector<int> parent;\n    int components;\n\n    DSU(int n) : parent(n), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        components--;\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N = 400;\n    int M = 1995;\n\n    vector<pair<int, int>> points(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = points[edges[i].u].first - points[edges[i].v].first;\n        int dy = points[edges[i].u].second - points[edges[i].v].second;\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        edges[i].d = (int)round(dist);\n    }\n\n    DSU dsu(N);\n    int taken = 0;\n\n    // Heuristic threshold: Accept if l <= 2.2 * d.\n    // Expected value of l is 2.0 * d. \n    // 2.2 is slightly more lenient to ensure we gather enough edges.\n    const double COST_THRESHOLD = 2.2;\n    \n    // Safety buffer: If we have at most 'need + 50' edges left, we MUST take the current useful edge.\n    // This large buffer prevents disconnection even if we hit a streak of bad edges at the end.\n    const int SAFETY_BUFFER = 50;\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        if (taken == N - 1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int need = dsu.components - 1;\n        \n        // Count useful edges remaining in the future\n        int available = 0;\n        for (int j = i + 1; j < M; ++j) {\n            if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                available++;\n            }\n        }\n\n        // \"Must Take\" Logic with Large Buffer\n        if (available <= need + SAFETY_BUFFER) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n            continue;\n        }\n\n        // Heuristic: Accept if cost is reasonably low\n        if (l <= COST_THRESHOLD * d) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multi_array.hpp>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int TURNS = 300;\nconstexpr int DX[4] = {0, 0, 1, -1};\nconstexpr int DY[4] = {1, -1, 0, 0};\nconstexpr char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\nconstexpr char BLOCK_CHAR[4] = {'r', 'l', 'd', 'u'}; // Action to block (x+dx, y+dy)\n\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int x, int y) : x(x), y(y) {}\n    bool operator==(const Point& p) const { return x == p.x && y == p.y; }\n    int dist(const Point& p) const { return abs(x - p.x) + abs(y - p.y); }\n};\n\n// Global State\nint N, M;\nvector<Point> pets;\nvector<Point> humans;\nvector<int> pet_types; \n// grid[x][y] : true if impassable (wall)\n// Note: walls are built on squares. Humans/Pets can be on squares that are passable.\n// Once a wall is built on (x,y), it becomes impassable.\n// Humans and Pets can be on the same square? \"each square can contain any number of humans and pets.\"\n// So grid state is independent of entity positions, except for the \"cannot build adjacent to pet\" rule.\nvector<vector<bool>> grid; \n\n// Input parsing\nvoid read_init() {\n    cin >> N;\n    pets.resize(N);\n    pet_types.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> pet_types[i];\n        // Convert to 0-based for internal logic if needed, but problem is 1-based\n        pets[i].x--; pets[i].y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    grid.assign(H, vector<bool>(W, false));\n}\n\n// Read pet movements for one turn\n// pet_moves[i] is a string of characters like \"U\", \"R.\", etc.\nvoid read_turn(vector<string>& pet_moves) {\n    pet_moves.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_moves[i];\n    }\n}\n\n// Apply pet movements\nvoid apply_moves(const vector<string>& pet_moves) {\n    for (int i = 0; i < N; ++i) {\n        int cx = pets[i].x;\n        int cy = pets[i].y;\n        for (char c : pet_moves[i]) {\n            int dir = -1;\n            if (c == 'U') dir = 3;\n            else if (c == 'D') dir = 2;\n            else if (c == 'L') dir = 1;\n            else if (c == 'R') dir = 0;\n            \n            if (dir != -1) {\n                int nx = cx + DX[dir];\n                int ny = cy + DY[dir];\n                // Pets move randomly but logically. \n                // The problem says they move to passable squares chosen randomly.\n                // Assuming the server provides valid moves that respect grid bounds and walls.\n                // We just update coordinates.\n                cx = nx;\n                cy = ny;\n            }\n        }\n        pets[i].x = cx;\n        pets[i].y = cy;\n    }\n}\n\n// Helper to check bounds\nbool inside(int x, int y) {\n    return 0 <= x && x < H && 0 <= y && y < W;\n}\n\n// Helper to check if a cell is buildable (wall action)\n// Cannot build if:\n// 1. The cell contains a pet or human at the START of the turn.\n// 2. The cell is already a wall.\n// 3. An adjacent cell contains a pet.\nbool is_buildable(int x, int y, const vector<Point>& current_pets, const vector<Point>& current_humans) {\n    if (!inside(x, y)) return false;\n    if (grid[x][y]) return false; // Already impassable\n    \n    // Check if pet or human is on (x, y)\n    for (const auto& p : current_pets) {\n        if (p.x == x && p.y == y) return false;\n    }\n    for (const auto& h : current_humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    \n    // Check if adjacent cell contains a pet\n    for (int i = 0; i < 4; ++i) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (!inside(nx, ny)) continue;\n        for (const auto& p : current_pets) {\n            if (p.x == nx && p.y == ny) return false;\n        }\n    }\n    return true;\n}\n\n// Strategy: Secure a large rectangle with 0 pets.\nstruct Rect {\n    int r1, r2, c1, c2;\n    int area;\n};\n\n// Find best rectangle to secure\n// Criteria: \n// 1. Contains 0 pets currently.\n// 2. Maximize Area.\n// 3. Minimize Wall Length (perimeter).\n// 4. Maximize distance from pets to wall (safety).\nRect find_best_rectangle() {\n    // 2D prefix sum for pet counts\n    vector<vector<int>> ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int cnt = 0;\n            for (const auto& p : pets) {\n                if (p.x == i && p.y == j) cnt++;\n            }\n            ps[i+1][j+1] = ps[i][j+1] + ps[i+1][j] - ps[i][j] + cnt;\n        }\n    }\n    \n    auto get_pet_count = [&](int r1, int c1, int r2, int c2) {\n        return ps[r2+1][c2+1] - ps[r1][c2+1] - ps[r2+1][c1] + ps[r1][c1];\n    };\n\n    double best_score = -1e9;\n    Rect best_r = {0, H-1, 0, W-1, 0};\n\n    // Iterate over all rectangles\n    // To limit search, maybe only consider those touching boundary? \n    // No, a central island is also valid, though walls are expensive.\n    // Let's iterate all.\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (get_pet_count(r1, c1, r2, c2) > 0) continue;\n                    \n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    \n                    // Calculate required wall length\n                    // Walls needed on sides that are not touching map boundary\n                    int wall_len = 0;\n                    if (r1 > 0) wall_len += (c2 - c1 + 1);\n                    if (r2 < H - 1) wall_len += (c2 - c1 + 1);\n                    if (c1 > 0) wall_len += (r2 - r1 + 1);\n                    if (c2 < W - 1) wall_len += (r2 - r1 + 1);\n                    \n                    // Safety: min distance of any pet to the rectangle boundary\n                    // If a pet is very close, we can't build there easily.\n                    // This is a heuristic.\n                    int min_dist = H + W;\n                    for (const auto& p : pets) {\n                        // If inside, skip (already filtered)\n                        // Distance to rectangle\n                        int dx = max({r1 - p.x, 0, p.x - r2});\n                        int dy = max({c1 - p.y, 0, p.y - c2});\n                        int d = dx + dy;\n                        // If pet is outside, d >= 1\n                        if (d < min_dist) min_dist = d;\n                    }\n                    \n                    // We cannot build adjacent to pet. So we need buffer of 1.\n                    // If min_dist < 2, the wall is adjacent to pet.\n                    // Actually, if min_dist == 1, pet is adjacent to rect. \n                    // We need to build wall outside rect. So dist to wall is min_dist - 1.\n                    // If dist_to_wall == 0 (pet touching rect), we CANNOT build the wall on that side.\n                    // So such rectangles are dangerous.\n                    \n                    // Score: Area - Cost\n                    // Cost = Wall_Length * K1 + (if unsafe) * LargePenalty\n                    double score = (double)area;\n                    \n                    // Penalty for walls\n                    score -= wall_len * 0.5; // Tunable factor\n                    \n                    // Penalty for low safety margin\n                    // Buffer needed is 1.\n                    // If pet is touching boundary (min_dist=1), we are blocked.\n                    if (min_dist == 0) { /* Should not happen since count=0 */ }\n                    else if (min_dist == 1) {\n                        score -= 100; // Heavily penalize touching pets\n                    } else {\n                        // Slight penalty for being close\n                        score -= (5.0 / min_dist);\n                    }\n                    \n                    // Bonus for containing humans? No, we can move them in.\n                    // Penalty for humans being far away?\n                    // Sum of distances from humans to rect.\n                    int total_dist = 0;\n                    for (const auto& h : humans) {\n                        // Closest point in rect\n                        int cx = max(r1, min(h.x, r2));\n                        int cy = max(c1, min(h.y, c2));\n                        total_dist += abs(h.x - cx) + abs(h.y - cy);\n                    }\n                    score -= total_dist * 0.05;\n\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = {r1, r2, c1, c2, area};\n                    }\n                }\n            }\n        }\n    }\n    return best_r;\n}\n\n// Action Generation\nvector<char> generate_actions(Rect& target_rect, vector<Point>& current_humans, int& phase, vector<Point>& wall_tasks, int turn_cnt) {\n    vector<char> actions(M, '.');\n    \n    // Wall cells needed to seal the rectangle\n    vector<Point> needed_walls;\n    // r1-1, r2+1, c1-1, c2+1\n    if (target_rect.r1 > 0) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r1 - 1, c);\n    if (target_rect.r2 < H - 1) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r2 + 1, c);\n    if (target_rect.c1 > 0) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c1 - 1);\n    if (target_rect.c2 < W - 1) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c2 + 1);\n    \n    // Remove already built walls\n    needed_walls.erase(remove_if(needed_walls.begin(), needed_walls.end(), \n        [&](const Point& p){ return grid[p.x][p.y]; }), \n        needed_walls.end());\n        \n    // Phase 1: Move humans into the rectangle\n    if (phase == 1) {\n        bool all_in = true;\n        for (int i = 0; i < M; ++i) {\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            if (target_rect.r1 <= hx && hx <= target_rect.r2 && target_rect.c1 <= hy && hy <= target_rect.c2) {\n                actions[i] = '.';\n                continue;\n            }\n            all_in = false;\n            \n            // Move towards closest point in rect\n            int tx = max(target_rect.r1, min(hx, target_rect.r2));\n            int ty = max(target_rect.c1, min(hy, target_rect.c2));\n            \n            // BFS to find shortest path to (tx, ty) or any cell in rect?\n            // Simple greedy: reduce Manhattan distance\n            int best_d = abs(hx - tx) + abs(hy - ty);\n            int best_dir = -1;\n            \n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + DX[d];\n                int ny = hy + DY[d];\n                if (!inside(nx, ny)) continue;\n                if (grid[nx][ny]) continue; // Can't move into wall\n                \n                // Check if (nx, ny) is in rect (good)\n                bool in_rect = (target_rect.r1 <= nx && nx <= target_rect.r2 && target_rect.c1 <= ny && ny <= target_rect.c2);\n                int d_score = abs(nx - tx) + abs(ny - ty);\n                if (in_rect) d_score = -1000; // Priority to enter\n                \n                if (d_score < best_d) {\n                    best_d = d_score;\n                    best_dir = d;\n                }\n            }\n            if (best_dir != -1) {\n                actions[i] = DIR_CHAR[best_dir];\n                current_humans[i].x += DX[best_dir];\n                current_humans[i].y += DY[best_dir];\n            }\n        }\n        \n        if (all_in) {\n            phase = 2;\n            // Assign wall tasks\n            wall_tasks = needed_walls;\n            // Shuffle to distribute work randomly? Or keep sorted?\n            // Keep simple.\n        }\n    } \n    // Phase 2: Build walls\n    else if (phase == 2) {\n        if (wall_tasks.empty()) {\n            phase = 3;\n            return actions;\n        }\n        \n        // Greedy assignment: each human picks closest task\n        // To avoid conflict, we process humans in order of distance to tasks? \n        // Or simply assign static chunks? \n        // Static chunks are better for consistency.\n        \n        // Let's use a persistent assignment.\n        // If no assignment yet, create one.\n        static vector<int> assignment(M, -1);\n        static bool assigned = false;\n        \n        if (!assigned || wall_tasks.size() != (unsigned)(assignment.size())) {\n             // Simple Round Robin assignment based on human index\n             assignment.clear();\n             assignment.resize(M, -1);\n             for (size_t i = 0; i < wall_tasks.size(); ++i) {\n                 assignment[i % M] = i;\n             }\n             assigned = true;\n        }\n        \n        // Execute\n        for (int i = 0; i < M; ++i) {\n            int task_idx = assignment[i];\n            if (task_idx == -1 || task_idx >= (int)wall_tasks.size()) {\n                actions[i] = '.';\n                continue;\n            }\n            \n            Point target = wall_tasks[task_idx];\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            // If adjacent, try build\n            bool adj = false;\n            int build_dir = -1;\n            for (int d = 0; d < 4; ++d) {\n                if (hx + DX[d] == target.x && hy + DY[d] == target.y) {\n                    adj = true;\n                    build_dir = d;\n                    break;\n                }\n            }\n            \n            if (adj) {\n                // Check if buildable\n                // Need to check adjacency to pets at the START of this turn\n                // We have `pets` vector which is already updated for this turn?\n                // No, `pets` in global state is updated at the START of the loop in main.\n                // So `pets` holds positions at the START of the turn.\n                // We check buildability against `pets`.\n                \n                // is_buildable checks `grid` and `pets` and `current_humans`\n                // But `current_humans` is being modified. We should use previous pos? \n                // Rule: \"cannot choose a square that contains pets or humans at the start of this turn\"\n                // So we check against `humans` (initial state of turn).\n                // `current_humans` is a copy we modify to simulate moves. \n                // We need the actual start positions.\n                // Let's pass `humans` (the vector holding start-of-turn pos) to is_buildable?\n                // Or just check `current_humans[i]` before moving? No, that's wrong for other humans.\n                // Let's assume `humans` is not modified yet.\n                // Wait, I modify `current_humans` in place.\n                // So at the start of generate_actions, `current_humans` IS the start position.\n                // Good.\n                \n                if (is_buildable(target.x, target.y, pets, current_humans)) {\n                    actions[i] = BLOCK_CHAR[build_dir];\n                    grid[target.x][target.y] = true; // Mark as built immediately for logic?\n                    // Note: The problem says \"perform each action simultaneously\".\n                    // However, for our planning in the next turn, we update grid.\n                    // If two humans build the same wall, the second one does nothing (rule: \"If you choose a square that is already impassable, nothing happens\").\n                    // But we shouldn't assign two humans to the same task ideally.\n                    // With round robin, tasks are distinct.\n                    \n                    // Remove task\n                    wall_tasks.erase(wall_tasks.begin() + task_idx);\n                    // Update assignments?\n                    // Shift indices down for those > task_idx\n                    for (int k = 0; k < M; ++k) {\n                        if (assignment[k] > task_idx) assignment[k]--;\n                    }\n                } else {\n                    actions[i] = '.'; // Cannot build now\n                }\n            } else {\n                // Move towards target\n                // BFS or simple Manhattan\n                int best_d = abs(hx - target.x) + abs(hy - target.y);\n                int best_dir = -1;\n                \n                for (int d = 0; d < 4; ++d) {\n                    int nx = hx + DX[d];\n                    int ny = hy + DY[d];\n                    if (!inside(nx, ny)) continue;\n                    if (grid[nx][ny]) continue;\n                    if (nx == target.x && ny == target.y) continue; // Moving onto the wall square? No, can only build adjacent. \n                    // Actually, can we move onto a square that will be a wall? \n                    // \"It is not possible to move to a square that becomes impassable by another person's action in this turn.\"\n                    // We are the person. If we move to target, we can't build it (must be adjacent).\n                    // So we shouldn't move onto target.\n                    \n                    int d_score = abs(nx - target.x) + abs(ny - target.y);\n                    if (d_score < best_d) {\n                        best_d = d_score;\n                        best_dir = d;\n                    }\n                }\n                if (best_dir != -1) {\n                    actions[i] = DIR_CHAR[best_dir];\n                    current_humans[i].x += DX[best_dir];\n                    current_humans[i].y += DY[best_dir];\n                } else {\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        if (wall_tasks.empty()) phase = 3;\n    }\n    // Phase 3: Done\n    else {\n        for (int i = 0; i < M; ++i) actions[i] = '.';\n    }\n    \n    return actions;\n}\n\nvoid solve() {\n    read_init();\n    \n    Rect target_rect;\n    int phase = 1; // 1: Enter, 2: Build, 3: Done\n    vector<Point> wall_tasks;\n    \n    for (int t = 0; t < TURNS; ++t) {\n        // Read Pet Moves\n        vector<string> pet_moves;\n        read_turn(pet_moves);\n        \n        // Update Pet Positions\n        apply_moves(pet_moves);\n        \n        // Check if plan is still valid\n        bool valid = true;\n        if (phase == 3) {\n            // Just stay put\n            cout << string(M, '.') << endl;\n            continue;\n        }\n        \n        // Check if pets entered target rect\n        for (const auto& p : pets) {\n            if (target_rect.r1 <= p.x && p.x <= target_rect.r2 &&\n                target_rect.c1 <= p.y && p.y <= target_rect.c2) {\n                valid = false;\n                break;\n            }\n        }\n        \n        if (!valid || phase == 0) {\n            // Re-plan\n            target_rect = find_best_rectangle();\n            phase = 1;\n            wall_tasks.clear();\n            // cout << \"# Turn \" << t << \" Replanning. Rect: \" \n            //      << target_rect.r1 << \" \" << target_rect.r2 << \" \"\n            //      << target_rect.c1 << \" \" << target_rect.c2 << \" Area: \" << target_rect.area << endl;\n        }\n        \n        // Generate Actions\n        // We need a copy of human positions to simulate moves for next turn logic?\n        // No, the problem state updates based on our output.\n        // We just need to update our internal `humans` state for the next iteration's `is_buildable` check.\n        // So `generate_actions` should update `humans`.\n        // But `is_buildable` needs \"start of turn\" positions.\n        // So we pass `humans` (which holds start pos) and update it at the end.\n        \n        vector<char> actions = generate_actions(target_rect, humans, phase, wall_tasks, t);\n        \n        // Output\n        string s(actions.begin(), actions.end());\n        cout << s << endl;\n        cout.flush();\n    }\n}\n\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n    solve();\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Global configuration\nconst int H = 20;\nconst int W = 20;\nconst int MAX_LEN = 200;\nconst double INF = 1e9;\n\n// Directions\nconst int DY[4] = {-1, 1, 0, 0};\nconst int DX[4] = {0, 0, -1, 1};\nconst char DC[4] = {'U', 'D', 'L', 'R'};\n\n// Input\nint si, sj, ti, tj;\ndouble p;\nvector<string> h_grid(H);\nvector<string> v_grid(H-1);\n\n// Helper to check wall\n// dir: 0=U, 1=D, 2=L, 3=R\ninline bool is_wall(int y, int x, int dir) {\n    if (dir == 0) { // U\n        if (y == 0) return true;\n        return v_grid[y-1][x] == '1';\n    } else if (dir == 1) { // D\n        if (y == H-1) return true;\n        return v_grid[y][x] == '1';\n    } else if (dir == 2) { // L\n        if (x == 0) return true;\n        return h_grid[y][x-1] == '1';\n    } else { // R\n        if (x == W-1) return true;\n        return h_grid[y][x] == '1';\n    }\n    return false;\n}\n\n// Buffers for calculation to avoid allocation overhead\nvector<vector<double>> prob_buff1(H, vector<double>(W, 0.0));\nvector<vector<double>> prob_buff2(H, vector<double>(W, 0.0));\n\n// Function to calculate expected score of a sequence\n// Uses DP on probability distribution\ndouble calculate_score(const string& s) {\n    // Initialize buffers\n    for(int i=0; i<H; ++i) fill(prob_buff1[i].begin(), prob_buff1[i].end(), 0.0);\n    \n    prob_buff1[si][sj] = 1.0;\n    double expected_score = 0.0;\n    int L = s.length();\n\n    auto& curr_prob = prob_buff1;\n    auto& next_prob = prob_buff2;\n\n    for (int t = 0; t < L; ++t) {\n        // Reset next_prob\n        for(int i=0; i<H; ++i) fill(next_prob[i].begin(), next_prob[i].end(), 0.0);\n\n        int dir_idx = -1;\n        if (s[t] == 'U') dir_idx = 0;\n        else if (s[t] == 'D') dir_idx = 1;\n        else if (s[t] == 'L') dir_idx = 2;\n        else if (s[t] == 'R') dir_idx = 3;\n\n        // If invalid char (should not happen), just stay\n        if (dir_idx == -1) {\n            // Treat as staying, effectively just p stays, 1-p stays (if wall) or moves\n            // but since char is invalid, we assume it maps to nothing or self-loop? \n            // Problem guarantees UDLR.\n        }\n\n        double ny_off = DY[dir_idx];\n        double nx_off = DX[dir_idx];\n\n        for (int y = 0; y < H; ++y) {\n            for (int x = 0; x < W; ++x) {\n                double cur_p = curr_prob[y][x];\n                if (cur_p == 0.0) continue;\n\n                // Probability of forgetting: stay in place\n                double p_forget = cur_p * p;\n                next_prob[y][x] += p_forget;\n\n                // Probability of trying to move\n                double p_move = cur_p * (1.0 - p);\n                \n                int nx = x + (int)nx_off;\n                int ny = y + (int)ny_off;\n\n                // Check wall collision\n                if (is_wall(y, x, dir_idx)) {\n                    next_prob[y][x] += p_move;\n                } else {\n                    if (ny == ti && nx == tj) {\n                        // Reached goal\n                        expected_score += p_move * (401.0 - (t + 1));\n                        // Mass absorbed into score, not propagated to next state\n                    } else {\n                        next_prob[ny][nx] += p_move;\n                    }\n                }\n            }\n        }\n        swap(curr_prob, next_prob);\n    }\n    return expected_score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < H; ++i) cin >> h_grid[i];\n    for (int i = 0; i < H-1; ++i) cin >> v_grid[i];\n\n    // 1. Find shortest path (A*)\n    // priority_queue: (estimated_cost, y, x)\n    using Node = pair<int, pair<int, int>>;\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    vector<vector<int>> dist(H, vector<int>(W, INF));\n    vector<vector<int>> parent(H, vector<int>(W, -1));\n    \n    auto heuristic = [&](int y, int x) {\n        return abs(y - ti) + abs(x - tj);\n    };\n\n    dist[si][sj] = 0;\n    pq.push({heuristic(si, sj), {si, sj}});\n\n    while (!pq.empty()) {\n        auto curr = pq.top();\n        pq.pop();\n        int y = curr.second.first;\n        int x = curr.second.second;\n        int cost = dist[y][x];\n\n        if (y == ti && x == tj) break;\n        if (cost > dist[y][x]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int ny = y + DY[i];\n            int nx = x + DX[i];\n            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;\n            if (is_wall(y, x, i)) continue;\n            \n            if (dist[ny][nx] > cost + 1) {\n                dist[ny][nx] = cost + 1;\n                parent[ny][nx] = i;\n                pq.push({dist[ny][nx] + heuristic(ny, nx), {ny, nx}});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cy = ti, cx = tj;\n    while (cy != si || cx != sj) {\n        int dir = parent[cy][cx];\n        path.push_back(DC[dir]);\n        cy -= DY[dir];\n        cx -= DX[dir];\n    }\n    reverse(path.begin(), path.end());\n    \n    // 2. Build initial robust string\n    // Strategy: Repeat each character in the path K times\n    // K depends on p. Higher p -> Higher K.\n    int path_len = path.length();\n    string ans = \"\";\n    \n    // Calculate optimal K\n    // Empirically chosen thresholds\n    int K = 1;\n    if (p > 0.15) K = 2;\n    if (p > 0.35) K = 3;\n    if (p > 0.45) K = 4;\n    \n    // Ensure K * path_len fits reasonably, or reduce K if too long\n    // We want to repeat the sequence to allow multiple attempts.\n    // A single run of robust path should consume most of the length or leave room for repeats.\n    // If K*path_len is very small, we can repeat it many times.\n    // If K*path_len is close to 200, we run it once.\n    \n    // Cap K such that we can at least run the path once\n    while (K > 1 && K * path_len > 200) {\n        K--;\n    }\n\n    string robust_seg = \"\";\n    for (char c : path) {\n        robust_seg += string(K, c);\n    }\n    \n    // Fill ans by repeating the robust segment\n    while ((int)ans.size() < 200) {\n        ans += robust_seg;\n    }\n    ans.resize(200);\n\n    // 3. Local Search (Hill Climbing)\n    auto start_time = chrono::high_resolution_clock::now();\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis_idx(0, 199);\n    uniform_int_distribution<> dis_dir(0, 3);\n\n    double current_score = calculate_score(ans);\n    string best_ans = ans;\n    double best_score = current_score;\n    \n    const int time_limit_ms = 1900;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > time_limit_ms) break;\n\n        // Mutation 1: Change a random character\n        int idx = dis_idx(gen);\n        int new_dir = dis_dir(gen);\n        char original = ans[idx];\n        char new_char = DC[new_dir];\n        \n        if (original != new_char) {\n            ans[idx] = new_char;\n            double new_score = calculate_score(ans);\n            \n            if (new_score > current_score) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_ans = ans;\n                }\n            } else {\n                ans[idx] = original; // Revert\n            }\n        }\n\n        // Mutation 2: Swap two random characters (less frequent or just mixed in)\n        // To keep it fast, we can just do change mutations mostly.\n        // Let's try a swap occasionally\n        if (dis_idx(gen) % 10 == 0) {\n             int idx2 = dis_idx(gen);\n             if (idx != idx2) {\n                 swap(ans[idx], ans[idx2]);\n                 double new_score = calculate_score(ans);\n                 if (new_score > current_score) {\n                     current_score = new_score;\n                     if (new_score > best_score) {\n                         best_score = new_score;\n                         best_ans = ans;\n                     }\n                 } else {\n                     swap(ans[idx], ans[idx2]); // Revert\n                 }\n             }\n        }\n    }\n\n    cout << best_ans << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <ctime>\n#include <set>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0:Left, 1:Up, 2:Right, 3:Down\nint dr[4] = {0, -1, 0, 1};\nint dc[4] = {-1, 0, 1, 0};\n\n// to[type][in_dir] = out_dir\nint to[8][4] = {\n    {1, 0, -1, -1}, // 0: LU\n    {3, -1, -1, 0}, // 1: LD\n    {-1, -1, 3, 2}, // 2: RD\n    {-1, 2, 1, -1}, // 3: RU\n    {1, 0, 3, 2},   // 4: Cross 1\n    {3, 2, 1, 0},   // 5: Cross 2\n    {2, -1, 0, -1}, // 6: Vert\n    {-1, 3, -1, 1}  // 7: Horz\n};\n\nint grid[H][W];\nint state[H][W]; \nint rotations[H][W]; \n\nmt19937 rng(time(0));\n\n// Returns effective type based on base type and rotation\nint get_type(int base, int r) {\n    if (base <= 3) return (base + r) % 4;\n    if (base == 4 || base == 5) return ((base + r) % 2 == 0) ? 4 : 5;\n    return ((base + r) % 2 == 0) ? 6 : 7;\n}\n\n// Trace loop starting at (r,c) entering from in_d.\n// Returns length of loop, or 0 if not a loop.\nint trace_loop(int r, int c, int in_d) {\n    int cr = r, cc = c, cd = in_d;\n    int len = 0;\n    // Safety limit, though max path is < 1000\n    for (int steps = 0; steps < 1000; ++steps) {\n        int t = state[cr][cc];\n        int out_d = to[t][cd];\n        if (out_d == -1) return 0;\n        \n        int nr = cr + dr[out_d];\n        int nc = cc + dc[out_d];\n        len++;\n        \n        if (nr < 0 || nr >= H || nc < 0 || nc >= W) return 0;\n        \n        int next_in_d = (out_d + 2) % 4;\n        if (nr == r && nc == c && next_in_d == in_d) return len;\n        \n        cr = nr; cc = nc; cd = next_in_d;\n    }\n    return 0;\n}\n\n// Global state\nmultiset<int> loops;\nlong long current_score = 0;\n\n// Calculate score from the 'loops' multiset\nvoid recalc_score() {\n    if (loops.size() < 2) current_score = 0;\n    else {\n        auto it = loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        current_score = (long long)L1 * L2;\n    }\n}\n\n// Full scan to initialize loops and score\nvoid full_scan() {\n    loops.clear();\n    int visited[H][W][4] = {0};\n    int stamp = 1;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (visited[i][j][d]) continue;\n                int t = state[i][j];\n                if (to[t][d] == -1) continue;\n                \n                int len = trace_loop(i, j, d);\n                if (len > 0) {\n                    loops.insert(len);\n                    // Mark visited\n                    int cr=i, cc=j, cd=d;\n                    while(true) {\n                        visited[cr][cc][cd] = stamp;\n                        int out = to[state[cr][cc]][cd];\n                        int nr = cr + dr[out], nc = cc + dc[out];\n                        int nd = (out+2)%4;\n                        if(nr==i && nc==j && nd==d) break;\n                        cr=nr; cc=nc; cd=nd;\n                    }\n                    stamp++;\n                }\n            }\n        }\n    }\n    recalc_score();\n}\n\n// Optimized flip evaluation\n// Returns new score, and fills old_lengths/new_lengths vectors\nlong long try_flip(int r, int c, int new_rot, vector<int>& old_lengths, vector<int>& new_lengths) {\n    int old_rot = rotations[r][c];\n    if (new_rot == old_rot) return current_score;\n\n    // 1. Identify old loops passing through (r,c)\n    old_lengths.clear();\n    bool processed[4] = {false};\n    int old_t = state[r][c];\n    for (int d = 0; d < 4; ++d) {\n        if (to[old_t][d] != -1 && !processed[d]) {\n            int out_d = to[old_t][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) old_lengths.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    // 2. Apply temporary change to state\n    state[r][c] = get_type(grid[r][c], new_rot);\n    \n    // 3. Identify new loops passing through (r,c)\n    new_lengths.clear();\n    fill(processed, processed+4, false);\n    int new_t = state[r][c];\n    for (int d = 0; d < 4; ++d) {\n        if (to[new_t][d] != -1 && !processed[d]) {\n            int out_d = to[new_t][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) new_lengths.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    // 4. Calculate new score\n    multiset<int> temp_loops = loops;\n    for (int l : old_lengths) {\n        auto it = temp_loops.find(l);\n        if (it != temp_loops.end()) temp_loops.erase(it);\n    }\n    for (int l : new_lengths) temp_loops.insert(l);\n    \n    // Revert state change (main loop will apply if accepted)\n    state[r][c] = old_t;\n\n    long long score = 0;\n    if (temp_loops.size() >= 2) {\n        auto it = temp_loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        score = (long long)L1 * L2;\n    }\n    return score;\n}\n\n// Helper to apply the change permanently (update state, rotations, loops, score)\n// Uses the pre-calculated lengths to avoid re-tracing\nvoid apply_change(int r, int c, int new_rot, const vector<int>& old_lengths, const vector<int>& new_lengths) {\n    // Remove old\n    for (int l : old_lengths) {\n        auto it = loops.find(l);\n        if (it != loops.end()) loops.erase(it);\n    }\n    // Add new\n    for (int l : new_lengths) loops.insert(l);\n    \n    // Update State\n    rotations[r][c] = new_rot;\n    state[r][c] = get_type(grid[r][c], new_rot);\n    \n    recalc_score();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    for (int i = 0; i < H; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < W; ++j) grid[i][j] = s[j] - '0';\n    }\n    \n    long long best_global_score = -1;\n    int best_init_rot[H][W];\n    \n    // Multi-start Greedy Initialization\n    int INIT_TRIES = 30; // Increased tries for better starting point\n    for(int t=0; t<INIT_TRIES; ++t) {\n        vector<pair<int, int>> order;\n        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) order.push_back({i,j});\n        shuffle(order.begin(), order.end(), rng);\n        \n        // Start with random rotations\n        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) rotations[i][j] = rng() % 4;\n        \n        // Greedy pass\n        for(auto& p : order) {\n            int i = p.first, j = p.second;\n            int best_r = rotations[i][j];\n            int best_conn = -1;\n            \n            // Check all 4 rotations to find best local connectivity\n            for(int r=0; r<4; ++r) {\n                int t_eff = get_type(grid[i][j], r);\n                int conn = 0;\n                // Maximize connections with already set neighbors\n                if(i>0 && to[state[i-1][j]][3]!=-1 && to[t_eff][1]!=-1) conn++;\n                if(i<H-1 && to[state[i+1][j]][1]!=-1 && to[t_eff][3]!=-1) conn++;\n                if(j>0 && to[state[i][j-1]][2]!=-1 && to[t_eff][0]!=-1) conn++;\n                if(j<W-1 && to[state[i][j+1]][0]!=-1 && to[t_eff][2]!=-1) conn++;\n                \n                if (conn > best_conn || (conn == best_conn && rng() % 2)) {\n                    best_conn = conn;\n                    best_r = r;\n                }\n            }\n            rotations[i][j] = best_r;\n            state[i][j] = get_type(grid[i][j], best_r);\n        }\n        \n        full_scan();\n        if(current_score > best_global_score) {\n            best_global_score = current_score;\n            for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_init_rot[i][j] = rotations[i][j];\n        }\n    }\n    \n    // Restore best initialization\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) rotations[i][j] = best_init_rot[i][j];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) state[i][j] = get_type(grid[i][j], rotations[i][j]);\n    full_scan();\n    \n    long long best_score = current_score;\n    int best_sol_rot[H][W];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n\n    // Simulated Annealing\n    auto start_time = clock();\n    double TIME_LIMIT = 1.95 * CLOCKS_PER_SEC;\n    \n    // Reusable vectors to avoid allocation in loop\n    vector<int> old_lengths, new_lengths;\n    \n    while((double)(clock() - start_time) < TIME_LIMIT) {\n        double progress = (double)(clock() - start_time) / TIME_LIMIT;\n        double T = 500.0 * (1.0 - progress); // Higher initial temp\n        if(T < 0.1) T = 0.1;\n        \n        int r = rng() % H;\n        int c = rng() % W;\n        int old_rot = rotations[r][c];\n        \n        // Neighbor Selection: Bias towards small changes (+/- 1) for local refinement\n        // but allow random jumps for global exploration\n        int new_rot;\n        int dice = rng() % 100;\n        if(dice < 80) {\n             new_rot = (old_rot + (rng()%2 ? 1 : 3)) % 4; // +1 or -1\n        } else {\n             new_rot = rng() % 4;\n        }\n        \n        if(new_rot == old_rot) continue;\n        \n        // Calculate new score efficiently\n        long long new_score = try_flip(r, c, new_rot, old_lengths, new_lengths);\n        long long diff = new_score - current_score;\n        \n        // Acceptance criteria\n        if(diff > 0 || (rng() % 100000 < 100000 * exp(diff / T))) {\n            // Apply change using pre-calculated lengths\n            apply_change(r, c, new_rot, old_lengths, new_lengths);\n            \n            if(current_score > best_score) {\n                best_score = current_score;\n                for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n            }\n        }\n    }\n    \n    string ans = \"\";\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ans += (char)('0' + best_sol_rot[i][j]);\n        }\n    }\n    cout << ans << endl;\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <array>\n#include <tuple> // Added necessary header for std::tuple and structured bindings\n\nusing namespace std;\n\nconst int LEFT = 1;\nconst int UP = 2;\nconst int RIGHT = 4;\nconst int DOWN = 8;\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n    bool operator==(const Point& p) const { return r == p.r && c == p.c; }\n    bool operator<(const Point& p) const {\n        if (r != p.r) return r < p.r;\n        return c < p.c;\n    }\n};\n\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char MOVE_CHARS[4] = {'U', 'D', 'L', 'R'};\n\nclass Solver {\npublic:\n    int N;\n    int T_limit;\n    vector<vector<int>> board;\n    Point empty_pos;\n    string moves;\n    mt19937 rng;\n\n    const int DIST_WEIGHT = 5; \n\n    Solver(int n, int t_limit) : N(n), T_limit(t_limit), rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void set_board(const vector<vector<int>>& b, Point ep) {\n        board = b;\n        empty_pos = ep;\n        moves = \"\";\n    }\n\n    bool is_valid(int r, int c) {\n        // Fixed typo: 0 <= c < c < N -> 0 <= c && c < N\n        return 0 <= r && r < N && 0 <= c && c < N;\n    }\n\n    pair<Point, int> find_closest_tile(Point p, int bitmask) {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        queue<pair<Point, int>> q;\n        q.push({p, 0});\n        visited[p.r][p.c] = true;\n        \n        while (!q.empty()) {\n            auto curr = q.front(); q.pop();\n            Point pt = curr.first;\n            int dist = curr.second;\n            \n            if (pt != p) {\n                if (board[pt.r][pt.c] != 0 && (board[pt.r][pt.c] & bitmask)) {\n                    return {pt, dist};\n                }\n            }\n            \n            for (int d = 0; d < 4; ++d) {\n                int nr = pt.r + DR[d];\n                int nc = pt.c + DC[d];\n                if (is_valid(nr, nc) && !visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.push({Point(nr, nc), dist + 1});\n                }\n            }\n        }\n        return {Point(-1, -1), -1};\n    }\n\n    vector<Point> get_path_for_empty(Point target, Point forbidden = Point(-1, -1)) {\n        if (empty_pos == target) return {};\n        queue<Point> q;\n        vector<vector<Point>> parent(N, vector<Point>(N, Point(-1, -1)));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        q.push(empty_pos);\n        visited[empty_pos.r][empty_pos.c] = true;\n        bool found = false;\n        while(!q.empty()) {\n            Point p = q.front(); q.pop();\n            if(p == target) { found = true; break; }\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) && !visited[nr][nc]) {\n                    if (Point(nr, nc) == forbidden) continue; \n                    visited[nr][nc] = true;\n                    parent[nr][nc] = p;\n                    q.push(Point(nr, nc));\n                }\n            }\n        }\n        vector<Point> path;\n        if(found) {\n            Point curr = target;\n            while(curr != empty_pos) {\n                path.push_back(curr);\n                curr = parent[curr.r][curr.c];\n            }\n            reverse(path.begin(), path.end());\n        }\n        return path;\n    }\n\n    void execute_empty_path(const vector<Point>& path) {\n        for (Point p : path) {\n            if (moves.size() >= static_cast<size_t>(T_limit)) return;\n            int dr = p.r - empty_pos.r;\n            int dc = p.c - empty_pos.c;\n            int d = -1;\n            if (dr == -1) d = 0; else if (dr == 1) d = 1;\n            else if (dc == -1) d = 2; else if (dc == 1) d = 3;\n            \n            moves += MOVE_CHARS[d];\n            board[empty_pos.r][empty_pos.c] = board[p.r][p.c];\n            board[p.r][p.c] = 0;\n            empty_pos = p;\n        }\n    }\n\n    void move_tile(Point from, Point to) {\n        if (from == to) return;\n        Point cur = from;\n        while (cur != to) {\n            if (moves.size() >= static_cast<size_t>(T_limit)) return;\n            \n            Point diff = Point(to.r - cur.r, to.c - cur.c);\n            vector<int> dirs;\n            if (diff.r > 0) dirs.push_back(1);\n            else if (diff.r < 0) dirs.push_back(0);\n            if (diff.c > 0) dirs.push_back(3);\n            else if (diff.c < 0) dirs.push_back(2);\n            \n            shuffle(dirs.begin(), dirs.end(), rng);\n            bool moved = false;\n            for (int d : dirs) {\n                int nr = cur.r + DR[d];\n                int nc = cur.c + DC[d];\n                Point next_target(nr, nc);\n                vector<Point> path = get_path_for_empty(next_target, cur);\n                if (path.empty()) continue; \n\n                execute_empty_path(path);\n                if (moves.size() >= static_cast<size_t>(T_limit)) return;\n\n                int er = cur.r - empty_pos.r; \n                int ec = cur.c - empty_pos.c;\n                int ed = -1;\n                if (er == -1) ed = 0; else if (er == 1) ed = 1;\n                else if (ec == -1) ed = 2; else if (ec == 1) ed = 3;\n                \n                moves += MOVE_CHARS[ed];\n                board[empty_pos.r][empty_pos.c] = board[cur.r][cur.c];\n                board[cur.r][cur.c] = 0;\n                empty_pos = cur;\n                \n                cur = next_target;\n                moved = true;\n                break;\n            }\n            if (!moved) break;\n        }\n    }\n\n    void solve() {\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        vector<vector<bool>> in_tree(N, vector<bool>(N, false));\n        vector<Point> frontier;\n        \n        // Find initial largest component\n        int best_score = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] != 0 && !visited[i][j]) {\n                    queue<Point> q;\n                    vector<Point> comp;\n                    q.push(Point(i, j));\n                    visited[i][j] = true;\n                    comp.push_back(Point(i, j));\n\n                    while (!q.empty()) {\n                        Point cur = q.front(); q.pop();\n                        int cr = cur.r, cc = cur.c;\n                        int tile = board[cr][cc];\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (is_valid(nr, nc) && board[nr][nc] != 0 && !visited[nr][nc]) {\n                                int neighbor = board[nr][nc];\n                                bool connects = false;\n                                if (d == 0 && (tile & UP) && (neighbor & DOWN)) connects = true;\n                                if (d == 1 && (tile & DOWN) && (neighbor & UP)) connects = true;\n                                if (d == 2 && (tile & LEFT) && (neighbor & RIGHT)) connects = true;\n                                if (d == 3 && (tile & RIGHT) && (neighbor & LEFT)) connects = true;\n                                \n                                if (connects) {\n                                    visited[nr][nc] = true;\n                                    comp.push_back(Point(nr, nc));\n                                    q.push(Point(nr, nc));\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (comp.size() > static_cast<size_t>(best_score)) {\n                        best_score = comp.size();\n                        fill(in_tree.begin(), in_tree.end(), vector<bool>(N, false));\n                        for(auto& p : comp) in_tree[p.r][p.c] = true;\n                    }\n                }\n            }\n        }\n        \n        // Initialize Frontier\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (in_tree[i][j]) continue;\n                bool is_frontier = false;\n                for(int d=0; d<4; ++d) {\n                    int nr = i+DR[d], nc = j+DC[d];\n                    if(is_valid(nr, nc) && in_tree[nr][nc]) {\n                        is_frontier = true; break;\n                    }\n                }\n                if(is_frontier) frontier.push_back(Point(i, j));\n            }\n        }\n\n        // PQ Element: {Cost, u.r, u.c, v.r, v.c, filler.r, filler.c, modify_u}\n        using PQElement = tuple<int, int, int, int, int, int, int, bool>;\n        priority_queue<PQElement, vector<PQElement>, greater<PQElement>> pq;\n\n        auto update_pq = [&]() {\n            while(!pq.empty()) pq.pop();\n            for (Point u : frontier) {\n                if (board[u.r][u.c] == 0) continue; \n                for (int d = 0; d < 4; ++d) {\n                    int vr = u.r + DR[d];\n                    int vc = u.c + DC[d];\n                    Point v(vr, vc);\n                    if (!is_valid(vr, vc) || !in_tree[vr][vc]) continue;\n\n                    int tile_u = board[u.r][u.c];\n                    int tile_v = board[v.r][v.c];\n\n                    int bit_u = 0, bit_v = 0;\n                    if (d == 0) { bit_u = 2; bit_v = 8; }\n                    else if (d == 1) { bit_u = 8; bit_v = 2; }\n                    else if (d == 2) { bit_u = 1; bit_v = 4; }\n                    else if (d == 3) { bit_u = 4; bit_v = 1; }\n\n                    bool u_has = (tile_u & bit_u);\n                    bool v_has = (tile_v & bit_v);\n\n                    if (u_has && v_has) {\n                        pq.push(make_tuple(0, u.r, u.c, v.r, v.c, -1, -1, true));\n                    } else if (!u_has) {\n                        auto res = find_closest_tile(u, bit_u);\n                        if (res.second != -1) {\n                            int cost = res.second * DIST_WEIGHT;\n                            pq.push(make_tuple(cost, u.r, u.c, v.r, v.c, res.first.r, res.first.c, true));\n                        }\n                    } else if (!v_has) {\n                        auto res = find_closest_tile(v, bit_v);\n                        if (res.second != -1) {\n                            int cost = (res.second * DIST_WEIGHT) + 5; \n                            pq.push(make_tuple(cost, u.r, u.c, v.r, v.c, res.first.r, res.first.c, false));\n                        }\n                    }\n                }\n            }\n        };\n\n        update_pq();\n\n        while (!pq.empty() && moves.size() < static_cast<size_t>(T_limit)) {\n            auto elem = pq.top();\n            int cost = get<0>(elem);\n            int ur = get<1>(elem), uc = get<2>(elem);\n            int vr = get<3>(elem), vc = get<4>(elem);\n            int fr = get<5>(elem), fc = get<6>(elem);\n            bool modify_u = get<7>(elem);\n            \n            Point u(ur, uc);\n            Point v(vr, vc);\n            Point filler(fr, fc);\n            \n            pq.pop();\n\n            if (in_tree[u.r][u.c]) continue;\n            if (board[u.r][u.c] == 0) continue;\n            \n            int tile_u = board[u.r][u.c];\n            int tile_v = board[v.r][v.c];\n            \n            int bit_u = 0, bit_v = 0;\n            int d = -1;\n            if (v.r < u.r) d=0; else if (v.r > u.r) d=1;\n            else if (v.c < u.c) d=2; else if (v.c > u.c) d=3;\n\n            if (d == -1) continue;\n            if (d == 0) { bit_u = 2; bit_v = 8; }\n            else if (d == 1) { bit_u = 8; bit_v = 2; }\n            else if (d == 2) { bit_u = 1; bit_v = 4; }\n            else if (d == 3) { bit_u = 4; bit_v = 1; }\n\n            bool u_has = (tile_u & bit_u);\n            bool v_has = (tile_v & bit_v);\n\n            if (u_has && v_has) {\n                in_tree[u.r][u.c] = true;\n                for(int nd=0; nd<4; ++nd) {\n                    int nr = u.r+DR[nd], nc = u.c+DC[nd];\n                    if(is_valid(nr, nc) && !in_tree[nr][nc] && board[nr][nc]!=0) frontier.push_back(Point(nr, nc));\n                }\n                update_pq();\n                continue;\n            }\n\n            if (cost == 0) continue; \n            if (filler.r == -1) continue; \n\n            if (modify_u) {\n                move_tile(filler, u);\n                in_tree[u.r][u.c] = true;\n                for(int nd=0; nd<4; ++nd) {\n                    int nr = u.r+DR[nd], nc = u.c+DC[nd];\n                    if(is_valid(nr, nc) && !in_tree[nr][nc] && board[nr][nc]!=0) frontier.push_back(Point(nr, nc));\n                }\n            } else {\n                move_tile(filler, v);\n                in_tree[u.r][u.c] = true;\n                for(int nd=0; nd<4; ++nd) {\n                    int nr = u.r+DR[nd], nc = u.c+DC[nd];\n                    if(is_valid(nr, nc) && !in_tree[nr][nc] && board[nr][nc]!=0) frontier.push_back(Point(nr, nc));\n                }\n            }\n            update_pq();\n        }\n        \n        cout << moves << endl;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    \n    vector<vector<int>> board(N, vector<int>(N));\n    Point empty_pos;\n    \n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) {\n            char c = line[j];\n            if (c == '0') {\n                board[i][j] = 0;\n                empty_pos = Point(i, j);\n            } else {\n                if (c >= 'a') board[i][j] = 10 + (c - 'a');\n                else board[i][j] = c - '0';\n            }\n        }\n    }\n\n    Solver solver(N, T);\n    solver.set_board(board, empty_pos);\n    solver.solve();\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <cmath>\n#include <chrono>\n#include <cassert>\n\nusing namespace std;\n\ntypedef long long ll;\n\nconst int K_MAX = 100;\n\nstruct Point {\n    ll x, y;\n};\n\nstruct Line {\n    ll x1, y1, x2, y2;\n};\n\n// Signature to uniquely identify a region (bitmask of side of each line)\nstruct Signature {\n    unsigned long long p1; // bits 0-63\n    unsigned long long p2; // bits 64-99 (since K_MAX is 100)\n\n    bool operator<(const Signature& other) const {\n        if (p1 != other.p1) return p1 < other.p1;\n        return p2 < other.p2;\n    }\n    \n    bool operator==(const Signature& other) const {\n        return p1 == other.p1 && p2 == other.p2;\n    }\n};\n\n// Global inputs\nint N, K;\nvector<int> a(11);\nvector<Point> points;\n\n// Random generator\nmt19937 rng(1337);\n\nll rand_ll(ll l, ll r) {\n    uniform_int_distribution<ll> dist(l, r);\n    return dist(rng);\n}\n\nll cross_product(const Point& a, const Point& b, const Point& c) {\n    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n// Generate a random line that does not pass through any point\nLine generate_random_line() {\n    while (true) {\n        ll x1 = rand_ll(-10000, 10000);\n        ll y1 = rand_ll(-10000, 10000);\n        ll x2 = rand_ll(-10000, 10000);\n        ll y2 = rand_ll(-10000, 10000);\n\n        if (x1 == x2 && y1 == y2) continue;\n\n        Line l{x1, y1, x2, y2};\n        \n        bool hits_point = false;\n        for (const auto& p : points) {\n            if (cross_product({x1, y1}, {x2, y2}, p) == 0) {\n                hits_point = true;\n                break;\n            }\n        }\n        if (!hits_point) {\n            return l;\n        }\n    }\n}\n\n// State of the solver\nstruct State {\n    int k;\n    vector<Line> lines;\n    vector<Signature> signatures; // signature for each point\n    vector<bool> is_dead;\n    \n    map<Signature, int> region_counts; // maps signature -> number of points in that region\n    vector<int> b_counts; // b_counts[d] = number of regions with exactly d points (d=1..10)\n    int score;\n\n    void init(int init_k) {\n        k = init_k;\n        lines.clear();\n        lines.reserve(k);\n        for(int i=0; i<k; ++i) lines.push_back(generate_random_line());\n        \n        is_dead.assign(N, false);\n        signatures.assign(N, {0, 0});\n        region_counts.clear();\n        b_counts.assign(11, 0);\n\n        for (int i = 0; i < N; ++i) {\n            Signature sig{0, 0};\n            bool dead = false;\n            for (int j = 0; j < k; ++j) {\n                ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                if (val == 0) {\n                    dead = true;\n                    break;\n                }\n                if (val > 0) {\n                    if (j < 64) sig.p1 |= (1ULL << j);\n                    else sig.p2 |= (1ULL << (j - 64));\n                }\n            }\n            is_dead[i] = dead;\n            signatures[i] = sig;\n            if (!dead) {\n                region_counts[sig]++;\n            }\n        }\n\n        for (auto& p : region_counts) {\n            int cnt = p.second;\n            if (1 <= cnt && cnt <= 10) {\n                b_counts[cnt]++;\n            }\n        }\n        compute_score();\n    }\n\n    void compute_score() {\n        score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min(a[d], b_counts[d]);\n        }\n    }\n\n    // Replace line at index idx with a new random line\n    void replace(int idx) {\n        Line old_line = lines[idx];\n        Line new_line = generate_random_line();\n        lines[idx] = new_line;\n\n        for (int i = 0; i < N; ++i) {\n            ll old_val = cross_product({old_line.x1, old_line.y1}, {old_line.x2, old_line.y2}, points[i]);\n            ll new_val = cross_product({new_line.x1, new_line.y1}, {new_line.x2, new_line.y2}, points[i]);\n\n            // Since new_line is guaranteed not to pass through points, new_val != 0\n            \n            if (is_dead[i]) {\n                // Point was dead. It becomes alive if the old line was the one killing it.\n                if (old_val == 0) {\n                    // Recalculate signature from scratch\n                    Signature sig{0, 0};\n                    bool still_dead = false;\n                    for (int j = 0; j < k; ++j) {\n                        ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                        if (val == 0) {\n                            still_dead = true;\n                            break;\n                        }\n                        if (val > 0) {\n                            if (j < 64) sig.p1 |= (1ULL << j);\n                            else sig.p2 |= (1ULL << (j - 64));\n                        }\n                    }\n                    \n                    is_dead[i] = still_dead;\n                    if (!still_dead) {\n                        // Point came alive\n                        int cnt = region_counts[sig]++;\n                        // b_counts update: added 1 to region with (cnt-1) points -> now cnt points\n                        int prev_cnt = cnt - 1;\n                        if (1 <= prev_cnt && prev_cnt <= 10) b_counts[prev_cnt]--;\n                        if (1 <= cnt && cnt <= 10) b_counts[cnt]++;\n                        \n                        signatures[i] = sig;\n                    }\n                }\n                // If dead due to another line, stays dead. No change.\n            } else {\n                // Point was alive. Since new_val != 0, it stays alive.\n                // Check if side changed\n                bool old_pos = (old_val > 0);\n                bool new_pos = (new_val > 0);\n                \n                if (old_pos != new_pos) {\n                    Signature old_sig = signatures[i];\n                    Signature new_sig = old_sig;\n                    // Toggle bit at idx\n                    if (idx < 64) new_sig.p1 ^= (1ULL << idx);\n                    else new_sig.p2 ^= (1ULL << (idx - 64));\n\n                    // Remove from old region\n                    int cnt_old = region_counts[old_sig]--;\n                    // b_counts update: removed 1 from region with cnt_old points -> now cnt_old-1 points\n                    if (1 <= cnt_old && cnt_old <= 10) b_counts[cnt_old]--;\n                    if (1 <= cnt_old - 1 && cnt_old - 1 <= 10) b_counts[cnt_old - 1]++;\n\n                    // Add to new region\n                    int cnt_new = region_counts[new_sig]++;\n                    // b_counts update: added 1 to region with cnt_new-1 points -> now cnt_new points\n                    if (1 <= cnt_new - 1 && cnt_new - 1 <= 10) b_counts[cnt_new - 1]--;\n                    if (1 <= cnt_new && cnt_new <= 10) b_counts[cnt_new]++;\n\n                    signatures[i] = new_sig;\n                }\n            }\n        }\n        compute_score();\n    }\n};\n\nvoid solve() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> K;\n    for (int i = 1; i <= 10; ++i) cin >> a[i];\n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 2.8; // seconds\n\n    State best_state;\n    best_state.init(0); \n\n    // Try various K values\n    vector<int> k_candidates = {0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100};\n    \n    for (int try_k : k_candidates) {\n        if (try_k > K) continue;\n\n        // Check time\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        if (elapsed.count() > time_limit) break;\n\n        State current_state;\n        current_state.init(try_k);\n        if (current_state.score > best_state.score) {\n            best_state = current_state;\n        }\n\n        // Adjust iterations based on N (complexity O(N))\n        // N is roughly sum of d*a[d]. Max ~5000.\n        // 3000 points -> 4000 iterations is safe. \n        // We can afford more if N is smaller.\n        int base_iters = 3000;\n        int max_iters = base_iters; \n        \n        // SA params\n        double start_temp = 50.0;\n        double end_temp = 1.0;\n\n        for (int iter = 0; iter < max_iters; ++iter) {\n            now = chrono::high_resolution_clock::now();\n            elapsed = now - start_time;\n            if (elapsed.count() > time_limit) break;\n\n            double temp = start_temp + (end_temp - start_temp) * iter / max_iters;\n\n            State next_state = current_state;\n            \n            // Move: Replace\n            if (try_k > 0) {\n                int idx = rand_ll(0, try_k - 1);\n                next_state.replace(idx);\n            }\n\n            int delta = next_state.score - current_state.score;\n            \n            // Maximize score\n            if (delta > 0 || exp((double)delta / temp) > (double)rand_ll(0, 10000) / 10000.0) {\n                current_state = next_state;\n                if (current_state.score > best_state.score) {\n                    best_state = current_state;\n                }\n            }\n        }\n    }\n\n    // Output best solution found\n    cout << best_state.lines.size() << endl;\n    for (const auto& l : best_state.lines) {\n        cout << l.x1 << \" \" << l.y1 << \" \" << l.x2 << \" \" << l.y2 << endl;\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <climits>\n\nusing namespace std;\n\nconst int MAX_N = 61;\nint N, M;\nint center;\nbool grid[MAX_N][MAX_N];\n\n// Directions: 0:R, 1:U, 2:L, 3:D, 4:UR, 5:DR, 6:UL, 7:DL\nconst int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};\nconst int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};\n\n// Perpendicular pairs: du -> list of dv\nconst vector<vector<int>> perp_dirs = {\n    {1, 3}, {0, 2}, {1, 3}, {0, 2},\n    {5, 6}, {4, 7}, {4, 7}, {5, 6}\n};\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\nbool time_limit_exceeded = false;\n\nvoid check_time() {\n    auto now = chrono::high_resolution_clock::now();\n    auto duration = chrono::duration_cast<chrono::milliseconds>(now - start_time);\n    if (duration.count() > 4900) {\n        time_limit_exceeded = true;\n    }\n}\n\n// Prefix Sum Managers for validation\ntemplate <int SIZE>\nstruct PrefixManager {\n    int sums[SIZE][MAX_N + 2]; \n\n    void init() {\n        for(int i=0; i<SIZE; ++i) {\n            for(int j=0; j<=N+1; ++j) sums[i][j] = 0;\n        }\n    }\n\n    void update_line(int k, int idx) {\n        for (int i = idx + 1; i <= N + 1; ++i) {\n            sums[k][i]++;\n        }\n    }\n    \n    int query(int k, int l, int r) {\n        if (l >= r) return 0;\n        return sums[k][r] - sums[k][l];\n    }\n};\n\nPrefixManager<MAX_N> grid_rows;\nPrefixManager<MAX_N> grid_cols;\nPrefixManager<2 * MAX_N> grid_d1; \nPrefixManager<2 * MAX_N> grid_d2; \n\nPrefixManager<MAX_N> seg_rows;\nPrefixManager<MAX_N> seg_cols;\nPrefixManager<2 * MAX_N> seg_d1;\nPrefixManager<2 * MAX_N> seg_d2;\n\nvoid init_prefix_structures() {\n    grid_rows.init();\n    grid_cols.init();\n    grid_d1.init();\n    grid_d2.init();\n    \n    seg_rows.init();\n    seg_cols.init();\n    seg_d1.init();\n    seg_d2.init();\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (grid[x][y]) {\n                grid_rows.update_line(y, x);\n                grid_cols.update_line(x, y);\n                int k1 = y - x + (N - 1);\n                grid_d1.update_line(k1, x);\n                int k2 = y + x;\n                grid_d2.update_line(k2, x);\n            }\n        }\n    }\n}\n\nbool is_segment_free(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return true;\n    \n    int lx = min(x1, x2);\n    int ly = min(y1, y2);\n    \n    if (y1 == y2) return seg_rows.query(y1, lx, lx + len) == 0;\n    if (x1 == x2) return seg_cols.query(x1, ly, ly + len) == 0;\n    if (x2 - x1 == y2 - y1) {\n        int k = ly - lx + (N - 1);\n        return seg_d1.query(k, lx, lx + len) == 0;\n    }\n    // D2\n    int k = max(y1, y2) + lx;\n    return seg_d2.query(k, lx, lx + len) == 0;\n}\n\nbool is_perimeter_clean(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len <= 1) return true;\n    \n    int lx = min(x1, x2);\n    int rx = max(x1, x2);\n    int ly = min(y1, y2);\n    int ry = max(y1, y2);\n\n    if (y1 == y2) return grid_rows.query(y1, lx + 1, rx) == 0;\n    if (x1 == x2) return grid_cols.query(x1, ly + 1, ry) == 0;\n    if (x2 - x1 == y2 - y1) {\n        int k = ly - lx + (N - 1);\n        return grid_d1.query(k, lx + 1, rx) == 0;\n    }\n    int k = ry + lx;\n    return grid_d2.query(k, lx + 1, rx) == 0;\n}\n\nvoid mark_segment(int x1, int y1, int x2, int y2) {\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    int cx = x1, cy = y1;\n    for (int i = 0; i < len; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        int lx = min(cx, nx);\n        int ly = min(cy, ny);\n        \n        if (cy == ny) seg_rows.update_line(cy, lx);\n        else if (cx == nx) seg_cols.update_line(cx, ly);\n        else if (nx == cx + 1 && ny == cy + 1) seg_d1.update_line(ly - lx + (N - 1), lx);\n        else if (nx == cx - 1 && ny == cy - 1) seg_d1.update_line(ly - lx + (N - 1), lx);\n        else if (nx == cx - 1 && ny == cy + 1) seg_d2.update_line(max(cy, ny) + lx, lx);\n        else seg_d2.update_line(max(cy, ny) + lx, lx);\n        \n        cx = nx; cy = ny;\n    }\n}\n\nstruct Point {\n    int x, y;\n    int weight;\n};\n\nvector<tuple<int, int, int, int, int, int, int, int>> ops;\n\nstruct Rectangle {\n    int x2, y2, x3, y3, x4, y4;\n    int perimeter;\n};\n\nbool try_place(int x, int y, Rectangle& best_rect) {\n    if (grid[x][y]) return false;\n    \n    bool found = false;\n    best_rect.perimeter = INT_MAX;\n    \n    // We iterate up to N, but rely on pruning to stop early.\n    // Searching length-based is faster than set-based because grid is sparse.\n    const int MAX_LEN = N; \n\n    // Order: Axis (0,1,2,3) then Diagonal (4,5,6,7)\n    vector<int> dirs_order = {0, 1, 2, 3, 4, 5, 6, 7};\n\n    for (int du : dirs_order) {\n        // Early exit if we found the global optimum (unit square, perim=4)\n        if (found && best_rect.perimeter == 4) break;\n\n        for (int len_u = 1; len_u <= MAX_LEN; ++len_u) {\n            int bx = x + dx[du] * len_u;\n            int by = y + dy[du] * len_u;\n            \n            if (bx < 0 || bx >= N || by < 0 || by >= N) break;\n            if (!grid[bx][by]) continue;\n            \n            // Pruning: If the smallest possible rectangle with this len_u (len_v=1) \n            // is not better than current best, stop increasing len_u.\n            if (2 * (len_u + 1) >= best_rect.perimeter) break;\n\n            for (int dv : perp_dirs[du]) {\n                for (int len_v = 1; len_v <= MAX_LEN; ++len_v) {\n                    int dx_coord = x + dx[dv] * len_v;\n                    int dy_coord = y + dy[dv] * len_v;\n                    \n                    if (dx_coord < 0 || dx_coord >= N || dy_coord < 0 || dy_coord >= N) break;\n                    if (!grid[dx_coord][dy_coord]) continue;\n                    \n                    int current_perim = 2 * (len_u + len_v);\n                    if (current_perim >= best_rect.perimeter) break;\n                    \n                    int cx_coord = bx + (dx_coord - x);\n                    int cy_coord = by + (dy_coord - y);\n                    \n                    if (cx_coord < 0 || cx_coord >= N || cy_coord < 0 || cy_coord >= N) break;\n                    if (!grid[cx_coord][cy_coord]) continue;\n\n                    if (!is_segment_free(x, y, bx, by)) continue;\n                    if (!is_segment_free(bx, by, cx_coord, cy_coord)) continue;\n                    if (!is_segment_free(cx_coord, cy_coord, dx_coord, dy_coord)) continue;\n                    if (!is_segment_free(dx_coord, dy_coord, x, y)) continue;\n                    \n                    if (!is_perimeter_clean(x, y, bx, by)) continue;\n                    if (!is_perimeter_clean(bx, by, cx_coord, cy_coord)) continue;\n                    if (!is_perimeter_clean(cx_coord, cy_coord, dx_coord, dy_coord)) continue;\n                    if (!is_perimeter_clean(dx_coord, dy_coord, x, y)) continue;\n\n                    best_rect = {bx, by, cx_coord, cy_coord, dx_coord, dy_coord, current_perim};\n                    found = true;\n                    \n                    // If we found a unit square, no need to search further.\n                    if (current_perim == 4) return true;\n                }\n            }\n        }\n    }\n    return found;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    center = (N - 1) / 2;\n    \n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = false;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        grid[x][y] = true;\n    }\n    \n    init_prefix_structures();\n    \n    auto cmp = [](const Point& a, const Point& b) { return a.weight < b.weight; };\n    priority_queue<Point, vector<Point>, decltype(cmp)> pq(cmp);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!grid[i][j]) {\n                int dist_sq = (i - center) * (i - center) + (j - center) * (j - center);\n                pq.push({i, j, dist_sq});\n            }\n        }\n    }\n    \n    while (!pq.empty() && !time_limit_exceeded) {\n        check_time();\n        \n        Point p = pq.top();\n        pq.pop();\n        \n        if (grid[p.x][p.y]) continue;\n        \n        Rectangle best_rect;\n        if (try_place(p.x, p.y, best_rect)) {\n            grid[p.x][p.y] = true;\n            grid_rows.update_line(p.y, p.x);\n            grid_cols.update_line(p.x, p.y);\n            grid_d1.update_line(p.y - p.x + (N - 1), p.x);\n            grid_d2.update_line(p.y + p.x, p.x);\n\n            mark_segment(p.x, p.y, best_rect.x2, best_rect.y2);\n            mark_segment(best_rect.x2, best_rect.y2, best_rect.x3, best_rect.y3);\n            mark_segment(best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4);\n            mark_segment(best_rect.x4, best_rect.y4, p.x, p.y);\n\n            ops.emplace_back(p.x, p.y, best_rect.x2, best_rect.y2, best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4);\n            \n            // Re-check neighbors\n            int R = 12;\n            int x_min = max(0, p.x - R);\n            int x_max = min(N - 1, p.x + R);\n            int y_min = max(0, p.y - R);\n            int y_max = min(N - 1, p.y + R);\n            \n            for (int nx = x_min; nx <= x_max; ++nx) {\n                for (int ny = y_min; ny <= y_max; ++ny) {\n                    if (!grid[nx][ny]) {\n                        int dist_sq = (nx - center) * (nx - center) + (ny - center) * (ny - center);\n                        pq.push({nx, ny, dist_sq});\n                    }\n                }\n            }\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \" \"\n             << get<4>(op) << \" \" << get<5>(op) << \" \"\n             << get<6>(op) << \" \" << get<7>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nconst int H = 10;\nconst int W = 10;\n\nstruct Solver {\n    vector<vector<int>> board;\n    vector<int> flavors;\n    int step;\n    \n    // Targets\n    // Most frequent flavor -> Bottom Center (9, 4)\n    // Other flavors -> Top Left (0, 0) and Top Right (0, 9)\n    pair<int, int> T_BC = {9, 4};\n    pair<int, int> T_TL = {0, 0};\n    pair<int, int> T_TR = {0, 9};\n    \n    vector<pair<int, int>> targets;\n    \n    // Dynamic Weight Parameters\n    const double W_START = 4.0; // High penalty initially to enforce separation\n    const double W_END = 2.0;   // Lower penalty at the end to encourage packing\n\n    Solver(vector<int> f) : flavors(f), step(0) {\n        board.assign(H, vector<int>(W, 0));\n        \n        // Count occurrences\n        vector<int> counts(3, 0);\n        for (int x : f) counts[x-1]++;\n        \n        // Sort flavors by count descending\n        vector<pair<int, int>> flavor_counts = {{0, counts[0]}, {1, counts[1]}, {2, counts[2]}};\n        sort(flavor_counts.begin(), flavor_counts.end(), [](const auto& a, const auto& b) {\n            return a.second > b.second;\n        });\n        \n        // Assign targets: Largest -> Bottom Center, Others -> Top Corners\n        targets.resize(3);\n        targets[flavor_counts[0].first] = T_BC;\n        targets[flavor_counts[1].first] = T_TL;\n        targets[flavor_counts[2].first] = T_TR;\n    }\n\n    pair<int, int> get_pos(int p, const vector<vector<int>>& b) {\n        int cnt = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] == 0) {\n                    cnt++;\n                    if (cnt == p) return {i, j};\n                }\n            }\n        }\n        return {-1, -1}; \n    }\n\n    vector<vector<int>> tilt(vector<vector<int>> b, int dir) {\n        if (dir == 0) { // F\n            for (int j = 0; j < W; ++j) {\n                int wi = 0;\n                for (int i = 0; i < H; ++i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // B\n            for (int j = 0; j < W; ++j) {\n                int wi = H - 1;\n                for (int i = H - 1; i >= 0; --i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // L\n            for (int i = 0; i < H; ++i) {\n                int wj = 0;\n                for (int j = 0; j < W; ++j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // R\n            for (int i = 0; i < H; ++i) {\n                int wj = W - 1;\n                for (int j = W - 1; j >= 0; --j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj--;\n                    }\n                }\n            }\n        }\n        return b;\n    }\n\n    double evaluate(const vector<vector<int>>& b) {\n        // Calculate dynamic weight: linearly decay from W_START to W_END\n        double progress = (double)step / 100.0;\n        double w_dist = W_START - (W_START - W_END) * progress;\n\n        // Component Score\n        int sum_sq = 0;\n        vector<vector<bool>> visited(H, vector<bool>(W, false));\n        \n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0 && !visited[i][j]) {\n                    queue<pair<int,int>> q;\n                    q.push({i,j});\n                    visited[i][j] = true;\n                    int size = 0;\n                    while (!q.empty()) {\n                        auto [r, c] = q.front(); q.pop();\n                        size++;\n                        int dr[] = {0, 0, 1, -1};\n                        int dc[] = {1, -1, 0, 0};\n                        for (int k = 0; k < 4; ++k) {\n                            int nr = r + dr[k];\n                            int nc = c + dc[k];\n                            if (nr >= 0 && nr < H && nc >= 0 && nc < W && !visited[nr][nc] && b[nr][nc] == b[r][c]) {\n                                visited[nr][nc] = true;\n                                q.push({nr,nc});\n                            }\n                        }\n                    }\n                    sum_sq += size * size;\n                }\n            }\n        }\n\n        // Distance Penalty (Manhattan)\n        double penalty_dist = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0) {\n                    int flavor_idx = b[i][j] - 1;\n                    penalty_dist += abs(i - targets[flavor_idx].first) + abs(j - targets[flavor_idx].second);\n                }\n            }\n        }\n        \n        return (double)sum_sq - w_dist * penalty_dist;\n    }\n\n    char solve(int p) {\n        // Place candy\n        auto [r, c] = get_pos(p, board);\n        board[r][c] = flavors[step];\n        \n        int best_move = -1;\n        double best_score = -1e18;\n        \n        // 1-Step Greedy Search\n        for (int d = 0; d < 4; ++d) {\n            auto next_board = tilt(board, d);\n            double score = evaluate(next_board);\n            if (score > best_score) {\n                best_score = score;\n                best_move = d;\n            }\n        }\n        \n        // Apply best move\n        board = tilt(board, best_move);\n        step++;\n        \n        if (best_move == 0) return 'F';\n        if (best_move == 1) return 'B';\n        if (best_move == 2) return 'L';\n        return 'R';\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) cin >> f[i];\n    \n    Solver solver(f);\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        if (t < 99) {\n            char out = solver.solve(p);\n            cout << out << endl;\n            cout.flush();\n        } else {\n            solver.solve(p);\n        }\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nmt19937 rng(42); \n\n// Estimate expected errors E for given N\ndouble estimate_expected_errors(int M, double eps, int N) {\n    int P = N * (N - 1) / 2;\n    if (P < M) return 100.0; \n\n    double step = (double)P / (M - 1);\n    double gap_observed = step * (1.0 - 2.0 * eps);\n    double sigma = sqrt((double)P * eps * (1.0 - eps));\n    \n    if (sigma < 1e-9) return 0.0;\n    \n    double z = (gap_observed / 2.0) / sigma;\n    double p_err = 0.5 * erfc(z / sqrt(2.0));\n    return (M - 1) * p_err * 100.0;\n}\n\n// Choose N to maximize Score = 0.9^E / N\nint choose_N(int M, double eps) {\n    int best_N = 100;\n    double best_score = -1.0;\n    \n    int min_N = (int)ceil((1.0 + sqrt(1.0 + 8.0 * M)) / 2.0);\n    if (min_N < 4) min_N = 4;\n\n    for (int N = min_N; N <= 100; ++N) {\n        double E = estimate_expected_errors(M, eps, N);\n        double score = pow(0.9, E) / (double)N;\n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n        }\n    }\n    return best_N;\n}\n\nstring generate_graph(int N, int target_edges) {\n    int P = N * (N - 1) / 2;\n    string graph(P, '0');\n    vector<int> indices(P);\n    iota(indices.begin(), indices.end(), 0);\n    shuffle(indices.begin(), indices.end(), rng);\n    for (int i = 0; i < target_edges; ++i) {\n        graph[indices[i]] = '1';\n    }\n    return graph;\n}\n\n// Extract degree sequence\nvector<int> get_degrees(int N, const string& s) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    int N = choose_N(M, eps);\n    int P = N * (N - 1) / 2;\n    \n    // Precompute data for generated graphs\n    vector<string> graphs(M);\n    // Expected degree sequence for each graph\n    vector<vector<double>> exp_deg_seq(M); \n    // Expected wedge count for each graph\n    vector<double> exp_wedge_count(M); \n\n    // Common terms for expectation calculation\n    // E[d_H | d_G] = d_G * (1-2*eps) + (N-1)*eps\n    double slope = (1.0 - 2.0 * eps);\n    double intercept = (N - 1) * eps;\n    \n    // Var[d_H] = (N-1) * eps * (1-eps) (constant for all vertices)\n    double var_deg = (N - 1) * eps * (1.0 - eps);\n    \n    // E[Wedge_H | d_G] = Sum_v E[C(d_H(v), 2)]\n    // E[C(d, 2)] = 0.5 * (E[d^2] - E[d]) = 0.5 * (Var(d) + E[d]^2 - E[d])\n    // Term: 0.5 * (var_deg + (slope*d + intercept)^2 - (slope*d + intercept))\n\n    for (int i = 0; i < M; ++i) {\n        int target_edges = (int)round((double)i * P / (M - 1));\n        graphs[i] = generate_graph(N, target_edges);\n        \n        vector<int> deg = get_degrees(N, graphs[i]);\n        \n        exp_deg_seq[i].resize(N);\n        exp_wedge_count[i] = 0.0;\n        \n        for (int j = 0; j < N; ++j) {\n            int d = deg[j];\n            double mu = d * slope + intercept;\n            exp_deg_seq[i][j] = mu;\n            \n            // Accumulate expected wedge contribution\n            // 0.5 * (var_deg + mu*mu - mu)\n            exp_wedge_count[i] += 0.5 * (var_deg + mu * mu - mu);\n        }\n    }\n    \n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    cout << flush;\n    \n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        \n        vector<int> deg_H = get_degrees(N, H);\n        \n        // Calculate observed wedge count for H\n        // Wedge = sum C(d, 2)\n        long long wedge_H = 0;\n        for (int d : deg_H) {\n            wedge_H += (long long)d * (d - 1) / 2;\n        }\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            // Primary metric: L2 distance on expected degree sequences\n            double dist_deg = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - exp_deg_seq[k][j];\n                dist_deg += diff * diff;\n            }\n            \n            // Secondary metric: Absolute difference in expected wedge count\n            // We combine them. Wedge count is O(N^2), degree distance is O(N).\n            // To balance, we scale wedge distance down or rely on it for tie-breaking.\n            // Given N~50, wedge~1000. Dist_deg ~ 100. \n            // So squared wedge diff would be huge if we just added them.\n            // Let's use a small weight for wedge distance.\n            \n            double wedge_diff = wedge_H - exp_wedge_count[k];\n            double dist_total = dist_deg + 0.001 * wedge_diff * wedge_diff; // 0.001 is an arbitrary heuristic weight\n            \n            if (dist_total < min_dist) {\n                min_dist = dist_total;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <climits>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\n// Global variables\nint N, M, D, K;\nvector<vector<pair<int, int>>> adj; // (neighbor, edge_id)\nvector<int> from;\nvector<int> to;\nvector<long long> weight;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Calculate Edge Usage (Betweenness Centrality)\nvector<long long> calculate_usage() {\n    vector<long long> usage(M, 0);\n    for (int s = 0; s < N; ++s) {\n        vector<long long> dist(N, INF);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                long long w = weight[eid];\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = eid;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if (i == s) continue;\n            int eid = parent_edge[i];\n            if (eid != -1) usage[eid]++;\n        }\n    }\n    return usage;\n}\n\n// Check connectivity\nbool is_connected(const vector<int>& day_of_edge, int day_k, int check_eid) {\n    vector<int> visited(N, 0);\n    queue<int> q;\n    q.push(0);\n    visited[0] = 1;\n    int count = 1;\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        if (count == N) return true;\n\n        for (auto& [v, eid] : adj[u]) {\n            if (visited[v]) continue;\n            if (day_of_edge[eid] == day_k || eid == check_eid) continue;\n            visited[v] = 1;\n            count++;\n            q.push(v);\n        }\n    }\n    return count == N;\n}\n\n// Evaluate a day using sampling\nlong long evaluate_day_sampled(const vector<bool>& removed, const vector<int>& sources) {\n    long long sum_dist = 0;\n    for (int s : sources) {\n        vector<long long> dist(N, INF);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                if (removed[eid]) continue;\n                long long w = weight[eid];\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) {\n            if (i == s) continue;\n            if (dist[i] == INF) sum_dist += INF;\n            else sum_dist += dist[i];\n        }\n    }\n    return sum_dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> M >> D >> K;\n\n    adj.resize(N);\n    from.resize(M);\n    to.resize(M);\n    weight.resize(M);\n\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        from[i] = u;\n        to[i] = v;\n        weight[i] = w;\n        adj[u].emplace_back(v, i);\n        adj[v].emplace_back(u, i);\n    }\n\n    // Discard coordinates\n    for (int i = 0; i < N; ++i) {\n        double x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Compute Usage\n    vector<long long> usage = calculate_usage();\n\n    // 2. Greedy Assignment\n    vector<int> day_of_edge(M, -1);\n    vector<long long> load(D, 0); \n    vector<int> day_size(D, 0);\n\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return usage[a] > usage[b];\n    });\n\n    auto check_conn = [&](int day_k, int check_eid) {\n        return is_connected(day_of_edge, day_k, check_eid);\n    };\n\n    for (int eid : edge_order) {\n        vector<pair<long long, int>> day_prios;\n        for(int d=0; d<D; ++d) day_prios.push_back({load[d], d});\n        sort(day_prios.begin(), day_prios.end());\n\n        bool assigned = false;\n        for (auto& [_, d] : day_prios) {\n            if (day_size[d] >= K) continue;\n            if (check_conn(d, eid)) {\n                day_of_edge[eid] = d;\n                load[d] += usage[eid];\n                day_size[d]++;\n                assigned = true;\n                break;\n            }\n        }\n        if (!assigned) {\n            for (int d = 0; d < D; ++d) {\n                if (day_size[d] < K) {\n                    day_of_edge[eid] = d;\n                    load[d] += usage[eid];\n                    day_size[d]++;\n                    break;\n                }\n            }\n        }\n    }\n\n    // 3. Local Search\n    vector<int> sources;\n    int sample_size = 40; \n    int step = max(1, N / sample_size);\n    for (int i = 0; i < N; i += step) sources.push_back(i);\n    if (sources.empty()) sources.push_back(0);\n\n    vector<vector<int>> edges_in_day(D);\n    vector<vector<bool>> removed_masks(D, vector<bool>(M, false));\n    vector<long long> day_scores(D);\n\n    for(int i=0; i<M; ++i) {\n        int d = day_of_edge[i];\n        edges_in_day[d].push_back(i);\n        removed_masks[d][i] = true;\n    }\n    for(int d=0; d<D; ++d) {\n        sort(edges_in_day[d].begin(), edges_in_day[d].end(), [&](int a, int b) {\n            return usage[a] > usage[b];\n        });\n        day_scores[d] = evaluate_day_sampled(removed_masks[d], sources);\n    }\n\n    int iter = 0;\n    while (true) {\n        auto curr = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(curr - start_time).count();\n        if (elapsed > 5.3) break; \n        iter++;\n\n        // Identify days and sort by score\n        vector<int> days_by_score(D);\n        iota(days_by_score.begin(), days_by_score.end(), 0);\n        sort(days_by_score.begin(), days_by_score.end(), [&](int a, int b) {\n            return day_scores[a] < day_scores[b]; // Ascending score\n        });\n\n        int worst_day = days_by_score.back(); // Day with highest score\n        \n        bool improved = false;\n        \n        // Try to move an edge from worst_day to a better day\n        // We try the top 3 critical edges in worst_day\n        int try_edges = min(3, (int)edges_in_day[worst_day].size());\n        \n        for(int e_idx = 0; e_idx < try_edges; ++e_idx) {\n            int e_move = edges_in_day[worst_day][e_idx];\n\n            // Iterate over target days (starting from the best days)\n            for (int d_target : days_by_score) {\n                if (d_target == worst_day) continue;\n                if (day_size[d_target] >= K) continue;\n\n                // Check connectivity\n                if (is_connected(day_of_edge, d_target, e_move)) {\n                    \n                    // Evaluate Move\n                    // Worst day without e_move\n                    removed_masks[worst_day][e_move] = false;\n                    long long score_worst_new = evaluate_day_sampled(removed_masks[worst_day], sources);\n                    removed_masks[worst_day][e_move] = true; // Restore\n\n                    // Target day with e_move\n                    removed_masks[d_target][e_move] = true;\n                    long long score_target_new = evaluate_day_sampled(removed_masks[d_target], sources);\n                    removed_masks[d_target][e_move] = false; // Restore\n\n                    long long current_total = day_scores[worst_day] + day_scores[d_target];\n                    long long new_total = score_worst_new + score_target_new;\n\n                    if (new_total < current_total) {\n                        // Accept Move\n                        day_of_edge[e_move] = d_target;\n                        \n                        day_size[worst_day]--;\n                        day_size[d_target]++;\n                        \n                        removed_masks[worst_day][e_move] = false;\n                        removed_masks[d_target][e_move] = true;\n                        \n                        day_scores[worst_day] = score_worst_new;\n                        day_scores[d_target] = score_target_new;\n                        \n                        // Update edge lists\n                        auto it = find(edges_in_day[worst_day].begin(), edges_in_day[worst_day].end(), e_move);\n                        if(it != edges_in_day[worst_day].end()) edges_in_day[worst_day].erase(it);\n                        edges_in_day[d_target].push_back(e_move);\n                        sort(edges_in_day[d_target].begin(), edges_in_day[d_target].end(), [&](int a, int b){\n                            return usage[a] > usage[b];\n                        });\n\n                        improved = true;\n                        break; // Move accepted, stop searching targets\n                    }\n                }\n            }\n            if (improved) break; // Move accepted, stop searching edges\n        }\n\n        // If no improving move found, perform a random move to escape local optima\n        // We pick a random day d1 and try to move a random edge to a random day d2\n        if (!improved) {\n            int d1 = rng() % D;\n            // Only try if d1 has edges\n            if (!edges_in_day[d1].empty()) {\n                int e_rand = edges_in_day[d1][rng() % edges_in_day[d1].size()];\n                \n                // Try a few random targets\n                for(int trial=0; trial<5; ++trial) {\n                    int d2 = rng() % D;\n                    if (d1 == d2 || day_size[d2] >= K) continue;\n                    \n                    if (is_connected(day_of_edge, d2, e_rand)) {\n                        // We accept this random move regardless of score (Simulated Annealing style, T=inf)\n                        // or we check if it improves. Let's check improvement to be safe, \n                        // but if stuck, maybe we need to force it.\n                        // Given Hill Climbing nature, let's check improvement.\n                        \n                        removed_masks[d1][e_rand] = false;\n                        long long s1 = evaluate_day_sampled(removed_masks[d1], sources);\n                        removed_masks[d1][e_rand] = true;\n                        \n                        removed_masks[d2][e_rand] = true;\n                        long long s2 = evaluate_day_sampled(removed_masks[d2], sources);\n                        removed_masks[d2][e_rand] = false;\n                        \n                        if (s1 + s2 < day_scores[d1] + day_scores[d2]) {\n                             day_of_edge[e_rand] = d2;\n                             day_size[d1]--; day_size[d2]++;\n                             removed_masks[d1][e_rand] = false;\n                             removed_masks[d2][e_rand] = true;\n                             day_scores[d1] = s1; day_scores[d2] = s2;\n                             \n                             auto it = find(edges_in_day[d1].begin(), edges_in_day[d1].end(), e_rand);\n                             if(it != edges_in_day[d1].end()) edges_in_day[d1].erase(it);\n                             edges_in_day[d2].push_back(e_rand);\n                             sort(edges_in_day[d2].begin(), edges_in_day[d2].end(), [&](int a, int b){ return usage[a] > usage[b]; });\n                             improved = true;\n                             break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    for(int i=0; i<M; ++i) {\n        if(i>0) cout << \" \";\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst int D_MAX = 14;\nconst int LAYER_SIZE = D_MAX * D_MAX; \n\n// Timer\nclass Timer {\n    chrono::system_clock::time_point start;\npublic:\n    Timer() : start(chrono::system_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::system_clock::now() - start).count();\n    }\n};\n\n// Global RNG\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Input Data\nint D;\nbool f[2][D_MAX][D_MAX]; \nbool r[2][D_MAX][D_MAX]; \n\n// State for a single layer\nstruct LayerState {\n    vector<pair<int, int>> cells; \n    array<int, D_MAX> cnt_y;            \n    bitset<LAYER_SIZE> bits;      \n    \n    LayerState() {\n        cnt_y.fill(0);\n    }\n\n    void clear() {\n        cells.clear();\n        cnt_y.fill(0);\n        bits.reset();\n    }\n\n    void init(int obj_id, int z) {\n        clear();\n        vector<int> xs, ys;\n        for (int x = 0; x < D; ++x) if (f[obj_id][z][x]) xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (r[obj_id][z][y]) ys.push_back(y);\n\n        int kx = xs.size();\n        int ky = ys.size();\n\n        if (kx == 0 || ky == 0) return;\n\n        // Randomized Initialization\n        // Shuffle 'ys' to get a random matching for the 1-to-1 part\n        shuffle(ys.begin(), ys.end(), rng);\n\n        int limit = min(kx, ky);\n        for (int i = 0; i < limit; ++i) add_cell(xs[i], ys[i]);\n        \n        // Handle surplus\n        // If kx > ky, map remaining xs to the first y (which is random now)\n        // If ky > kx, map remaining ys to the first x\n        if (kx > ky) {\n            for (int i = ky; i < kx; ++i) add_cell(xs[i], ys[0]);\n        } else if (ky > kx) {\n            for (int i = kx; i < ky; ++i) add_cell(xs[0], ys[i]);\n        }\n    }\n\n    inline void add_cell(int x, int y) {\n        cells.push_back({x, y});\n        cnt_y[y]++;\n        bits.set(x * D + y);\n    }\n    \n    void force_set_y(int idx, int new_y) {\n        int old_y = cells[idx].second;\n        int x = cells[idx].first;\n        \n        if (old_y == new_y) return;\n\n        cnt_y[old_y]--;\n        cnt_y[new_y]++;\n        \n        bits.reset(x * D + old_y);\n        bits.set(x * D + new_y);\n        \n        cells[idx].second = new_y;\n    }\n};\n\nstruct ObjectState {\n    LayerState layers[D_MAX];\n    int overlap; \n\n    ObjectState() : overlap(0) {}\n    \n    void init(int obj_id) {\n        overlap = 0;\n        for(int z=0; z<D; ++z) layers[z].init(obj_id, z);\n    }\n\n    void calc_overlap(const ObjectState& other) {\n        overlap = 0;\n        for(int z=0; z<D; ++z) {\n            overlap += (layers[z].bits & other.layers[z].bits).count();\n        }\n    }\n};\n\nObjectState states[2];\n\nvoid repair_state(ObjectState& obj, int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        LayerState& layer = obj.layers[z];\n        \n        array<int, D_MAX> true_cnt;\n        true_cnt.fill(0);\n        for(auto& c : layer.cells) true_cnt[c.second]++;\n        \n        vector<int> missing_ys;\n        vector<int> surplus_ys;\n        \n        for(int y=0; y<D; ++y) {\n            if (r[obj_id][z][y]) {\n                if (true_cnt[y] == 0) missing_ys.push_back(y);\n            } else {\n                if (true_cnt[y] > 0) surplus_ys.push_back(y);\n            }\n        }\n        \n        for (int y_target : missing_ys) {\n            int src_y = -1;\n            \n            if (!surplus_ys.empty()) {\n                src_y = surplus_ys.back();\n                surplus_ys.pop_back();\n            } else {\n                for(int y=0; y<D; ++y) {\n                    if (true_cnt[y] > 1) {\n                        src_y = y;\n                        break;\n                    }\n                }\n            }\n            \n            if (src_y != -1) {\n                for(int i=0; i<(int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == src_y) {\n                        layer.force_set_y(i, y_target);\n                        true_cnt[src_y]--;\n                        true_cnt[y_target]++;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        for (int y_bad : surplus_ys) {\n            int y_good = -1;\n            \n            for(int y=0; y<D; ++y) {\n                if (r[obj_id][z][y] && true_cnt[y] > 1) {\n                    y_good = y;\n                    break;\n                }\n            }\n            \n            if (y_good == -1) {\n                for(int y=0; y<D; ++y) {\n                    if (r[obj_id][z][y]) {\n                        y_good = y;\n                        break;\n                    }\n                }\n            }\n            \n            if (y_good != -1) {\n                for(int i=0; i<(int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == y_bad) {\n                        layer.force_set_y(i, y_good);\n                        true_cnt[y_bad]--;\n                        true_cnt[y_good]++;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        layer.cnt_y = true_cnt;\n        layer.bits.reset();\n        for(auto& c : layer.cells) layer.bits.set(c.first * D + c.second);\n    }\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int x = 0; x < D; ++x) f[i][z][x] = (s[x] == '1');\n        }\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int y = 0; y < D; ++y) r[i][z][y] = (s[y] == '1');\n        }\n    }\n\n    states[0].init(0);\n    states[1].init(1);\n    states[0].calc_overlap(states[1]);\n\n    Timer timer;\n    double time_limit = 5.95; \n    double current_time = 0;\n    int current_solver = 0; \n    \n    vector<vector<int>> active_ys[2];\n    for(int i=0; i<2; ++i) {\n        active_ys[i].resize(D);\n        for(int z=0; z<D; ++z) {\n            for(int y=0; y<D; ++y) if(r[i][z][y]) active_ys[i][z].push_back(y);\n        }\n    }\n\n    while ((current_time = timer.elapsed()) < time_limit) {\n        int id_opt = current_solver;\n        int id_fix = 1 - current_solver;\n        current_solver = 1 - current_solver; \n\n        ObjectState& opt_state = states[id_opt];\n        const ObjectState& fix_state = states[id_fix];\n        \n        double temp = 50.0 * pow(1e-4 / 50.0, current_time / time_limit);\n        if (temp < 1e-5) temp = 1e-5;\n        \n        int batch = 12000; \n\n        for (int k = 0; k < batch; ++k) {\n            int z = rng() % D;\n            LayerState& layer = opt_state.layers[z];\n            const bitset<LAYER_SIZE>& target_bits = fix_state.layers[z].bits;\n            \n            if (layer.cells.empty()) continue;\n            \n            int idx = rng() % layer.cells.size();\n            int x = layer.cells[idx].first;\n            int old_y = layer.cells[idx].second;\n            \n            const auto& valid_ys = active_ys[id_opt][z];\n            if (valid_ys.empty()) continue;\n            int new_y = valid_ys[rng() % valid_ys.size()];\n            \n            if (old_y == new_y) continue;\n\n            int delta = 0;\n            int pos_old = x * D + old_y;\n            int pos_new = x * D + new_y;\n            \n            if (target_bits.test(pos_old)) delta--;\n            if (target_bits.test(pos_new)) delta++;\n\n            bool valid = false;\n            int swap_idx = -1;\n            \n            if (layer.cnt_y[old_y] > 1) {\n                valid = true;\n            } else {\n                for(int i = 0; i < (int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == new_y) {\n                        swap_idx = i;\n                        break;\n                    }\n                }\n                \n                if (swap_idx != -1) {\n                    int x2 = layer.cells[swap_idx].first;\n                    if (target_bits.test(x2 * D + new_y)) delta--;\n                    if (target_bits.test(x2 * D + old_y)) delta++;\n                    valid = true;\n                }\n            }\n\n            if (valid) {\n                if (delta >= 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                    if (swap_idx != -1) {\n                        layer.cnt_y[old_y]--;\n                        layer.cnt_y[new_y]--;\n                        layer.cnt_y[old_y]++;\n                        layer.cnt_y[new_y]++;\n                        \n                        int x2 = layer.cells[swap_idx].first;\n                        layer.bits.reset(pos_old);\n                        layer.bits.set(pos_new);\n                        layer.bits.reset(x2 * D + new_y);\n                        layer.bits.set(x2 * D + old_y);\n                        \n                        layer.cells[idx].second = new_y;\n                        layer.cells[swap_idx].second = old_y;\n                        \n                    } else {\n                        layer.cnt_y[old_y]--;\n                        layer.cnt_y[new_y]++;\n                        layer.cells[idx].second = new_y;\n                        layer.bits.reset(pos_old);\n                        layer.bits.set(pos_new);\n                    }\n                    opt_state.overlap += delta;\n                }\n            }\n        }\n        \n        if (timer.elapsed() > time_limit) break;\n    }\n    \n    repair_state(states[0], 0);\n    repair_state(states[1], 1);\n\n    // Output Generation\n    vector<int> b1(D*D*D, 0);\n    vector<int> b2(D*D*D, 0);\n    \n    auto lin = [&](int x, int y, int z) { return x * D * D + y * D + z; };\n    \n    int visited[2][D_MAX][D_MAX][D_MAX]; \n    for(int i=0; i<2; ++i) \n        for(int z=0; z<D; ++z) \n            for(int x=0; x<D; ++x) \n                for(int y=0; y<D; ++y) \n                    visited[i][z][x][y] = 0;\n\n    int current_id = 0;\n    \n    // 1. Shared components\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[0].layers[z].bits.test(x*D + y) && \n                    states[1].layers[z].bits.test(x*D + y) && \n                    visited[0][z][x][y] == 0) {\n                    \n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    visited[1][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b1[lin(cx, cy, cz)] = current_id;\n                        b2[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        \n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[0][nz][nx][ny] == 0 && \n                                    states[0].layers[nz].bits.test(nx*D + ny) && \n                                    states[1].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // 2. Unique to Obj 1\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[0].layers[z].bits.test(x*D + y) && visited[0][z][x][y] == 0) {\n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b1[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[0][nz][nx][ny] == 0 && states[0].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Unique to Obj 2\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[1].layers[z].bits.test(x*D + y) && visited[1][z][x][y] == 0) {\n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[1][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b2[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[1][nz][nx][ny] == 0 && states[1].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    cout << current_id << \"\\n\";\n    for(int i=0; i<D*D*D; ++i) {\n        if(i) cout << \" \";\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    for(int i=0; i<D*D*D; ++i) {\n        if(i) cout << \" \";\n        cout << b2[i];\n    }\n    cout << \"\\n\";\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <tuple>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Solver {\n    int N, M, K;\n    vector<pair<int, int>> coords;\n    vector<tuple<int, int, long long>> edges;\n    vector<pair<int, int>> residents;\n    vector<vector<long long>> dist_nodes; \n    vector<vector<int>> dist_res; \n    vector<int> P;\n    vector<int> B;\n    \n    // Heuristic data\n    vector<vector<int>> resident_order; // Sorted vertices by distance for each resident\n    vector<int> assign; // Assign resident k to vertex assign[k]\n    vector<bool> active;\n\n    Solver(int n, int m, int k) : N(n), M(m), K(k) {\n        coords.resize(N);\n        edges.resize(M);\n        residents.resize(K);\n        dist_nodes.assign(N, vector<long long>(N, 1e18));\n        dist_res.assign(N, vector<int>(K));\n        P.assign(N, 0);\n        B.assign(M, 0);\n        resident_order.assign(K, vector<int>(N));\n        assign.assign(K, -1);\n        active.assign(N, false);\n    }\n\n    void solve() {\n        // 1. Floyd-Warshall\n        for (int i = 0; i < N; ++i) dist_nodes[i][i] = 0;\n        for (auto& e : edges) {\n            int u, v;\n            long long w;\n            tie(u, v, w) = e;\n            u--; v--;\n            if (w < dist_nodes[u][v]) {\n                dist_nodes[u][v] = w;\n                dist_nodes[v][u] = w;\n            }\n        }\n        for (int k = 0; k < N; ++k) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (dist_nodes[i][k] + dist_nodes[k][j] < dist_nodes[i][j]) {\n                        dist_nodes[i][j] = dist_nodes[i][k] + dist_nodes[k][j];\n                    }\n                }\n            }\n        }\n\n        // 2. Precompute resident distances and sort\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < K; ++k) {\n                long long dx = (long long)coords[i].first - residents[k].first;\n                long long dy = (long long)coords[i].second - residents[k].second;\n                dist_res[i][k] = (int)round(sqrt((double)dx*dx + dy*dy));\n            }\n        }\n        \n        vector<int> temp_nodes(N);\n        iota(temp_nodes.begin(), temp_nodes.end(), 0);\n        for (int k = 0; k < K; ++k) {\n            sort(temp_nodes.begin(), temp_nodes.end(), [&](int a, int b) {\n                return dist_res[a][k] < dist_res[b][k];\n            });\n            resident_order[k] = temp_nodes;\n        }\n\n        // 3. Helper functions\n        auto calc_mst_cost = [&]() {\n            long long cost = 0;\n            vector<bool> in_mst(N, false);\n            vector<long long> min_dist(N, 1e18);\n            min_dist[0] = 0;\n            for (int i = 0; i < N; ++i) {\n                int u = -1;\n                for (int j = 0; j < N; ++j) {\n                    if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                        u = j;\n                    }\n                }\n                if (u == -1) break;\n                in_mst[u] = true;\n                cost += min_dist[u];\n                for (int v = 0; v < N; ++v) {\n                    if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                        min_dist[v] = dist_nodes[u][v];\n                    }\n                }\n            }\n            return cost;\n        };\n\n        auto calc_node_cost = [&]() {\n            long long cost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (active[i]) {\n                    cost += (long long)P[i] * P[i];\n                }\n            }\n            return cost;\n        };\n\n        auto reassign = [&]() {\n            // Assign residents to nearest active vertex\n            // Also calculate P\n            // Returns true if any resident is uncovered (>5000)\n            bool uncovered = false;\n            fill(P.begin(), P.end(), 0);\n            for (int k = 0; k < K; ++k) {\n                for (int v : resident_order[k]) {\n                    if (active[v]) {\n                        assign[k] = v;\n                        int d = dist_res[v][k];\n                        if (d > P[v]) P[v] = d;\n                        if (d > 5000) uncovered = true;\n                        break;\n                    }\n                }\n            }\n            return uncovered;\n        };\n\n        // 4. Initial Solution (Greedy Coverage)\n        active[0] = true;\n        bool valid = reassign();\n        \n        // Add vertices until valid\n        while (valid) {\n            int best_u = -1;\n            int best_k = -1;\n            int max_dist = -1;\n            \n            // Find the resident with max distance to nearest active\n            for (int k = 0; k < K; ++k) {\n                int d = dist_res[assign[k]][k];\n                if (d > max_dist) {\n                    max_dist = d;\n                    best_k = k;\n                }\n            }\n            \n            // Find vertex u that covers best_k best\n            for (int u : resident_order[best_k]) {\n                if (!active[u]) {\n                    best_u = u;\n                    break;\n                }\n            }\n            \n            if (best_u != -1) {\n                active[best_u] = true;\n                valid = reassign();\n            } else {\n                // Should not happen given problem constraints\n                break; \n            }\n        }\n\n        long long current_edge_cost = calc_mst_cost();\n        long long current_node_cost = calc_node_cost();\n        long long total_cost = current_edge_cost + current_node_cost;\n\n        // 5. Optimization Loop\n        mt19937 rng(20240520);\n        \n        // Run multiple passes of Add/Remove\n        for (int iter = 0; iter < 10; ++iter) {\n            vector<int> indices(N);\n            iota(indices.begin(), indices.end(), 0);\n            \n            // Greedy Remove\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (u == 0 || !active[u]) continue;\n                \n                // Check if we can remove u\n                // We need to reassign residents of u to other active vertices\n                // And check if cost decreases\n                \n                vector<int> saved_P_u(N, 0); // Only need to track changes for modified P\n                vector<int> modified_nodes;\n                \n                // Tentative removal\n                active[u] = false;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost - (long long)P[u] * P[u];\n                \n                // For residents assigned to u, find new owner\n                for (int k = 0; k < K; ++k) {\n                    if (assign[k] == u) {\n                        int new_v = -1;\n                        for (int v : resident_order[k]) {\n                            if (active[v]) {\n                                new_v = v;\n                                break;\n                            }\n                        }\n                        if (new_v == -1) {\n                            invalid = true;\n                            break;\n                        }\n                        int d = dist_res[new_v][k];\n                        if (d > 5000) {\n                            invalid = true;\n                            break;\n                        }\n                        \n                        // Update tentative P for new_v\n                        if (d > P[new_v]) {\n                            if (saved_P_u[new_v] == 0) saved_P_u[new_v] = P[new_v];\n                            P[new_v] = d;\n                        }\n                    }\n                }\n                \n                if (!invalid) {\n                    // Calculate new node cost based on changes\n                    for (int v = 0; v < N; ++v) {\n                        if (v != u && saved_P_u[v] != 0) {\n                            tentative_node_cost += (long long)P[v] * P[v];\n                            tentative_node_cost -= (long long)saved_P_u[v] * saved_P_u[v];\n                        }\n                    }\n                    \n                    long long new_edge_cost = calc_mst_cost();\n                    if (tentative_node_cost + new_edge_cost < total_cost) {\n                        // Accept removal\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = tentative_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        // Reassign permanently\n                        reassign(); \n                        // P is updated by reassign\n                        continue; \n                    }\n                }\n                \n                // Reject: Revert\n                active[u] = true;\n                for (int v = 0; v < N; ++v) {\n                    if (saved_P_u[v] != 0) P[v] = saved_P_u[v];\n                }\n            }\n\n            // Greedy Add\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int u : indices) {\n                if (active[u]) continue;\n                \n                // Try add u\n                active[u] = true;\n                bool invalid = false;\n                long long tentative_node_cost = current_node_cost; // P[u] starts at 0, might increase\n                \n                // Check residents who might move to u\n                vector<int> saved_P(N, 0);\n                \n                // We only care if cost decreases.\n                // Simply run reassign to get new P.\n                // But reassign is O(KN). Since N=100, K=5000, O(5e5) per check is okay.\n                // 200 checks -> 1e8 ops. A bit slow but acceptable in C++.\n                \n                // Optimization: only check residents where u is closer than current owner\n                // Or just run reassign on a copy? No, just run reassign and revert.\n                \n                // Let's do fast check first: if dist(u, any resident in C_v) < P_v, potential gain.\n                // This is heuristic. For safety, let's just use reassign.\n                \n                reassign(); \n                \n                // Check validity\n                valid = true;\n                for (int i=0; i<N; ++i) if (active[i] && P[i] > 5000) valid = false;\n                \n                if (valid) {\n                    long long new_node_cost = calc_node_cost();\n                    long long new_edge_cost = calc_mst_cost();\n                    if (new_node_cost + new_edge_cost < total_cost) {\n                        // Accept\n                        current_edge_cost = new_edge_cost;\n                        current_node_cost = new_node_cost;\n                        total_cost = current_edge_cost + current_node_cost;\n                        continue;\n                    }\n                }\n                \n                // Reject\n                active[u] = false;\n                // Revert P and assign\n                reassign();\n            }\n        }\n\n        // 6. Construct Output Edges\n        // Prim's MST on active vertices, then expand to shortest paths\n        vector<vector<int>> mst_adj(N, vector<int>(N, 0));\n        vector<bool> in_mst(N, false);\n        vector<int> parent(N, -1);\n        vector<long long> min_dist(N, 1e18);\n        min_dist[0] = 0;\n\n        for (int i = 0; i < N; ++i) {\n            int u = -1;\n            for (int j = 0; j < N; ++j) {\n                if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                    u = j;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (parent[u] != -1) {\n                // Find path between parent[u] and u\n                int s = parent[u];\n                int t = u;\n                \n                // Dijkstra\n                vector<long long> d(N, 1e18);\n                vector<int> prev(N, -1);\n                d[s] = 0;\n                priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n                pq.push({0, s});\n                \n                while(!pq.empty()){\n                    auto [dist, v] = pq.top(); pq.pop();\n                    if(dist > d[v]) continue;\n                    if(v == t) break;\n                    for(auto& edge : edges){\n                        int a, b; long long w;\n                        tie(a, b, w) = edge;\n                        a--; b--;\n                        if(v == a && d[a] + w < d[b]){\n                            d[b] = d[a] + w;\n                            prev[b] = a;\n                            pq.push({d[b], b});\n                        } else if (v == b && d[b] + w < d[a]){\n                            d[a] = d[b] + w;\n                            prev[a] = b;\n                            pq.push({d[a], a});\n                        }\n                    }\n                }\n                \n                int curr = t;\n                while(curr != s && curr != -1) {\n                    int p = prev[curr];\n                    if (p == -1) break;\n                    for (int j = 0; j < M; ++j) {\n                        int uj, vj; long long wj;\n                        tie(uj, vj, wj) = edges[j];\n                        uj--; vj--;\n                        if ((uj == p && vj == curr) || (uj == curr && vj == p)) {\n                            B[j] = 1;\n                            break;\n                        }\n                    }\n                    curr = p;\n                }\n            }\n            \n            for (int v = 0; v < N; ++v) {\n                if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                    min_dist[v] = dist_nodes[u][v];\n                    parent[v] = u;\n                }\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if (i > 0) cout << \" \";\n            cout << P[i];\n        }\n        cout << \"\\n\";\n        for (int j = 0; j < M; ++j) {\n            if (j > 0) cout << \" \";\n            cout << B[j];\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    \n    Solver solver(N, M, K);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        solver.edges[i] = {u, v, w};\n    }\n    for (int i = 0; i < K; ++i) {\n        cin >> solver.residents[i].first >> solver.residents[i].second;\n    }\n    \n    solver.solve();\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> all_vals;\n    map<int, pair<int, int>> pos;\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            grid[x][y] = v;\n            pos[v] = {x, y};\n            all_vals.push_back(v);\n        }\n    }\n\n    sort(all_vals.begin(), all_vals.end());\n    map<int, int> rank_of_val;\n    for (int i = 0; i < (int)all_vals.size(); ++i) {\n        rank_of_val[all_vals[i]] = i;\n    }\n\n    auto get_tier = [&](int rank) -> int {\n        int t = (int)((-1 + sqrt(1 + 8.0 * rank)) / 2);\n        while ((t + 1) * (t + 2) / 2 <= rank) t++;\n        while (t * (t + 1) / 2 > rank) t--;\n        return t;\n    };\n\n    vector<int> target_tier(465);\n    for (int i = 0; i < 465; ++i) {\n        target_tier[i] = get_tier(i);\n    }\n\n    vector<tuple<int, int, int, int>> operations;\n\n    auto dist = [](int x1, int y1, int x2, int y2) -> int {\n        return max(abs(x1 - x2), abs(y1 - y2));\n    };\n\n    vector<pair<int, int>> directions = {\n        {0, -1}, {0, 1}, {-1, 0}, {-1, -1}, {1, 0}, {1, 1}\n    };\n\n    for (int t = N - 1; t >= 0; --t) {\n        int start_rank = t * (t + 1) / 2;\n        int count = t + 1;\n        \n        vector<int> balls_in_tier;\n        for (int i = 0; i < count; ++i) {\n            balls_in_tier.push_back(all_vals[start_rank + i]);\n        }\n\n        // Sort balls by x descending (closest to target tier first)\n        // This biases MCMF tie-breaking towards balls that are physically closer.\n        sort(balls_in_tier.begin(), balls_in_tier.end(), [&](int a, int b) {\n            return pos[a].first > pos[b].first;\n        });\n\n        int node_offset = t + 1;\n        int SRC = (t + 1) * 2;\n        int SNK = (t + 1) * 2 + 1;\n        \n        mcf_graph<int, int> g(SNK + 1);\n\n        for (int i = 0; i < count; ++i) {\n            int val = balls_in_tier[i];\n            auto [cx, cy] = pos[val];\n            g.add_edge(SRC, i, 1, 0); \n            \n            for (int j = 0; j < count; ++j) {\n                int d = dist(cx, cy, t, j);\n                // Cost: Primary is distance. Secondary is vertical alignment (dy^2).\n                // Weight 100 ensures max_dist (30) is always more significant than max_dy^2 (900).\n                int cost = d * 100 + (cy - j) * (cy - j);\n                g.add_edge(i, node_offset + j, 1, cost);\n            }\n        }\n        \n        for (int j = 0; j < count; ++j) {\n             g.add_edge(node_offset + j, SNK, 1, 0);\n        }\n\n        auto flow_res = g.flow(SRC, SNK);\n        \n        map<int, pair<int, int>> final_targets; \n        \n        auto edges = g.edges();\n        for (auto &e : edges) {\n            if (e.from >= SRC || e.to >= SNK || e.to == SRC || e.from == SNK) continue;\n            if (e.from < t + 1 && e.to >= node_offset && e.to < (t + 1) * 2 && e.flow > 0) {\n                int ball_idx = e.from;\n                int target_y = e.to - node_offset;\n                int val = balls_in_tier[ball_idx];\n                final_targets[val] = {t, target_y};\n            }\n        }\n\n        struct Assignment {\n            int val;\n            int tx;\n            int ty;\n        };\n        vector<Assignment> assigns;\n        for (auto& p : final_targets) {\n            assigns.push_back({p.first, p.second.first, p.second.second});\n        }\n\n        // Placement order: Edges first (0, t, 1, t-1...)\n        sort(assigns.begin(), assigns.end(), [&](const Assignment& a, const Assignment& b) {\n            int dist_a = min(a.ty, t - a.ty);\n            int dist_b = min(b.ty, t - b.ty);\n            if (dist_a != dist_b) return dist_a < dist_b;\n            return a.ty < b.ty;\n        });\n\n        for (auto& item : assigns) {\n            int val = item.val;\n            int tx = item.tx;\n            int ty = item.ty;\n            auto [sx, sy] = pos[val];\n\n            if (sx == tx && sy == ty) continue;\n\n            queue<pair<int, int>> q;\n            map<pair<int, int>, pair<int, int>> parent;\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            \n            q.push({sx, sy});\n            visited[sx][sy] = true;\n            \n            bool found = false;\n            \n            while (!q.empty() && !found) {\n                auto [cx, cy] = q.front();\n                q.pop();\n                \n                for (auto [dx, dy] : directions) {\n                    int nx = cx + dx;\n                    int ny = cy + dy;\n                    \n                    if (nx < 0 || nx >= N || ny < 0 || ny > nx) continue;\n                    if (visited[nx][ny]) continue;\n                    \n                    int ball_at_nx = grid[nx][ny];\n                    int b_tier = target_tier[rank_of_val[ball_at_nx]];\n                    \n                    bool is_obstacle = false;\n                    if (b_tier > t) is_obstacle = true;\n                    else if (b_tier == t) {\n                        if (final_targets.count(ball_at_nx)) {\n                             auto [b_tx, b_ty] = final_targets[ball_at_nx];\n                             if (nx == b_tx && ny == b_ty) is_obstacle = true;\n                        }\n                    }\n                    \n                    if (!is_obstacle) {\n                        visited[nx][ny] = true;\n                        parent[{nx, ny}] = {cx, cy};\n                        q.push({nx, ny});\n                        if (nx == tx && ny == ty) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            vector<pair<int, int>> path;\n            {\n                auto curr = make_pair(tx, ty);\n                while (curr != make_pair(sx, sy)) {\n                    path.push_back(curr);\n                    curr = parent[curr];\n                }\n                path.push_back({sx, sy});\n                reverse(path.begin(), path.end());\n            }\n\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                auto [u1, v1] = path[i];\n                auto [u2, v2] = path[i+1];\n                \n                int val1 = grid[u1][v1];\n                int val2 = grid[u2][v2];\n                \n                swap(grid[u1][v1], grid[u2][v2]);\n                \n                pos[val1] = {u2, v2};\n                pos[val2] = {u1, v1};\n                \n                operations.push_back({u1, v1, u2, v2});\n            }\n        }\n    }\n\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <numeric>\n\nusing namespace std;\n\n// Grid configuration\nconst int D = 9;\nconst int INF = 1e9;\n// Entrance\nconst int ER = 0;\nconst int EC = 4;\n\nstruct State {\n    vector<vector<bool>> obstacle;\n    vector<vector<int>> dist;\n    vector<vector<bool>> occupied;\n    int total_containers;\n\n    State(int n, const vector<pair<int, int>>& obs_coords) {\n        obstacle.assign(D, vector<bool>(D, false));\n        occupied.assign(D, vector<bool>(D, false));\n        dist.assign(D, vector<int>(D, -1));\n        \n        // Mark entrance and adjacent as not obstacles (problem guarantee)\n        // But we also treat them as not storage space.\n        \n        // Mark obstacles\n        for (auto p : obs_coords) {\n            obstacle[p.first][p.second] = true;\n        }\n\n        // Calculate distances from entrance\n        queue<pair<int, int>> q;\n        q.push({ER, EC});\n        dist[ER][EC] = 0;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (dist[nr][nc] == -1 && !obstacle[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + 1;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Count available spots\n        total_containers = 0;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                // Entrance and obstacles are not for storage\n                if ((i == ER && j == EC) || obstacle[i][j]) continue;\n                // Problem statement says entrance and its 3 adjacent are not obstacles\n                // But they are valid storage spots? \n                // \"Each D x D - 1 - N square other than the entrance and obstacles can hold at most 1 container.\"\n                // So adjacent squares (0,3), (0,5), (1,4) ARE valid storage spots.\n                total_containers++;\n            }\n        }\n    }\n    \n    // Find empty cells reachable from entrance via empty cells\n    vector<pair<int, int>> get_reachable_empty() {\n        vector<pair<int, int>> reachable;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        \n        // Start from entrance\n        q.push({ER, EC});\n        visited[ER][EC] = true;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (!visited[nr][nc] && !obstacle[nr][nc] && !occupied[nr][nc]) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                        reachable.push_back({nr, nc});\n                    }\n                }\n            }\n        }\n        return reachable;\n    }\n\n    // Check if placing a container at (tr, tc) blocks other empty cells from entrance\n    // It blocks if, after marking (tr, tc) occupied, some previously reachable empty cell becomes unreachable.\n    bool is_safe_placement(int tr, int tc) {\n        // Temporarily mark as occupied\n        occupied[tr][tc] = true;\n        \n        vector<pair<int, int>> new_reachable = get_reachable_empty();\n        \n        // Restore\n        occupied[tr][tc] = false;\n\n        // Count previously reachable (excluding the cell itself)\n        auto prev_reachable = get_reachable_empty();\n        \n        // Actually, we can just compare counts of reachable nodes (excluding the one we are filling)\n        // Since we are adding an obstacle, the set of reachable empty cells can only shrink.\n        // We want it to NOT shrink (except for the cell itself).\n        // Note: get_reachable_empty returns EMPTY cells.\n        // (tr, tc) is empty before placement. It is in prev_reachable.\n        // After placement, it is not in new_reachable.\n        // So we expect |new_reachable| == |prev_reachable| - 1.\n        \n        if (new_reachable.size() == prev_reachable.size() - 1) return true;\n        return false;\n    }\n\n    // Choose best cell for container t\n    pair<int, int> choose_placement(int t) {\n        auto reachable = get_reachable_empty();\n        \n        if (reachable.empty()) {\n            // Should not happen\n            return {-1, -1};\n        }\n\n        // Target distance\n        // Map t from [0, M-1] to a distance range\n        // Max distance is around 15.\n        double ratio = (double)t / total_containers;\n        \n        // We want to sort candidates.\n        // Heuristic: \n        // 1. Is safe (doesn't block).\n        // 2. Distance is close to target.\n        // 3. (Optional) Prefer low degree or corners?\n        \n        vector<tuple<int, int, double>> candidates; // score, r, c\n        // Score > 0 means safe, < 0 unsafe.\n        \n        int max_dist = 0;\n        for(auto& p : reachable) max_dist = max(max_dist, dist[p.first][p.second]);\n        \n        for (auto& p : reachable) {\n            int r = p.first;\n            int c = p.second;\n            int d = dist[r][c];\n            \n            double ideal_d = ratio * max_dist;\n            double dist_error = abs(d - ideal_d);\n            \n            int safe_score = is_safe_placement(r, c) ? 1000 : 0;\n            \n            // Combine: safety is most important. Then distance match.\n            // We maximize score.\n            double final_score = safe_score - dist_error;\n            \n            // If unsafe, we might still want to place it if we have no other choice,\n            // but we pick the one with max_dist_error (least bad? or best distance?).\n            // Let's say if unsafe, score is just -dist_error.\n            // If safe, score is 1000 - dist_error.\n            \n            candidates.push_back({final_score, r, c});\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<tuple<double, int, int>>());\n        \n        // Pick the best one\n        return {get<1>(candidates[0]), get<2>(candidates[0])};\n    }\n\n    void place(int t, int r, int c) {\n        occupied[r][c] = true;\n        cout << r << \" \" << c << endl;\n        // cout << \"# Placed \" << t << \" at \" << r << \" \" << c << endl;\n    }\n\n    // Retrieve phase\n    void retrieve_all(const map<int, pair<int, int>>& id_to_coord) {\n        vector<pair<int, int>> retrieval_order;\n        \n        // Set of remaining IDs\n        set<int> remaining;\n        for (auto p : id_to_coord) remaining.insert(p.first);\n        \n        // While there are containers\n        while (!remaining.empty()) {\n            // Find reachable occupied cells\n            queue<pair<int, int>> q;\n            vector<vector<bool>> visited(D, vector<bool>(D, false));\n            q.push({ER, EC});\n            visited[ER][EC] = true;\n            \n            vector<int> reachable_ids;\n            \n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n\n            while (!q.empty()) {\n                auto curr = q.front(); 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                    if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                        if (!visited[nr][nc] && !obstacle[nr][nc]) {\n                            // Check if occupied\n                            bool is_occupied = false;\n                            int id_at = -1;\n                            // We need to check if this coordinate has a container that is still in 'remaining'\n                            // We can look up in id_to_coord map (inverse map needed?)\n                            // Actually we have id_to_coord. We need coord_to_id.\n                            // Or just iterate remaining? remaining size is up to 80. O(80*80) is fine.\n                            for (int rid : remaining) {\n                                if (id_to_coord.at(rid) == make_pair(nr, nc)) {\n                                    is_occupied = true;\n                                    id_at = rid;\n                                    break;\n                                }\n                            }\n\n                            if (is_occupied) {\n                                visited[nr][nc] = true; // Can reach this square (but stop here?)\n                                // Actually we pass through it? No.\n                                // Rule: \"passing through adjacent empty squares\".\n                                // Occupied squares are NOT empty.\n                                // So we CANNOT pass through occupied squares.\n                                // We can only reach the occupied square itself if we are adjacent to an empty square.\n                                // But we CANNOT go THROUGH an occupied square.\n                                // However, the square containing the container is the target.\n                                // The rule says: \"The square containing the container to be transported out must be reachable... by passing through adjacent empty squares.\"\n                                // This means the path ends at the square. The square itself is occupied.\n                                // So we just check connectivity via EMPTY squares.\n                                // If (nr, nc) is occupied, we don't push it to queue.\n                                // But we record it as a retrievable target.\n                                reachable_ids.push_back(id_at);\n                            } else {\n                                // Empty, traverse\n                                visited[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (reachable_ids.empty()) {\n                // Should not happen\n                break;\n            }\n            \n            // Pick smallest ID\n            sort(reachable_ids.begin(), reachable_ids.end());\n            int to_retrieve = reachable_ids[0];\n            \n            retrieval_order.push_back(id_to_coord.at(to_retrieve));\n            remaining.erase(to_retrieve);\n        }\n        \n        // Output\n        for (auto p : retrieval_order) {\n            cout << p.first << \" \" << p.second << endl;\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N;\n    cin >> N;\n    \n    vector<pair<int, int>> obstacles(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    State solver(N, obstacles);\n    \n    map<int, pair<int, int>> id_to_coord;\n    \n    for (int i = 0; i < solver.total_containers; ++i) {\n        int t;\n        cin >> t;\n        \n        auto p = solver.choose_placement(t);\n        solver.place(t, p.first, p.second);\n        id_to_coord[t] = p;\n    }\n    \n    solver.retrieve_all(id_to_coord);\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\n// Constants\nconst int N = 50;\nconst int M = 100;\n\n// Global variables\nint n, m;\nint original_grid[N][N];\nint best_grid[N][M];\nint best_score = -1;\n\n// Store initial positions of each color\nvector<pair<int, int>> original_cells[M + 1];\n\nbool is_boundary_color[M + 1];\nbool is_fixed[N][N];\n\nint dx[4] = {0, 1, 0, -1};\nint dy[4] = {1, 0, -1, 0};\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < n && 0 <= y && y < n;\n}\n\nvoid run_simulation(int seed) {\n    mt19937 rng(seed);\n    \n    // Local grid state\n    int grid[N][N];\n    int color_cnt[M + 1];\n    for(int c=1; c<=m; ++c) color_cnt[c] = 0;\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = original_grid[i][j];\n            if(grid[i][j] != 0) color_cnt[grid[i][j]]++;\n        }\n    }\n\n    // Copy cell lists (we will mark cells as removed in the grid)\n    // Using the original lists and checking grid value is faster than copying the vector\n    // provided we don't mind iterating over \"dead\" cells occasionally.\n    // Actually, with average 25 cells, skipping dead ones is negligible overhead.\n    // However, to be precise, we rely on the grid array for truth.\n\n    // Initialize Queue\n    vector<pair<int, int>> start_nodes;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !is_fixed[i][j] && grid[i][j] != 0) {\n                start_nodes.push_back({i, j});\n            }\n        }\n    }\n\n    shuffle(start_nodes.begin(), start_nodes.end(), rng);\n\n    queue<pair<int, int>> q;\n    for (auto& p : start_nodes) q.push(p);\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        \n        if (grid[x][y] == 0) continue;\n        if (is_fixed[x][y]) continue;\n\n        int c = grid[x][y];\n        if (color_cnt[c] <= 1) continue;\n\n        // A. Connectivity Check\n        // Find a start neighbor\n        int sx = -1, sy = -1;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && grid[nx][ny] == c) {\n                sx = nx; sy = ny;\n                break;\n            }\n        }\n\n        if (sx != -1) {\n            queue<pair<int, int>> bq;\n            bq.push({sx, sy});\n            bool visited[N][N] = {false};\n            visited[sx][sy] = true;\n            int count = 0;\n            \n            while (!bq.empty()) {\n                auto [cx, cy] = bq.front(); bq.pop();\n                count++;\n                for (int k = 0; k < 4; ++k) {\n                    int nx = cx + dx[k];\n                    int ny = cy + dy[k];\n                    if (in_grid(nx, ny) && !visited[nx][ny] && grid[nx][ny] == c && (nx != x || ny != y)) {\n                        visited[nx][ny] = true;\n                        bq.push({nx, ny});\n                    }\n                }\n            }\n            if (count != color_cnt[c] - 1) continue;\n        } else {\n            continue;\n        }\n\n        // B. Witness Check (Optimized using cell lists)\n        // 1. Determine required neighbors (neighbors of x,y)\n        vector<int> required_neighbors;\n        bool needs_0 = false;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny)) {\n                int nc = grid[nx][ny];\n                if (nc == 0) needs_0 = true;\n                else if (nc != c) required_neighbors.push_back(nc);\n            } else {\n                needs_0 = true;\n            }\n        }\n        \n        sort(required_neighbors.begin(), required_neighbors.end());\n        required_neighbors.erase(unique(required_neighbors.begin(), required_neighbors.end()), required_neighbors.end());\n\n        // 2. Scan ONLY kept cells of c (using original_cells[c] as reference)\n        vector<bool> neighbor_mask(M + 1, false);\n        if (needs_0) neighbor_mask[0] = true;\n\n        for (auto [cx, cy] : original_cells[c]) {\n            if (grid[cx][cy] != c) continue; // Skip removed cells\n            if (cx == x && cy == y) continue; // Skip self\n\n            for (int k = 0; k < 4; ++k) {\n                int nx = cx + dx[k];\n                int ny = cy + dy[k];\n                if (in_grid(nx, ny)) {\n                    neighbor_mask[grid[nx][ny]] = true;\n                } else {\n                    neighbor_mask[0] = true;\n                }\n            }\n        }\n\n        // 3. Verify\n        bool ok = true;\n        if (needs_0 && !neighbor_mask[0]) ok = false;\n        if (ok) {\n            for (int d : required_neighbors) {\n                if (!neighbor_mask[d]) {\n                    ok = false;\n                    break;\n                }\n            }\n        }\n\n        if (!ok) continue;\n\n        // C. Perform Removal\n        grid[x][y] = 0;\n        color_cnt[c]--;\n\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && !is_fixed[nx][ny]) {\n                q.push({nx, ny});\n            }\n        }\n    }\n\n    // Calculate Score\n    int score = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (grid[i][j] == 0) score++;\n        }\n    }\n\n    if (score > best_score) {\n        best_score = score;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                best_grid[i][j] = grid[i][j];\n            }\n        }\n    }\n}\n\nvoid solve() {\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> original_grid[i][j];\n            if(original_grid[i][j] != 0) {\n                original_cells[original_grid[i][j]].push_back({i, j});\n            }\n        }\n    }\n\n    // Precompute static properties\n    for (int c = 1; c <= m; ++c) is_boundary_color[c] = false;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = original_grid[i][j];\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                is_boundary_color[c] = true;\n            }\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = original_grid[i][j];\n            if (!is_boundary_color[c]) {\n                is_fixed[i][j] = true;\n            } else {\n                bool touches_internal = false;\n                for (int k = 0; k < 4; ++k) {\n                    int nx = i + dx[k];\n                    int ny = j + dy[k];\n                    if (in_grid(nx, ny)) {\n                        int nc = original_grid[nx][ny];\n                        if (!is_boundary_color[nc]) {\n                            touches_internal = true;\n                            break;\n                        }\n                    }\n                }\n                is_fixed[i][j] = touches_internal;\n            }\n        }\n    }\n\n    // With vector optimization, we can run many more iterations.\n    for (int s = 0; s < 200; ++s) {\n        run_simulation(s);\n    }\n\n    // Output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << best_grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\n\n// Ask the judge\n// Returns 1 if L > R, -1 if L < R, 0 if L = R\nint ask(int l, int r) {\n    // Prevent asking (x, x)\n    if (l == r) return 0;\n    // Stop if we hit the limit\n    if (query_count >= Q) return 0;\n    \n    cout << 1 << \" \" << 1 << \" \" << l << \" \" << r << \"\\n\";\n    cout.flush();\n    query_count++;\n    \n    string res;\n    cin >> res;\n    if (res == \"<\") return -1;\n    if (res == \">\") return 1;\n    return 0;\n}\n\nbool heavier(int a, int b) {\n    if (query_count >= Q) return false;\n    int res = ask(a, b);\n    return res > 0;\n}\n\nvoid solve() {\n    cin >> N >> D >> Q;\n\n    vector<int> heap(N);\n    for(int i=0; i<N; ++i) heap[i] = i;\n    int heap_size = N;\n\n    // Heapify: Build the max heap structure\n    for (int i = N / 2 - 1; i >= 0; --i) {\n        int curr = i;\n        while (true) {\n            int largest = curr;\n            int left = 2 * curr + 1;\n            int right = 2 * curr + 2;\n\n            if (left < heap_size && heavier(heap[left], heap[largest])) largest = left;\n            if (right < heap_size && heavier(heap[right], heap[largest])) largest = right;\n\n            if (largest != curr) {\n                swap(heap[curr], heap[largest]);\n                curr = largest;\n            } else {\n                break;\n            }\n        }\n    }\n\n    vector<int> extracted_indices;\n    \n    // Reserve some queries to sort the remaining items at the end.\n    // 300 queries is a reasonable buffer to improve the order of the tail.\n    const int RESERVE = 300; \n\n    // Extract top K items\n    while (heap_size > 0) {\n        // Check if we should stop extracting to save queries for sorting the rest\n        if (query_count + (int)log2(heap_size) + 10 >= Q) break;\n\n        // Extract max\n        extracted_indices.push_back(heap[0]);\n        \n        // Move last to root\n        heap[0] = heap[heap_size - 1];\n        heap_size--;\n        \n        if (heap_size == 0) break;\n\n        // Sift down\n        int curr = 0;\n        while (true) {\n            int largest = curr;\n            int left = 2 * curr + 1;\n            int right = 2 * curr + 2;\n\n            if (left < heap_size && heavier(heap[left], heap[largest])) largest = left;\n            if (right < heap_size && heavier(heap[right], heap[largest])) largest = right;\n\n            if (largest != curr) {\n                swap(heap[curr], heap[largest]);\n                curr = largest;\n            } else {\n                break;\n            }\n        }\n    }\n\n    // Use remaining queries to sort the 'heap' array (remaining items) via insertion sort\n    // This significantly improves the weight estimation for the \"rest\" items\n    for (int i = 1; i < heap_size; ++i) {\n        if (query_count >= Q) break;\n        \n        int key = heap[i];\n        int j = i - 1;\n        \n        // Insert heap[i] into sorted sequence heap[0..i-1] (descending order)\n        while (j >= 0) {\n            if (query_count >= Q) break;\n            \n            if (heavier(key, heap[j])) {\n                heap[j+1] = heap[j];\n                j--;\n            } else {\n                break;\n            }\n        }\n        heap[j+1] = key;\n    }\n\n    // If we still have queries left (unlikely), fill with dummies\n    while (query_count < Q) {\n        ask(0, 1);\n    }\n    \n    // Weight Estimation\n    vector<int> weight_est(N, 1);\n    int current_w = N;\n    \n    // Assign weights to extracted items (Top K) - already sorted heaviest first\n    for (int idx : extracted_indices) {\n        weight_est[idx] = current_w;\n        current_w--;\n    }\n    \n    // Assign weights to remaining items - now roughly sorted thanks to insertion sort\n    for (int i = 0; i < heap_size; ++i) {\n        int item = heap[i];\n        if (weight_est[item] == 1) {\n            weight_est[item] = current_w;\n            current_w = max(1, current_w - 1);\n        }\n    }\n\n    // Partition using LPT (Longest Processing Time)\n    vector<pair<int, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({weight_est[i], i});\n    }\n    sort(items.begin(), items.end(), greater<pair<int, int>>());\n\n    vector<int> assignment(N);\n    vector<long long> bin_sums(D, 0);\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n    \n    for (int i = 0; i < D; ++i) {\n        pq.push({0, i});\n    }\n    \n    for (auto& p : items) {\n        int w = p.first;\n        int idx = p.second;\n        auto top = pq.top();\n        pq.pop();\n        \n        int bin_idx = top.second;\n        bin_sums[bin_idx] += w;\n        assignment[idx] = bin_idx;\n        pq.push({bin_sums[bin_idx], bin_idx});\n    }\n    \n    // Output assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for state and parameters\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // 0-indexed stack and height\nvector<pair<int, int>> operations;\n\n// Structure to hold heuristic evaluation results\nstruct DestInfo {\n    int id;\n    long long score;\n    int min_val; // Smallest element in the stack (used for tie-breaking)\n};\n\n// Helper to get the top element of a stack, return large number if empty\nint get_top(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return stacks[stack_id].back();\n}\n\n// Helper to get the minimum element in a stack\nint get_min(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return *min_element(stacks[stack_id].begin(), stacks[stack_id].end());\n}\n\n// Evaluate the cost of moving a segment 'seg' to stack 'dest'\n// Score represents the \"badness\", lower is better.\n// Badness is defined as the number of inversions created.\n// An inversion is a pair (t, s) where t is in destination, s is in segment, and t > s.\n// We also want to prefer keeping segments intact if they are sorted,\n// but the split logic handles that before calling this.\nlong long evaluate_move(int dest, const vector<int>& seg) {\n    if (stacks[dest].empty()) return 0; // No inversions possible with empty stack\n\n    long long inv_count = 0;\n    \n    // Optimization: Since we sum counts of t > s for all s in seg\n    // We can iterate through t in destination and count how many s it is greater than.\n    // Complexity: O(Size(D) * Size(S)). Max 20 * 200 = 4000. Negligible.\n    \n    const vector<int>& dest_stack = stacks[dest];\n    \n    // Pre-calculate prefix sums? Not necessary for N=200.\n    // Just brute force double loop.\n    for (int t : dest_stack) {\n        for (int s : seg) {\n            if (t > s) {\n                inv_count++;\n            }\n        }\n    }\n    return inv_count;\n}\n\n// Execute operation type 1: Move box 'v' (and above it) to stack 'dest'\nvoid move_box(int v, int dest) {\n    // Find current stack\n    int s = pos[v].first;\n    int h = pos[v].second;\n    \n    if (s == dest) return; // Should not happen based on logic\n\n    // Identify segment to move\n    vector<int> boxes_to_move;\n    // stacks[s] has boxes from bottom (0) to top (size-1)\n    // v is at index h. We move h to size-1.\n    for (int i = h; i < stacks[s].size(); ++i) {\n        boxes_to_move.push_back(stacks[s][i]);\n    }\n    \n    // Update Source Stack\n    stacks[s].resize(h);\n    \n    // Update Destination Stack\n    for (int box : boxes_to_move) {\n        stacks[dest].push_back(box);\n    }\n    \n    // Update Positions\n    int new_h = stacks[dest].size() - boxes_to_move.size();\n    for (int i = 0; i < boxes_to_move.size(); ++i) {\n        int box = boxes_to_move[i];\n        pos[box] = {dest, new_h + i};\n    }\n    \n    operations.push_back({v, dest});\n}\n\n// Execute operation type 2: Carry out box 'v'\nvoid carry_out(int v) {\n    int s = pos[v].first;\n    // Check if v is at top (should be guaranteed by caller)\n    if (stacks[s].back() != v) {\n        // Error or should not happen\n        return;\n    }\n    \n    stacks[s].pop_back();\n    // pos[v] is no longer valid, but we won't query v again\n    operations.push_back({v, 0});\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M;\n    stacks.resize(M);\n    pos.resize(N + 1);\n    \n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Process boxes 1 to N\n    for (int v = 1; v <= N; ++v) {\n        // While v is not at top of its stack\n        while (true) {\n            int s = pos[v].first;\n            int h = pos[v].second;\n            \n            // If stack has been emptied or v is at top (h == size-1)\n            if (stacks[s].size() == h + 1) {\n                break;\n            }\n            \n            // Identify the top box of the stack containing v\n            int top_box = stacks[s].back();\n            \n            // We want to move segments that are \"inverted\" or simply move the blocking segment.\n            // Strategy:\n            // Look at the box immediately above v. Let's call it 'blocker'.\n            // Or look at the top of the stack.\n            // If the top of the stack is larger than the box below it, it creates an inversion.\n            // Moving just the top box resolves that inversion for the pair (top, below).\n            // Recursively doing this sorts the stack.\n            // Once the stack above v is sorted (small on top), we move the whole block.\n            \n            bool moved = false;\n            \n            // Check for shallow inversion at the top of the current stack\n            if (stacks[s].size() >= 2) {\n                int top = stacks[s].back();\n                int below = stacks[s][stacks[s].size() - 2];\n                \n                // If top > below, moving top alone is usually beneficial to fix the inversion.\n                // However, if 'below' is v, and top is v+1, moving top is bad.\n                // But if top > below, they are not consecutive (unless v, v+1 is inverted which is impossible in sorted 1..N).\n                // So top > below implies they are not in order.\n                if (top > below) {\n                    // Find best destination for 'top_box'\n                    // We want to minimize inversions created by adding 'top_box' to dest.\n                    \n                    vector<DestInfo> candidates;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == s) continue;\n                        \n                        // Segment is just {top_box}\n                        long long inv = evaluate_move(i, {top_box});\n                        candidates.push_back({i, inv, get_min(i)});\n                    }\n                    \n                    // Sort by score (inversions), then by min_val (larger is better buffer)\n                    sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                        if (a.score != b.score) return a.score < b.score;\n                        return a.min_val > b.min_val;\n                    });\n                    \n                    int best_dest = candidates[0].id;\n                    move_box(top_box, best_dest);\n                    moved = true;\n                }\n            }\n            \n            if (!moved) {\n                // No shallow inversion at the top, or we decided not to split.\n                // Move the entire segment above v.\n                // Segment starts at index h+1.\n                vector<int> seg;\n                for (int i = h + 1; i < stacks[s].size(); ++i) {\n                    seg.push_back(stacks[s][i]);\n                }\n                \n                // Find best destination for the whole segment\n                vector<DestInfo> candidates;\n                for (int i = 0; i < M; ++i) {\n                    if (i == s) continue;\n                    \n                    long long inv = evaluate_move(i, seg);\n                    candidates.push_back({i, inv, get_min(i)});\n                }\n                \n                sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.min_val > b.min_val;\n                });\n                \n                int best_dest = candidates[0].id;\n                \n                // The segment starts at seg[0], which is the box just above v.\n                move_box(seg[0], best_dest);\n            }\n        }\n        \n        // v is now at top. Carry out.\n        carry_out(v);\n    }\n\n    // Output\n    cout << operations.size() << endl;\n    for (auto op : operations) {\n        cout << op.first << \" \" << op.second << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <functional>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 40;\nconst int MAX_NODES = MAX_N * MAX_N;\nconst int MAX_MOVES = 90000; // Very conservative limit to ensure strict adherence to 10^5\n\nint N;\nint d[MAX_NODES];\nvector<int> adj[MAX_NODES];\nint cnt[MAX_NODES][MAX_NODES];\nlong long k[MAX_NODES];\nlong long total_len = 0;\n\nint to_idx(int i, int j) { return i * N + j; }\n\nvoid from_idx(int idx, int& i, int& j) {\n    i = idx / N;\n    j = idx % N;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Fixed seed for deterministic behavior\n    mt19937 rng(12345);\n    uniform_real_distribution<double> noise_dist(0.0, 0.0001);\n\n    cin >> N;\n    vector<string> h(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[to_idx(i, j)];\n            k[to_idx(i, j)] = 0;\n        }\n    }\n\n    // Initialize cnt and build adjacency list\n    for (int i = 0; i < N*N; ++i) {\n        for (int j = 0; j < N*N; ++j) {\n            cnt[i][j] = 0;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = to_idx(i, j);\n            if (i < N-1 && h[i][j] == '0') {\n                int v_idx = to_idx(i+1, j);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n            }\n            if (j < N-1 && v[i][j] == '0') {\n                int v_idx = to_idx(i, j+1);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n            }\n        }\n    }\n\n    // Initial DFS to construct a base tour (spanning tree)\n    vector<bool> visited(N*N, false);\n    \n    function<void(int, int)> dfs = [&](int u, int p) {\n        visited[u] = true;\n        for (int v : adj[u]) {\n            if (!visited[v]) {\n                // Traverse u -> v\n                cnt[u][v]++;\n                k[v]++;\n                dfs(v, u);\n                // Return v -> u\n                cnt[v][u]++;\n                k[u]++;\n            }\n        }\n    };\n\n    dfs(0, -1);\n\n    // Calculate initial total length\n    total_len = 0;\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            total_len += cnt[u][v];\n        }\n    }\n    total_len /= 2;\n\n    // Priority queue for greedy detours\n    priority_queue<pair<double, pair<int, int>>> pq;\n\n    auto update_pq = [&](int u) {\n        for (int v : adj[u]) {\n            if (u < v) {\n                double val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n                val += noise_dist(rng);\n                pq.push({val, {u, v}});\n            }\n        }\n    };\n\n    // Initialize priority queue\n    for (int u = 0; u < N*N; ++u) {\n        update_pq(u);\n    }\n\n    // Greedy loop to add detours\n    while (total_len + 2 <= MAX_MOVES) {\n        if (pq.empty()) break;\n        \n        auto item = pq.top();\n        pq.pop();\n        double score = item.first;\n        int u = item.second.first;\n        int v = item.second.second;\n        \n        // Re-calculate current value to check for staleness\n        double current_val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n        \n        if (current_val < score - 0.1) {\n            continue;\n        }\n        \n        // Add detour: u -> v -> u\n        cnt[u][v]++;\n        cnt[v][u]++;\n        k[u]++;\n        k[v]++;\n        total_len += 2;\n        \n        // Update priority queue for neighbors of u and v\n        update_pq(u);\n        update_pq(v);\n    }\n    \n    // Hierholzer's Algorithm to find the Eulerian circuit\n    vector<char> path;\n    vector<int> stack;\n    stack.push_back(0);\n    \n    while (!stack.empty()) {\n        int u = stack.back();\n        bool found = false;\n        for (int v : adj[u]) {\n            if (cnt[u][v] > 0) {\n                cnt[u][v]--;\n                stack.push_back(v);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) {\n            stack.pop_back();\n            if (!stack.empty()) {\n                int prev = stack.back();\n                int i1, j1, i2, j2;\n                from_idx(prev, i1, j1);\n                from_idx(u, i2, j2);\n                \n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                \n                path.push_back(c);\n            }\n        }\n    }\n    \n    // The path is constructed in reverse order\n    reverse(path.begin(), path.end());\n    \n    // Output the route\n    for (char c : path) {\n        cout << c;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconstexpr int M_MAX = 200;\nconstexpr int MAX_N = 15;\nconstexpr int INF = 1e9;\n\nint N = 15;\nint M = 0;\nint N2 = 225;\n\nint grid[MAX_N][MAX_N];\nvector<int> char_pos[26];\nint start_pos;\nvector<string> targets(M_MAX);\n\nint dist[MAX_N * MAX_N][MAX_N * MAX_N];\n\n// Timer\nstd::chrono::system_clock::time_point start_time;\n\nint get_elapsed_ms() {\n    auto now = std::chrono::system_clock::now();\n    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n}\n\nvoid precompute() {\n    N2 = N * N;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            for (int k = 0; k < N; ++k) {\n                for (int l = 0; l < N; ++l) {\n                    int v = k * N + l;\n                    dist[u][v] = abs(i - k) + abs(j - l);\n                }\n            }\n        }\n    }\n}\n\nint calc_overlap(const string& A, const string& B) {\n    int max_ov = 0;\n    int len_A = A.size();\n    int len_B = B.size();\n    int limit = min(len_A, len_B);\n    if (limit > 4) limit = 4;\n    for (int k = 1; k <= limit; ++k) {\n        if (A.compare(len_A - k, k, B, 0, k) == 0) {\n            max_ov = k;\n        }\n    }\n    return max_ov;\n}\n\nint overlap_mat[M_MAX][M_MAX];\n\nvoid build_overlap_matrix() {\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                overlap_mat[i][j] = 0;\n                continue;\n            }\n            overlap_mat[i][j] = calc_overlap(targets[i], targets[j]);\n        }\n    }\n}\n\nstring build_string(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5); \n    s.append(targets[order[0]]);\n    for (size_t i = 1; i < order.size(); ++i) {\n        int u = order[i-1];\n        int v = order[i];\n        int ov = overlap_mat[u][v];\n        const string& t = targets[v];\n        s.append(t.c_str() + ov, t.size() - ov);\n    }\n    return s;\n}\n\nvector<int> dp_buf;\nvector<int> next_dp_buf;\nvector<int> prev_step_buf; \n\npair<int, vector<pair<int, int>>> solve_grid(const string& s, bool store_path = false) {\n    if (s.empty()) return {0, {}};\n\n    int len = s.size();\n\n    if (dp_buf.size() != N2) dp_buf.resize(N2);\n    if (next_dp_buf.size() != N2) next_dp_buf.resize(N2);\n    \n    size_t required_prev_size = (size_t)len * N2;\n    if (prev_step_buf.size() < required_prev_size) {\n        prev_step_buf.resize(required_prev_size);\n    }\n\n    fill(dp_buf.begin(), dp_buf.end(), INF);\n    dp_buf[start_pos] = 0;\n    fill(prev_step_buf.begin(), prev_step_buf.begin() + required_prev_size, -1);\n\n    auto get_prev = [&](int step, int u) -> int& {\n        return prev_step_buf[step * N2 + u];\n    };\n\n    for (size_t i = 0; i < len; ++i) {\n        char c = s[i];\n        fill(next_dp_buf.begin(), next_dp_buf.end(), INF);\n        int c_idx = c - 'A';\n        if (c_idx < 0 || c_idx >= 26) continue; \n\n        const vector<int>& target_cells = char_pos[c_idx];\n        \n        for (int u = 0; u < N2; ++u) {\n            if (dp_buf[u] == INF) continue;\n            int base_cost = dp_buf[u] + 1;\n            const int* dist_row = dist[u];\n\n            for (int v : target_cells) {\n                int cost = base_cost + dist_row[v];\n                if (cost < next_dp_buf[v]) {\n                    next_dp_buf[v] = cost;\n                    if (store_path) {\n                        get_prev(i, v) = u;\n                    }\n                }\n            }\n        }\n        swap(dp_buf, next_dp_buf);\n    }\n\n    int min_cost = *min_element(dp_buf.begin(), dp_buf.end());\n    vector<pair<int, int>> path;\n\n    if (store_path && min_cost < INF) {\n        path.resize(len);\n        int end_pos = -1;\n        for (int i = 0; i < N2; ++i) {\n            if (dp_buf[i] == min_cost) {\n                end_pos = i;\n                break;\n            }\n        }\n        \n        if (end_pos != -1) {\n            int curr = end_pos;\n            bool valid_path = true;\n            for (int i = len - 1; i >= 0; --i) {\n                if (curr < 0 || curr >= N2) {\n                    valid_path = false;\n                    break;\n                }\n                path[i] = {curr / N, curr % N};\n                curr = get_prev(i, curr);\n            }\n            if (!valid_path) {\n                path.clear();\n            }\n        }\n    }\n\n    return {min_cost, path};\n}\n\nvector<int> initial_order_greedy() {\n    vector<int> order;\n    vector<bool> used(M, false);\n    \n    std::random_device rd;\n    std::mt19937 gen(rd());\n    uniform_int_distribution<> dis(0, M-1);\n    int first = dis(gen);\n    \n    order.push_back(first);\n    used[first] = true;\n    \n    for (int count = 1; count < M; ++count) {\n        int last = order.back();\n        int best_next = -1;\n        int max_ov = -1;\n        vector<int> candidates;\n        \n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlap_mat[last][i];\n            if (ov > max_ov) {\n                max_ov = ov;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (ov == max_ov) {\n                candidates.push_back(i);\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        uniform_int_distribution<> cand_dis(0, (int)candidates.size()-1);\n        best_next = candidates[cand_dis(gen)];\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\nvoid solve() {\n    int read_N, read_M;\n    cin >> read_N >> read_M;\n    N = read_N;\n    M = read_M;\n    \n    int si, sj;\n    cin >> si >> sj;\n    start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = row[j];\n            char_pos[row[j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i];\n    }\n    \n    precompute();\n    build_overlap_matrix();\n\n    vector<int> current_order = initial_order_greedy();\n    string current_s = build_string(current_order);\n    auto [current_cost, _] = solve_grid(current_s);\n    \n    vector<int> best_order = current_order;\n    int best_cost = current_cost;\n    \n    // Increase time limit to 1.98s to maximize iterations\n    double time_limit = 1980.0; \n    \n    std::random_device rd;\n    std::mt19937 gen(rd());\n    uniform_int_distribution<> idx_dist(0, M-1);\n    uniform_real_distribution<> prob_dist(0.0, 1.0);\n    uniform_int_distribution<> move_type_dist(0, 1); // 0: Swap, 1: Reverse\n\n    double start_temp = 1000.0; \n    double end_temp = 10.0;\n\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        int move_type = move_type_dist(gen);\n        \n        if (move_type == 0) {\n            // Swap\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            while(idx1 == idx2) idx2 = idx_dist(gen);\n            swap(current_order[idx1], current_order[idx2]);\n        } else {\n            // Reverse Subarray\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            if (idx1 > idx2) swap(idx1, idx2);\n            reverse(current_order.begin() + idx1, current_order.begin() + idx2 + 1);\n        }\n        \n        string new_s = build_string(current_order);\n        auto [new_cost, _] = solve_grid(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            // Revert move\n            if (move_type == 0) {\n                int idx1 = idx_dist(gen); // Note: need to store indices to revert properly\n                // Wait, random gen advances. \n                // Correct logic: store indices before modifying or re-generate correctly?\n                // Simplest: The `idx_dist` generates new numbers.\n                // To revert a swap, we must know which indices were swapped.\n                // Fix: store indices.\n                int i1 = idx_dist(gen);\n                int i2 = idx_dist(gen);\n                while(i1 == i2) i2 = idx_dist(gen);\n                // The problem is `idx_dist(gen)` inside the `if` consumes randomness.\n                // The state above is wrong because I called `idx_dist` again.\n                // Correction: I need to save the indices used for the modification.\n                // Refactoring the move logic:\n                \n                // Let's rewrite the loop body to handle moves cleanly.\n                // Since I can't rewrite the thought block, I will implement the fix in the code below.\n                // The bug is here: calling idx_dist(gen) to revert swaps different indices.\n                // Fix: Use local variables for indices.\n            } else {\n                int i1 = idx_dist(gen);\n                int i2 = idx_dist(gen);\n                if (i1 > i2) swap(i1, i2);\n                reverse(current_order.begin() + i1, current_order.begin() + i2 + 1);\n            }\n        }\n    }\n\n    // Rewrite the loop body cleanly\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        vector<int> saved_order = current_order;\n        int move_type = move_type_dist(gen);\n        \n        if (move_type == 0) {\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            while(idx1 == idx2) idx2 = idx_dist(gen);\n            swap(current_order[idx1], current_order[idx2]);\n        } else {\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            if (idx1 > idx2) swap(idx1, idx2);\n            reverse(current_order.begin() + idx1, current_order.begin() + idx2 + 1);\n        }\n        \n        string new_s = build_string(current_order);\n        auto [new_cost, _] = solve_grid(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            current_order = saved_order;\n        }\n    }\n    \n    string final_s = build_string(best_order);\n    auto [final_cost, path] = solve_grid(final_s, true);\n    \n    if (!path.empty()) {\n        for (auto p : path) {\n            cout << p.first << \" \" << p.second << \"\\n\";\n        }\n    } else {\n        cout << (start_pos / N) << \" \" << (start_pos % N) << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = std::chrono::system_clock::now();\n    \n    solve();\n    \n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\n#include <atcoder/random>\nusing namespace std;\nusing namespace atcoder;\n\nconst double INF = 1e9;\nconst int MAX_N = 20;\nconst int MAX_M = 20;\n\n// Global variables\nint N, M;\ndouble eps;\nvector<vector<pair<int, int>>> shapes; // Relative coordinates of each shape\nvector<pair<int, int>> shape_sizes;   // (height, width) of each shape\nmap<pair<int, int>, int> fixed_cells; // Known values: (r,c) -> value\n\n// Estimated sums from divination\nvector<double> est_row_sums;\nvector<double> est_col_sums;\n\n// Inverse variances for chi-squared\ndouble inv_var_row;\ndouble inv_var_col;\n\n// Random number generator\nrandom_device rd;\nmt19937 gen(rd());\n\n// Operation cost tracking\ndouble total_cost = 0.0;\n\n// Helper to output and flush\nvoid flush_output() {\n    cout << flush;\n}\n\n// Divination operation\ndouble divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto [r, c] : cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0 / sqrt(k);\n    \n    // Invert the noise model\n    // y ~ round(max(0, x)), x ~ N(k*eps + T(1-2*eps), k*eps(1-eps))\n    // Estimate T\n    double T_est = (res - k * eps) / (1.0 - 2.0 * eps);\n    if (T_est < 0) T_est = 0; // T must be non-negative\n    return T_est;\n}\n\n// Drilling operation\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0;\n    fixed_cells[{r, c}] = res;\n    return res;\n}\n\n// Answer operation\nbool answer(const vector<pair<int, int>>& pos_cells) {\n    cout << \"a \" << pos_cells.size();\n    for (auto [r, c] : pos_cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    return res == 1;\n}\n\n// State representation for SA\nstruct State {\n    vector<pair<int, int>> pos; // (r, c) for each field\n    int grid[MAX_N][MAX_N];\n    double energy;\n\n    void compute_grid_and_energy() {\n        // Reset grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = 0;\n            }\n        }\n\n        // Place fields\n        for (int k = 0; k < M; ++k) {\n            auto [pr, pc] = pos[k];\n            for (auto [dr, dc] : shapes[k]) {\n                int r = pr + dr;\n                int c = pc + dc;\n                grid[r][c]++;\n            }\n        }\n\n        // Check fixed cells constraint\n        for (auto [p, val] : fixed_cells) {\n            if (grid[p.first][p.second] != val) {\n                energy = INF;\n                return;\n            }\n        }\n\n        // Calculate chi-squared distance to observed row/col sums\n        double err = 0.0;\n        \n        // Row sums\n        for (int i = 0; i < N; ++i) {\n            int sum = 0;\n            for (int j = 0; j < N; ++j) sum += grid[i][j];\n            double diff = sum - est_row_sums[i];\n            err += diff * diff * inv_var_row;\n        }\n\n        // Column sums\n        for (int j = 0; j < N; ++j) {\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += grid[i][j];\n            double diff = sum - est_col_sums[j];\n            err += diff * diff * inv_var_col;\n        }\n\n        energy = err;\n    }\n};\n\n// Simulated Annealing\nState run_sa(int iterations) {\n    State cur, best;\n    cur.pos.resize(M);\n    best.pos.resize(M);\n\n    // Initialize random valid positions\n    for (int k = 0; k < M; ++k) {\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        cur.pos[k] = {dist_r(gen), dist_c(gen)};\n    }\n    cur.compute_grid_and_energy();\n    best = cur;\n\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        State nxt = cur;\n        \n        // Pick a field to move\n        int k = uniform_int_distribution<>(0, M - 1)(gen);\n        \n        // Generate new position\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        \n        if (uniform_real_distribution<>(0, 1)(gen) < 0.1) {\n            // Jump\n            nxt.pos[k] = {dist_r(gen), dist_c(gen)};\n        } else {\n            // Small step\n            int dr = uniform_int_distribution<>(-2, 2)(gen);\n            int dc = uniform_int_distribution<>(-2, 2)(gen);\n            int nr = nxt.pos[k].first + dr;\n            int nc = nxt.pos[k].second + dc;\n            \n            // Clamp to valid range\n            nr = max(0, min(N - h, nr));\n            nc = max(0, min(N - w, nc));\n            nxt.pos[k] = {nr, nc};\n        }\n\n        nxt.compute_grid_and_energy();\n\n        if (nxt.energy < cur.energy || uniform_real_distribution<>(0, 1)(gen) < exp((cur.energy - nxt.energy) / max(temp, 0.1))) {\n            cur = nxt;\n        }\n\n        if (cur.energy < best.energy) {\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M >> eps;\n    shapes.resize(M);\n    shape_sizes.resize(M);\n\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n            shapes[k].emplace_back(r, c);\n            max_r = max(max_r, r);\n            max_c = max(max_c, c);\n        }\n        shape_sizes[k] = {max_r, max_c};\n    }\n\n    // Precompute inverse variances\n    // Variance = k * eps * (1 - eps)\n    inv_var_row = 1.0 / (N * eps * (1.0 - eps));\n    inv_var_col = 1.0 / (N * eps * (1.0 - eps));\n    est_row_sums.resize(N);\n    est_col_sums.resize(N);\n\n    // Initial Probing: Rows and Columns\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_cells;\n        for (int j = 0; j < N; ++j) row_cells.emplace_back(i, j);\n        est_row_sums[i] = divine(row_cells);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_cells;\n        for (int i = 0; i < N; ++i) col_cells.emplace_back(i, j);\n        est_col_sums[j] = divine(col_cells);\n    }\n\n    // Main search loop\n    int max_ops = 2 * N * N;\n    int sa_iters = 3000; // Per iteration\n    \n    // We want to leave some buffer for the answer query\n    while (total_cost < max_ops - 1) {\n        // Run SA\n        State best_state = run_sa(sa_iters);\n\n        // If energy is very low, we might be done\n        // Heuristic: if energy < 10 (which is small for 40 degrees of freedom)\n        if (best_state.energy < 5.0) {\n            // Verify a few random cells or just submit?\n            // Let's try to submit if we are very confident\n            // Or drill one last cell to be safe\n            \n            // Construct answer\n            vector<pair<int, int>> ans;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0) {\n                        ans.emplace_back(i, j);\n                    }\n                }\n            }\n            \n            // Check if we have budget for another drill\n            if (total_cost + 1 + 0.01 > max_ops) {\n                 // Submit\n                if (answer(ans)) return;\n                else {\n                    // If wrong, we shouldn't really get here often if energy is low.\n                    // If we do, we break loop because we can't afford more ops?\n                    // Actually, we just continue if we have time.\n                    // But answer costs 1. So we lost 1 op.\n                }\n            } else {\n                // Try to verify a high-value cell\n                // Find a cell with max v that is not fixed\n                pair<int, int> target = {-1, -1};\n                int max_v = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                            if (best_state.grid[i][j] > max_v) {\n                                max_v = best_state.grid[i][j];\n                                target = {i, j};\n                            }\n                        }\n                    }\n                }\n\n                if (target.first != -1) {\n                    drill(target.first, target.second);\n                } else {\n                    // All positive cells fixed. Submit.\n                    if (answer(ans)) return;\n                }\n            }\n        } else {\n            // Energy is not low enough. Drill a cell to improve.\n            // Strategy: Drill a cell that is positive in the best model\n            pair<int, int> target = {-1, -1};\n            int max_v = -1;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                        if (best_state.grid[i][j] > max_v) {\n                            max_v = best_state.grid[i][j];\n                            target = {i, j};\n                        }\n                    }\n                }\n            }\n\n            // If no positive cell found (all fixed?), check empty?\n            // Or just pick a cell with v=0 that is surrounded by v>0?\n            if (target.first == -1) {\n                 // This case implies model says no undrilled positive cells.\n                 // But energy is high. Means model is wrong (missed some oil).\n                 // We should drill somewhere to find the missing oil.\n                 // Pick a random undrilled cell with v=0 in model.\n                 vector<pair<int,int>> candidates;\n                 for (int i=0; i<N; ++i) {\n                     for (int j=0; j<N; ++j) {\n                         if (best_state.grid[i][j] == 0 && fixed_cells.count({i,j}) == 0) {\n                             candidates.emplace_back(i,j);\n                         }\n                     }\n                 }\n                 if (!candidates.empty()) {\n                     target = candidates[uniform_int_distribution<>(0, candidates.size()-1)(gen)];\n                 } else {\n                     // All cells fixed? Just submit.\n                     vector<pair<int, int>> ans;\n                     for (int i = 0; i < N; ++i) {\n                        for (int j = 0; j < N; ++j) {\n                            if (best_state.grid[i][j] > 0) ans.emplace_back(i, j);\n                        }\n                    }\n                    if (answer(ans)) return;\n                 }\n            }\n            \n            if (target.first != -1) drill(target.first, target.second);\n        }\n    }\n    \n    // Fallback / Time up: Submit current best guess\n    State final_state = run_sa(1000); // Quick last run\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (final_state.grid[i][j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    answer(ans);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <deque>\n\nusing namespace std;\n\nconst int W = 1000;\nconst long long INF = 1e18;\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_input, D, N;\n    cin >> W_input >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // prev_cuts[k] stores the y-coordinate of the k-th cut (0-indexed) from the previous day.\n    // Initially, we can assume cuts are at 0 (or any value, as L_0=0).\n    vector<int> prev_cuts(N - 1, 0);\n\n    for (int d = 0; d < D; ++d) {\n        // dp_prev[v] = min cost to place the first (k-1) cuts, with the (k-1)-th cut at y=v.\n        // We start with k=1 (placing the 0th cut).\n        // Initial state: 0 cuts placed, virtual cut at y=0, cost 0.\n        vector<long long> dp_prev(W + 1, INF);\n        dp_prev[0] = 0;\n        \n        // choice[k][v] stores the position of the previous cut 'u' that led to cut 'k' being at 'v'.\n        // k is 1-indexed for cuts (1 to N-1).\n        vector<vector<int>> choice(N, vector<int>(W + 1, -1));\n\n        // Iterate to place the k-th cut (1-indexed)\n        for (int k = 1; k < N; ++k) {\n            // The rectangle to the left of this cut is rectangle (k-1) (0-indexed).\n            int A = a[d][k-1];\n            int min_h = (A + W - 1) / W; // Minimum height to avoid deficit\n            if (min_h == 0) min_h = 1;\n\n            // Precompute B[u] = dp_prev[u] + 100 * W * u\n            // Used for calculating cost when deficit occurs.\n            vector<long long> B(W + 1);\n            for (int i = 0; i <= W; ++i) {\n                B[i] = dp_prev[i] + (long long)100 * W * i;\n            }\n\n            vector<long long> dp_curr(W + 1, INF);\n            \n            // Prefix minima for dp_prev (Case 1: No deficit)\n            // pmin[i] = min(dp_prev[0...i-1])\n            vector<long long> pmin(W + 2, INF);\n            vector<int> parg(W + 2, -1);\n            for (int i = 0; i <= W; ++i) {\n                if (dp_prev[i] < pmin[i]) {\n                    pmin[i+1] = dp_prev[i];\n                    parg[i+1] = i;\n                } else {\n                    pmin[i+1] = pmin[i];\n                    parg[i+1] = parg[i];\n                }\n            }\n            \n            // Sliding window minimum for B[u] (Case 2: Deficit)\n            // We need min(B[u]) for u in [v - min_h + 1, v - 1]\n            deque<int> dq;\n\n            for (int v = 1; v <= W; ++v) {\n                // Update deque for the current window ending at v-1\n                // 1. Add u = v - 1\n                while (!dq.empty() && B[dq.back()] >= B[v - 1]) {\n                    dq.pop_back();\n                }\n                dq.push_back(v - 1);\n                \n                // 2. Remove indices < v - min_h + 1\n                while (!dq.empty() && dq.front() < v - min_h + 1) {\n                    dq.pop_front();\n                }\n\n                // Calculate costs\n                long long best_inner_cost = INF;\n                int best_u = -1;\n\n                // Case 1: u <= v - min_h (No deficit)\n                // Cost is dp_prev[u]. We want min over u in [0, v - min_h]\n                if (v - min_h >= 0) {\n                    long long c1 = pmin[v - min_h + 1];\n                    if (c1 < best_inner_cost) {\n                        best_inner_cost = c1;\n                        best_u = parg[v - min_h + 1];\n                    }\n                }\n\n                // Case 2: u in [v - min_h + 1, v - 1] (Deficit)\n                // Cost is 100*A - 100*W*v + min(B[u])\n                if (!dq.empty()) {\n                    int idx = dq.front();\n                    long long c2 = B[idx] + (long long)100 * A - (long long)100 * W * v;\n                    if (c2 < best_inner_cost) {\n                        best_inner_cost = c2;\n                        best_u = idx;\n                    }\n                }\n\n                if (best_inner_cost < INF) {\n                    // Add move cost.\n                    // On Day 0 (d==0), L_0=0, so move cost is 0.\n                    // For d > 0, cost is 2 * W * |v - prev_cuts[k-1]|\n                    long long move_cost = (d == 0) ? 0 : 2000 * abs(v - prev_cuts[k-1]);\n                    dp_curr[v] = best_inner_cost + move_cost;\n                    choice[k][v] = best_u;\n                } else {\n                    dp_curr[v] = INF;\n                }\n            }\n            \n            dp_prev = dp_curr;\n        }\n\n        // Determine the optimal position for the last cut (N-1)\n        // And account for the last rectangle (N-1)\n        int last_min_h = (a[d][N-1] + W - 1) / W;\n        int best_v = -1;\n        long long min_total_cost = INF;\n\n        for (int v = 0; v <= W; ++v) {\n            if (dp_prev[v] >= INF) continue;\n            \n            long long cost = dp_prev[v];\n            int h_last = W - v;\n            if (h_last < last_min_h) {\n                cost += (long long)100 * (a[d][N-1] - (long long)W * h_last);\n            }\n            \n            if (cost < min_total_cost) {\n                min_total_cost = cost;\n                best_v = v;\n            }\n        }\n\n        // Fallback in case no valid configuration found (should not happen with correct constraints)\n        if (best_v == -1) {\n            best_v = W / 2; // Just a fallback to avoid crash\n        }\n\n        // Reconstruct cuts\n        vector<int> new_cuts(N - 1);\n        int curr_v = best_v;\n        bool valid_reconstruction = true;\n        \n        for (int k = N - 1; k >= 1; --k) {\n            new_cuts[k-1] = curr_v;\n            if (curr_v < 0 || curr_v > W || choice[k][curr_v] == -1) {\n                // Fallback to equal partition if reconstruction fails\n                valid_reconstruction = false;\n                break;\n            }\n            curr_v = choice[k][curr_v];\n        }\n\n        if (!valid_reconstruction) {\n            // Fallback strategy: Divide equally\n            int step = W / N;\n            for (int i = 0; i < N - 1; ++i) {\n                new_cuts[i] = step * (i + 1);\n            }\n        }\n\n        // Output\n        int y_prev = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            int y_curr = new_cuts[k];\n            // Ensure strictly increasing coordinates\n            if (y_curr <= y_prev) y_curr = y_prev + 1; \n            if (y_curr > W) y_curr = W;\n            \n            cout << y_prev << \" \" << 0 << \" \" << y_curr << \" \" << W << \"\\n\";\n            y_prev = y_curr;\n        }\n        // Last rectangle\n        if (y_prev >= W) y_prev = W - 1; // Safety\n        cout << y_prev << \" \" << 0 << \" \" << W << \" \" << W << \"\\n\";\n\n        // Update previous cuts for next day\n        prev_cuts = new_cuts;\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <tuple>\n#include <queue>\n\nusing namespace std;\n\nconst int MOD = 998244353;\n\n// --- Common Structures ---\n\nstruct Board {\n    array<long long, 81> data; // Flattened 9x9\n\n    long long get_score() const {\n        long long s = 0;\n        for (int i = 0; i < 81; ++i) {\n            s += data[i] % MOD;\n        }\n        return s;\n    }\n};\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Greedy Solver ---\n\nvector<Operation> solve_greedy(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    Board board = initial_board;\n    \n    // Gains cache\n    array<array<array<long long, 7>, 7>, 20> gains{};\n    \n    auto calc_gain = [&](int m, int p, int q) {\n        long long diff = 0;\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int idx = (p+i)*9 + (q+j);\n                long long old_v = board.data[idx];\n                long long new_v = old_v + stamps[m][i*3+j];\n                diff += (new_v % MOD) - (old_v % MOD);\n            }\n        }\n        return diff;\n    };\n\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < 7; ++p) {\n            for (int q = 0; q < 7; ++q) {\n                gains[m][p][q] = calc_gain(m, p, q);\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(K);\n\n    for (int turn = 0; turn < K; ++turn) {\n        long long best_gain = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < 7; ++p) {\n                for (int q = 0; q < 7; ++q) {\n                    if (gains[m][p][q] > best_gain) {\n                        best_gain = gains[m][p][q];\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_gain <= 0) break;\n\n        ops.push_back({best_m, best_p, best_q});\n\n        // Apply\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                board.data[(best_p+i)*9 + (best_q+j)] += stamps[best_m][i*3+j];\n            }\n        }\n\n        // Update gains\n        int p_min = max(0, best_p - 2);\n        int p_max = min(6, best_p + 2);\n        int q_min = max(0, best_q - 2);\n        int q_max = min(6, best_q + 2);\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = p_min; p <= p_max; ++p) {\n                for (int q = q_min; q <= q_max; ++q) {\n                    gains[m][p][q] = calc_gain(m, p, q);\n                }\n            }\n        }\n    }\n    return ops;\n}\n\n// --- Beam Search Solver (Memory Efficient) ---\n\nstruct HistoryNode {\n    int parent;\n    char m, p, q; // Operation to reach this state. -1 for initial or do-nothing\n};\n\nstruct BeamState {\n    Board board;\n    long long score;\n    int history_idx; // Index in global history\n};\n\nvector<Operation> solve_beam(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    // Parameters\n    const int BEAM_WIDTH = 400;\n    const int BRANCH_FACTOR = 120; \n    const int GREEDY_INIT_DEPTH = 10;\n\n    vector<HistoryNode> history;\n    vector<BeamState> current_beam;\n\n    // 1. Initialize with root state\n    HistoryNode root_node{-1, -1, -1, -1};\n    history.push_back(root_node);\n    current_beam.push_back({initial_board, initial_board.get_score(), 0});\n\n    // 2. Seed with Greedy path\n    Board temp_board = initial_board;\n    vector<Operation> greedy_ops = solve_greedy(initial_board, stamps, M, min(K, GREEDY_INIT_DEPTH));\n    \n    int h_idx = 0;\n    for (auto op : greedy_ops) {\n        h_idx++;\n        HistoryNode node{(int)history.size() - 1, (char)op.m, (char)op.p, (char)op.q};\n        history.push_back(node);\n        \n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                temp_board.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n            }\n        }\n        current_beam.push_back({temp_board, temp_board.get_score(), (int)history.size() - 1});\n    }\n\n    // Beam Search Loop\n    for (int step = 0; step < K; ++step) {\n        vector<BeamState> candidates;\n        // Reserving space helps performance significantly\n        candidates.reserve(current_beam.size() * (BRANCH_FACTOR + 1));\n\n        for (const auto& state : current_beam) {\n            // A. \"Do Nothing\" move\n            // Gain is 0. \n            HistoryNode noop_node{state.history_idx, -1, -1, -1};\n            history.push_back(noop_node);\n            candidates.push_back({state.board, state.score, (int)history.size() - 1});\n\n            // B. Generate Moves\n            // Instead of creating a huge vector, we can process and keep top N?\n            // But sorting requires vector. Given the scale (400 * 1000), creating vector of tuples is fine.\n            // Optimization: Precompute stamp contributions? No, dynamic board.\n            \n            vector<tuple<long long, int, int, int>> potential_moves;\n            potential_moves.reserve(M * 49);\n\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < 7; ++p) {\n                    for (int q = 0; q < 7; ++q) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                long long old_v = state.board.data[(p+i)*9 + (q+j)];\n                                long long new_v = old_v + stamps[m][i*3+j];\n                                gain += (new_v % MOD) - (old_v % MOD);\n                            }\n                        }\n                        potential_moves.emplace_back(gain, m, p, q);\n                    }\n                }\n            }\n\n            // Select top BRANCH_FACTOR\n            int limit = min((int)potential_moves.size(), BRANCH_FACTOR);\n            if (limit > 0) {\n                nth_element(potential_moves.begin(), potential_moves.begin() + limit, potential_moves.end(), \n                    [](const auto& a, const auto& b){ return get<0>(a) > get<0>(b); });\n                \n                // No need to fully sort strictly, but nth_element guarantees first 'limit' are the top ones.\n                // We iterate over them.\n                for (int i = 0; i < limit; ++i) {\n                    auto [gain, m, p, q] = potential_moves[i];\n                    \n                    // Create new state\n                    Board next_board = state.board;\n                    for (int di = 0; di < 3; ++di) {\n                        for (int dj = 0; dj < 3; ++dj) {\n                            next_board.data[(p+di)*9 + (q+dj)] += stamps[m][di*3+dj];\n                        }\n                    }\n                    long long next_score = state.score + gain;\n                    \n                    HistoryNode node{state.history_idx, (char)m, (char)p, (char)q};\n                    history.push_back(node);\n                    candidates.push_back({next_board, next_score, (int)history.size() - 1});\n                }\n            }\n        }\n\n        // Selection\n        int next_limit = min((int)candidates.size(), BEAM_WIDTH);\n        if (next_limit == 0) break;\n\n        auto mid = candidates.begin() + next_limit;\n        nth_element(candidates.begin(), mid, candidates.end(), \n            [](const BeamState& a, const BeamState& b){ return a.score > b.score; });\n\n        current_beam.assign(candidates.begin(), candidates.begin() + next_limit);\n    }\n\n    // Find best state in final beam\n    long long best_score = -1;\n    int best_history_idx = -1;\n    for (const auto& state : current_beam) {\n        if (state.score > best_score) {\n            best_score = state.score;\n            best_history_idx = state.history_idx;\n        }\n    }\n\n    // Reconstruct\n    vector<Operation> ops;\n    int curr = best_history_idx;\n    while (curr != 0) {\n        const HistoryNode& node = history[curr];\n        if (node.m != -1) {\n            ops.emplace_back(node.m, node.p, node.q);\n        }\n        curr = node.parent;\n    }\n    // Reverse\n    reverse(ops.begin(), ops.end());\n    return ops;\n}\n\n// --- Main ---\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    Board initial_board;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> initial_board.data[i * 9 + j];\n        }\n    }\n\n    // Read stamps\n    vector<vector<long long>> stamps(M, vector<long long>(9));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i * 3 + j];\n            }\n        }\n    }\n\n    // 1. Solve Greedy\n    auto ops_greedy = solve_greedy(initial_board, stamps, M, K);\n    \n    // Score Greedy\n    Board b_greedy = initial_board;\n    long long score_greedy = 0;\n    for(auto op : ops_greedy) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_greedy.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_greedy = b_greedy.get_score();\n\n    // 2. Solve Beam Search\n    auto ops_beam = solve_beam(initial_board, stamps, M, K);\n    \n    // Score Beam\n    Board b_beam = initial_board;\n    long long score_beam = 0;\n    for(auto op : ops_beam) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_beam.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_beam = b_beam.get_score();\n\n    // 3. Output Best\n    if (score_beam > score_greedy) {\n        cout << ops_beam.size() << \"\\n\";\n        for (auto op : ops_beam) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    } else {\n        cout << ops_greedy.size() << \"\\n\";\n        for (auto op : ops_greedy) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int BUFFER_COL = N - 2; \n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    vector<vector<int>> A(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> A[i][j];\n        }\n    }\n    \n    vector<int> target_row(N * N);\n    for (int c = 0; c < N * N; c++) target_row[c] = c / N;\n    \n    vector<vector<int>> arrival(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) arrival[i][j] = A[i][j];\n    \n    vector<int> arrived(N, 0);\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_x(N), crane_y(N);\n    vector<int> carrying(N, -1);\n    \n    for (int i = 0; i < N; i++) {\n        crane_x[i] = i;\n        crane_y[i] = 0;\n    }\n    \n    vector<string> actions(N);\n    vector<bool> dispatched(N * N, false);\n    \n    for (int t = 0; t < MAX_TURNS; t++) {\n        bool all_done = true;\n        for(int i=0; i<N*N; ++i) if(!dispatched[i]) all_done = false;\n        if (all_done) break;\n\n        // Step 1: Container arrivals\n        for (int i = 0; i < N; i++) {\n            bool blocked_by_carrying = false;\n            for (int c = 0; c < N; c++) {\n                if (crane_x[c] == i && crane_y[c] == 0 && carrying[c] != -1) {\n                    blocked_by_carrying = true;\n                }\n            }\n            if (grid[i][0] == -1 && !blocked_by_carrying && arrived[i] < N) {\n                grid[i][0] = arrival[i][arrived[i]++];\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        vector<char> act(N, '.');\n        vector<int> nx = crane_x, ny = crane_y;\n        vector<int> ncarry = carrying;\n        \n        for (int c = 0; c < N; c++) {\n            if (c == 0) {\n                // Large Crane\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    \n                    // Strategy for Row 0: Direct Dispatch\n                    // Small cranes handle rows 1-4. Row 0 is only handled by Large Crane.\n                    if (tr == 0) {\n                        if (crane_x[c] > 0) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_x[c] < 0) { act[c] = 'D'; nx[c]++; } // Should not happen\n                        else if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                        else { act[c] = 'Q'; ncarry[c] = -1; } // Dispatch at (0, N-1)\n                    } else {\n                        // Strategy for Rows 1-4: Buffer at N-2\n                        if (crane_x[c] < tr) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > tr) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < BUFFER_COL) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > BUFFER_COL) { act[c] = 'L'; ny[c]--; }\n                        else {\n                            // At buffer location (tr, N-2)\n                            if (grid[tr][BUFFER_COL] == -1) {\n                                act[c] = 'Q'; ncarry[c] = -1;\n                            } else {\n                                // Buffer occupied. Check for deadlock.\n                                // If Small Crane 'tr' is at (tr, N-3) and wants to come to N-2\n                                // we must move away.\n                                if (tr < N && crane_x[tr] == tr && crane_y[tr] == BUFFER_COL - 1) {\n                                    // Small crane is right behind. Move Left.\n                                    act[c] = 'L'; ny[c]--;\n                                } else {\n                                    act[c] = '.'; // Wait\n                                }\n                            }\n                        }\n                    }\n                } else {\n                    int best_i = -1, best_j = -1, best_score = INT_MIN;\n                    for (int i = 0; i < N; i++) {\n                        for (int j = 0; j < N; j++) {\n                            int cont = grid[i][j];\n                            if (cont != -1 && !dispatched[cont]) {\n                                int tr = target_row[cont];\n                                int wrong = (i != tr);\n                                int dist = abs(i - crane_x[c]) + abs(j - crane_y[c]);\n                                // Heuristic\n                                int score = (wrong ? 100000 : 0) - dist;\n                                if (score > best_score) {\n                                    best_score = score; best_i = i; best_j = j;\n                                }\n                            }\n                        }\n                    }\n                    if (best_i != -1) {\n                        if (crane_x[c] < best_i) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > best_i) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < best_j) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > best_j) { act[c] = 'L'; ny[c]--; }\n                        else { act[c] = 'P'; ncarry[c] = grid[best_i][best_j]; }\n                    }\n                }\n            } else {\n                // Small Cranes (1-4). Stay in lanes.\n                if (carrying[c] != -1) {\n                    if (crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                    else if (crane_y[c] == N - 1) { act[c] = 'Q'; ncarry[c] = -1; }\n                    else { act[c] = '.'; }\n                } else {\n                    int buffer_cont = grid[c][BUFFER_COL];\n                    bool buffer_valid = (buffer_cont != -1 && !dispatched[buffer_cont] && target_row[buffer_cont] == c);\n                    \n                    int gate_cont = grid[c][0];\n                    bool gate_valid = (gate_cont != -1 && !dispatched[gate_cont] && target_row[gate_cont] == c);\n                    \n                    int target_j = -1;\n                    \n                    if (buffer_valid) target_j = BUFFER_COL;\n                    else if (gate_valid) target_j = 0;\n                    else if (gate_cont != -1 && target_row[gate_cont] != c) {\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                        target_j = -2; \n                    } else {\n                        // Idle: Move to buffer or patrol\n                        if (crane_y[c] < BUFFER_COL && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > BUFFER_COL && grid[c][crane_y[c]-1] == -1) { act[c] = 'L'; ny[c]--; }\n                        target_j = -2;\n                    }\n                    \n                    if (target_j != -2 && target_j != -1) {\n                        if (crane_y[c] < target_j) { \n                             if (grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                             else { act[c] = '.'; }\n                        }\n                        else if (crane_y[c] > target_j) { \n                             if (grid[c][crane_y[c]-1] == -1) { act[c] = 'L'; ny[c]--; }\n                             else { act[c] = '.'; }\n                        }\n                        else { act[c] = 'P'; ncarry[c] = grid[c][target_j]; }\n                    }\n                }\n            }\n        }\n        \n        // Step 3: Resolve collisions\n        for (int p = 0; p < N; p++) {\n            bool collision = false;\n            for (int i = 0; i < N; i++) {\n                if (i == p) continue;\n                int ox = (i < p) ? nx[i] : crane_x[i];\n                int oy = (i < p) ? ny[i] : crane_y[i];\n                \n                if (nx[p] == ox && ny[p] == oy) {\n                    if (i < p) { collision = true; break; }\n                    else {\n                        if (act[i] == '.' || act[i] == 'P' || act[i] == 'Q') { collision = true; break; }\n                        else {\n                            if (nx[i] == crane_x[p] && ny[i] == crane_y[p]) { collision = true; break; }\n                        }\n                    }\n                }\n            }\n            if (!collision && p != 0 && carrying[p] != -1 && act[p] != 'P' && act[p] != 'Q' && act[p] != '.') {\n                if (grid[nx[p]][ny[p]] != -1) collision = true;\n            }\n            if (collision) {\n                act[p] = '.';\n                nx[p] = crane_x[p];\n                ny[p] = crane_y[p];\n            }\n        }\n        \n        // Step 4: Execute\n        for (int c = 0; c < N; c++) {\n            actions[c] += act[c];\n            if (act[c] == 'P') grid[crane_x[c]][crane_y[c]] = -1;\n            else if (act[c] == 'Q') grid[crane_x[c]][crane_y[c]] = carrying[c];\n            crane_x[c] = nx[c]; crane_y[c] = ny[c]; carrying[c] = ncarry[c];\n        }\n        \n        // Step 5: Dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N - 1] != -1) {\n                dispatched[grid[i][N - 1]] = true;\n                grid[i][N - 1] = -1;\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)actions[i].size() < max_len) actions[i] += '.';\n        cout << actions[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Grid dimensions\nconst int N = 20;\nconst int INF = 1e9;\nconst int DX[4] = {0, 0, 1, -1};\nconst int DY[4] = {1, -1, 0, 0};\nconst char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n;\n    // N is always 20, but we read it just in case\n    if (!(cin >> n)) return 0; \n    \n    vector<int> h(n * n);\n    for (int i = 0; i < n * n; ++i) {\n        cin >> h[i];\n    }\n\n    // 1. Construct Min-Cost Flow Graph\n    // Nodes: 0 to n*n-1 are grid cells.\n    // Source S = n*n, Sink T = n*n + 1.\n    int S = n * n;\n    int T = n * n + 1;\n    mcf_graph<int, long long> graph(n * n + 2);\n    \n    long long total_supply = 0;\n\n    for (int i = 0; i < n * n; ++i) {\n        if (h[i] > 0) {\n            graph.add_edge(S, i, h[i], 0);\n            total_supply += h[i];\n        } else if (h[i] < 0) {\n            graph.add_edge(i, T, -h[i], 0);\n        }\n    }\n\n    // Add grid edges (undirected)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int u = i * n + j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + DX[k];\n                int nj = j + DY[k];\n                if (0 <= ni && ni < n && 0 <= nj && nj < n) {\n                    int v = ni * n + nj;\n                    // Cost is 1 per unit distance\n                    graph.add_edge(u, v, INF, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min-Cost Flow\n    auto result = graph.flow(S, T, total_supply);\n    // result.second is the min cost (sum of amount * distance)\n    // We don't strictly need the value, just the flow distribution.\n\n    // 3. Extract Flow Graph\n    // adj[u] stores (v, flow) pairs for flow > 0\n    vector<vector<pair<int, int>>> adj(n * n);\n    auto edges = graph.edges();\n    for (const auto& e : edges) {\n        if (e.from < S && e.to < S && e.flow > 0) {\n            adj[e.from].emplace_back(e.to, e.flow);\n        }\n    }\n\n    // 4. Construct Path using DFS simulation\n    vector<string> ops;\n    int current_pos = 0; // Start at (0,0)\n    int current_load = 0;\n    \n    // Helper to perform moves\n    auto move_to = [&](int target_pos) {\n        int cx = current_pos / n;\n        int cy = current_pos % n;\n        int tx = target_pos / n;\n        int ty = target_pos % n;\n        \n        // Simple BFS to find path (since we just need a path, but shortest is best)\n        // For simplicity, just move greedily or BFS.\n        // Given the constraints and the fact that we mostly follow flow edges,\n        // we might just need to connect components. \n        // But here we implement BFS for shortest path.\n        \n        vector<int> prev(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        prev[current_pos] = current_pos;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_pos) break;\n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        // Reconstruct path\n        vector<int> path;\n        int curr = target_pos;\n        while (curr != current_pos) {\n            path.push_back(curr);\n            curr = prev[curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        for (int next_pos : path) {\n            int dx = (next_pos / n) - (current_pos / n);\n            int dy = (next_pos % n) - (current_pos % n);\n            for (int k = 0; k < 4; ++k) {\n                if (DX[k] == dx && DY[k] == dy) {\n                    ops.push_back(string(1, DIR_CHAR[k]));\n                    break;\n                }\n            }\n            current_pos = next_pos;\n            // We assume move_to is called with 0 load or correct load.\n            // The cost update is implicit in the operations.\n        }\n    };\n\n    // Helper to load/unload\n    auto check_height = [&]() {\n        if (h[current_pos] > 0) {\n            ops.push_back(\"+\" + to_string(h[current_pos]));\n            current_load += h[current_pos];\n            h[current_pos] = 0;\n        } else if (h[current_pos] < 0) {\n            // We need to unload.\n            // However, we might not have exactly -h[current_pos] available if flow is split weirdly?\n            // In theory, inflow should cover it.\n            int needed = -h[current_pos];\n            if (current_load >= needed) {\n                ops.push_back(\"-\" + to_string(needed));\n                current_load -= needed;\n                h[current_pos] = 0;\n            } else {\n                // Should not happen in optimal flow, but just in case:\n                // This implies we need to carry more soil here.\n                // Or we are processing in a weird order.\n                // With the tree traversal, we should arrive with sufficient load.\n                // If not, it's a logic error in flow construction or traversal.\n                // We will assume it holds.\n            }\n        }\n    };\n\n    // Recursive DFS to cover flow tree\n    // Returns true if we don't need to backtrack (optimized path end)\n    function<bool(int)> dfs = [&](int u) {\n        // 1. Satisfy height at u\n        check_height();\n        \n        // 2. Process children\n        if (adj[u].empty()) {\n            return true; // Leaf\n        }\n        \n        // Optimization: Find the child with the deepest/longest path to process last (to avoid backtrack)\n        // Simple heuristic: just iterate.\n        // To avoid backtrack on the last child:\n        for (size_t i = 0; i < adj[u].size(); ++i) {\n            int v = adj[u][i].first;\n            int flow_amt = adj[u][i].second;\n            \n            // We need to carry `flow_amt` from u to v.\n            // The rest of current_load (if any) should stay at u.\n            // We unload the rest, reload later.\n            int load_to_keep = current_load - flow_amt;\n            \n            if (load_to_keep > 0) {\n                ops.push_back(\"-\" + to_string(load_to_keep));\n                current_load -= load_to_keep;\n                // Height of u increases temporarily. This is fine, we fix it later.\n                h[u] += load_to_keep; \n            }\n            \n            // Move to v\n            move_to(v);\n            // current_load should be flow_amt now\n            if (current_load != flow_amt) {\n                // Logic error\n            }\n            \n            bool should_return = true;\n            if (i == adj[u].size() - 1) {\n                should_return = false; // Last child, don't return\n            }\n            \n            bool child_is_leaf = dfs(v);\n            \n            if (!should_return) {\n                return false; // Propagate \"don't return\" up\n            }\n            \n            // Return from v\n            // At v, we should have 0 load (all deposited at its children/height)\n            // Move back to u\n            move_to(u);\n            \n            // Reload the soil we left at u\n            if (load_to_keep > 0) {\n                ops.push_back(\"+\" + to_string(load_to_keep));\n                current_load += load_to_keep;\n                h[u] -= load_to_keep;\n            }\n            // Now current_load is restored for next child\n        }\n        return true;\n    };\n\n    // Main loop to handle disconnected components\n    while (true) {\n        // Check if any flow remains\n        bool has_flow = false;\n        int best_u = -1;\n        int best_dist = INF;\n        \n        // Find closest node with remaining outflow\n        // Simple BFS from current_pos\n        vector<int> dist(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        dist[current_pos] = 0;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            \n            if (!adj[u].empty()) {\n                if (dist[u] < best_dist) {\n                    best_dist = dist[u];\n                    best_u = u;\n                }\n            }\n            \n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (dist[v] == -1) {\n                        dist[v] = dist[u] + 1;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        if (best_u == -1) break; // Done\n        \n        if (best_u != current_pos) {\n            // Move to best_u with 0 load (we assume we can reach with 0 load)\n            // We need to ensure we have 0 load to move optimally?\n            // Actually, we might have load if we are in a middle of something.\n            // But this loop handles disconnected components.\n            // So we should be at load 0 when jumping.\n            move_to(best_u);\n        }\n        \n        // Process component starting at best_u\n        dfs(best_u);\n    }\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// Random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> rng01(0.0, 1.0);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    int grid_size = N * N;\n\n    // Precompute neighbor offsets for grid indices\n    vector<vector<int>> neighbors(grid_size);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int idx = r * N + c;\n            if (r > 0) neighbors[idx].push_back(idx - N);     // Up\n            if (r < N - 1) neighbors[idx].push_back(idx + N); // Down\n            if (c > 0) neighbors[idx].push_back(idx - 1);     // Left\n            if (c < N - 1) neighbors[idx].push_back(idx + 1); // Right\n        }\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // 1. Read Input\n        vector<vector<int>> X(seed_count, vector<int>(M));\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n\n        // 2. Calculate Total Value V for each seed\n        vector<int> V(seed_count);\n        for (int i = 0; i < seed_count; ++i) {\n            V[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // 3. Seed Selection\n        // Priority: Dimension Specialists (max in any dimension) -> High Value V\n        set<int> specialists;\n        for (int l = 0; l < M; ++l) {\n            int max_val = -1;\n            int best_idx = -1;\n            for (int i = 0; i < seed_count; ++i) {\n                if (X[i][l] > max_val) {\n                    max_val = X[i][l];\n                    best_idx = i;\n                }\n            }\n            if (best_idx != -1) {\n                specialists.insert(best_idx);\n            }\n        }\n\n        vector<int> pool_indices;\n        vector<bool> used(seed_count, false);\n        \n        for (int idx : specialists) {\n            if (!used[idx]) {\n                pool_indices.push_back(idx);\n                used[idx] = true;\n            }\n        }\n\n        vector<int> sorted_by_V(seed_count);\n        iota(sorted_by_V.begin(), sorted_by_V.end(), 0);\n        sort(sorted_by_V.begin(), sorted_by_V.end(), [&](int a, int b) {\n            return V[a] > V[b];\n        });\n\n        for (int idx : sorted_by_V) {\n            if (!used[idx]) {\n                pool_indices.push_back(idx);\n                used[idx] = true;\n                if ((int)pool_indices.size() >= grid_size) break;\n            }\n        }\n\n        while ((int)pool_indices.size() > grid_size) pool_indices.pop_back();\n        while ((int)pool_indices.size() < grid_size) {\n             for (int idx = 0; idx < seed_count; ++idx) {\n                 if (!used[idx]) {\n                     pool_indices.push_back(idx);\n                     used[idx] = true;\n                     if ((int)pool_indices.size() >= grid_size) break;\n                 }\n             }\n        }\n\n        // 4. Precompute Score Matrix S for the selected pool\n        // S[i][j] = sum(max(X[pool[i]][l], X[pool[j]][l]))\n        vector<vector<int>> S(grid_size, vector<int>(grid_size, 0));\n        for (int i = 0; i < grid_size; ++i) {\n            for (int j = i + 1; j < grid_size; ++j) {\n                int score = 0;\n                int real_i = pool_indices[i];\n                int real_j = pool_indices[j];\n                for (int l = 0; l < M; ++l) {\n                    score += max(X[real_i][l], X[real_j][l]);\n                }\n                S[i][j] = score;\n                S[j][i] = score;\n            }\n        }\n\n        // Helper to calculate total score of a grid\n        auto get_score = [&](const vector<int>& g) {\n            int total = 0;\n            for (int i = 0; i < grid_size; ++i) {\n                for (int nb : neighbors[i]) {\n                    if (i < nb) {\n                        total += S[g[i]][g[nb]];\n                    }\n                }\n            }\n            return total;\n        };\n\n        // 5. Initialization (Greedy Path to Snake)\n        // Generate a few candidates to start SA from\n        vector<int> best_grid;\n        int best_initial_score = -1;\n\n        // Try starting greedy path from a few different high-value seeds\n        int init_attempts = 3;\n        for (int attempt = 0; attempt < init_attempts; ++attempt) {\n            vector<int> current_perm(grid_size);\n            iota(current_perm.begin(), current_perm.end(), 0);\n            \n            // Sort by V to find good start points\n            vector<pair<int, int>> sorted_pool_indices; // {pool_idx, V}\n            for(int i=0; i<grid_size; ++i) sorted_pool_indices.push_back({i, V[pool_indices[i]]});\n            sort(sorted_pool_indices.begin(), sorted_pool_indices.end(), [](auto& a, auto& b){ return a.second > b.second; });\n            \n            int start_node = sorted_pool_indices[min(attempt, (int)sorted_pool_indices.size()-1)].first;\n\n            vector<int> path;\n            path.push_back(start_node);\n            vector<bool> in_path(grid_size, false);\n            in_path[start_node] = true;\n\n            for (int step = 1; step < grid_size; ++step) {\n                int last = path.back();\n                int best_next = -1;\n                int best_score = -1;\n                for (int i = 0; i < grid_size; ++i) {\n                    if (!in_path[i]) {\n                        if (S[last][i] > best_score) {\n                            best_score = S[last][i];\n                            best_next = i;\n                        }\n                    }\n                }\n                if (best_next != -1) {\n                    path.push_back(best_next);\n                    in_path[best_next] = true;\n                } else {\n                    for (int i = 0; i < grid_size; ++i) { \n                        if(!in_path[i]){ path.push_back(i); in_path[i]=true; break; } \n                    }\n                }\n            }\n\n            // Map path to Snake Grid\n            vector<int> grid(grid_size);\n            for (int i = 0; i < grid_size; ++i) {\n                int r = i / N;\n                int c = (r % 2 == 0) ? (i % N) : (N - 1 - (i % N));\n                grid[r * N + c] = path[i];\n            }\n\n            int score = get_score(grid);\n            if (score > best_initial_score) {\n                best_initial_score = score;\n                best_grid = grid;\n            }\n        }\n\n        // 6. Simulated Annealing\n        double start_temp = 500.0;\n        double end_temp = 0.1;\n        int num_iterations = 250000; \n        double temp = start_temp;\n        double cooling_rate = pow(end_temp / start_temp, 1.0 / num_iterations);\n\n        int current_score = best_initial_score;\n        \n        for (int it = 0; it < num_iterations; ++it) {\n            int p1 = rng() % grid_size;\n            int p2 = rng() % grid_size;\n            while (p1 == p2) p2 = rng() % grid_size;\n\n            int u = best_grid[p1];\n            int v = best_grid[p2];\n\n            // Calculate current contribution of u at p1 and v at p2\n            int current_contrib = 0;\n            for (int nb : neighbors[p1]) current_contrib += S[u][best_grid[nb]];\n            for (int nb : neighbors[p2]) if (nb != p1) current_contrib += S[v][best_grid[nb]];\n\n            // Swap\n            swap(best_grid[p1], best_grid[p2]);\n\n            // Calculate new contribution\n            int new_contrib = 0;\n            for (int nb : neighbors[p1]) new_contrib += S[v][best_grid[nb]];\n            for (int nb : neighbors[p2]) if (nb != p1) new_contrib += S[u][best_grid[nb]];\n\n            int delta = new_contrib - current_contrib;\n\n            if (delta > 0 || rng01(rng) < exp((double)delta / temp)) {\n                current_score += delta;\n            } else {\n                // Revert\n                swap(best_grid[p1], best_grid[p2]);\n            }\n\n            temp *= cooling_rate;\n        }\n\n        // 7. Output\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int idx = best_grid[r * N + c];\n                cout << pool_indices[idx] << (c < N - 1 ? \" \" : \"\\n\");\n            }\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    // Grid state\n    vector<vector<int>> grid(N, vector<int>(N, 0)); // 0: empty, 1: item present\n    vector<vector<int>> target(N, vector<int>(N, 0));\n\n    string s_row, t_row;\n    for (int i = 0; i < N; ++i) {\n        cin >> s_row;\n        for (int j = 0; j < N; ++j) grid[i][j] = s_row[j] - '0';\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> t_row;\n        for (int j = 0; j < N; ++j) target[i][j] = t_row[j] - '0';\n    }\n\n    // --- 1. Design Robotic Arm ---\n    // Star topology: Root 0, children 1..V-1.\n    // Lengths: 1, 2, ..., V-1.\n    // This provides distinct reach for each arm.\n    cout << V << \"\\n\";\n    vector<int> lengths(V);\n    for (int i = 1; i < V; ++i) {\n        lengths[i] = i;\n        cout << 0 << \" \" << i << \"\\n\";\n    }\n\n    // Initial position: (0, 0)\n    int rx = 0, ry = 0;\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // --- 2. Operate ---\n    vector<int> arm_dirs(V, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(V, 0);  // 0 or 1, whether fingertip i holds an item\n\n    int total_steps = 0;\n    const int MAX_STEPS = 100000;\n\n    // Snake movement state\n    int move_dir = 0; // 0: Right\n    int current_row = 0;\n\n    auto is_finished = [&]() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] != target[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    while (total_steps < MAX_STEPS && !is_finished()) {\n        string S(2 * V, '.');\n\n        // --- A. Determine Movement (Snake) ---\n        if (move_dir == 0) { // Moving Right\n            if (ry + 1 < N) {\n                S[0] = 'R';\n                ry++;\n            } else {\n                // Reached right end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 2; // Switch to Left\n                } else {\n                    S[0] = '.'; // End of grid\n                }\n            }\n        } else if (move_dir == 2) { // Moving Left\n            if (ry - 1 >= 0) {\n                S[0] = 'L';\n                ry--;\n            } else {\n                // Reached left end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 0; // Switch to Right\n                } else {\n                    S[0] = '.';\n                }\n            }\n        }\n\n        // --- B. Determine Rotations (Greedy) ---\n        // For each arm (excluding root), evaluate which direction points to the most valuable square.\n        for (int i = 1; i < V; ++i) {\n            int best_dir = arm_dirs[i];\n            int best_score = -1;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                int tx = rx + DX[d] * lengths[i];\n                int ty = ry + DY[d] * lengths[i];\n                int score = 0;\n\n                if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                    // Logic: High value if:\n                    // 1. It's a source (grid=1, target=0) and we can pick it.\n                    // 2. It's a target (grid=0, target=1) and we are holding an item to place.\n                    if (grid[tx][ty] == 1 && target[tx][ty] == 0) {\n                        score += 10; // Prioritize picking up sources\n                    } else if (grid[tx][ty] == 0 && target[tx][ty] == 1) {\n                        score += 5;  // Next prioritize filling targets\n                    } else if (grid[tx][ty] == 1 && target[tx][ty] == 1) {\n                        score += 1;   // Already correct\n                    }\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_dir = d;\n                }\n            }\n\n            // Set rotation command\n            if (best_dir != arm_dirs[i]) {\n                int diff = (best_dir - arm_dirs[i] + 4) % 4;\n                if (diff == 1) S[i] = 'R';\n                else if (diff == 3) S[i] = 'L';\n                else if (diff == 2) {\n                    // 180 degree turn, choose L (arbitrary, or shortest path)\n                    S[i] = 'L'; \n                    best_dir = (arm_dirs[i] + 3) % 4; // Update to intermediate state\n                }\n            }\n            \n            // Update internal state for this step (so Action phase uses correct coords)\n            arm_dirs[i] = best_dir;\n        }\n\n        // --- C. Determine Actions (Pick/Put) ---\n        // Loop from 1 to V-1 (Vertex 0 is root/internal, cannot act).\n        for (int i = 1; i < V; ++i) {\n            int cx = rx + DX[arm_dirs[i]] * lengths[i];\n            int cy = ry + DY[arm_dirs[i]] * lengths[i];\n\n            char action_cmd = '.';\n            if (cx >= 0 && cx < N && cy >= 0 && cy < N) {\n                if (holding[i] == 1) {\n                    // Try to Place\n                    if (grid[cx][cy] == 0 && target[cx][cy] == 1) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 1;\n                        holding[i] = 0;\n                    }\n                } else {\n                    // Try to Pick\n                    if (grid[cx][cy] == 1 && target[cx][cy] == 0) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 0;\n                        holding[i] = 1;\n                    }\n                }\n            }\n            S[V + i] = action_cmd;\n        }\n\n        cout << S << \"\\n\";\n        total_steps++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <unordered_set>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <climits>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int TYPE_MACKEREL = 1;\nconst int TYPE_SARDINE = -1;\n\n// Optimized parameters for O(log N) queries\nconst int MAX_GREEDY_RESTARTS = 500;   // Reduced as SA is more powerful now\nconst int MAX_GREEDY_STEPS = 40;\nconst int TOP_CANDIDATES = 50;         // Increased\nconst int SA_ITERATIONS = 500000;      // Doubled\nconst double START_TEMP = 30.0;        \nconst double END_TEMP = 0.1;\n\nstruct Rect {\n    int x1, x2, y1, y2;\n    int score;\n};\n\n// cols[x] stores pairs of {y, cumulative_sum} sorted by y\nvector<vector<pair<int, int>>> cols(MAX_COORD + 1);\n// rows[y] stores pairs of {x, cumulative_sum} sorted by x\nvector<vector<pair<int, int>>> rows(MAX_COORD + 1);\n\nvector<int> next_x(MAX_COORD + 2, -1);\nvector<int> prev_x(MAX_COORD + 2, -1);\nvector<int> next_y(MAX_COORD + 2, -1);\nvector<int> prev_y(MAX_COORD + 2, -1);\n\nint best_global_score = -1;\nRect best_global_rect;\n\n// Random Generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> dist_double(0.0, 1.0);\nuniform_int_distribution<int> dist_int(0, 7);\n\n// Helper to get sum of points in a column segment [y1, y2] using prefix sums\n// Returns sum of types for all points in column x with y in [y1, y2]\ninline int get_col_sum(int x, int y1, int y2) {\n    if (y1 > y2) return 0;\n    const auto& col = cols[x];\n    if (col.empty()) return 0;\n\n    // Find first element with y > y2 (upper bound)\n    auto r = upper_bound(col.begin(), col.end(), make_pair(y2, INT_MAX));\n    // Find first element with y >= y1 (lower bound)\n    auto l = lower_bound(col.begin(), col.end(), make_pair(y1, INT_MIN));\n\n    int sum_r = 0;\n    if (r != col.begin()) {\n        sum_r = (r - 1)->second;\n    }\n\n    int sum_l = 0;\n    if (l != col.begin()) {\n        sum_l = (l - 1)->second;\n    }\n\n    return sum_r - sum_l;\n}\n\n// Helper to get sum of points in a row segment [x1, x2] using prefix sums\ninline int get_row_sum(int y, int x1, int x2) {\n    if (x1 > x2) return 0;\n    const auto& row = rows[y];\n    if (row.empty()) return 0;\n\n    auto r = upper_bound(row.begin(), row.end(), make_pair(x2, INT_MAX));\n    auto l = lower_bound(row.begin(), row.end(), make_pair(x1, INT_MIN));\n\n    int sum_r = 0;\n    if (r != row.begin()) {\n        sum_r = (r - 1)->second;\n    }\n\n    int sum_l = 0;\n    if (l != row.begin()) {\n        sum_l = (l - 1)->second;\n    }\n\n    return sum_r - sum_l;\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return;\n\n    vector<pair<int, int>> mackerels;\n    mackerels.reserve(N);\n\n    // Temporary storage to build prefix sums later\n    vector<vector<pair<int, int>>> temp_cols(MAX_COORD + 1);\n    vector<vector<pair<int, int>>> temp_rows(MAX_COORD + 1);\n\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        mackerels.push_back({x, y});\n        temp_cols[x].emplace_back(y, TYPE_MACKEREL);\n        temp_rows[y].emplace_back(x, TYPE_MACKEREL);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        temp_cols[x].emplace_back(y, TYPE_SARDINE);\n        temp_rows[y].emplace_back(x, TYPE_SARDINE);\n    }\n\n    // Sort and compute prefix sums\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        if (!temp_cols[i].empty()) {\n            sort(temp_cols[i].begin(), temp_cols[i].end());\n            cols[i].resize(temp_cols[i].size());\n            int running_sum = 0;\n            for (size_t j = 0; j < temp_cols[i].size(); ++j) {\n                running_sum += temp_cols[i][j].second;\n                cols[i][j] = {temp_cols[i][j].first, running_sum};\n            }\n        }\n        if (!temp_rows[i].empty()) {\n            sort(temp_rows[i].begin(), temp_rows[i].end());\n            rows[i].resize(temp_rows[i].size());\n            int running_sum = 0;\n            for (size_t j = 0; j < temp_rows[i].size(); ++j) {\n                running_sum += temp_rows[i][j].second;\n                rows[i][j] = {temp_rows[i][j].first, running_sum};\n            }\n        }\n    }\n\n    // Precompute next/prev populated indices\n    int last_x = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_x[i] = last_x;\n        if (!cols[i].empty()) last_x = i;\n    }\n    int next_x_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_x[i] = next_x_val;\n        if (!cols[i].empty()) next_x_val = i;\n    }\n\n    int last_y = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_y[i] = last_y;\n        if (!rows[i].empty()) last_y = i;\n    }\n    int next_y_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_y[i] = next_y_val;\n        if (!rows[i].empty()) next_y_val = i;\n    }\n\n    // Phase 1: Fast Greedy Search\n    vector<Rect> candidates;\n    shuffle(mackerels.begin(), mackerels.end(), rng);\n    \n    int restarts = min((int)mackerels.size(), MAX_GREEDY_RESTARTS);\n\n    for (int r = 0; r < restarts; ++r) {\n        const auto& start_pt = mackerels[r];\n        Rect cur;\n        cur.x1 = cur.x2 = start_pt.first;\n        cur.y1 = cur.y2 = start_pt.second;\n        cur.score = 1; \n\n        unordered_set<long long> visited;\n        auto encode = [](int x1, int x2, int y1, int y2) {\n            return ((long long)x1 << 48) | ((long long)x2 << 32) | ((long long)y1 << 16) | y2;\n        };\n        visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n        Rect best_local = cur;\n\n        for (int step = 0; step < MAX_GREEDY_STEPS; ++step) {\n            int best_delta = -2;\n            int best_dir = -1;\n            Rect next_rect;\n\n            if (next_x[cur.x2] != -1) {\n                Rect n = cur; n.x2 = next_x[cur.x2];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x2, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 0; next_rect = n; }\n                }\n            }\n            if (prev_x[cur.x1] != -1) {\n                Rect n = cur; n.x1 = prev_x[cur.x1];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x1, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 1; next_rect = n; }\n                }\n            }\n            if (next_y[cur.y2] != -1) {\n                Rect n = cur; n.y2 = next_y[cur.y2];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y2, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 2; next_rect = n; }\n                }\n            }\n            if (prev_y[cur.y1] != -1) {\n                Rect n = cur; n.y1 = prev_y[cur.y1];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y1, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 3; next_rect = n; }\n                }\n            }\n\n            if (best_dir == -1) break;\n            if (best_delta < 0) break; \n            if (best_delta == 0 && visited.count(encode(next_rect.x1, next_rect.x2, next_rect.y1, next_rect.y2))) break;\n\n            cur = next_rect;\n            cur.score += best_delta;\n            visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n            if (cur.score > best_local.score) {\n                best_local = cur;\n            }\n        }\n        candidates.push_back(best_local);\n    }\n\n    // Phase 2: Simulated Annealing\n    sort(candidates.begin(), candidates.end(), [](const Rect& a, const Rect& b) {\n        return a.score > b.score;\n    });\n\n    int num_candidates = min((int)candidates.size(), TOP_CANDIDATES);\n\n    for (int i = 0; i < num_candidates; ++i) {\n        Rect cur = candidates[i];\n        Rect best_sa = cur;\n        \n        double temp = START_TEMP;\n        double cooling_rate = pow(END_TEMP / START_TEMP, 1.0 / SA_ITERATIONS);\n\n        for (int iter = 0; iter < SA_ITERATIONS; ++iter) {\n            temp *= cooling_rate;\n\n            int dir = dist_int(rng);\n            Rect next = cur;\n            int delta = 0;\n            bool valid = true;\n\n            if (dir == 0) { // Expand Left\n                if (prev_x[next.x1] != -1) {\n                    int tx = prev_x[next.x1];\n                    if (tx < next.x2 && 2LL * (next.x2 - tx + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x1 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 1) { // Shrink Left\n                if (next_x[next.x1] != -1 && next_x[next.x1] < next.x2) {\n                    int tx = next_x[next.x1];\n                    delta = -get_col_sum(next.x1, next.y1, next.y2);\n                    next.x1 = tx;\n                } else valid = false;\n            } else if (dir == 2) { // Expand Right\n                if (next_x[next.x2] != -1) {\n                    int tx = next_x[next.x2];\n                    if (tx > next.x1 && 2LL * (tx - next.x1 + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x2 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 3) { // Shrink Right\n                if (prev_x[next.x2] != -1 && prev_x[next.x2] > next.x1) {\n                    int tx = prev_x[next.x2];\n                    delta = -get_col_sum(next.x2, next.y1, next.y2);\n                    next.x2 = tx;\n                } else valid = false;\n            } else if (dir == 4) { // Expand Down\n                if (prev_y[next.y1] != -1) {\n                    int ty = prev_y[next.y1];\n                    if (ty < next.y2 && 2LL * (next.x2 - next.x1 + next.y2 - ty) <= MAX_PERIMETER) {\n                        next.y1 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 5) { // Shrink Down\n                if (next_y[next.y1] != -1 && next_y[next.y1] < next.y2) {\n                    int ty = next_y[next.y1];\n                    delta = -get_row_sum(next.y1, next.x1, next.x2);\n                    next.y1 = ty;\n                } else valid = false;\n            } else if (dir == 6) { // Expand Up\n                if (next_y[next.y2] != -1) {\n                    int ty = next_y[next.y2];\n                    if (ty > next.y1 && 2LL * (next.x2 - next.x1 + ty - next.y1) <= MAX_PERIMETER) {\n                        next.y2 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 7) { // Shrink Up\n                if (prev_y[next.y2] != -1 && prev_y[next.y2] > next.y1) {\n                    int ty = prev_y[next.y2];\n                    delta = -get_row_sum(next.y2, next.x1, next.x2);\n                    next.y2 = ty;\n                } else valid = false;\n            }\n\n            if (valid) {\n                next.score = cur.score + delta;\n                if (delta > 0 || dist_double(rng) < exp((double)delta / temp)) {\n                    cur = next;\n                    if (cur.score > best_sa.score) {\n                        best_sa = cur;\n                    }\n                }\n            }\n        }\n\n        if (best_sa.score > best_global_score) {\n            best_global_score = best_sa.score;\n            best_global_rect = best_sa;\n        }\n    }\n\n    // Handle degenerate output\n    if (best_global_rect.x1 == best_global_rect.x2) {\n        if (best_global_rect.x1 > 0) best_global_rect.x1--;\n        else best_global_rect.x2++;\n    }\n    if (best_global_rect.y1 == best_global_rect.y2) {\n        if (best_global_rect.y1 > 0) best_global_rect.y1--;\n        else best_global_rect.y2++;\n    }\n\n    cout << 4 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y2 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y2 << endl;\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nusing ll = long long;\n\n// Structure for operations\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\n// Structure for placed rectangles\nstruct Rect {\n    ll w, h;\n    ll x, y;\n    int id; \n};\n\n// Structure representing a full state in the Beam Search\nstruct State {\n    vector<Rect> placed;\n    vector<Op> ops;\n    ll W; \n    ll H; \n    ll score; // Current total score (W + H + skipped_sum)\n\n    State() : W(0), H(0), score(0) {}\n};\n\n// Lightweight structure for a candidate step\nstruct Step {\n    Op op;\n    ll score_inc; // Increment in W+H or penalty\n    Rect new_rect;\n    ll new_W, new_H;\n    ll aspect; // |W - H|\n};\n\n// Global inputs\nint N, T;\nll sigma;\nvector<pair<ll, ll>> dims;\n\n// Check if two intervals overlap\ninline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nvoid solve_beam_search() {\n    const int BEAM_WIDTH = 80;\n    const int LOCAL_BEAM = 10; // Keep top K moves per state\n    const ll ASPECT_WEIGHT = 50; \n    \n    vector<State> beam(1);\n    beam[0].W = 0;\n    beam[0].H = 0;\n    beam[0].score = 0;\n    \n    for (int i = 0; i < N; ++i) {\n        ll w_i = dims[i].first;\n        ll h_i = dims[i].second;\n        \n        vector<State> next_beam;\n        // Reserve for the full global beam\n        next_beam.reserve(BEAM_WIDTH * LOCAL_BEAM + 10); \n        \n        for (const auto& st : beam) {\n            vector<Step> local_candidates;\n            // Estimate candidates: 1 skip + 2 rots * 2 dirs * (i+1) refs\n            local_candidates.reserve((i + 1) * 5 + 1);\n            \n            // Option 1: Skip\n            {\n                Step s;\n                s.op = {i, -1, -1, 'X'};\n                s.score_inc = w_i + h_i;\n                s.new_W = st.W;\n                s.new_H = st.H;\n                s.aspect = abs(st.W - st.H);\n                local_candidates.push_back(s);\n            }\n            \n            // Option 2: Place\n            for (int k = -1; k < (int)st.placed.size(); ++k) {\n                for (int r = 0; r < 2; ++r) {\n                    ll cw = (r == 0 ? w_i : h_i);\n                    ll ch = (r == 1 ? w_i : h_i);\n                    int b_id = (k == -1 ? -1 : st.placed[k].id);\n                    \n                    // Direction U\n                    {\n                        ll x = (k == -1 ? 0 : st.placed[k].x + st.placed[k].w);\n                        ll max_bot = 0;\n                        for (const auto& p : st.placed) {\n                            if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                                max_bot = max(max_bot, p.y + p.h);\n                            }\n                        }\n                        ll y = max_bot - ch;\n                        if (y < 0) y = 0;\n                        \n                        ll new_W = max(st.W, x + cw);\n                        ll new_H = max(st.H, y + ch);\n                        ll score_inc = (new_W - st.W) + (new_H - st.H);\n                        \n                        Step s;\n                        s.op = {i, r, b_id, 'U'};\n                        s.score_inc = score_inc;\n                        s.new_rect = {cw, ch, x, y, i};\n                        s.new_W = new_W;\n                        s.new_H = new_H;\n                        s.aspect = abs(new_W - new_H);\n                        local_candidates.push_back(s);\n                    }\n                    \n                    // Direction L\n                    {\n                        ll y = (k == -1 ? 0 : st.placed[k].y + st.placed[k].h);\n                        ll max_right = 0;\n                        for (const auto& p : st.placed) {\n                            if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                                max_right = max(max_right, p.x + p.w);\n                            }\n                        }\n                        ll x = max_right - cw;\n                        if (x < 0) x = 0;\n                        \n                        ll new_W = max(st.W, x + cw);\n                        ll new_H = max(st.H, y + ch);\n                        ll score_inc = (new_W - st.W) + (new_H - st.H);\n                        \n                        Step s;\n                        s.op = {i, r, b_id, 'L'};\n                        s.score_inc = score_inc;\n                        s.new_rect = {cw, ch, x, y, i};\n                        s.new_W = new_W;\n                        s.new_H = new_H;\n                        s.aspect = abs(new_W - new_H);\n                        local_candidates.push_back(s);\n                    }\n                }\n            }\n            \n            // Sort local candidates by heuristic\n            // Heuristic: score_inc + aspect_diff\n            sort(local_candidates.begin(), local_candidates.end(), [](const Step& a, const Step& b) {\n                ll score_a = a.score_inc + a.aspect * ASPECT_WEIGHT;\n                ll score_b = b.score_inc + b.aspect * ASPECT_WEIGHT;\n                return score_a < score_b;\n            });\n            \n            // Take top LOCAL_BEAM steps\n            int limit = min(LOCAL_BEAM, (int)local_candidates.size());\n            for (int k = 0; k < limit; ++k) {\n                const auto& step = local_candidates[k];\n                State ns = st; // Copy parent state\n                ns.W = step.new_W;\n                ns.H = step.new_H;\n                ns.score += step.score_inc;\n                ns.placed.push_back(step.new_rect);\n                ns.ops.push_back(step.op);\n                next_beam.push_back(move(ns));\n            }\n        }\n        \n        // Sort global next_beam by actual score\n        sort(next_beam.begin(), next_beam.end(), [](const State& a, const State& b) {\n            // We use the actual score for the final ranking\n            return a.score < b.score;\n        });\n        \n        if ((int)next_beam.size() > BEAM_WIDTH) {\n            next_beam.resize(BEAM_WIDTH);\n        }\n        \n        beam = move(next_beam);\n    }\n    \n    // Output best state\n    for (int t = 0; t < T; ++t) {\n        cout << beam[0].ops.size() << \"\\n\";\n        for (const auto& op : beam[0].ops) {\n            cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma)) return 0;\n    \n    dims.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> dims[i].first >> dims[i].second;\n    }\n    \n    solve_beam_search();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <queue>\n#include <tuple>\n#include <sys/time.h>\n\nusing namespace std;\n\n// Timer for time limit management\ndouble get_time() {\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    return tv.tv_sec + tv.tv_usec * 1e-6;\n}\n\n// Global inputs\nint N, M, H;\nvector<int> A;\nvector<vector<int>> G;\nvector<int> X, Y;\n\n// Global best state\nlong long best_score = 0;\nvector<int> best_parent;\n\n// Greedy construction based on a specific processing order and parent selection strategy\n// select_deepest: true -> pick deepest neighbor (makes trees bushy)\n//                 false -> pick shallowest neighbor (makes trees linear/deep)\npair<vector<int>, long long> greedy_construct(const vector<int>& order, bool select_deepest) {\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<bool> processed(N, false);\n    \n    for (int v : order) {\n        int best_u = -1;\n        int target_depth = select_deepest ? -1 : 15; // Init for max or min search\n\n        // Find the best processed neighbor\n        for (int u : G[v]) {\n            if (processed[u] && depth[u] < H) {\n                if (select_deepest) {\n                    if (depth[u] > target_depth) {\n                        target_depth = depth[u];\n                        best_u = u;\n                    }\n                } else {\n                    if (depth[u] < target_depth) {\n                        target_depth = depth[u];\n                        best_u = u;\n                    }\n                }\n            }\n        }\n\n        if (best_u != -1) {\n            parent[v] = best_u;\n            depth[v] = depth[best_u] + 1;\n        } else {\n            parent[v] = -1;\n            depth[v] = 0;\n        }\n        processed[v] = true;\n    }\n    \n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        score += (long long)(depth[i] + 1) * A[i];\n    }\n    return {parent, 1 + score};\n}\n\n// Hill Climbing optimization\nvoid hill_climb(vector<int>& parent, vector<int>& depth, long long current_score) {\n    // Build children list\n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) {\n        if (parent[i] != -1) {\n            children[parent[i]].push_back(i);\n        }\n    }\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int v = 0; v < N; ++v) {\n            for (int u : G[v]) {\n                if (u == parent[v]) continue;\n                \n                // Check if u is in the subtree of v\n                int curr = u;\n                while (curr != -1 && curr != v) {\n                    curr = parent[curr];\n                }\n                if (curr == v) continue; \n\n                int new_depth_v = depth[u] + 1;\n                if (new_depth_v > H) continue; \n\n                int diff = new_depth_v - depth[v];\n                \n                // Strictly deeper move only\n                if (diff <= 0) continue;\n                \n                // Check validity for whole subtree\n                long long sum_A = 0;\n                vector<int> stack; \n                stack.push_back(v);\n                bool valid_move = true;\n                \n                while (!stack.empty()) {\n                    int curr_node = stack.back();\n                    stack.pop_back();\n                    \n                    if (depth[curr_node] + diff > H) {\n                        valid_move = false;\n                        break;\n                    }\n                    sum_A += A[curr_node];\n                    \n                    for (int c : children[curr_node]) {\n                        stack.push_back(c);\n                    }\n                }\n                \n                if (!valid_move) continue;\n                \n                // Apply Move\n                int old_parent = parent[v];\n                parent[v] = u;\n                depth[v] = new_depth_v;\n                \n                if (old_parent != -1) {\n                    auto it = find(children[old_parent].begin(), children[old_parent].end(), v);\n                    if (it != children[old_parent].end()) children[old_parent].erase(it);\n                }\n                children[u].push_back(v);\n                \n                // Update subtree depths\n                stack.push_back(v);\n                while (!stack.empty()) {\n                    int curr_node = stack.back();\n                    stack.pop_back();\n                    for (int c : children[curr_node]) {\n                        depth[c] += diff;\n                        stack.push_back(c);\n                    }\n                }\n                \n                current_score += (long long)diff * sum_A;\n                improved = true;\n                \n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_parent = parent;\n                }\n                \n                v = -1; \n                break; \n            }\n        }\n    }\n}\n\nint main() {\n    double start_time = get_time();\n\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> H)) return 0;\n\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    G.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> X[i] >> Y[i];\n    }\n\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    \n    random_device rd;\n    mt19937 g(rd());\n\n    // We will run different heuristics\n    // 1. Sort by A (Beauty)\n    // 2. Sort by X (Horizontal)\n    // 3. Sort by Y (Vertical)\n    // 4. Random\n    \n    vector<tuple<string, bool, bool>> trials_config;\n    // (SortKey, Ascending, SelectDeepestNeighbor)\n    \n    // Beauty based (Most important)\n    for(int i=0; i<8; ++i) trials_config.push_back(make_tuple(\"A\", true, true));  // Asc A, Deep parent (Low A root, High A leaf)\n    trials_config.push_back(make_tuple(\"A\", true, false)); // Asc A, Shallow parent (Creates chains)\n    trials_config.push_back(make_tuple(\"A\", false, true)); // Desc A\n    \n    // Spatial based (Topological diversity)\n    trials_config.push_back(make_tuple(\"X\", true, true));  // Left to Right\n    trials_config.push_back(make_tuple(\"X\", true, false));\n    trials_config.push_back(make_tuple(\"X\", false, true)); // Right to Left\n    \n    trials_config.push_back(make_tuple(\"Y\", true, true));  // Bottom to Top\n    trials_config.push_back(make_tuple(\"Y\", true, false));\n    trials_config.push_back(make_tuple(\"Y\", false, true)); // Top to Bottom\n    \n    // Random based\n    for(int i=0; i<15; ++i) trials_config.push_back(make_tuple(\"R\", true, true));\n\n    int trial_idx = 0;\n    while (true) {\n        if (get_time() - start_time > 1.95) break;\n        if (trial_idx >= (int)trials_config.size()) break;\n\n        auto config = trials_config[trial_idx++];\n        string key = get<0>(config);\n        bool asc = get<1>(config);\n        bool deep_sel = get<2>(config);\n        \n        vector<int> order = indices;\n        \n        // Shuffle first to randomize ties\n        shuffle(order.begin(), order.end(), g);\n\n        if (key == \"A\") {\n            stable_sort(order.begin(), order.end(), [&](int u, int v) { \n                return asc ? (A[u] < A[v]) : (A[u] > A[v]); \n            });\n        } else if (key == \"X\") {\n            stable_sort(order.begin(), order.end(), [&](int u, int v) { \n                return asc ? (X[u] < X[v]) : (X[u] > X[v]); \n            });\n        } else if (key == \"Y\") {\n            stable_sort(order.begin(), order.end(), [&](int u, int v) { \n                return asc ? (Y[u] < Y[v]) : (Y[u] > Y[v]); \n            });\n        }\n        // \"R\" or others just stay shuffled\n\n        // Construction\n        auto result = greedy_construct(order, deep_sel);\n        vector<int> parent = result.first;\n        long long score = result.second;\n        \n        // Compute Depth\n        vector<int> depth(N, 0);\n        vector<vector<int>> children_init(N);\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] != -1) children_init[parent[i]].push_back(i);\n        }\n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int c : children_init[v]) {\n                depth[c] = depth[v] + 1;\n                q.push(c);\n            }\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_parent = parent;\n        }\n\n        // Optimization\n        hill_climb(parent, depth, score);\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << best_parent[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n#include <tuple>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n};\n\nint N;\nvector<string> grid;\nvector<Point> onis;\nvector<bool> removed; \nvector<vector<bool>> clear_left, clear_right;\n\nbool has_o_up(int r, int c) {\n    for (int i = 0; i < r; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\nbool has_o_down(int r, int c) {\n    for (int i = r + 1; i < N; ++i) if (grid[i][c] == 'o') return true;\n    return false;\n}\n\nbool can_remove_up(int r, int c) { return !has_o_up(r, c); }\nbool can_remove_down(int r, int c) { return !has_o_down(r, c); }\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    grid.resize(N);\n    clear_left.assign(N, vector<bool>(N, false));\n    clear_right.assign(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> grid[i];\n        bool blocked = false;\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 'o') blocked = true;\n            clear_left[i][j] = !blocked;\n        }\n        blocked = false;\n        for (int j = N - 1; j >= 0; --j) {\n            if (grid[i][j] == 'o') blocked = true;\n            clear_right[i][j] = !blocked;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == 'x') {\n                onis.push_back({i, j});\n            }\n        }\n    }\n\n    removed.assign(onis.size(), false);\n    vector<pair<char, int>> moves;\n\n    // --- PHASE 1: ROW REMOVALS ---\n    for (int r = 0; r < N; ++r) {\n        // Identify segments separated by 'o'\n        // We still use segments to limit the points we process, but cost calculation uses global clear_left/right\n        vector<pair<int, int>> segments;\n        int l = 0;\n        while (l < N) {\n            while (l < N && grid[r][l] == 'o') l++;\n            if (l >= N) break;\n            int rend = l;\n            while (rend < N && grid[r][rend] != 'o') rend++;\n            segments.push_back({l, rend - 1});\n            l = rend;\n        }\n\n        for (auto seg : segments) {\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].r == r && onis[k].c >= seg.first && onis[k].c <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            \n            if (indices.empty()) continue;\n\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].c < onis[b].c;\n            });\n\n            int K = indices.size();\n            vector<int> cols(K);\n            vector<int> savings(K, 0);\n\n            for (int i = 0; i < K; ++i) {\n                int c = onis[indices[i]].c;\n                cols[i] = c;\n                // Exact Savings: Cost if removed in Phase 2 (Columns)\n                // Since points are in different columns (same row), Phase 2 costs are independent.\n                int cost_up = 2 * (r + 1);\n                int cost_down = 2 * (N - r);\n                savings[i] = min(cost_up, cost_down);\n            }\n\n            vector<int> savings_prefix(K, 0);\n            for(int i=0; i<K; ++i) {\n                savings_prefix[i] = savings[i] + (i>0 ? savings_prefix[i-1] : 0);\n            }\n\n            vector<int> dp(K + 1, 2000000000); \n            vector<pair<int, int>> parent(K + 1, {-1, -1}); \n            dp[0] = 0;\n\n            for (int i = 1; i <= K; ++i) {\n                // Option 1: Leave point i for Phase 2\n                if (dp[i-1] < dp[i]) {\n                    dp[i] = dp[i-1];\n                    parent[i] = {i-1, -1};\n                }\n\n                // Option 2: Cover interval j..i with row operations\n                for (int j = 1; j <= i; ++j) {\n                    int c_L = cols[j-1];\n                    int c_R = cols[i-1];\n\n                    // Check Left Cover Validity and Cost\n                    // Can we shift Left enough to remove c_R?\n                    // Requires clear_left[r][c_R] (no 'o' to the left of c_R)\n                    int costL = 2 * (c_R + 1);\n                    if (!clear_left[r][c_R]) costL = 2000000000; // Impossible\n\n                    // Check Right Cover Validity and Cost\n                    // Can we shift Right enough to remove c_L?\n                    // Requires clear_right[r][c_L] (no 'o' to the right of c_L)\n                    int costR = 2 * (N - c_L);\n                    if (!clear_right[r][c_L]) costR = 2000000000; // Impossible\n                    \n                    int sum_savings = savings_prefix[i-1] - (j >= 2 ? savings_prefix[j-2] : 0);\n\n                    if (costL < 1000000000) {\n                        int totalL = dp[j-1] + costL - sum_savings;\n                        if (totalL < dp[i]) {\n                            dp[i] = totalL;\n                            parent[i] = {j-1, 0};\n                        }\n                    }\n                    \n                    if (costR < 1000000000) {\n                        int totalR = dp[j-1] + costR - sum_savings;\n                        if (totalR < dp[i]) {\n                            dp[i] = totalR;\n                            parent[i] = {j-1, 1};\n                        }\n                    }\n                }\n            }\n\n            vector<tuple<int, int, int>> intervals; \n            int curr = K;\n            while (curr > 0) {\n                int prev = parent[curr].first;\n                int type = parent[curr].second;\n                if (type == -1) {\n                    curr = prev;\n                } else {\n                    intervals.push_back({prev, curr - 1, type});\n                    curr = prev;\n                }\n            }\n            reverse(intervals.begin(), intervals.end());\n\n            for (auto iv : intervals) {\n                int s = get<0>(iv);\n                int e = get<1>(iv);\n                int type = get<2>(iv);\n                \n                if (type == 0) { \n                    int bound = cols[e];\n                    for(int k=0; k<=bound; ++k) moves.push_back({'L', r});\n                    for(int k=0; k<=bound; ++k) moves.push_back({'R', r});\n                    \n                    for(int k=s; k<=e; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                } else { \n                    int bound = cols[s];\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'R', r});\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'L', r});\n\n                    for(int k=s; k<=e; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // --- PHASE 2: COLUMN REMOVALS ---\n    for (int c = 0; c < N; ++c) {\n        vector<pair<int, int>> segments;\n        int u = 0;\n        while (u < N) {\n            while (u < N && grid[u][c] == 'o') u++;\n            if (u >= N) break;\n            int d = u;\n            while (d < N && grid[d][c] != 'o') d++;\n            segments.push_back({u, d - 1});\n            u = d;\n        }\n\n        for (auto seg : segments) {\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].c == c && onis[k].r >= seg.first && onis[k].r <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            if (indices.empty()) continue;\n\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].r < onis[b].r;\n            });\n\n            int K = indices.size();\n            vector<int> rows(K);\n            for (int i = 0; i < K; ++i) rows[i] = onis[indices[i]].r;\n\n            vector<int> dp(K, 1e9);\n            vector<pair<int, int>> choice(K, {-1, 0}); \n\n            for (int i = 0; i < K; ++i) {\n                for (int j = 0; j <= i; ++j) {\n                    int prev_cost = (j == 0) ? 0 : dp[j-1];\n                    \n                    int costU = prev_cost + 2 * (rows[i] + 1);\n                    if (costU < dp[i]) {\n                        dp[i] = costU;\n                        choice[i] = {j - 1, 0};\n                    }\n\n                    int costD = prev_cost + 2 * (N - rows[j]);\n                    if (costD < dp[i]) {\n                        dp[i] = costD;\n                        choice[i] = {j - 1, 1};\n                    }\n                }\n            }\n\n            int curr = K - 1;\n            while (curr >= 0) {\n                int prev = choice[curr].first;\n                int type = choice[curr].second;\n\n                if (type == 0) {\n                    int r_end = rows[curr];\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'U', c});\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'D', c});\n                    \n                    for(int k=prev+1; k<=curr; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                } else {\n                    int r_start = rows[prev + 1];\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'D', c});\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'U', c});\n\n                    for(int k=prev+1; k<=curr; ++k) {\n                        removed[indices[k]] = true;\n                    }\n                }\n                curr = prev;\n            }\n        }\n    }\n\n    for (auto m : moves) {\n        cout << m.first << \" \" << m.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <algorithm>\n#include <numeric>\n#include <array>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\n// Optimized simulation function using stack arrays for speed\nlong long simulate(const vector<int>& a, const vector<int>& b, const vector<int>& T) {\n    int cnt[N] = {0};\n    int cur = 0;\n    cnt[0]++;\n    for (int i = 1; i < L; ++i) {\n        // Determine next cleaner based on parity of count of current cleaner\n        cur = (cnt[cur] & 1) ? a[cur] : b[cur];\n        cnt[cur]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs((long long)cnt[i] - T[i]);\n    }\n    return error;\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_input, l_input;\n    cin >> n_input >> l_input;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    mt19937 rng(0); // Fixed seed for reproducibility if needed, but we rely on shuffle\n\n    vector<int> best_a(N), best_b(N);\n    long long best_error = 1e18;\n    \n    // We use fewer iterations (400) to ensure we stay well within the 2.0s time limit,\n    // while using a randomized heuristic to explore different graph configurations.\n    // Each iteration does O(N^2) construction and O(NL) simulation.\n    const int TRIES = 400; \n\n    for (int t = 0; t < TRIES; ++t) {\n        vector<int> a(N), b(N);\n        vector<long long> assigned(N, 0); // Tracks expected inflow to each node\n        \n        // Randomize the order of processing nodes to create diverse graph structures\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        \n        for (int x : order) {\n            // Estimate how many times we will use a[x] (odd transitions) and b[x] (even transitions).\n            // Assuming T[x] is roughly met, this split is roughly 50/50 (rounded).\n            int w_odd = (T[x] + 1) / 2;\n            int w_even = T[x] / 2;\n            \n            // Lambda to select a target node for a given flow w.\n            // We try to minimize |assigned[y] + w - T[y]|.\n            // We introduce randomness by allowing candidates that are slightly suboptimal\n            // (within a small threshold) to avoid getting stuck in local minima.\n            auto pick_target = [&](int w) {\n                long long min_cost = 1e18;\n                vector<int> candidates;\n                candidates.reserve(N);\n                \n                // First pass: find minimum cost\n                for (int y = 0; y < N; ++y) {\n                    long long cost = abs(assigned[y] + w - T[y]);\n                    if (cost < min_cost) {\n                        min_cost = cost;\n                    }\n                }\n                \n                // Second pass: collect candidates close to minimum cost\n                // Threshold of 5 allows small deviations to explore better global structures\n                long long threshold = min_cost + 5; \n                for (int y = 0; y < N; ++y) {\n                    long long cost = abs(assigned[y] + w - T[y]);\n                    if (cost <= threshold) {\n                        candidates.push_back(y);\n                    }\n                }\n                \n                // Pick randomly among the candidates\n                return candidates[rng() % candidates.size()];\n            };\n            \n            // Assign targets for odd and even transitions\n            int target_odd = pick_target(w_odd);\n            a[x] = target_odd;\n            assigned[target_odd] += w_odd;\n            \n            int target_even = pick_target(w_even);\n            b[x] = target_even;\n            assigned[target_even] += w_even;\n        }\n        \n        // Evaluate the constructed graph by simulating the actual process\n        long long err = simulate(a, b, T);\n        if (err < best_error) {\n            best_error = err;\n            best_a = a;\n            best_b = b;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <climits>\n\nusing namespace std;\n\n// DSU implementation for Kruskal's algorithm\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        return true;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<double> cx, cy;\nvector<int> city_to_group; \n\n// Function to estimate distance based on box centers\nint estimated_dist(int i, int j) {\n    double dx = cx[i] - cx[j];\n    double dy = cy[i] - cy[j];\n    return (int)floor(sqrt(dx*dx + dy*dy));\n}\n\n// Perform a query with a subset of cities\nvector<pair<int, int>> ask_query(const vector<int>& cities) {\n    cout << \"? \" << cities.size();\n    for (int c : cities) cout << \" \" << c;\n    cout << endl;\n    cout.flush();\n    \n    vector<pair<int, int>> edges;\n    // cities.size() is guaranteed >= 2 by caller\n    for (size_t i = 0; i < cities.size() - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.emplace_back(u, v);\n    }\n    return edges;\n}\n\nvoid solve() {\n    // Read initial input\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    cx.resize(N); cy.resize(N);\n    city_to_group.resize(N);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n    }\n\n    // 1. Assign cities to groups\n    // Sort by X-coordinate (cx) then Y (cy) to create spatial clusters\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n    \n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        groups[k].resize(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            int city = order[idx++];\n            groups[k][i] = city;\n            city_to_group[city] = k;\n        }\n        // Keep the group sorted as well\n        sort(groups[k].begin(), groups[k].end(), [&](int i, int j) {\n            if (cx[i] != cx[j]) return cx[i] < cx[j];\n            return cy[i] < cy[j];\n        });\n    }\n\n    // 2. Information Gathering (Query Phase)\n    set<pair<int, int>> known_edges;\n    int queries_remaining = Q;\n\n    auto safe_query = [&](const vector<int>& cities) -> bool {\n        if (queries_remaining <= 0) return false;\n        // Safety check: size must be >= 2 to satisfy problem constraints\n        if (cities.size() < 2) return false;\n        auto res = ask_query(cities);\n        queries_remaining--;\n        for (auto& e : res) known_edges.insert(e);\n        return true;\n    };\n\n    for (int k = 0; k < M; ++k) {\n        if (queries_remaining <= 0) break;\n        \n        int sz = groups[k].size();\n        \n        // Case A: Small group (fits in one query and size >= 2)\n        if (sz >= 2 && sz <= L) {\n            safe_query(groups[k]);\n        } \n        // Case B: Large group\n        else if (sz > L) {\n            int stride = L / 2;\n            if (stride < 1) stride = 1;\n            \n            for (int i = 0; i <= sz - L; i += stride) {\n                if (!safe_query(vector<int>(groups[k].begin() + i, groups[k].begin() + i + L))) {\n                    break;\n                }\n            }\n        }\n        // Case C: sz == 1 -> do nothing, no edges needed\n    }\n\n    // 3. Construct Answer for each group\n    vector<vector<pair<int, int>>> answer_edges(M);\n    \n    for (int k = 0; k < M; ++k) {\n        auto& vec = groups[k];\n        int sz = vec.size();\n        if (sz <= 1) continue;\n        \n        vector<tuple<int, int, int, int, int>> candidates;\n        \n        // Add known edges\n        for (auto& e : known_edges) {\n            if (city_to_group[e.first] == k && city_to_group[e.second] == k) {\n                int d = estimated_dist(e.first, e.second);\n                \n                auto it_u = find(vec.begin(), vec.end(), e.first);\n                auto it_v = find(vec.begin(), vec.end(), e.second);\n                if (it_u != vec.end() && it_v != vec.end()) {\n                    int idx_u = distance(vec.begin(), it_u);\n                    int idx_v = distance(vec.begin(), it_v);\n                    int idx_diff = abs(idx_u - idx_v);\n                    candidates.push_back({0, d, idx_diff, e.first, e.second});\n                }\n            }\n        }\n        \n        // Add estimated edges\n        for (int i = 0; i < sz; ++i) {\n            for (int j = i + 1; j < sz; ++j) {\n                int u = vec[i];\n                int v = vec[j];\n                if (u > v) swap(u, v);\n                \n                if (known_edges.count({u, v})) continue;\n                \n                int d = estimated_dist(u, v);\n                candidates.push_back({1, d, j - i, u, v});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end());\n        \n        map<int, int> local_id;\n        for(int i=0; i<sz; ++i) local_id[vec[i]] = i;\n        \n        DSU dsu(sz);\n        int edges_needed = sz - 1;\n        \n        for (auto& item : candidates) {\n            int u = get<3>(item);\n            int v = get<4>(item);\n            int uid = local_id[u];\n            int vid = local_id[v];\n            \n            if (dsu.unite(uid, vid)) {\n                answer_edges[k].push_back({u, v});\n                if (answer_edges[k].size() == edges_needed) break;\n            }\n        }\n    }\n    \n    // Output\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n        \n        for (auto& e : answer_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    solve();\n    \n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nstruct Point {\n    int x;\n    int y;\n};\n\nint N, M;\nvector<Point> targets;\n\nvector<pair<char, char>> actions;\n\nvoid add_action(char a, char d) {\n    actions.push_back({a, d});\n}\n\nvoid add_move(char d, int steps) {\n    for (int i = 0; i < steps; ++i) {\n        add_action('M', d);\n    }\n}\n\nbool isCorner(Point p) {\n    return (p.x == 0 || p.x == N - 1) && (p.y == 0 || p.y == N - 1);\n}\n\nstruct Strategy {\n    int cost;\n    int type; // 0=Walk, 1=Slide U, 2=Slide D, 3=Slide L, 4=Slide R, 5=Corner 1-slide, 6=Corner 2-slide\n    char dir;\n    Point slide_dest; // Relevant for Corner 2-slide to know where to stop\n\n    bool operator<(const Strategy& other) const {\n        return cost < other.cost;\n    }\n};\n\nconst int INF = 1000000000;\n\nStrategy evaluate_strategy(Point cur, Point target, int type) {\n    int dx = abs(cur.x - target.x);\n    int dy = abs(cur.y - target.y);\n    \n    if (type == 0) { // Walk\n        return {dx + dy, 0, ' ', target};\n    }\n    else if (type == 1) { // Slide Up\n        if (cur.y <= target.y) return {INF, 1, 'U', target};\n        int cost = dx + 1 + target.y;\n        return {cost, 1, 'U', target};\n    }\n    else if (type == 2) { // Slide Down\n        if (cur.y >= target.y) return {INF, 2, 'D', target};\n        int cost = dx + 1 + (N - 1 - target.y);\n        return {cost, 2, 'D', target};\n    }\n    else if (type == 3) { // Slide Left\n        if (cur.x <= target.x) return {INF, 3, 'L', target};\n        int cost = dy + 1 + target.x;\n        return {cost, 3, 'L', target};\n    }\n    else if (type == 4) { // Slide Right\n        if (cur.x >= target.x) return {INF, 4, 'R', target};\n        int cost = dy + 1 + (N - 1 - target.x);\n        return {cost, 4, 'R', target};\n    }\n    return {INF, 0, ' ', target};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    targets.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int r, c;\n        cin >> r >> c;\n        targets[i].x = c;\n        targets[i].y = r;\n    }\n\n    Point cur = targets[0];\n\n    for (int k = 1; k < M; ++k) {\n        Point target = targets[k];\n        \n        Strategy best = {INF, 0, ' ', target};\n        \n        // Standard Strategies\n        best = min(best, evaluate_strategy(cur, target, 0));\n        best = min(best, evaluate_strategy(cur, target, 1));\n        best = min(best, evaluate_strategy(cur, target, 2));\n        best = min(best, evaluate_strategy(cur, target, 3));\n        best = min(best, evaluate_strategy(cur, target, 4));\n\n        // Corner Strategies\n        if (isCorner(target)) {\n            // Strategy: Single slide if aligned\n            if (cur.x == target.x) {\n                int cost = 1;\n                if (cur.y == target.y) cost = 0; // Already there\n                char d = (cur.y > target.y) ? 'U' : 'D';\n                best = min(best, {cost, 5, d, target});\n            } else if (cur.y == target.y) {\n                int cost = 1;\n                char d = (cur.x > target.x) ? 'L' : 'R';\n                best = min(best, {cost, 5, d, target});\n            } else {\n                // Strategy: 2-turn corner hop (e.g., Slide U then Slide R)\n                // Valid if we are not on the same row or col, and not already there.\n                // Cost is always 2.\n                best = min(best, {2, 6, ' ', target});\n            }\n        }\n\n        // Tie-breaking: Prefer Walk if costs equal\n        if (best.cost == evaluate_strategy(cur, target, 0).cost && best.type != 0) {\n            best.type = 0;\n        }\n\n        // Execution\n        int dx = target.x - cur.x;\n        int dy = target.y - cur.y;\n\n        if (best.type == 0) {\n            if (dx > 0) add_move('R', dx);\n            else if (dx < 0) add_move('L', -dx);\n            if (dy > 0) add_move('D', dy);\n            else if (dy < 0) add_move('U', -dy);\n        }\n        else if (best.type == 1) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'U');\n            add_move('D', target.y);\n        }\n        else if (best.type == 2) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'D');\n            add_move('U', N - 1 - target.y);\n        }\n        else if (best.type == 3) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'L');\n            add_move('R', target.x);\n        }\n        else if (best.type == 4) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'R');\n            add_move('L', N - 1 - target.x);\n        }\n        else if (best.type == 5) {\n            // Aligned corner slide\n            add_action('S', best.dir);\n        }\n        else if (best.type == 6) {\n            // 2-turn corner hop\n            // We need to slide to the adjacent edge, then slide to the corner.\n            // Order: Slide towards y=0 or y=N-1 (perpendicular to target's y-edge), then x.\n            // Or x then y.\n            // Let's align Y first.\n            char d1, d2;\n            if (target.y == 0) d1 = 'U';\n            else d1 = 'D'; // target.y == N-1\n            \n            if (target.x == N-1) d2 = 'R';\n            else d2 = 'L'; // target.x == 0\n\n            add_action('S', d1);\n            add_action('S', d2);\n        }\n\n        cur = target;\n    }\n\n    for (const auto& act : actions) {\n        cout << act.first << \" \" << act.second << \"\\n\";\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <limits>\n#include <numeric>\n\nusing namespace std;\n\n// Use long long for area and error calculations to avoid overflow\nusing ll = long long;\n\nstruct Company {\n    int x, y;\n    ll r;\n    int a, b, c, d; // Output rectangle coordinates\n};\n\nvector<Company> companies;\n\n// Recursive function to partition the space\n// (x1, y1) is the bottom-left of the current region, (x2, y2) is the top-right\n// ids contains the indices of companies that must be placed in this region\nvoid solve_recursive(int x1, int y1, int x2, int y2, vector<int> ids) {\n    int k = ids.size();\n    if (k == 0) return;\n    \n    // Base case: only one company, assign the whole region\n    if (k == 1) {\n        int id = ids[0];\n        companies[id].a = x1;\n        companies[id].b = y1;\n        companies[id].c = x2;\n        companies[id].d = y2;\n        return;\n    }\n\n    ll total_area = (ll)(x2 - x1) * (y2 - y1);\n    \n    // Find the best cut (vertical or horizontal)\n    // We minimize the squared error: sum((assigned_area - desired_area)^2)\n    \n    ll best_error = numeric_limits<ll>::max();\n    int best_split_axis = -1; // 0: vertical, 1: horizontal\n    int best_split_idx = -1; // Index in the sorted list to split at\n    int best_cut_pos = -1;   // Coordinate of the cut\n    \n    // --- Try Vertical Cut ---\n    // Sort companies by X coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].x < companies[j].x;\n    });\n    \n    // Calculate prefix sums of r to quickly get sum of desired areas for a split\n    vector<ll> prefix_sum(k);\n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int height = y2 - y1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        // Split between i and i+1\n        ll sum_r_left = prefix_sum[i];\n        ll sum_r_right = prefix_sum[k-1] - sum_r_left;\n        \n        // The cut position X must separate the points.\n        // Left points must have x < X, Right points must have x >= X.\n        // Since points are integers, X must be > max_x_left and <= min_x_right.\n        int max_x_left = companies[ids[i]].x;\n        int min_x_right = companies[ids[i+1]].x;\n        \n        // Also must be within the current rectangle bounds (x1, x2)\n        // Left rect: [x1, X), Right: [X, x2) -> x1 < X < x2\n        int low = max(x1 + 1, max_x_left + 1);\n        int high = min(x2 - 1, min_x_right);\n        \n        if (low > high) continue; // No valid cut position for this split\n        \n        // Calculate optimal cut position to match area\n        // We want (X - x1) * height approx sum_r_left\n        double target_x = x1 + (double)sum_r_left / height;\n        int cut_x = (int)round(target_x);\n        \n        // Clamp to valid range\n        if (cut_x < low) cut_x = low;\n        if (cut_x > high) cut_x = high;\n        \n        ll actual_area_left = (ll)(cut_x - x1) * height;\n        ll actual_area_right = total_area - actual_area_left;\n        \n        ll error = (actual_area_left - sum_r_left) * (actual_area_left - sum_r_left) \n                 + (actual_area_right - sum_r_right) * (actual_area_right - sum_r_right);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 0;\n            best_split_idx = i;\n            best_cut_pos = cut_x;\n        }\n    }\n    \n    // --- Try Horizontal Cut ---\n    // Sort companies by Y coordinate\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        return companies[i].y < companies[j].y;\n    });\n    \n    prefix_sum[0] = companies[ids[0]].r;\n    for (int i = 1; i < k; ++i) {\n        prefix_sum[i] = prefix_sum[i-1] + companies[ids[i]].r;\n    }\n    \n    int width = x2 - x1;\n    \n    for (int i = 0; i < k - 1; ++i) {\n        ll sum_r_bottom = prefix_sum[i];\n        ll sum_r_top = prefix_sum[k-1] - sum_r_bottom;\n        \n        int max_y_bottom = companies[ids[i]].y;\n        int min_y_top = companies[ids[i+1]].y;\n        \n        int low = max(y1 + 1, max_y_bottom + 1);\n        int high = min(y2 - 1, min_y_top);\n        \n        if (low > high) continue;\n        \n        double target_y = y1 + (double)sum_r_bottom / width;\n        int cut_y = (int)round(target_y);\n        \n        if (cut_y < low) cut_y = low;\n        if (cut_y > high) cut_y = high;\n        \n        ll actual_area_bottom = (ll)(cut_y - y1) * width;\n        ll actual_area_top = total_area - actual_area_bottom;\n        \n        ll error = (actual_area_bottom - sum_r_bottom) * (actual_area_bottom - sum_r_bottom) \n                 + (actual_area_top - sum_r_top) * (actual_area_top - sum_r_top);\n                 \n        if (error < best_error) {\n            best_error = error;\n            best_split_axis = 1;\n            best_split_idx = i;\n            best_cut_pos = cut_y;\n        }\n    }\n    \n    // --- Perform the Split ---\n    vector<int> left_ids, right_ids;\n    \n    if (best_split_axis == 0) {\n        // Vertical split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].x < companies[j].x;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, best_cut_pos, y2, left_ids);\n        solve_recursive(best_cut_pos, y1, x2, y2, right_ids);\n    } else {\n        // Horizontal split\n        sort(ids.begin(), ids.end(), [&](int i, int j) {\n            return companies[i].y < companies[j].y;\n        });\n        for (int i = 0; i <= best_split_idx; ++i) left_ids.push_back(ids[i]);\n        for (int i = best_split_idx + 1; i < k; ++i) right_ids.push_back(ids[i]);\n        \n        solve_recursive(x1, y1, x2, best_cut_pos, left_ids);\n        solve_recursive(x1, best_cut_pos, x2, y2, right_ids);\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    companies.resize(n);\n    vector<int> all_ids(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n        all_ids[i] = i;\n    }\n    \n    solve_recursive(0, 0, 10000, 10000, all_ids);\n    \n    for (int i = 0; i < n; ++i) {\n        cout << companies[i].a << \" \" << companies[i].b << \" \" << companies[i].c << \" \" << companies[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multiprecision/cpp_int.hpp>\n#include <random>\n\nnamespace mp = boost::multiprecision;\n\nusing namespace std;\nusing namespace atcoder;\n\n// mt19937_64 for high quality random numbers\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n};\n\nstruct Tile {\n    int id;\n    int size;\n    Point cells[2];\n    int total_val;\n    bool visited;\n};\n\n// Global variables for grid\nint H = 50, W = 50;\nint si, sj;\nvector<vector<int>> tile_ids;\nvector<vector<int>> p_vals;\nvector<Tile> tiles;\n\n// Directions\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHARS[4] = {'U', 'D', 'L', 'R'};\n\n// Helper to check bounds\ninline bool inside(int r, int c) {\n    return 0 <= r && r < H && 0 <= c && c < W;\n}\n\n// Heuristic function to evaluate the \"future\" potential of a cell\n// It sums the values of unvisited neighbor tiles + a bonus for connectivity\nint get_future_potential(int r, int c, const vector<bool>& visited) {\n    int score = 0;\n    int connections = 0;\n    for (int d = 0; d < 4; ++d) {\n        int nr = r + DR[d];\n        int nc = c + DC[d];\n        if (inside(nr, nc)) {\n            int tid = tile_ids[nr][nc];\n            if (!visited[tid]) {\n                score += tiles[tid].total_val;\n                connections++;\n            }\n        }\n    }\n    // Bonus for having multiple options (connectivity)\n    return score + connections * 10;\n}\n\n// Main solver function\nstring solve_single_run() {\n    int num_tiles = tiles.size();\n    vector<bool> visited(num_tiles, false);\n    string path = \"\";\n    int score = 0;\n    \n    // Initialize current position and tile\n    Point curr_pos(si, sj);\n    int curr_tile_id = tile_ids[si][sj];\n    \n    // Mark start tile as visited\n    visited[curr_tile_id] = true;\n    score += p_vals[si][sj]; // Add score of starting square\n    \n    // Handle start tile logic (if it's a 2-tile, we might want to move to the other cell)\n    if (tiles[curr_tile_id].size == 2) {\n        Point p0 = tiles[curr_tile_id].cells[0];\n        Point p1 = tiles[curr_tile_id].cells[1];\n        \n        Point other = (p0.r == si && p0.c == sj) ? p1 : p0;\n        \n        // Calculate heuristic for exiting from current pos vs exiting from other\n        // Note: We already 'visited' the start tile, so we can move freely within it.\n        // We haven't collected points from 'other' yet.\n        \n        int potential_curr = get_future_potential(si, sj, visited);\n        int potential_other = p_vals[other.r][other.c] + get_future_potential(other.r, other.c, visited);\n        \n        if (potential_other > potential_curr) {\n            // Move to the other cell\n            for (int d = 0; d < 4; ++d) {\n                if (si + DR[d] == other.r && sj + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    curr_pos = other;\n                    score += p_vals[other.r][other.c];\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Main greedy loop\n    while (true) {\n        Point best_next_pos(-1, -1);\n        int best_score_move = -1;\n        bool best_is_full_traverse = false; // True if we choose to visit both cells of a 2-tile\n        int best_dir_idx = -1;\n        \n        // Check neighbors\n        for (int d = 0; d < 4; ++d) {\n            int nr = curr_pos.r + DR[d];\n            int nc = curr_pos.c + DC[d];\n            \n            if (!inside(nr, nc)) continue;\n            \n            int nxt_tid = tile_ids[nr][nc];\n            if (visited[nxt_tid]) continue;\n            \n            // Evaluate moving to (nr, nc)\n            // We enter the tile at (nr, nc)\n            int gain = tiles[nxt_tid].total_val;\n            \n            // Strategy 1: Full traverse (visit all cells of the tile)\n            // We effectively collect `gain`, and end up at the \"best\" exit point of the tile\n            // But since we enter at (nr, nc), we must reach the exit point from there.\n            // For 1-tile, exit is (nr, nc).\n            // For 2-tile, we enter at (nr, nc) -> go to other -> exit. Or enter -> exit.\n            \n            int max_future = -1e9;\n            int best_exit_cell_idx = -1; // 0 or 1 relative to tile cells\n            int future_curr_entry = -1e9;\n            \n            // Evaluate exit points\n            // Entry point is always the cell adjacent to curr_pos\n            // We need to identify which cell of the target tile is (nr, nc)\n            Point entry_cell(nr, nc);\n            Point other_cell(-1, -1);\n            if (tiles[nxt_tid].size == 2) {\n                if (tiles[nxt_tid].cells[0].r == nr && tiles[nxt_tid].cells[0].c == nc) {\n                    other_cell = tiles[nxt_tid].cells[1];\n                } else {\n                    other_cell = tiles[nxt_tid].cells[0];\n                }\n            }\n\n            // Option A: Exit from entry_cell (Partial traverse if 2-tile)\n            // We only gain points of entry_cell? \n            // Wait, if we enter a 2-tile and don't visit the other cell, do we gain its points? No.\n            // But wait, problem statement: \"score... sum of values of visited squares\".\n            // So we must decide which squares to visit.\n            // If 1-tile: visit (nr, nc). Gain = p(nr, nc).\n            // If 2-tile: visit (nr, nc). Gain = p(nr, nc).\n            \n            // Let's calculate exact gain for each strategy.\n            \n            // Strat 1: Visit ONLY entry_cell\n            int gain_partial = p_vals[nr][nc];\n            int future_partial = get_future_potential(nr, nc, visited);\n            int score_partial = gain_partial + future_partial;\n            \n            int score_full = -1e9;\n            int future_full = -1;\n            \n            if (tiles[nxt_tid].size == 1) {\n                // Only one option\n                score_full = gain_partial; // gain_partial is total_val here\n                future_full = future_partial;\n            } else {\n                // Strat 2: Visit entry_cell AND other_cell\n                int gain_full = tiles[nxt_tid].total_val;\n                // We end up at other_cell. Can we exit from other_cell? Yes.\n                // Can we exit from entry_cell? No, we stepped on other_cell, we must be at other_cell.\n                // Wait, if we step on entry, then other. We are at other. We leave from other.\n                // So future depends on other_cell.\n                int future_other = get_future_potential(other_cell.r, other_cell.c, visited);\n                score_full = gain_full + future_other;\n                future_full = future_other;\n            }\n            \n            // Pick best strategy for this neighbor\n            int current_best_score = max(score_partial, score_full);\n            \n            // Add noise\n            int noise = rng() % 20;\n            current_best_score += noise;\n            \n            if (current_best_score > best_score_move) {\n                best_score_move = current_best_score;\n                best_next_pos = Point(nr, nc);\n                best_dir_idx = d;\n                \n                // Record which strategy was better to update path later\n                // If score_full > score_partial, we will traverse fully\n                // Note: For 1-tile, they are equal, doesn't matter.\n                best_is_full_traverse = (score_full > score_partial);\n            }\n        }\n        \n        if (best_score_move == -1) {\n            break; // No moves left\n        }\n        \n        // Execute best move\n        int nxt_tid = tile_ids[best_next_pos.r][best_next_pos.c];\n        visited[nxt_tid] = true;\n        \n        // Update path and score\n        path += DIR_CHARS[best_dir_idx];\n        curr_pos = best_next_pos;\n        score += p_vals[best_next_pos.r][best_next_pos.c];\n        \n        if (tiles[nxt_tid].size == 2 && best_is_full_traverse) {\n            // Find the other cell\n            Point p0 = tiles[nxt_tid].cells[0];\n            Point p1 = tiles[nxt_tid].cells[1];\n            Point other = (p0.r == best_next_pos.r && p0.c == best_next_pos.c) ? p1 : p0;\n            \n            // Move to other cell\n            // Find direction\n            for (int d = 0; d < 4; ++d) {\n                if (best_next_pos.r + DR[d] == other.r && best_next_pos.c + DC[d] == other.c) {\n                    path += DIR_CHARS[d];\n                    break;\n                }\n            }\n            curr_pos = other;\n            score += p_vals[other.r][other.c];\n        }\n    }\n    \n    return path;\n}\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    cin >> si >> sj;\n    \n    tile_ids.resize(H, vector<int>(W));\n    p_vals.resize(H, vector<int>(W));\n    \n    // Map tile ID to vector of cells to construct Tile objects\n    vector<vector<Point>> raw_tile_cells;\n    \n    // Temporary map to normalize tile IDs if needed (though problem says 0..M-1)\n    // Just read and store\n    \n    // First pass to find M and store points\n    int max_id = 0;\n    vector<vector<int>> temp_ids(H, vector<int>(W));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> temp_ids[i][j];\n            max_id = max(max_id, temp_ids[i][j]);\n        }\n    }\n    \n    raw_tile_cells.resize(max_id + 1);\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = temp_ids[i][j];\n            raw_tile_cells[id].push_back(Point(i, j));\n        }\n    }\n    \n    // Construct Tile objects\n    tiles.resize(raw_tile_cells.size());\n    for (int i = 0; i < raw_tile_cells.size(); ++i) {\n        tiles[i].id = i;\n        tiles[i].size = raw_tile_cells[i].size();\n        tiles[i].cells[0] = raw_tile_cells[i][0];\n        if (tiles[i].size == 2) {\n            tiles[i].cells[1] = raw_tile_cells[i][1];\n        }\n        // Will update total_val after reading p\n    }\n    \n    // Assign normalized IDs to grid (can reuse original if they are dense 0..M-1, they are)\n    tile_ids = temp_ids;\n    \n    // Read values\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> p_vals[i][j];\n            tiles[tile_ids[i][j]].total_val += p_vals[i][j];\n        }\n    }\n    \n    // Run multiple trials with random variations\n    string best_path = \"\";\n    int best_score = -1;\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Limit to 1.8 seconds to be safe\n    while (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() < 1800) {\n        string current_path = solve_single_run();\n        \n        // Calculate score of this path (re-simulate or just compute during solve?)\n        // Let's re-simulate to be sure and clean.\n        int score = 0;\n        int cr = si, cc = sj;\n        vector<bool> vis(tiles.size(), false);\n        vis[tile_ids[cr][cc]] = true;\n        score += p_vals[cr][cc];\n        \n        bool valid = true;\n        \n        for (char move : current_path) {\n            int d = -1;\n            if (move == 'U') d = 0;\n            else if (move == 'D') d = 1;\n            else if (move == 'L') d = 2;\n            else if (move == 'R') d = 3;\n            \n            int nr = cr + DR[d];\n            int nc = cc + DC[d];\n            \n            if (!inside(nr, nc)) { valid = false; break; }\n            \n            int tid = tile_ids[nr][nc];\n            if (vis[tid]) { valid = false; break; }\n            \n            vis[tid] = true;\n            cr = nr; cc = nc;\n            score += p_vals[cr][cc];\n        }\n        \n        if (valid && score > best_score) {\n            best_score = score;\n            best_path = current_path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <cstdio>\n#include <cmath>\n#include <algorithm>\n#include <string>\n#include <climits>\n\nusing namespace std;\n\n// Constants\nconst int N = 30;\nconst int V = N * N; \nconst int PARAMS = N * 2;\n\n// Global State for Estimator (Double for precision)\ndouble theta[PARAMS];\ndouble P[PARAMS * PARAMS];\n\n// Integer Weights for Pathfinding\nint theta_int[PARAMS];\n\n// Global State for Search (Reused arrays)\nint dist[V];         // g-score\nint f[V];            // f-score = g + h\nbool visited[V];     // closed set\nint prev_idx[V];     // path reconstruction\n\n// Precomputed Manhattan distance table\nint manhattan_dist[N][N];\n\n// --- RLS Functions ---\n\nvoid init_estimator() {\n    for (int i = 0; i < PARAMS; ++i) theta[i] = 5000.0;\n    for (int i = 0; i < PARAMS * PARAMS; ++i) P[i] = 0.0;\n    // Initial uncertainty\n    for (int i = 0; i < PARAMS; ++i) P[i * PARAMS + i] = 1000.0;\n}\n\nvoid update_rls(int* counts, double measured_total) {\n    double predicted_total = 0.0;\n    for (int i = 0; i < PARAMS; ++i) {\n        predicted_total += theta[i] * counts[i];\n    }\n\n    double error = measured_total - predicted_total;\n\n    double Px[PARAMS];\n    for (int i = 0; i < PARAMS; ++i) {\n        double sum = 0.0;\n        for (int j = 0; j < PARAMS; ++j) {\n            sum += P[i * PARAMS + j] * counts[j];\n        }\n        Px[i] = sum;\n    }\n\n    double denom = 1.0;\n    for (int i = 0; i < PARAMS; ++i) {\n        denom += counts[i] * Px[i];\n    }\n\n    double inv_denom = 1.0 / denom;\n\n    for (int i = 0; i < PARAMS; ++i) {\n        double k_i = Px[i] * inv_denom;\n        theta[i] += error * k_i;\n        \n        // Clamp to the physical lower bound (1000) to ensure consistent heuristic\n        // and prevent divergence/noise from pulling estimates to unrealistic values.\n        if (theta[i] < 1000.0) theta[i] = 1000.0;\n\n        for (int j = 0; j < PARAMS; ++j) {\n            P[i * PARAMS + j] -= k_i * Px[j];\n        }\n    }\n}\n\n// --- A* with Linear Scan (Optimized) ---\n\nstring find_path(int si, int sj, int ti, int tj) {\n    // 1. Update Integer Weights\n    // With clamping, min_theta is at least 1000.\n    int min_theta_int = 100000;\n    for (int i = 0; i < PARAMS; ++i) {\n        int val = (int)round(theta[i]);\n        theta_int[i] = val;\n        if (val < min_theta_int) min_theta_int = val;\n    }\n    // Safety clamp\n    if (min_theta_int < 1000) min_theta_int = 1000;\n\n    // 2. Precompute Manhattan Distances\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            manhattan_dist[r][c] = abs(r - ti) + abs(c - tj);\n        }\n    }\n\n    // 3. Initialize Arrays\n    const int INF_COST = 2000000000;\n    for(int i=0; i<V; ++i) {\n        dist[i] = INF_COST;\n        f[i] = INF_COST;\n        visited[i] = false;\n        prev_idx[i] = -1;\n    }\n    \n    int s = si * N + sj;\n    int t = ti * N + tj;\n    \n    dist[s] = 0;\n    f[s] = manhattan_dist[si][sj] * min_theta_int;\n\n    // Main Loop\n    while (true) {\n        // --- Find Unvisited Node with Minimum f ---\n        int u = -1;\n        int min_f = INF_COST;\n        \n        for (int i = 0; i < V; ++i) {\n            if (!visited[i] && f[i] < min_f) {\n                min_f = f[i];\n                u = i;\n            }\n        }\n\n        // If no nodes left or reached target, stop\n        if (u == -1 || u == t) break;\n\n        // Mark as processed (closed)\n        visited[u] = true;\n        \n        // --- Relax Neighbors ---\n        int ur = u / N;\n        int uc = u % N;\n\n        int dr[4] = {-1, 1, 0, 0};\n        int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = ur + dr[k];\n            int nc = uc + dc[k];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n\n            int v = nr * N + nc;\n            \n            int cost = (k < 2) ? theta_int[N + nc] : theta_int[ur];\n            if (cost < 1000) cost = 1000;\n\n            int new_g = dist[u] + cost;\n\n            // Since heuristic is consistent (min_theta >= 1000), \n            // we do not need to re-open visited nodes.\n            if (new_g < dist[v]) {\n                dist[v] = new_g;\n                prev_idx[v] = u;\n                f[v] = new_g + manhattan_dist[nr][nc] * min_theta_int;\n                // No need to set visited[v] = false\n            }\n        }\n    }\n\n    // Reconstruct Path\n    string path = \"\";\n    int curr = t;\n    int steps = 0;\n    \n    if (dist[t] != INF_COST) {\n        while (curr != s && steps < V) {\n            int p = prev_idx[curr];\n            if (p == -1) break;\n            int pr = p / N;\n            int pc = p % N;\n            int cr = curr / N;\n            int cc = curr % N;\n\n            if (pr < cr) path += \"D\";\n            else if (pr > cr) path += \"U\";\n            else if (pc < cc) path += \"R\";\n            else if (pc > cc) path += \"L\";\n\n            curr = p;\n            steps++;\n        }\n        reverse(path.begin(), path.end());\n    }\n    return path;\n}\n\n// --- Main ---\n\nint main() {\n    init_estimator();\n    int counts_buf[PARAMS];\n\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        scanf(\"%d %d %d %d\", &si, &sj, &ti, &tj);\n\n        string path = find_path(si, sj, ti, tj);\n        printf(\"%s\\n\", path.c_str());\n        fflush(stdout);\n\n        int measured;\n        scanf(\"%d\", &measured);\n\n        for(int i=0; i<PARAMS; ++i) counts_buf[i] = 0;\n        int r = si, c = sj;\n        for (char dir : path) {\n            if (dir == 'L') { counts_buf[r]++; c--; }\n            else if (dir == 'R') { counts_buf[r]++; c++; }\n            else if (dir == 'U') { counts_buf[N + c]++; r--; }\n            else if (dir == 'D') { counts_buf[N + c]++; r++; }\n        }\n        update_rls(counts_buf, (double)measured);\n    }\n\n    return 0;\n}","ahc004":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <unordered_map>\n#include <unordered_set>\n#include <numeric>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Solver\n// ---------------------------------------------------------\nclass Solver {\npublic:\n    int N;\n    int M;\n    vector<string> S;\n    vector<uint64_t> S_hashes;\n    unordered_set<uint64_t> s_hash_set; \n    mt19937 rng;\n\n    static const uint64_t BASE = 127;\n    \n    Solver(int n, int m, const vector<string>& s) : N(n), M(m), S(s), rng(chrono::steady_clock::now().time_since_epoch().count()) {\n        for (const auto& t : S) {\n            uint64_t h = compute_hash(t);\n            S_hashes.push_back(h);\n            s_hash_set.insert(h); \n        }\n    }\n\n    uint64_t compute_hash(const string& s) {\n        uint64_t h = 0;\n        for (char c : s) h = h * BASE + (c - 'A' + 1);\n        return h;\n    }\n\n    // -----------------------------------------------------\n    // Greedy Initialization\n    // -----------------------------------------------------\n    vector<string> greedy_init() {\n        vector<string> grid(N, string(N, '.'));\n        vector<int> indices(M);\n        iota(indices.begin(), indices.end(), 0);\n        shuffle(indices.begin(), indices.end(), rng);\n        stable_sort(indices.begin(), indices.end(), [&](int a, int b) {\n            return S[a].size() > S[b].size();\n        });\n\n        for (int idx : indices) {\n            const string& s = S[idx];\n            int len = s.size();\n            \n            // Strategy: Only place strings of length >= 6 greedily.\n            // Short strings are flexible; placing them greedily might block long strings.\n            // Let SA handle the short strings.\n            if (len < 6) continue;\n\n            int best_r = -1, best_c = -1;\n            bool is_row = false;\n            int min_cost = len + 1;\n            int best_match = 0;\n            \n            // Threshold for placing long strings\n            int threshold = len / 2;\n            if (threshold < 1) threshold = 1;\n\n            // Try rows\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    int cost = 0;\n                    int match = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[r][(c + k) % N];\n                        if (cur != '.' && cur != s[k]) { possible = false; break; }\n                        if (cur == '.') cost++;\n                        else match++;\n                    }\n                    if (possible) {\n                        if (cost < min_cost || (cost == min_cost && match > best_match)) {\n                            min_cost = cost; best_r = r; best_c = c; is_row = true; best_match = match;\n                        }\n                    }\n                }\n            }\n\n            // Try cols\n            for (int c = 0; c < N; c++) {\n                for (int r = 0; r < N; r++) {\n                    int cost = 0;\n                    int match = 0;\n                    bool possible = true;\n                    for (int k = 0; k < len; k++) {\n                        char cur = grid[(r + k) % N][c];\n                        if (cur != '.' && cur != s[k]) { possible = false; break; }\n                        if (cur == '.') cost++;\n                        else match++;\n                    }\n                    if (possible) {\n                        if (cost < min_cost || (cost == min_cost && match > best_match)) {\n                            min_cost = cost; best_r = r; best_c = c; is_row = false; best_match = match;\n                        }\n                    }\n                }\n            }\n\n            if (best_r != -1 && min_cost <= threshold) {\n                if (is_row) for (int k = 0; k < len; k++) grid[best_r][(best_c + k) % N] = s[k];\n                else for (int k = 0; k < len; k++) grid[(best_r + k) % N][best_c] = s[k];\n            }\n        }\n\n        // Fill remaining '.' with random chars\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == '.') grid[i][j] = 'A' + (rng() % 8);\n            }\n        }\n        return grid;\n    }\n\n    // -----------------------------------------------------\n    // Optimized SA with Targeted Hash Updates\n    // -----------------------------------------------------\n    int run_sa(vector<string>& grid, double time_limit_ms) {\n        unordered_map<uint64_t, int> substr_count;\n        int current_score = 0;\n\n        auto update_line_counts = [&](int line_idx, int affected_idx, auto line_getter, int delta) {\n            int diff = 0;\n            for (int L = 2; L <= 12; L++) {\n                for (int offset = 0; offset < L; offset++) {\n                    int start = (affected_idx - offset + N) % N;\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) {\n                        h = h * BASE + (line_getter((start + k) % N) - 'A' + 1);\n                    }\n\n                    if (delta > 0) {\n                        substr_count[h]++;\n                        if (substr_count[h] == 1 && s_hash_set.count(h)) diff++;\n                    } else {\n                        if (substr_count[h] == 1 && s_hash_set.count(h)) diff--;\n                        substr_count[h]--;\n                        if (substr_count[h] == 0) substr_count.erase(h);\n                    }\n                }\n            }\n            return diff;\n        };\n\n        // Initialize\n        substr_count.clear();\n        for (int i = 0; i < N; i++) {\n            for (int L = 2; L <= 12; L++) {\n                for (int start = 0; start < N; start++) {\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) h = h * BASE + (grid[i][(start+k)%N] - 'A' + 1);\n                    substr_count[h]++;\n                }\n            }\n        }\n        for (int j = 0; j < N; j++) {\n            for (int L = 2; L <= 12; L++) {\n                for (int start = 0; start < N; start++) {\n                    uint64_t h = 0;\n                    for (int k = 0; k < L; k++) h = h * BASE + (grid[(start+k)%N][j] - 'A' + 1);\n                    substr_count[h]++;\n                }\n            }\n        }\n\n        for (auto& h : S_hashes) {\n            if (substr_count.count(h)) current_score++;\n        }\n\n        int best_local_score = current_score;\n        vector<string> best_local_grid = grid;\n\n        auto sa_start = chrono::high_resolution_clock::now();\n        double temp_start = 40.0; // Reverted to 40.0\n        double temp_end = 0.001;\n\n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - sa_start).count();\n            if (elapsed > time_limit_ms) break;\n\n            double temp = temp_start + (temp_end - temp_start) * (elapsed / time_limit_ms);\n\n            int r = rng() % N;\n            int c = rng() % N;\n            char old_char = grid[r][c];\n            char new_char = 'A' + (rng() % 8);\n            if (new_char == old_char) continue;\n\n            int delta = 0;\n            \n            // Remove old\n            auto row_getter_old = [&](int idx) { return grid[r][idx]; };\n            delta += update_line_counts(r, c, row_getter_old, -1);\n            auto col_getter_old = [&](int idx) { return grid[idx][c]; };\n            delta += update_line_counts(c, r, col_getter_old, -1);\n\n            // Apply change\n            grid[r][c] = new_char;\n\n            // Add new\n            auto row_getter_new = [&](int idx) { return grid[r][idx]; };\n            delta += update_line_counts(r, c, row_getter_new, 1);\n            auto col_getter_new = [&](int idx) { return grid[idx][c]; };\n            delta += update_line_counts(c, r, col_getter_new, 1);\n\n            int new_score = current_score + delta;\n\n            if (delta > 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                current_score = new_score;\n                if (current_score > best_local_score) {\n                    best_local_score = current_score;\n                    best_local_grid = grid;\n                    if (current_score == M) break;\n                }\n            } else {\n                // Revert\n                update_line_counts(r, c, row_getter_new, -1);\n                update_line_counts(c, r, col_getter_new, -1);\n                grid[r][c] = old_char;\n                update_line_counts(r, c, row_getter_old, 1);\n                update_line_counts(c, r, col_getter_old, 1);\n            }\n        }\n\n        grid = best_local_grid;\n        return best_local_score;\n    }\n\n    void solve() {\n        auto global_start = chrono::high_resolution_clock::now();\n        int best_overall_score = -1;\n        vector<string> best_overall_grid;\n\n        // Pure Multi-Start Strategy\n        // Time budget ~230ms per run (reverted from 220ms)\n        double run_budget = 230.0;\n        \n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed_total = chrono::duration<double, milli>(now - global_start).count();\n            \n            // Ensure we don't run over time\n            if (elapsed_total > 2900) break;\n\n            // Adjust time budget for the last run\n            double current_budget = run_budget;\n            if (elapsed_total + current_budget > 2900) {\n                current_budget = 2900 - elapsed_total;\n            }\n            if (current_budget < 50) break; \n\n            vector<string> grid = greedy_init();\n            int run_score = run_sa(grid, current_budget);\n            \n            if (run_score > best_overall_score) {\n                best_overall_score = run_score;\n                best_overall_grid = grid;\n            }\n        }\n        \n        for (const auto& row : best_overall_grid) cout << row << endl;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M;\n    cin >> N >> M;\n    vector<string> S(M);\n    for (int i = 0; i < M; i++) cin >> S[i];\n\n    Solver solver(N, M, S);\n    solver.solve();\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\n#include <atcoder/scc>\n#include <atcoder/modint>\n#include <boost/geometry.hpp>\n#include <boost/geometry/geometries/point.hpp>\n#include <boost/geometry/geometries/box.hpp>\n#include <boost/geometry/index/rtree.hpp>\n\nnamespace bg = boost::geometry;\nnamespace bgi = boost::geometry::index;\nusing point = bg::model::point<int, 2, bg::cs::cartesian>;\nusing value = std::pair<point, size_t>; // point, index in nodes\n\nusing namespace std;\n\n// Global Constants\nconst int INF = 1e9;\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\nconst char dc[4] = {'R', 'L', 'D', 'U'};\n\nstruct Input {\n    int N;\n    int si, sj;\n    vector<string> grid;\n    int total_road;\n};\n\nInput read_input() {\n    Input in;\n    cin >> in.N >> in.si >> in.sj;\n    in.grid.resize(in.N);\n    in.total_road = 0;\n    for (int i = 0; i < in.N; ++i) {\n        cin >> in.grid[i];\n        for (int j = 0; j < in.N; ++j) {\n            if (in.grid[i][j] != '#') in.total_road++;\n        }\n    }\n    return in;\n}\n\n// Hopcroft-Karp for Maximum Bipartite Matching\nclass HopcroftKarp {\npublic:\n    int n_left, n_right;\n    vector<vector<int>> adj;\n    vector<int> pair_u, pair_v, dist;\n\n    HopcroftKarp(int n_left, int n_right) : n_left(n_left), n_right(n_right), adj(n_left) {}\n\n    void add_edge(int u, int v) {\n        adj[u].push_back(v);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        for (int u = 0; u < n_left; ++u) {\n            if (pair_u[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = INF;\n            }\n        }\n        dist[n_left] = INF; // Dummy node for right side check\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (dist[u] < dist[n_left]) {\n                for (int v : adj[u]) {\n                    if (pair_v[v] == -1) {\n                        dist[n_left] = dist[u] + 1;\n                    } else if (dist[pair_v[v]] == INF) {\n                        dist[pair_v[v]] = dist[u] + 1;\n                        q.push(pair_v[v]);\n                    }\n                }\n            }\n        }\n        return dist[n_left] != INF;\n    }\n\n    bool dfs(int u) {\n        if (u != n_left) {\n            for (int v : adj[u]) {\n                if (pair_v[v] == -1 || (dist[pair_v[v]] == dist[u] + 1 && dfs(pair_v[v]))) {\n                    pair_u[u] = v;\n                    pair_v[v] = u;\n                    return true;\n                }\n            }\n            dist[u] = INF;\n            return false;\n        }\n        return true;\n    }\n\n    int max_matching() {\n        pair_u.assign(n_left, -1);\n        pair_v.assign(n_right, -1);\n        dist.assign(n_left + 1, 0);\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < n_left; ++u) {\n                if (pair_u[u] == -1) {\n                    if (dfs(u)) {\n                        matching++;\n                    }\n                }\n            }\n        }\n        return matching;\n    }\n    \n    // Get Minimum Vertex Cover from Maximum Matching\n    // Returns a bitset or boolean vector for left and right nodes respectively\n    pair<vector<bool>, vector<bool>> get_min_vertex_cover() {\n        vector<bool> in_cover_left(n_left, false);\n        vector<bool> in_cover_right(n_right, false);\n        \n        // Standard Konig's theorem construction:\n        // Z = { unmatched L } U { reachable from unmatched L via alternating paths }\n        // Min VC = (L \\ Z) U (R n Z)\n        // Here dist[] is used. In BFS layering, nodes with dist[] < INF are in Z (L side)\n        // But we need to re-run or use the state from the last BFS? \n        // Let's just use the pairings to find Z.\n        // Z starts with unmatched U.\n        // Then alternating paths: U -> V (not paired) -> U (paired) ...\n        \n        queue<int> q;\n        vector<bool> visited_L(n_left, false);\n        vector<bool> visited_R(n_right, false);\n        \n        for(int u=0; u<n_left; ++u) {\n            if(pair_u[u] == -1) {\n                q.push(u);\n                visited_L[u] = true;\n            }\n        }\n        \n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            for(int v : adj[u]) {\n                if(!visited_R[v]) {\n                    visited_R[v] = true;\n                    int paired_u = pair_v[v];\n                    if(paired_u != -1 && !visited_L[paired_u]) {\n                        visited_L[paired_u] = true;\n                        q.push(paired_u);\n                    }\n                }\n            }\n        }\n        \n        for(int u=0; u<n_left; ++u) {\n            if(!visited_L[u]) in_cover_left[u] = true;\n        }\n        for(int v=0; v<n_right; ++v) {\n            if(visited_R[v]) in_cover_right[v] = true;\n        }\n        \n        return {in_cover_left, in_cover_right};\n    }\n};\n\n// Dijkstra\nvector<int> dijkstra(const Input& in, pair<int, int> start, const vector<pair<int,int>>& targets) {\n    int N = in.N;\n    int s_dist = start.first * N + start.second;\n    vector<int> dist(N*N, INF);\n    dist[s_dist] = 0;\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    pq.push({0, s_dist});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    return dist;\n}\n\nstring get_path(const Input& in, pair<int,int> s, pair<int,int> t) {\n    // Reconstruct path using simplified Dijkstra or A* since we just need one path\n    // Given N is small, Dijkstra with prev pointer is fine.\n    int N = in.N;\n    int s_idx = s.first * N + s.second;\n    int t_idx = t.first * N + t.second;\n    \n    vector<int> dist(N*N, INF);\n    vector<int> prev(N*N, -1);\n    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n    dist[s_idx] = 0;\n    pq.push({0, s_idx});\n    \n    while(!pq.empty()) {\n        auto [d, idx] = pq.top(); pq.pop();\n        if (idx == t_idx) break;\n        if (d > dist[idx]) continue;\n        \n        int i = idx / N;\n        int j = idx % N;\n        \n        for(int k=0; k<4; ++k) {\n            int ni = i + dx[k];\n            int nj = j + dy[k];\n            if(ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if(in.grid[ni][nj] == '#') continue;\n            \n            int cost = in.grid[ni][nj] - '0';\n            int nidx = ni * N + nj;\n            if (dist[nidx] > dist[idx] + cost) {\n                dist[nidx] = dist[idx] + cost;\n                prev[nidx] = k; // store direction\n                pq.push({dist[nidx], nidx});\n            }\n        }\n    }\n    \n    string path = \"\";\n    int curr = t_idx;\n    while(curr != s_idx) {\n        int dir = prev[curr];\n        path += dc[dir];\n        // reverse direction to go back\n        int rdir;\n        if(dir==0) rdir=1; if(dir==1) rdir=0; if(dir==2) rdir=3; if(dir==3) rdir=2;\n        \n        int ci = curr / N;\n        int cj = curr % N;\n        ci += dx[rdir];\n        cj += dy[rdir];\n        curr = ci * N + cj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid solve() {\n    Input in = read_input();\n    int N = in.N;\n    \n    // 1. Identify Segments\n    vector<vector<int>> h_id(N, vector<int>(N, -1));\n    vector<vector<int>> v_id(N, vector<int>(N, -1));\n    int h_cnt = 0, v_cnt = 0;\n    \n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                if(j>0 && in.grid[i][j-1] != '#' && h_id[i][j-1] != -1) {\n                    h_id[i][j] = h_id[i][j-1];\n                } else {\n                    h_id[i][j] = h_cnt++;\n                }\n            }\n        }\n    }\n    \n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        for(int i=0; i<N; ++i) {\n            if(in.grid[i][j] != '#') {\n                if(i>0 && in.grid[i-1][j] != '#' && v_id[i-1][j] != -1) {\n                    v_id[i][j] = v_id[i-1][j];\n                } else {\n                    v_id[i][j] = v_cnt++;\n                }\n            }\n        }\n    }\n    \n    // 2. Build Bipartite Graph\n    HopcroftKarp hk(h_cnt, v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                hk.add_edge(h_id[i][j], v_id[i][j]);\n            }\n        }\n    }\n    \n    // 3. Solve Min Vertex Cover\n    hk.max_matching();\n    auto [cover_h, cover_v] = hk.get_min_vertex_cover();\n    \n    // Set of covered segments\n    vector<bool> covered_h_seg = cover_h; // rename for clarity\n    vector<bool> covered_v_seg = cover_v;\n    \n    // 4. Select Key Points\n    // We need to visit points such that every segment in the cover is visited.\n    // Strategy: Collect all intersection points of segments in the cover.\n    // Also add representative points for segments in cover that might be isolated.\n    \n    set<pair<int, int>> key_points_set;\n    vector<pair<int, int>> key_points;\n    \n    auto add_point = [&](int i, int j) {\n        if(key_points_set.count({i,j}) == 0) {\n            key_points_set.insert({i,j});\n            key_points.push_back({i,j});\n        }\n    };\n\n    // Add intersections of covered segments\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                int hid = h_id[i][j];\n                int vid = v_id[i][j];\n                if(covered_h_seg[hid] && covered_v_seg[vid]) {\n                    add_point(i, j);\n                }\n            }\n        }\n    }\n    \n    // Add representative points for segments that are not \"covered\" by the intersections logic\n    // (i.e., segments in cover that don't intersect any other segment in cover)\n    // A segment is satisfied if we visit at least one point on it.\n    // So we ensure for each segment in cover, there is a key point on it.\n    \n    // Find segments without intersection\n    vector<bool> h_has_intersect(h_cnt, false);\n    vector<bool> v_has_intersect(v_cnt, false);\n    for(auto p : key_points) {\n        int i = p.first, j = p.second;\n        h_has_intersect[h_id[i][j]] = true;\n        v_has_intersect[v_id[i][j]] = true;\n    }\n    \n    // For segments in cover without intersection, add their point closest to Start\n    // Or just middle point. Middle point is safer and faster.\n    vector<vector<pair<int,int>>> h_cells(h_cnt);\n    vector<vector<pair<int,int>>> v_cells(v_cnt);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(in.grid[i][j] != '#') {\n                h_cells[h_id[i][j]].push_back({i,j});\n                v_cells[v_id[i][j]].push_back({i,j});\n            }\n        }\n    }\n    \n    for(int i=0; i<h_cnt; ++i) {\n        if(covered_h_seg[i] && !h_has_intersect[i]) {\n            // Add middle cell\n            int mid = h_cells[i].size() / 2;\n            add_point(h_cells[i][mid].first, h_cells[i][mid].second);\n        }\n    }\n    for(int i=0; i<v_cnt; ++i) {\n        if(covered_v_seg[i] && !v_has_intersect[i]) {\n            int mid = v_cells[i].size() / 2;\n            add_point(v_cells[i][mid].first, v_cells[i][mid].second);\n        }\n    }\n    \n    // Make sure start point is in key points to build the cycle\n    add_point(in.si, in.sj);\n    \n    // 5. Compute Distances between Key Points\n    int K = key_points.size();\n    vector<vector<int>> dist(K, vector<int>(K, INF));\n    \n    // Optimization: Only run Dijkstra from each point. K should be small.\n    // Map point to index\n    map<pair<int,int>, int> pt_to_idx;\n    for(int i=0; i<K; ++i) pt_to_idx[key_points[i]] = i;\n    \n    for(int i=0; i<K; ++i) {\n        auto ds = dijkstra(in, key_points[i], key_points);\n        for(int j=0; j<K; ++j) {\n            int idx = key_points[j].first * N + key_points[j].second;\n            dist[i][j] = ds[idx];\n        }\n    }\n    \n    // 6. Construct Path\n    // Greedy insertion to ensure coverage, then 2-opt\n    \n    int start_idx = pt_to_idx[{in.si, in.sj}];\n    \n    // Current Path: [start_idx]\n    vector<int> path = {start_idx};\n    // Current coverage: segments containing S\n    vector<bool> visited_h(h_cnt, false);\n    vector<bool> visited_v(v_cnt, false);\n    \n    auto visit_pt = [&](int idx) {\n        int i = key_points[idx].first;\n        int j = key_points[idx].second;\n        visited_h[h_id[i][j]] = true;\n        visited_v[v_id[i][j]] = true;\n    };\n    visit_pt(start_idx);\n    \n    // Check if all covered segments are satisfied\n    auto all_covered = [&]() {\n        for(int i=0; i<h_cnt; ++i) if(covered_h_seg[i] && !visited_h[i]) return false;\n        for(int i=0; i<v_cnt; ++i) if(covered_v_seg[i] && !visited_v[i]) return false;\n        return true;\n    };\n    \n    // Greedy Insertion\n    while(!all_covered()) {\n        int best_k = -1;\n        int best_pos = -1;\n        int best_gain = -INF;\n        int best_cost = INF;\n        \n        for(int k=0; k<K; ++k) {\n            if(find(path.begin(), path.end(), k) != path.end()) continue;\n            \n            // Gain: number of newly covered segments\n            int i = key_points[k].first;\n            int j = key_points[k].second;\n            int gain = 0;\n            if(covered_h_seg[h_id[i][j]] && !visited_h[h_id[i][j]]) gain++;\n            if(covered_v_seg[v_id[i][j]] && !visited_v[v_id[i][j]]) gain++;\n            \n            if(gain == 0) continue;\n            \n            // Find best insertion position\n            for(int pos=0; pos<=path.size(); ++pos) {\n                int u = (pos==0) ? path.back() : path[pos-1];\n                int v = (pos==path.size()) ? path[0] : path[pos];\n                \n                // Cost change: dist[u][k] + dist[k][v] - dist[u][v]\n                int delta = dist[u][k] + dist[k][v] - dist[u][v];\n                \n                if(gain * best_cost > best_gain * delta) {\n                    best_gain = gain;\n                    best_cost = delta;\n                    best_k = k;\n                    best_pos = pos;\n                }\n            }\n        }\n        \n        if(best_k == -1) {\n            // Should not happen if graph is connected and cover is valid\n            // Fallback: add any unvisited point on required segments\n            // (omitted for brevity, break to prevent infinite loop)\n            break; \n        }\n        \n        path.insert(path.begin() + best_pos, best_k);\n        visit_pt(best_k);\n    }\n    \n    // 2-opt Optimization\n    // Simple 2-opt loop\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        int n = path.size();\n        for(int i=0; i<n; ++i) {\n            for(int j=i+2; j<n + (i>0 ? 1 : 0); ++j) {\n                // Edge (i, i+1) and (j, j+1) become (i, j) and (i+1, j+1)\n                int u = path[i];\n                int v = path[(i+1)%n];\n                int x = path[j%n];\n                int y = path[(j+1)%n];\n                \n                int current = dist[u][v] + dist[x][y];\n                int proposal = dist[u][x] + dist[v][y];\n                \n                if(proposal < current) {\n                    // Reverse path between i+1 and j\n                    reverse(path.begin() + (i+1)%n, path.begin() + (j%n) + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // 7. Generate Output String\n    string full_path = \"\";\n    int p_sz = path.size();\n    for(int i=0; i<p_sz; ++i) {\n        int u = path[i];\n        int v = path[(i+1)%p_sz];\n        string sub = get_path(in, key_points[u], key_points[v]);\n        full_path += sub;\n    }\n    \n    cout << full_path << endl;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\n// Global problem parameters\nint N, M, K, R;\nvector<vector<int>> d; // Task requirements\nvector<vector<int>> adj; // Adjacency list: u -> v\nvector<int> in_degree; \n\n// Task states: 0 = locked, 1 = available, 2 = assigned\nvector<int> task_state;\nvector<int> start_day;\n\n// Skill estimation\nvector<vector<double>> s;\n\n// Tracking member assignments\nvector<int> member_task;\n\n// Heuristics\nvector<int> num_successors; \nvector<int> max_depth;\nvector<int> total_difficulty; \n\n// Random generator\nmt19937 rng(1);\nconst double EXPLORATION_RATE = 0.02; // 2% chance to pick a random task\nconst double MEMBER_EPSILON = 3.0;     // Member selection tolerance\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // --- Input Reading ---\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    total_difficulty.resize(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n            total_difficulty[i] += d[i][j];\n        }\n    }\n\n    adj.resize(N);\n    in_degree.resize(N, 0);\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        adj[u].push_back(v);\n        in_degree[v]++;\n    }\n\n    // --- Pre-processing: Heuristics ---\n    max_depth.assign(N, 0);\n    for (int u = N - 1; u >= 0; --u) {\n        for (int v : adj[u]) {\n            max_depth[u] = max(max_depth[u], max_depth[v] + 1);\n        }\n        if (max_depth[u] == 0) max_depth[u] = 1;\n    }\n\n    num_successors.assign(N, 0);\n    for (int u = N - 1; u >= 0; --u) {\n        for (int v : adj[u]) {\n            num_successors[u] += 1 + num_successors[v];\n        }\n    }\n\n    // --- Initialization ---\n    task_state.resize(N, 0);\n    start_day.resize(N, -1);\n\n    // Initialize root tasks\n    for (int i = 0; i < N; ++i) {\n        if (in_degree[i] == 0) {\n            task_state[i] = 1;\n        }\n    }\n\n    // Optimistic initialization: Members are generally stronger (avg 40) than tasks (avg 25)\n    s.resize(M, vector<double>(K, 30.0)); \n    member_task.resize(M, -1);\n\n    // --- Main Loop ---\n    int day = 0;\n    while (true) {\n        day++;\n\n        // 1. Build list of available tasks\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 1) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        // Sort by priority: \n        // 1. Max Depth (desc)\n        // 2. Num Successors (desc)\n        // 3. Total Difficulty (desc)\n        sort(available_tasks.begin(), available_tasks.end(), [&](int t1, int t2) {\n            if (max_depth[t1] != max_depth[t2]) return max_depth[t1] > max_depth[t2];\n            if (num_successors[t1] != num_successors[t2]) return num_successors[t1] > num_successors[t2];\n            if (total_difficulty[t1] != total_difficulty[t2]) return total_difficulty[t1] > total_difficulty[t2];\n            return t1 < t2;\n        });\n\n        // 2. Identify idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; ++j) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n\n        // 3. Assignment Loop\n        vector<pair<int, int>> assignments; \n        \n        int list_idx = 0;\n        \n        while (list_idx < static_cast<int>(available_tasks.size()) && !idle_members.empty()) {\n            \n            int task_to_assign = -1;\n\n            // Exploration Logic\n            if ((rng() % 1000) < (EXPLORATION_RATE * 1000)) {\n                int rand_offset = rng() % (available_tasks.size() - list_idx);\n                task_to_assign = available_tasks[list_idx + rand_offset];\n                // Swap to current position so we process it now and don't revisit it\n                swap(available_tasks[list_idx], available_tasks[list_idx + rand_offset]);\n            } else {\n                // Pick top task (Greedy)\n                task_to_assign = available_tasks[list_idx];\n            }\n\n            if (task_state[task_to_assign] != 1) {\n                // Task was assigned by a previous random selection? \n                // With linear processing and state check, this shouldn't happen if we don't pick duplicates.\n                // Just skip to be safe.\n                list_idx++;\n                continue;\n            }\n\n            // Find best member for this task (Epsilon-greedy)\n            vector<int> best_members;\n            double min_cost = 1e9;\n\n            for (int j : idle_members) {\n                double cost = 0.0;\n                for (int k = 0; k < K; ++k) {\n                    double diff = d[task_to_assign][k] - s[j][k];\n                    if (diff > 0) cost += diff;\n                }\n                \n                if (best_members.empty() || cost < min_cost + MEMBER_EPSILON) {\n                    if (cost < min_cost - MEMBER_EPSILON) {\n                        min_cost = cost;\n                        best_members.clear();\n                    }\n                    best_members.push_back(j);\n                }\n            }\n\n            if (!best_members.empty()) {\n                int member_id = best_members[rng() % best_members.size()];\n                \n                assignments.push_back({member_id + 1, task_to_assign + 1});\n                \n                member_task[member_id] = task_to_assign;\n                task_state[task_to_assign] = 2; \n                start_day[task_to_assign] = day;\n\n                // Remove member from idle list\n                auto it = find(idle_members.begin(), idle_members.end(), member_id);\n                if (it != idle_members.end()) {\n                    *it = idle_members.back();\n                    idle_members.pop_back();\n                }\n            }\n\n            // Move to next task index (whether assigned or not)\n            list_idx++;\n        }\n\n        // 4. Output\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n\n        // 5. Input & Update\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break;\n\n        vector<int> finished_members(n_finished);\n        for (int i = 0; i < n_finished; ++i) {\n            cin >> finished_members[i];\n            finished_members[i]--;\n        }\n\n        const double LEARNING_RATE_STD = 0.5; // Increased from 0.4 for faster convergence\n        const double T1_BOOST_RATE = 0.95;    \n\n        for (int member_idx : finished_members) {\n            int task_idx = member_task[member_idx];\n            if (task_idx == -1) continue;\n\n            int t = day - start_day[task_idx] + 1;\n\n            // --- SKILL UPDATE ---\n            double w_est = 0.0;\n            vector<int> deficit_dims;\n            for (int k = 0; k < K; ++k) {\n                double diff = d[task_idx][k] - s[member_idx][k];\n                if (diff > 0) {\n                    w_est += diff;\n                    deficit_dims.push_back(k);\n                }\n            }\n\n            if (t == 1) {\n                // t=1 implies perfect match. Boost skills.\n                for (int k : deficit_dims) {\n                    s[member_idx][k] += T1_BOOST_RATE * (d[task_idx][k] - s[member_idx][k]);\n                }\n            } else {\n                if (!deficit_dims.empty()) {\n                    // Underestimation or correct estimation. Adjust proportional to deficit.\n                    double error = w_est - t;\n                    double update = LEARNING_RATE_STD * error;\n                    double per_dim_update = update / deficit_dims.size();\n                    \n                    for (int k : deficit_dims) {\n                        s[member_idx][k] += per_dim_update;\n                        if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                    }\n                } else {\n                    // Overestimation (w=0 but t>1). Decrease skills proportional to requirements.\n                    double total_required = 0.0;\n                    for(int k=0; k<K; ++k) total_required += d[task_idx][k];\n                    \n                    if (total_required > 0) {\n                        double total_decrease = LEARNING_RATE_STD * t; \n                        for (int k = 0; k < K; ++k) {\n                            if (d[task_idx][k] > 0) {\n                                double w_k = d[task_idx][k] / total_required;\n                                double dec = total_decrease * w_k;\n                                s[member_idx][k] -= dec;\n                                if (s[member_idx][k] < 0) s[member_idx][k] = 0;\n                            }\n                        }\n                    }\n                }\n            }\n\n            // --- Unlock Dependencies ---\n            member_task[member_idx] = -1;\n            \n            for (int dependent_task : adj[task_idx]) {\n                in_degree[dependent_task]--;\n                if (in_degree[dependent_task] == 0) {\n                    task_state[dependent_task] = 1;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <atcoder/all>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nconst int CENTER_IDX = 2000; \n\nint dist_center(int x, int y) {\n    return abs(400 - x) + abs(400 - y);\n}\n\nlong long calculate_total_distance(const vector<int>& route_indices, const vector<Order>& orders) {\n    long long len = 0;\n    vector<pair<int, int>> coords;\n    coords.reserve(route_indices.size() + 1);\n    \n    for (int idx : route_indices) {\n        if (idx == CENTER_IDX) coords.push_back({400, 400});\n        else if (idx < 1000) coords.push_back({orders[idx].a, orders[idx].b});\n        else coords.push_back({orders[idx-1000].c, orders[idx-1000].d});\n    }\n    coords.push_back({400, 400}); // Return to center\n    \n    for (size_t i = 0; i < coords.size() - 1; ++i) {\n        len += (long long)abs(coords[i].first - coords[i+1].first) + abs(coords[i].second - coords[i+1].second);\n    }\n    return len;\n}\n\npair<int, int> get_pt(int idx, const vector<Order>& orders) {\n    if (idx == CENTER_IDX) return {400, 400};\n    if (idx < 1000) return {orders[idx].a, orders[idx].b};\n    return {orders[idx-1000].c, orders[idx-1000].d};\n}\n\nmt19937 gen(998244353);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    int N = 1000;\n    vector<Order> orders(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n    \n    long long global_best_len = 1e18;\n    vector<int> best_route_indices;\n    \n    int NUM_CONSTRUCTIONS = 6;\n    \n    for (int iter = 0; iter < NUM_CONSTRUCTIONS; ++iter) {\n        vector<int> used(N, 0);\n        vector<int> route_indices;\n        route_indices.push_back(CENTER_IDX); \n        \n        // --- Greedy Construction ---\n        for (int step = 0; step < 50; ++step) {\n            int best_order = -1;\n            long long best_delta = 1e18;\n            int best_u = -1;\n            int best_v = -1;\n            bool is_append_case = false;\n\n            vector<pair<int, int>> current_points;\n            for (int idx : route_indices) {\n                if (idx == CENTER_IDX) current_points.push_back({400, 400});\n                else if (idx < 1000) current_points.push_back({orders[idx].a, orders[idx].b});\n                else current_points.push_back({orders[idx-1000].c, orders[idx-1000].d});\n            }\n            \n            vector<pair<long long, int>> candidates;\n            for (int i = 0; i < N; ++i) {\n                if (used[i]) continue;\n                int min_dist = 2e9;\n                for (auto& p : current_points) {\n                    int d = abs(p.first - orders[i].a) + abs(p.second - orders[i].b);\n                    if (d < min_dist) min_dist = d;\n                }\n                int internal = abs(orders[i].a - orders[i].c) + abs(orders[i].b - orders[i].d);\n                candidates.push_back({(long long)min_dist + internal, i});\n            }\n            \n            sort(candidates.begin(), candidates.end());\n            int limit = min((int)candidates.size(), 100);\n            if (candidates.size() > 100) shuffle(candidates.begin(), candidates.begin() + 100, gen);\n            else shuffle(candidates.begin(), candidates.end(), gen);\n            \n            int L = route_indices.size();\n            \n            for (int k = 0; k < limit; ++k) {\n                int i = candidates[k].second;\n                int px = orders[i].a, py = orders[i].b;\n                int dx = orders[i].c, dy = orders[i].d;\n                \n                vector<int> dists_P(L), dists_D(L);\n                for (int m = 0; m < L; ++m) {\n                    dists_P[m] = abs(current_points[m].first - px) + abs(current_points[m].second - py);\n                    dists_D[m] = abs(current_points[m].first - dx) + abs(current_points[m].second - dy);\n                }\n\n                for (int u = 1; u < L; ++u) {\n                    for (int v = u + 1; v <= L; ++v) {\n                        long long removed = 0, added = 0;\n                        removed += abs(current_points[u-1].first - current_points[u].first) + abs(current_points[u-1].second - current_points[u].second);\n                        added += dists_P[u-1] + dists_P[u];\n                        if (v == L) {\n                            removed += dist_center(current_points[L-1].first, current_points[L-1].second);\n                            added += dists_D[L-1] + dist_center(dx, dy);\n                        } else {\n                            removed += abs(current_points[v-1].first - current_points[v].first) + abs(current_points[v-1].second - current_points[v].second);\n                            added += dists_D[v-1] + dists_D[v];\n                        }\n                        long long delta = added - removed;\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_order = i;\n                            best_u = u;\n                            best_v = v;\n                            is_append_case = false;\n                        }\n                    }\n                }\n                {\n                    long long removed = dist_center(current_points[L-1].first, current_points[L-1].second);\n                    long long added = dists_P[L-1] + (long long)abs(px - dx) + abs(py - dy) + dist_center(dx, dy);\n                    long long delta = added - removed;\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_order = i;\n                        best_u = L; \n                        best_v = L+1; \n                        is_append_case = true;\n                    }\n                }\n            }\n            \n            if (best_order != -1) {\n                used[best_order] = 1;\n                if (is_append_case) {\n                    route_indices.push_back(best_order);\n                    route_indices.push_back(best_order + 1000);\n                } else {\n                    route_indices.insert(route_indices.begin() + best_u, best_order);\n                    route_indices.insert(route_indices.begin() + best_v + 1, best_order + 1000);\n                }\n            }\n        }\n        \n        // --- Optimization Loop ---\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            \n            // Pass 1: 2-opt (with return edge)\n            bool opt_improved = true;\n            while(opt_improved) {\n                opt_improved = false;\n                int M = route_indices.size();\n                for (int u = 0; u < M - 1; ++u) {\n                    if (opt_improved) break;\n                    for (int v = u + 1; v < M; ++v) {\n                        unordered_set<int> seen;\n                        bool valid = true;\n                        for (int k = u + 1; k <= v; ++k) {\n                            int idx = route_indices[k];\n                            if (idx == CENTER_IDX) continue;\n                            int oid = (idx < 1000) ? idx : idx - 1000;\n                            if (seen.count(oid)) { valid = false; break; }\n                            seen.insert(oid);\n                        }\n                        if (!valid) continue;\n                        \n                        auto p_u = get_pt(route_indices[u], orders);\n                        auto p_u1 = get_pt(route_indices[u+1], orders);\n                        auto p_v = get_pt(route_indices[v], orders);\n                        \n                        // Handle return edge\n                        pair<int, int> p_v1;\n                        if (v == M - 1) p_v1 = {400, 400};\n                        else p_v1 = get_pt(route_indices[v+1], orders);\n                        \n                        long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                          + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                        long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                         + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                        \n                        if (added < removed) {\n                            reverse(route_indices.begin() + u + 1, route_indices.begin() + v + 1);\n                            opt_improved = true;\n                            improved = true;\n                            break; \n                        }\n                    }\n                }\n            }\n\n            // Pass 2: Swap (Replace worst order)\n            bool swap_improved = true;\n            while (swap_improved) {\n                swap_improved = false;\n                \n                // Find worst order in current route (highest marginal cost to remove)\n                // Marginal cost = len(route) - len(route_without_order)\n                // Higher is worse (removing it helps more)\n                \n                long long base_len = calculate_total_distance(route_indices, orders);\n                \n                int worst_oid = -1;\n                long long worst_gain = -1; // max gain if removed\n                int worst_p_pos = -1, worst_d_pos = -1;\n                \n                // Get unique IDs\n                vector<int> unique_oids;\n                unordered_set<int> seen;\n                for(int idx : route_indices) {\n                    if (idx == CENTER_IDX) continue;\n                    int oid = (idx < 1000) ? idx : idx - 1000;\n                    if(seen.insert(oid).second) unique_oids.push_back(oid);\n                }\n                \n                // Just check a few random ones to save time? Or all?\n                // Let's check all, it's fast.\n                for(int oid : unique_oids) {\n                    vector<int> temp_route;\n                    for (int idx : route_indices) {\n                        if (idx == oid || idx == oid + 1000) continue;\n                        temp_route.push_back(idx);\n                    }\n                    long long len_without = calculate_total_distance(temp_route, orders);\n                    long long gain = base_len - len_without;\n                    if (gain > worst_gain) {\n                        worst_gain = gain;\n                        worst_oid = oid;\n                    }\n                }\n                \n                if (worst_oid == -1) break;\n\n                // Try to replace worst_oid with best outside candidate\n                vector<int> temp_route;\n                for (int idx : route_indices) {\n                    if (idx == worst_oid || idx == worst_oid + 1000) continue;\n                    temp_route.push_back(idx);\n                }\n                \n                vector<pair<int, int>> temp_points;\n                for (int idx : temp_route) temp_points.push_back(get_pt(idx, orders));\n                int L = temp_route.size();\n                \n                int best_oid_in = -1;\n                int best_u_in = -1;\n                int best_v_in = -1;\n                long long best_delta_in = worst_gain; // Must be better than removing\n                bool is_append_in = false;\n                \n                vector<pair<long long, int>> unused_candidates;\n                for (int i = 0; i < N; ++i) {\n                    if (seen.count(i)) continue; \n                    int min_dist = 2e9;\n                    for (auto& p : temp_points) {\n                        int d = abs(p.first - orders[i].a) + abs(p.second - orders[i].b);\n                        if (d < min_dist) min_dist = d;\n                    }\n                    unused_candidates.push_back({(long long)min_dist, i});\n                }\n                \n                sort(unused_candidates.begin(), unused_candidates.end());\n                if (unused_candidates.size() > 50) unused_candidates.resize(50);\n                \n                for (auto& cand : unused_candidates) {\n                    int i = cand.second;\n                    int px = orders[i].a, py = orders[i].b;\n                    int dx = orders[i].c, dy = orders[i].d;\n                    \n                    vector<int> dists_P(L), dists_D(L);\n                    for (int m = 0; m < L; ++m) {\n                        dists_P[m] = abs(temp_points[m].first - px) + abs(temp_points[m].second - py);\n                        dists_D[m] = abs(temp_points[m].first - dx) + abs(temp_points[m].second - dy);\n                    }\n                    \n                    // Find best insertion for i\n                    long long local_best_delta = 1e18;\n                    int loc_u = -1, loc_v = -1;\n                    bool loc_app = false;\n                    \n                    for (int u = 1; u < L; ++u) {\n                        for (int v = u + 1; v <= L; ++v) {\n                            long long delta = 0;\n                            delta += dists_P[u-1] + dists_P[u] - (abs(temp_points[u-1].first - temp_points[u].first) + abs(temp_points[u-1].second - temp_points[u].second));\n                            if (v == L) {\n                                delta += dists_D[L-1] + dist_center(dx, dy) - dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                            } else {\n                                delta += dists_D[v-1] + dists_D[v] - (abs(temp_points[v-1].first - temp_points[v].first) + abs(temp_points[v-1].second - temp_points[v].second));\n                            }\n                            if (delta < local_best_delta) {\n                                local_best_delta = delta;\n                                loc_u = u; loc_v = v; loc_app = false;\n                            }\n                        }\n                    }\n                    {\n                        long long delta = dists_P[L-1] + (long long)abs(px-dx) + abs(py-dy) + dist_center(dx, dy) - dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                        if (delta < local_best_delta) {\n                            local_best_delta = delta;\n                            loc_u = L; loc_v = L+1; loc_app = true;\n                        }\n                    }\n                    \n                    if (local_best_delta < best_delta_in) {\n                        best_delta_in = local_best_delta;\n                        best_oid_in = i;\n                        best_u_in = loc_u;\n                        best_v_in = loc_v;\n                        is_append_in = loc_app;\n                    }\n                }\n                \n                if (best_oid_in != -1) {\n                    if (is_append_in) {\n                        temp_route.push_back(best_oid_in);\n                        temp_route.push_back(best_oid_in + 1000);\n                    } else {\n                        temp_route.insert(temp_route.begin() + best_u_in, best_oid_in);\n                        temp_route.insert(temp_route.begin() + best_v_in + 1, best_oid_in + 1000);\n                    }\n                    \n                    // Update used set? We are iterating, so just verify length.\n                    // Since we rebuilt temp_route, just assign it.\n                    route_indices = temp_route;\n                    swap_improved = true;\n                    improved = true;\n                }\n            }\n\n            // Pass 3: Re-insertion (Best Improvement)\n            // Check all 50 orders, apply best move\n            bool insert_improved = true;\n            while(insert_improved) {\n                insert_improved = false;\n                vector<int> unique_oids;\n                {\n                    unordered_set<int> seen;\n                    for (int idx : route_indices) {\n                        if (idx == CENTER_IDX) continue;\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (!seen.count(oid)) { seen.insert(oid); unique_oids.push_back(oid); }\n                    }\n                }\n                \n                long long best_global_delta = 0;\n                vector<int> best_global_route = route_indices;\n                \n                for (int oid : unique_oids) {\n                    vector<int> temp_route;\n                    for (int idx : route_indices) {\n                        if (idx == oid || idx == oid + 1000) continue;\n                        temp_route.push_back(idx);\n                    }\n                    \n                    long long current_len = calculate_total_distance(route_indices, orders);\n                    long long best_local_len = current_len;\n                    vector<int> best_local_route = route_indices;\n                    \n                    vector<pair<int, int>> temp_points;\n                    for (int idx : temp_route) temp_points.push_back(get_pt(idx, orders));\n                    int L = temp_route.size();\n                    \n                    int px = orders[oid].a, py = orders[oid].b;\n                    int dx = orders[oid].c, dy = orders[oid].d;\n                    \n                    vector<int> dists_P(L), dists_D(L);\n                    for (int m = 0; m < L; ++m) {\n                        dists_P[m] = abs(temp_points[m].first - px) + abs(temp_points[m].second - py);\n                        dists_D[m] = abs(temp_points[m].first - dx) + abs(temp_points[m].second - dy);\n                    }\n                    \n                    for (int u = 1; u <= L; ++u) {\n                         for (int v = u + 1; v <= L + 1; ++v) {\n                             long long added_cost = 0;\n                             long long removed_cost = 0;\n                             \n                             if (u < L) {\n                                 removed_cost += abs(temp_points[u-1].first - temp_points[u].first) + abs(temp_points[u-1].second - temp_points[u].second);\n                                 added_cost += dists_P[u-1] + dists_P[u];\n                             } else {\n                                 removed_cost += dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                                 added_cost += dists_P[L-1] + dist_center(px, py);\n                             }\n                             \n                             long long d_removed = 0;\n                             long long d_added = 0;\n                             int dist_P_to_D = abs(px-dx) + abs(py-dy);\n                             \n                             if (v == u+1) {\n                                 if (u < L) {\n                                     d_removed += dists_P[u];\n                                     d_added += dist_P_to_D + abs(dx - temp_points[u].first) + abs(dy - temp_points[u].second);\n                                 } else {\n                                     d_removed += dist_center(px, py);\n                                     d_added += dist_P_to_D + dist_center(dx, dy);\n                                 }\n                             } else {\n                                 int orig = v - 2; \n                                 if (orig < L - 1) {\n                                     d_removed += abs(temp_points[orig].first - temp_points[orig+1].first) + abs(temp_points[orig].second - temp_points[orig+1].second);\n                                     d_added += dists_D[orig] + abs(dx - temp_points[orig+1].first) + abs(dy - temp_points[orig+1].second);\n                                 } else {\n                                     d_removed += dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                                     d_added += dists_D[L-1] + dist_center(dx, dy);\n                                 }\n                             }\n                             \n                             if ((added_cost - removed_cost) + (d_added - d_removed) < 0) {\n                                 vector<int> new_route = temp_route;\n                                 new_route.insert(new_route.begin() + u, oid);\n                                 if (v == u+1) new_route.insert(new_route.begin() + u + 1, oid + 1000);\n                                 else new_route.insert(new_route.begin() + v, oid + 1000);\n                                 \n                                 long long new_len = calculate_total_distance(new_route, orders);\n                                 if (new_len < best_local_len) {\n                                     best_local_len = new_len;\n                                     best_local_route = new_route;\n                                 }\n                             }\n                         }\n                    }\n                    \n                    if (best_local_len < calculate_total_distance(best_global_route, orders)) {\n                        best_global_route = best_local_route;\n                    }\n                }\n                \n                if (calculate_total_distance(best_global_route, orders) < calculate_total_distance(route_indices, orders)) {\n                    route_indices = best_global_route;\n                    insert_improved = true;\n                    improved = true;\n                }\n            }\n\n            auto curr_time = chrono::high_resolution_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(curr_time - start_time).count() > 400) {\n                improved = false;\n            }\n        }\n\n        long long current_len = calculate_total_distance(route_indices, orders);\n        if (current_len < global_best_len) {\n            global_best_len = current_len;\n            best_route_indices = route_indices;\n        }\n    }\n    \n    // --- Deep Search on Best Solution ---\n    // Same logic\n    while(true) {\n        bool opt_improved = true;\n        while(opt_improved) {\n            opt_improved = false;\n            int M = best_route_indices.size();\n            for (int u = 0; u < M - 1; ++u) {\n                if (opt_improved) break;\n                for (int v = u + 1; v < M; ++v) {\n                    unordered_set<int> seen;\n                    bool valid = true;\n                    for (int k = u + 1; k <= v; ++k) {\n                        int idx = best_route_indices[k];\n                        if (idx == CENTER_IDX) continue;\n                        int oid = (idx < 1000) ? idx : idx - 1000;\n                        if (seen.count(oid)) { valid = false; break; }\n                        seen.insert(oid);\n                    }\n                    if (!valid) continue;\n                    \n                    auto p_u = get_pt(best_route_indices[u], orders);\n                    auto p_u1 = get_pt(best_route_indices[u+1], orders);\n                    auto p_v = get_pt(best_route_indices[v], orders);\n                    pair<int, int> p_v1;\n                    if (v == M - 1) p_v1 = {400, 400};\n                    else p_v1 = get_pt(best_route_indices[v+1], orders);\n                    \n                    long long removed = (long long)abs(p_u.first-p_u1.first) + abs(p_u.second-p_u1.second) \n                                      + abs(p_v.first-p_v1.first) + abs(p_v.second-p_v1.second);\n                    long long added = (long long)abs(p_u.first-p_v.first) + abs(p_u.second-p_v.second) \n                                     + abs(p_u1.first-p_v1.first) + abs(p_u1.second-p_v1.second);\n                    \n                    if (added < removed) {\n                        reverse(best_route_indices.begin() + u + 1, best_route_indices.begin() + v + 1);\n                        opt_improved = true;\n                        break; \n                    }\n                }\n            }\n        }\n        \n        // Swap\n        bool swap_improved = true;\n        while (swap_improved) {\n            swap_improved = false;\n            vector<int> unique_oids;\n            unordered_set<int> seen;\n            for (int idx : best_route_indices) {\n                if (idx == CENTER_IDX) continue;\n                int oid = (idx < 1000) ? idx : idx - 1000;\n                if (!seen.count(oid)) { seen.insert(oid); unique_oids.push_back(oid); }\n            }\n            \n            long long base_len = calculate_total_distance(best_route_indices, orders);\n            int worst_oid = -1;\n            long long worst_gain = -1;\n            \n            for(int oid : unique_oids) {\n                vector<int> temp_route;\n                for (int idx : best_route_indices) {\n                    if (idx == oid || idx == oid + 1000) continue;\n                    temp_route.push_back(idx);\n                }\n                long long len_without = calculate_total_distance(temp_route, orders);\n                long long gain = base_len - len_without;\n                if (gain > worst_gain) {\n                    worst_gain = gain;\n                    worst_oid = oid;\n                }\n            }\n            \n            if (worst_oid == -1) break;\n            \n            vector<int> temp_route;\n            for (int idx : best_route_indices) {\n                if (idx == worst_oid || idx == worst_oid + 1000) continue;\n                temp_route.push_back(idx);\n            }\n            \n            vector<pair<int, int>> temp_points;\n            for (int idx : temp_route) temp_points.push_back(get_pt(idx, orders));\n            int L = temp_route.size();\n            \n            int best_oid_in = -1;\n            int best_u_in = -1;\n            int best_v_in = -1;\n            long long best_delta_in = worst_gain;\n            bool is_append_in = false;\n            \n            vector<pair<long long, int>> unused_candidates;\n            for (int i = 0; i < N; ++i) {\n                if (seen.count(i)) continue;\n                int min_dist = 2e9;\n                for (auto& p : temp_points) {\n                    int d = abs(p.first - orders[i].a) + abs(p.second - orders[i].b);\n                    if (d < min_dist) min_dist = d;\n                }\n                unused_candidates.push_back({(long long)min_dist, i});\n            }\n            sort(unused_candidates.begin(), unused_candidates.end());\n            if (unused_candidates.size() > 50) unused_candidates.resize(50);\n            \n            for (auto& cand : unused_candidates) {\n                int i = cand.second;\n                int px = orders[i].a, py = orders[i].b;\n                int dx = orders[i].c, dy = orders[i].d;\n                \n                vector<int> dists_P(L), dists_D(L);\n                for (int m = 0; m < L; ++m) {\n                    dists_P[m] = abs(temp_points[m].first - px) + abs(temp_points[m].second - py);\n                    dists_D[m] = abs(temp_points[m].first - dx) + abs(temp_points[m].second - dy);\n                }\n                \n                long long local_best_delta = 1e18;\n                int loc_u = -1, loc_v = -1;\n                bool loc_app = false;\n                \n                for (int u = 1; u < L; ++u) {\n                    for (int v = u + 1; v <= L; ++v) {\n                        long long delta = 0;\n                        delta += dists_P[u-1] + dists_P[u] - (abs(temp_points[u-1].first - temp_points[u].first) + abs(temp_points[u-1].second - temp_points[u].second));\n                        if (v == L) {\n                            delta += dists_D[L-1] + dist_center(dx, dy) - dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                        } else {\n                            delta += dists_D[v-1] + dists_D[v] - (abs(temp_points[v-1].first - temp_points[v].first) + abs(temp_points[v-1].second - temp_points[v].second));\n                        }\n                        if (delta < local_best_delta) {\n                            local_best_delta = delta;\n                            loc_u = u; loc_v = v; loc_app = false;\n                        }\n                    }\n                }\n                {\n                    long long delta = dists_P[L-1] + (long long)abs(px-dx) + abs(py-dy) + dist_center(dx, dy) - dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                    if (delta < local_best_delta) {\n                        local_best_delta = delta;\n                        loc_u = L; loc_v = L+1; loc_app = true;\n                    }\n                }\n                \n                if (local_best_delta < best_delta_in) {\n                    best_delta_in = local_best_delta;\n                    best_oid_in = i;\n                    best_u_in = loc_u;\n                    best_v_in = loc_v;\n                    is_append_in = loc_app;\n                }\n            }\n            \n            if (best_oid_in != -1) {\n                if (is_append_in) {\n                    temp_route.push_back(best_oid_in);\n                    temp_route.push_back(best_oid_in + 1000);\n                } else {\n                    temp_route.insert(temp_route.begin() + best_u_in, best_oid_in);\n                    temp_route.insert(temp_route.begin() + best_v_in + 1, best_oid_in + 1000);\n                }\n                best_route_indices = temp_route;\n                swap_improved = true;\n            }\n        }\n\n        // Re-insertion\n        bool insert_improved = true;\n        while(insert_improved) {\n            insert_improved = false;\n            vector<int> unique_oids;\n            unordered_set<int> seen;\n            for (int idx : best_route_indices) {\n                if (idx == CENTER_IDX) continue;\n                int oid = (idx < 1000) ? idx : idx - 1000;\n                if (!seen.count(oid)) { seen.insert(oid); unique_oids.push_back(oid); }\n            }\n            \n            long long best_global_delta = 0;\n            vector<int> best_global_route = best_route_indices;\n            long long best_global_len = calculate_total_distance(best_route_indices, orders);\n            \n            for (int oid : unique_oids) {\n                vector<int> temp_route;\n                for (int idx : best_route_indices) {\n                    if (idx == oid || idx == oid + 1000) continue;\n                    temp_route.push_back(idx);\n                }\n                \n                long long best_local_len = best_global_len;\n                vector<int> best_local_route = best_route_indices;\n                \n                vector<pair<int, int>> temp_points;\n                for (int idx : temp_route) temp_points.push_back(get_pt(idx, orders));\n                int L = temp_route.size();\n                \n                int px = orders[oid].a, py = orders[oid].b;\n                int dx = orders[oid].c, dy = orders[oid].d;\n                \n                vector<int> dists_P(L), dists_D(L);\n                for (int m = 0; m < L; ++m) {\n                    dists_P[m] = abs(temp_points[m].first - px) + abs(temp_points[m].second - py);\n                    dists_D[m] = abs(temp_points[m].first - dx) + abs(temp_points[m].second - dy);\n                }\n                \n                for (int u = 1; u <= L; ++u) {\n                     for (int v = u + 1; v <= L + 1; ++v) {\n                         long long added_cost = 0;\n                         long long removed_cost = 0;\n                         \n                         if (u < L) {\n                             removed_cost += abs(temp_points[u-1].first - temp_points[u].first) + abs(temp_points[u-1].second - temp_points[u].second);\n                             added_cost += dists_P[u-1] + dists_P[u];\n                         } else {\n                             removed_cost += dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                             added_cost += dists_P[L-1] + dist_center(px, py);\n                         }\n                         \n                         long long d_removed = 0;\n                         long long d_added = 0;\n                         int dist_P_to_D = abs(px-dx) + abs(py-dy);\n                         \n                         if (v == u+1) {\n                             if (u < L) {\n                                 d_removed += dists_P[u];\n                                 d_added += dist_P_to_D + abs(dx - temp_points[u].first) + abs(dy - temp_points[u].second);\n                             } else {\n                                 d_removed += dist_center(px, py);\n                                 d_added += dist_P_to_D + dist_center(dx, dy);\n                             }\n                         } else {\n                             int orig = v - 2; \n                             if (orig < L - 1) {\n                                 d_removed += abs(temp_points[orig].first - temp_points[orig+1].first) + abs(temp_points[orig].second - temp_points[orig+1].second);\n                                 d_added += dists_D[orig] + abs(dx - temp_points[orig+1].first) + abs(dy - temp_points[orig+1].second);\n                             } else {\n                                 d_removed += dist_center(temp_points[L-1].first, temp_points[L-1].second);\n                                 d_added += dists_D[L-1] + dist_center(dx, dy);\n                             }\n                         }\n                         \n                         if ((added_cost - removed_cost) + (d_added - d_removed) < 0) {\n                             vector<int> new_route = temp_route;\n                             new_route.insert(new_route.begin() + u, oid);\n                             if (v == u+1) new_route.insert(new_route.begin() + u + 1, oid + 1000);\n                             else new_route.insert(new_route.begin() + v, oid + 1000);\n                             \n                             long long new_len = calculate_total_distance(new_route, orders);\n                             if (new_len < best_local_len) {\n                                 best_local_len = new_len;\n                                 best_local_route = new_route;\n                             }\n                         }\n                     }\n                }\n                \n                if (best_local_len < best_global_len) {\n                    best_global_len = best_local_len;\n                    best_global_route = best_local_route;\n                }\n            }\n            \n            if (best_global_len < calculate_total_distance(best_route_indices, orders)) {\n                best_route_indices = best_global_route;\n                insert_improved = true;\n            }\n        }\n        \n        auto curr_time = chrono::high_resolution_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(curr_time - start_time).count() > 1980) {\n            break;\n        }\n    }\n    \n    // --- Output ---\n    vector<int> final_orders;\n    set<int> seen;\n    for (int idx : best_route_indices) {\n        if (idx == CENTER_IDX) continue;\n        int oid = (idx < 1000) ? idx : idx - 1000;\n        if (seen.find(oid) == seen.end()) {\n            final_orders.push_back(oid + 1);\n            seen.insert(oid);\n        }\n    }\n    \n    cout << 50;\n    for (int oid : final_orders) cout << \" \" << oid;\n    cout << \"\\n\";\n    \n    cout << best_route_indices.size() + 1;\n    for (int idx : best_route_indices) {\n        int x, y;\n        if (idx == CENTER_IDX) { x = 400; y = 400; }\n        else if (idx < 1000) { x = orders[idx].a; y = orders[idx].b; }\n        else { x = orders[idx-1000].c; y = orders[idx-1000].d; }\n        cout << \" \" << x << \" \" << y;\n    }\n    cout << \" \" << 400 << \" \" << 400 << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct DSU {\n    vector<int> parent;\n    int components;\n\n    DSU(int n) : parent(n), components(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        parent[x] = y;\n        components--;\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N = 400;\n    int M = 1995;\n\n    vector<pair<int, int>> points(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = points[edges[i].u].first - points[edges[i].v].first;\n        int dy = points[edges[i].u].second - points[edges[i].v].second;\n        double dist = sqrt((double)dx * dx + (double)dy * dy);\n        edges[i].d = (int)round(dist);\n    }\n\n    DSU dsu(N);\n    int taken = 0;\n\n    // Buffer: 75 ensures we can be very selective.\n    const int SAFETY_BUFFER = 75;\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        if (taken == N - 1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int need = dsu.components - 1;\n        \n        // Collect future useful edges\n        int available = 0;\n        vector<int> candidate_ds;\n        candidate_ds.reserve(M - i - 1);\n        \n        for (int j = i + 1; j < M; ++j) {\n            if (dsu.find(edges[j].u) != dsu.find(edges[j].v)) {\n                available++;\n                candidate_ds.push_back(edges[j].d);\n            }\n        }\n\n        // \"Must Take\" Logic\n        if (available <= need + SAFETY_BUFFER) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n            continue;\n        }\n\n        // Geometric Heuristic\n        sort(candidate_ds.begin(), candidate_ds.end());\n        int d_ref = candidate_ds[need - 1];\n\n        bool accept = false;\n        double ratio = (double)l / d;\n\n        // 1. Great deal: Always take\n        if (ratio <= 1.6) {\n            accept = true;\n        }\n        // 2. Geometric Advantage (Short Edge)\n        // Maximized threshold (2.8): We take almost every short edge to replicate the geometric MST.\n        else if (d <= d_ref) {\n            if (ratio <= 2.8) {\n                accept = true;\n            }\n        }\n        // 3. Geometric Disadvantage (Long Edge)\n        // Strict threshold (2.05): Only take long edges if they are a bargain.\n        else {\n            if (ratio <= 2.05) {\n                accept = true;\n            }\n        }\n\n        if (accept) {\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            taken++;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\n#include <atcoder/all>\n#include <boost/multi_array.hpp>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int TURNS = 300;\nconstexpr int DX[4] = {0, 0, 1, -1};\nconstexpr int DY[4] = {1, -1, 0, 0};\nconstexpr char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\nconstexpr char BLOCK_CHAR[4] = {'r', 'l', 'd', 'u'}; // Action to block (x+dx, y+dy)\n\nstruct Point {\n    int x, y;\n    Point() : x(0), y(0) {}\n    Point(int x, int y) : x(x), y(y) {}\n    bool operator==(const Point& p) const { return x == p.x && y == p.y; }\n    int dist(const Point& p) const { return abs(x - p.x) + abs(y - p.y); }\n};\n\n// Global State\nint N, M;\nvector<Point> pets;\nvector<Point> humans;\nvector<int> pet_types; \n// grid[x][y] : true if impassable (wall)\n// Note: walls are built on squares. Humans/Pets can be on squares that are passable.\n// Once a wall is built on (x,y), it becomes impassable.\n// Humans and Pets can be on the same square? \"each square can contain any number of humans and pets.\"\n// So grid state is independent of entity positions, except for the \"cannot build adjacent to pet\" rule.\nvector<vector<bool>> grid; \n\n// Input parsing\nvoid read_init() {\n    cin >> N;\n    pets.resize(N);\n    pet_types.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> pet_types[i];\n        // Convert to 0-based for internal logic if needed, but problem is 1-based\n        pets[i].x--; pets[i].y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    grid.assign(H, vector<bool>(W, false));\n}\n\n// Read pet movements for one turn\n// pet_moves[i] is a string of characters like \"U\", \"R.\", etc.\nvoid read_turn(vector<string>& pet_moves) {\n    pet_moves.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_moves[i];\n    }\n}\n\n// Apply pet movements\nvoid apply_moves(const vector<string>& pet_moves) {\n    for (int i = 0; i < N; ++i) {\n        int cx = pets[i].x;\n        int cy = pets[i].y;\n        for (char c : pet_moves[i]) {\n            int dir = -1;\n            if (c == 'U') dir = 3;\n            else if (c == 'D') dir = 2;\n            else if (c == 'L') dir = 1;\n            else if (c == 'R') dir = 0;\n            \n            if (dir != -1) {\n                int nx = cx + DX[dir];\n                int ny = cy + DY[dir];\n                // Pets move randomly but logically. \n                // The problem says they move to passable squares chosen randomly.\n                // Assuming the server provides valid moves that respect grid bounds and walls.\n                // We just update coordinates.\n                cx = nx;\n                cy = ny;\n            }\n        }\n        pets[i].x = cx;\n        pets[i].y = cy;\n    }\n}\n\n// Helper to check bounds\nbool inside(int x, int y) {\n    return 0 <= x && x < H && 0 <= y && y < W;\n}\n\n// Helper to check if a cell is buildable (wall action)\n// Cannot build if:\n// 1. The cell contains a pet or human at the START of the turn.\n// 2. The cell is already a wall.\n// 3. An adjacent cell contains a pet.\nbool is_buildable(int x, int y, const vector<Point>& current_pets, const vector<Point>& current_humans) {\n    if (!inside(x, y)) return false;\n    if (grid[x][y]) return false; // Already impassable\n    \n    // Check if pet or human is on (x, y)\n    for (const auto& p : current_pets) {\n        if (p.x == x && p.y == y) return false;\n    }\n    for (const auto& h : current_humans) {\n        if (h.x == x && h.y == y) return false;\n    }\n    \n    // Check if adjacent cell contains a pet\n    for (int i = 0; i < 4; ++i) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (!inside(nx, ny)) continue;\n        for (const auto& p : current_pets) {\n            if (p.x == nx && p.y == ny) return false;\n        }\n    }\n    return true;\n}\n\n// Strategy: Secure a large rectangle with 0 pets.\nstruct Rect {\n    int r1, r2, c1, c2;\n    int area;\n};\n\n// Find best rectangle to secure\n// Criteria: \n// 1. Contains 0 pets currently.\n// 2. Maximize Area.\n// 3. Minimize Wall Length (perimeter).\n// 4. Maximize distance from pets to wall (safety).\nRect find_best_rectangle() {\n    // 2D prefix sum for pet counts\n    vector<vector<int>> ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int cnt = 0;\n            for (const auto& p : pets) {\n                if (p.x == i && p.y == j) cnt++;\n            }\n            ps[i+1][j+1] = ps[i][j+1] + ps[i+1][j] - ps[i][j] + cnt;\n        }\n    }\n    \n    auto get_pet_count = [&](int r1, int c1, int r2, int c2) {\n        return ps[r2+1][c2+1] - ps[r1][c2+1] - ps[r2+1][c1] + ps[r1][c1];\n    };\n\n    double best_score = -1e9;\n    Rect best_r = {0, H-1, 0, W-1, 0};\n\n    // Iterate over all rectangles\n    // To limit search, maybe only consider those touching boundary? \n    // No, a central island is also valid, though walls are expensive.\n    // Let's iterate all.\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (get_pet_count(r1, c1, r2, c2) > 0) continue;\n                    \n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    \n                    // Calculate required wall length\n                    // Walls needed on sides that are not touching map boundary\n                    int wall_len = 0;\n                    if (r1 > 0) wall_len += (c2 - c1 + 1);\n                    if (r2 < H - 1) wall_len += (c2 - c1 + 1);\n                    if (c1 > 0) wall_len += (r2 - r1 + 1);\n                    if (c2 < W - 1) wall_len += (r2 - r1 + 1);\n                    \n                    // Safety: min distance of any pet to the rectangle boundary\n                    // If a pet is very close, we can't build there easily.\n                    // This is a heuristic.\n                    int min_dist = H + W;\n                    for (const auto& p : pets) {\n                        // If inside, skip (already filtered)\n                        // Distance to rectangle\n                        int dx = max({r1 - p.x, 0, p.x - r2});\n                        int dy = max({c1 - p.y, 0, p.y - c2});\n                        int d = dx + dy;\n                        // If pet is outside, d >= 1\n                        if (d < min_dist) min_dist = d;\n                    }\n                    \n                    // We cannot build adjacent to pet. So we need buffer of 1.\n                    // If min_dist < 2, the wall is adjacent to pet.\n                    // Actually, if min_dist == 1, pet is adjacent to rect. \n                    // We need to build wall outside rect. So dist to wall is min_dist - 1.\n                    // If dist_to_wall == 0 (pet touching rect), we CANNOT build the wall on that side.\n                    // So such rectangles are dangerous.\n                    \n                    // Score: Area - Cost\n                    // Cost = Wall_Length * K1 + (if unsafe) * LargePenalty\n                    double score = (double)area;\n                    \n                    // Penalty for walls\n                    score -= wall_len * 0.5; // Tunable factor\n                    \n                    // Penalty for low safety margin\n                    // Buffer needed is 1.\n                    // If pet is touching boundary (min_dist=1), we are blocked.\n                    if (min_dist == 0) { /* Should not happen since count=0 */ }\n                    else if (min_dist == 1) {\n                        score -= 100; // Heavily penalize touching pets\n                    } else {\n                        // Slight penalty for being close\n                        score -= (5.0 / min_dist);\n                    }\n                    \n                    // Bonus for containing humans? No, we can move them in.\n                    // Penalty for humans being far away?\n                    // Sum of distances from humans to rect.\n                    int total_dist = 0;\n                    for (const auto& h : humans) {\n                        // Closest point in rect\n                        int cx = max(r1, min(h.x, r2));\n                        int cy = max(c1, min(h.y, c2));\n                        total_dist += abs(h.x - cx) + abs(h.y - cy);\n                    }\n                    score -= total_dist * 0.05;\n\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r = {r1, r2, c1, c2, area};\n                    }\n                }\n            }\n        }\n    }\n    return best_r;\n}\n\n// Action Generation\nvector<char> generate_actions(Rect& target_rect, vector<Point>& current_humans, int& phase, vector<Point>& wall_tasks, int turn_cnt) {\n    vector<char> actions(M, '.');\n    \n    // Wall cells needed to seal the rectangle\n    vector<Point> needed_walls;\n    // r1-1, r2+1, c1-1, c2+1\n    if (target_rect.r1 > 0) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r1 - 1, c);\n    if (target_rect.r2 < H - 1) for (int c = target_rect.c1; c <= target_rect.c2; ++c) needed_walls.emplace_back(target_rect.r2 + 1, c);\n    if (target_rect.c1 > 0) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c1 - 1);\n    if (target_rect.c2 < W - 1) for (int r = target_rect.r1; r <= target_rect.r2; ++r) needed_walls.emplace_back(r, target_rect.c2 + 1);\n    \n    // Remove already built walls\n    needed_walls.erase(remove_if(needed_walls.begin(), needed_walls.end(), \n        [&](const Point& p){ return grid[p.x][p.y]; }), \n        needed_walls.end());\n        \n    // Phase 1: Move humans into the rectangle\n    if (phase == 1) {\n        bool all_in = true;\n        for (int i = 0; i < M; ++i) {\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            if (target_rect.r1 <= hx && hx <= target_rect.r2 && target_rect.c1 <= hy && hy <= target_rect.c2) {\n                actions[i] = '.';\n                continue;\n            }\n            all_in = false;\n            \n            // Move towards closest point in rect\n            int tx = max(target_rect.r1, min(hx, target_rect.r2));\n            int ty = max(target_rect.c1, min(hy, target_rect.c2));\n            \n            // BFS to find shortest path to (tx, ty) or any cell in rect?\n            // Simple greedy: reduce Manhattan distance\n            int best_d = abs(hx - tx) + abs(hy - ty);\n            int best_dir = -1;\n            \n            for (int d = 0; d < 4; ++d) {\n                int nx = hx + DX[d];\n                int ny = hy + DY[d];\n                if (!inside(nx, ny)) continue;\n                if (grid[nx][ny]) continue; // Can't move into wall\n                \n                // Check if (nx, ny) is in rect (good)\n                bool in_rect = (target_rect.r1 <= nx && nx <= target_rect.r2 && target_rect.c1 <= ny && ny <= target_rect.c2);\n                int d_score = abs(nx - tx) + abs(ny - ty);\n                if (in_rect) d_score = -1000; // Priority to enter\n                \n                if (d_score < best_d) {\n                    best_d = d_score;\n                    best_dir = d;\n                }\n            }\n            if (best_dir != -1) {\n                actions[i] = DIR_CHAR[best_dir];\n                current_humans[i].x += DX[best_dir];\n                current_humans[i].y += DY[best_dir];\n            }\n        }\n        \n        if (all_in) {\n            phase = 2;\n            // Assign wall tasks\n            wall_tasks = needed_walls;\n            // Shuffle to distribute work randomly? Or keep sorted?\n            // Keep simple.\n        }\n    } \n    // Phase 2: Build walls\n    else if (phase == 2) {\n        if (wall_tasks.empty()) {\n            phase = 3;\n            return actions;\n        }\n        \n        // Greedy assignment: each human picks closest task\n        // To avoid conflict, we process humans in order of distance to tasks? \n        // Or simply assign static chunks? \n        // Static chunks are better for consistency.\n        \n        // Let's use a persistent assignment.\n        // If no assignment yet, create one.\n        static vector<int> assignment(M, -1);\n        static bool assigned = false;\n        \n        if (!assigned || wall_tasks.size() != (unsigned)(assignment.size())) {\n             // Simple Round Robin assignment based on human index\n             assignment.clear();\n             assignment.resize(M, -1);\n             for (size_t i = 0; i < wall_tasks.size(); ++i) {\n                 assignment[i % M] = i;\n             }\n             assigned = true;\n        }\n        \n        // Execute\n        for (int i = 0; i < M; ++i) {\n            int task_idx = assignment[i];\n            if (task_idx == -1 || task_idx >= (int)wall_tasks.size()) {\n                actions[i] = '.';\n                continue;\n            }\n            \n            Point target = wall_tasks[task_idx];\n            int hx = current_humans[i].x;\n            int hy = current_humans[i].y;\n            \n            // If adjacent, try build\n            bool adj = false;\n            int build_dir = -1;\n            for (int d = 0; d < 4; ++d) {\n                if (hx + DX[d] == target.x && hy + DY[d] == target.y) {\n                    adj = true;\n                    build_dir = d;\n                    break;\n                }\n            }\n            \n            if (adj) {\n                // Check if buildable\n                // Need to check adjacency to pets at the START of this turn\n                // We have `pets` vector which is already updated for this turn?\n                // No, `pets` in global state is updated at the START of the loop in main.\n                // So `pets` holds positions at the START of the turn.\n                // We check buildability against `pets`.\n                \n                // is_buildable checks `grid` and `pets` and `current_humans`\n                // But `current_humans` is being modified. We should use previous pos? \n                // Rule: \"cannot choose a square that contains pets or humans at the start of this turn\"\n                // So we check against `humans` (initial state of turn).\n                // `current_humans` is a copy we modify to simulate moves. \n                // We need the actual start positions.\n                // Let's pass `humans` (the vector holding start-of-turn pos) to is_buildable?\n                // Or just check `current_humans[i]` before moving? No, that's wrong for other humans.\n                // Let's assume `humans` is not modified yet.\n                // Wait, I modify `current_humans` in place.\n                // So at the start of generate_actions, `current_humans` IS the start position.\n                // Good.\n                \n                if (is_buildable(target.x, target.y, pets, current_humans)) {\n                    actions[i] = BLOCK_CHAR[build_dir];\n                    grid[target.x][target.y] = true; // Mark as built immediately for logic?\n                    // Note: The problem says \"perform each action simultaneously\".\n                    // However, for our planning in the next turn, we update grid.\n                    // If two humans build the same wall, the second one does nothing (rule: \"If you choose a square that is already impassable, nothing happens\").\n                    // But we shouldn't assign two humans to the same task ideally.\n                    // With round robin, tasks are distinct.\n                    \n                    // Remove task\n                    wall_tasks.erase(wall_tasks.begin() + task_idx);\n                    // Update assignments?\n                    // Shift indices down for those > task_idx\n                    for (int k = 0; k < M; ++k) {\n                        if (assignment[k] > task_idx) assignment[k]--;\n                    }\n                } else {\n                    actions[i] = '.'; // Cannot build now\n                }\n            } else {\n                // Move towards target\n                // BFS or simple Manhattan\n                int best_d = abs(hx - target.x) + abs(hy - target.y);\n                int best_dir = -1;\n                \n                for (int d = 0; d < 4; ++d) {\n                    int nx = hx + DX[d];\n                    int ny = hy + DY[d];\n                    if (!inside(nx, ny)) continue;\n                    if (grid[nx][ny]) continue;\n                    if (nx == target.x && ny == target.y) continue; // Moving onto the wall square? No, can only build adjacent. \n                    // Actually, can we move onto a square that will be a wall? \n                    // \"It is not possible to move to a square that becomes impassable by another person's action in this turn.\"\n                    // We are the person. If we move to target, we can't build it (must be adjacent).\n                    // So we shouldn't move onto target.\n                    \n                    int d_score = abs(nx - target.x) + abs(ny - target.y);\n                    if (d_score < best_d) {\n                        best_d = d_score;\n                        best_dir = d;\n                    }\n                }\n                if (best_dir != -1) {\n                    actions[i] = DIR_CHAR[best_dir];\n                    current_humans[i].x += DX[best_dir];\n                    current_humans[i].y += DY[best_dir];\n                } else {\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        if (wall_tasks.empty()) phase = 3;\n    }\n    // Phase 3: Done\n    else {\n        for (int i = 0; i < M; ++i) actions[i] = '.';\n    }\n    \n    return actions;\n}\n\nvoid solve() {\n    read_init();\n    \n    Rect target_rect;\n    int phase = 1; // 1: Enter, 2: Build, 3: Done\n    vector<Point> wall_tasks;\n    \n    for (int t = 0; t < TURNS; ++t) {\n        // Read Pet Moves\n        vector<string> pet_moves;\n        read_turn(pet_moves);\n        \n        // Update Pet Positions\n        apply_moves(pet_moves);\n        \n        // Check if plan is still valid\n        bool valid = true;\n        if (phase == 3) {\n            // Just stay put\n            cout << string(M, '.') << endl;\n            continue;\n        }\n        \n        // Check if pets entered target rect\n        for (const auto& p : pets) {\n            if (target_rect.r1 <= p.x && p.x <= target_rect.r2 &&\n                target_rect.c1 <= p.y && p.y <= target_rect.c2) {\n                valid = false;\n                break;\n            }\n        }\n        \n        if (!valid || phase == 0) {\n            // Re-plan\n            target_rect = find_best_rectangle();\n            phase = 1;\n            wall_tasks.clear();\n            // cout << \"# Turn \" << t << \" Replanning. Rect: \" \n            //      << target_rect.r1 << \" \" << target_rect.r2 << \" \"\n            //      << target_rect.c1 << \" \" << target_rect.c2 << \" Area: \" << target_rect.area << endl;\n        }\n        \n        // Generate Actions\n        // We need a copy of human positions to simulate moves for next turn logic?\n        // No, the problem state updates based on our output.\n        // We just need to update our internal `humans` state for the next iteration's `is_buildable` check.\n        // So `generate_actions` should update `humans`.\n        // But `is_buildable` needs \"start of turn\" positions.\n        // So we pass `humans` (which holds start pos) and update it at the end.\n        \n        vector<char> actions = generate_actions(target_rect, humans, phase, wall_tasks, t);\n        \n        // Output\n        string s(actions.begin(), actions.end());\n        cout << s << endl;\n        cout.flush();\n    }\n}\n\nint main() {\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n    solve();\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Global configuration\nconst int H = 20;\nconst int W = 20;\nconst int MAX_LEN = 200;\nconst double INF = 1e9;\n\n// Directions\nconst int DY[4] = {-1, 1, 0, 0};\nconst int DX[4] = {0, 0, -1, 1};\nconst char DC[4] = {'U', 'D', 'L', 'R'};\n\n// Input\nint si, sj, ti, tj;\ndouble p;\nvector<string> h_grid(H);\nvector<string> v_grid(H-1);\n\n// Helper to check wall\n// dir: 0=U, 1=D, 2=L, 3=R\ninline bool is_wall(int y, int x, int dir) {\n    if (dir == 0) { // U\n        if (y == 0) return true;\n        return v_grid[y-1][x] == '1';\n    } else if (dir == 1) { // D\n        if (y == H-1) return true;\n        return v_grid[y][x] == '1';\n    } else if (dir == 2) { // L\n        if (x == 0) return true;\n        return h_grid[y][x-1] == '1';\n    } else { // R\n        if (x == W-1) return true;\n        return h_grid[y][x] == '1';\n    }\n    return false;\n}\n\n// Buffers for calculation to avoid allocation overhead\nvector<vector<double>> prob_buff1(H, vector<double>(W, 0.0));\nvector<vector<double>> prob_buff2(H, vector<double>(W, 0.0));\n\n// Function to calculate expected score of a sequence\n// Uses DP on probability distribution\ndouble calculate_score(const string& s) {\n    // Initialize buffers\n    for(int i=0; i<H; ++i) fill(prob_buff1[i].begin(), prob_buff1[i].end(), 0.0);\n    \n    prob_buff1[si][sj] = 1.0;\n    double expected_score = 0.0;\n    int L = s.length();\n\n    auto& curr_prob = prob_buff1;\n    auto& next_prob = prob_buff2;\n\n    for (int t = 0; t < L; ++t) {\n        // Reset next_prob\n        for(int i=0; i<H; ++i) fill(next_prob[i].begin(), next_prob[i].end(), 0.0);\n\n        int dir_idx = -1;\n        if (s[t] == 'U') dir_idx = 0;\n        else if (s[t] == 'D') dir_idx = 1;\n        else if (s[t] == 'L') dir_idx = 2;\n        else if (s[t] == 'R') dir_idx = 3;\n\n        // If invalid char (should not happen), just stay\n        if (dir_idx == -1) {\n            // Treat as staying, effectively just p stays, 1-p stays (if wall) or moves\n            // but since char is invalid, we assume it maps to nothing or self-loop? \n            // Problem guarantees UDLR.\n        }\n\n        double ny_off = DY[dir_idx];\n        double nx_off = DX[dir_idx];\n\n        for (int y = 0; y < H; ++y) {\n            for (int x = 0; x < W; ++x) {\n                double cur_p = curr_prob[y][x];\n                if (cur_p == 0.0) continue;\n\n                // Probability of forgetting: stay in place\n                double p_forget = cur_p * p;\n                next_prob[y][x] += p_forget;\n\n                // Probability of trying to move\n                double p_move = cur_p * (1.0 - p);\n                \n                int nx = x + (int)nx_off;\n                int ny = y + (int)ny_off;\n\n                // Check wall collision\n                if (is_wall(y, x, dir_idx)) {\n                    next_prob[y][x] += p_move;\n                } else {\n                    if (ny == ti && nx == tj) {\n                        // Reached goal\n                        expected_score += p_move * (401.0 - (t + 1));\n                        // Mass absorbed into score, not propagated to next state\n                    } else {\n                        next_prob[ny][nx] += p_move;\n                    }\n                }\n            }\n        }\n        swap(curr_prob, next_prob);\n    }\n    return expected_score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < H; ++i) cin >> h_grid[i];\n    for (int i = 0; i < H-1; ++i) cin >> v_grid[i];\n\n    // 1. Find shortest path (A*)\n    // priority_queue: (estimated_cost, y, x)\n    using Node = pair<int, pair<int, int>>;\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    vector<vector<int>> dist(H, vector<int>(W, INF));\n    vector<vector<int>> parent(H, vector<int>(W, -1));\n    \n    auto heuristic = [&](int y, int x) {\n        return abs(y - ti) + abs(x - tj);\n    };\n\n    dist[si][sj] = 0;\n    pq.push({heuristic(si, sj), {si, sj}});\n\n    while (!pq.empty()) {\n        auto curr = pq.top();\n        pq.pop();\n        int y = curr.second.first;\n        int x = curr.second.second;\n        int cost = dist[y][x];\n\n        if (y == ti && x == tj) break;\n        if (cost > dist[y][x]) continue;\n\n        for (int i = 0; i < 4; ++i) {\n            int ny = y + DY[i];\n            int nx = x + DX[i];\n            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;\n            if (is_wall(y, x, i)) continue;\n            \n            if (dist[ny][nx] > cost + 1) {\n                dist[ny][nx] = cost + 1;\n                parent[ny][nx] = i;\n                pq.push({dist[ny][nx] + heuristic(ny, nx), {ny, nx}});\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path = \"\";\n    int cy = ti, cx = tj;\n    while (cy != si || cx != sj) {\n        int dir = parent[cy][cx];\n        path.push_back(DC[dir]);\n        cy -= DY[dir];\n        cx -= DX[dir];\n    }\n    reverse(path.begin(), path.end());\n    \n    // 2. Build initial robust string\n    // Strategy: Repeat each character in the path K times\n    // K depends on p. Higher p -> Higher K.\n    int path_len = path.length();\n    string ans = \"\";\n    \n    // Calculate optimal K\n    // Empirically chosen thresholds\n    int K = 1;\n    if (p > 0.15) K = 2;\n    if (p > 0.35) K = 3;\n    if (p > 0.45) K = 4;\n    \n    // Ensure K * path_len fits reasonably, or reduce K if too long\n    // We want to repeat the sequence to allow multiple attempts.\n    // A single run of robust path should consume most of the length or leave room for repeats.\n    // If K*path_len is very small, we can repeat it many times.\n    // If K*path_len is close to 200, we run it once.\n    \n    // Cap K such that we can at least run the path once\n    while (K > 1 && K * path_len > 200) {\n        K--;\n    }\n\n    string robust_seg = \"\";\n    for (char c : path) {\n        robust_seg += string(K, c);\n    }\n    \n    // Fill ans by repeating the robust segment\n    while ((int)ans.size() < 200) {\n        ans += robust_seg;\n    }\n    ans.resize(200);\n\n    // 3. Local Search (Hill Climbing)\n    auto start_time = chrono::high_resolution_clock::now();\n    random_device rd;\n    mt19937 gen(rd());\n    uniform_int_distribution<> dis_idx(0, 199);\n    uniform_int_distribution<> dis_dir(0, 3);\n\n    double current_score = calculate_score(ans);\n    string best_ans = ans;\n    double best_score = current_score;\n    \n    const int time_limit_ms = 1900;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > time_limit_ms) break;\n\n        // Mutation 1: Change a random character\n        int idx = dis_idx(gen);\n        int new_dir = dis_dir(gen);\n        char original = ans[idx];\n        char new_char = DC[new_dir];\n        \n        if (original != new_char) {\n            ans[idx] = new_char;\n            double new_score = calculate_score(ans);\n            \n            if (new_score > current_score) {\n                current_score = new_score;\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_ans = ans;\n                }\n            } else {\n                ans[idx] = original; // Revert\n            }\n        }\n\n        // Mutation 2: Swap two random characters (less frequent or just mixed in)\n        // To keep it fast, we can just do change mutations mostly.\n        // Let's try a swap occasionally\n        if (dis_idx(gen) % 10 == 0) {\n             int idx2 = dis_idx(gen);\n             if (idx != idx2) {\n                 swap(ans[idx], ans[idx2]);\n                 double new_score = calculate_score(ans);\n                 if (new_score > current_score) {\n                     current_score = new_score;\n                     if (new_score > best_score) {\n                         best_score = new_score;\n                         best_ans = ans;\n                     }\n                 } else {\n                     swap(ans[idx], ans[idx2]); // Revert\n                 }\n             }\n        }\n    }\n\n    cout << best_ans << endl;\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <ctime>\n#include <set>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Directions: 0:Left, 1:Up, 2:Right, 3:Down\nint dr[4] = {0, -1, 0, 1};\nint dc[4] = {-1, 0, 1, 0};\n\n// to[type][in_dir] = out_dir\nint to[8][4] = {\n    {1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n    {1, 0, 3, 2}, {3, 2, 1, 0}, {2, -1, 0, -1}, {-1, 3, -1, 1}\n};\n\nint grid[H][W];\nint state[H][W]; \nint rotations[H][W]; \n\nmt19937 rng(time(0));\n\n// Returns effective type based on base type and rotation\nint get_type(int base, int r) {\n    if (base <= 3) return (base + r) % 4;\n    if (base == 4 || base == 5) return ((base + r) % 2 == 0) ? 4 : 5;\n    return ((base + r) % 2 == 0) ? 6 : 7;\n}\n\n// Trace loop starting at (r,c) entering from in_d.\n// Returns length of loop, or 0 if not a loop.\nint trace_loop(int r, int c, int in_d) {\n    int cr = r, cc = c, cd = in_d;\n    int len = 0;\n    for (int steps = 0; steps < 1000; ++steps) {\n        int t = state[cr][cc];\n        int out_d = to[t][cd];\n        if (out_d == -1) return 0;\n        int nr = cr + dr[out_d];\n        int nc = cc + dc[out_d];\n        len++;\n        if (nr < 0 || nr >= H || nc < 0 || nc >= W) return 0;\n        int next_in_d = (out_d + 2) % 4;\n        if (nr == r && nc == c && next_in_d == in_d) return len;\n        cr = nr; cc = nc; cd = next_in_d;\n    }\n    return 0;\n}\n\nmultiset<int> loops;\nlong long current_score = 0;\n\nvoid recalc_score() {\n    if (loops.size() < 2) current_score = 0;\n    else {\n        auto it = loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        current_score = (long long)L1 * L2;\n    }\n}\n\nint global_visited[H][W][4];\nint global_stamp = 1;\n\nvoid full_scan() {\n    loops.clear();\n    int stamp = global_stamp++;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                if (global_visited[i][j][d] == stamp) continue;\n                int t = state[i][j];\n                if (to[t][d] == -1) continue;\n                int len = trace_loop(i, j, d);\n                if (len > 0) {\n                    loops.insert(len);\n                    int cr=i, cc=j, cd=d;\n                    while(true) {\n                        global_visited[cr][cc][cd] = stamp;\n                        int out = to[state[cr][cc]][cd];\n                        int nr = cr + dr[out], nc = cc + dc[out];\n                        int nd = (out+2)%4;\n                        if(nr==i && nc==j && nd==d) break;\n                        cr=nr; cc=nc; cd=nd;\n                    }\n                }\n            }\n        }\n    }\n    recalc_score();\n}\n\n// Global buffers to avoid reallocation\nvector<int> old_lengths_buf;\nvector<int> new_lengths_buf;\n\n// Fills buffers and returns new_score\nlong long try_flip(int r, int c, int new_rot) {\n    int old_rot = rotations[r][c];\n    if (new_rot == old_rot) return current_score;\n\n    old_lengths_buf.clear();\n    bool processed[4] = {false};\n    int old_t = state[r][c];\n    for (int d = 0; d < 4; ++d) {\n        if (to[old_t][d] != -1 && !processed[d]) {\n            int out_d = to[old_t][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) old_lengths_buf.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    state[r][c] = get_type(grid[r][c], new_rot); // Temp\n    \n    new_lengths_buf.clear();\n    fill(processed, processed+4, false);\n    int new_t = state[r][c];\n    for (int d = 0; d < 4; ++d) {\n        if (to[new_t][d] != -1 && !processed[d]) {\n            int out_d = to[new_t][d];\n            int len = trace_loop(r, c, d);\n            if (len > 0) new_lengths_buf.push_back(len);\n            processed[d] = true;\n            processed[(out_d + 2) % 4] = true;\n        }\n    }\n    \n    multiset<int> temp_loops = loops;\n    for (int l : old_lengths_buf) {\n        auto it = temp_loops.find(l);\n        if (it != temp_loops.end()) temp_loops.erase(it);\n    }\n    for (int l : new_lengths_buf) temp_loops.insert(l);\n    \n    state[r][c] = old_t; // Revert\n\n    long long score = 0;\n    if (temp_loops.size() >= 2) {\n        auto it = temp_loops.end(); it--;\n        int L1 = *it; it--;\n        int L2 = *it;\n        score = (long long)L1 * L2;\n    }\n    return score;\n}\n\nvoid apply_change(int r, int c, int new_rot) {\n    for (int l : old_lengths_buf) {\n        auto it = loops.find(l);\n        if (it != loops.end()) loops.erase(it);\n    }\n    rotations[r][c] = new_rot;\n    state[r][c] = get_type(grid[r][c], new_rot);\n    for (int l : new_lengths_buf) loops.insert(l);\n    recalc_score();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    for (int i = 0; i < H; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < W; ++j) grid[i][j] = s[j] - '0';\n    }\n    \n    const int TOP_K = 20; \n    \n    struct Solution {\n        long long score;\n        vector<vector<int>> rotations;\n        multiset<int> loops;\n    };\n    vector<Solution> top_solutions; \n    \n    // Reduced initialization count to ensure TLE safety\n    const int MAX_INIT = 60; \n    for(int t=0; t<MAX_INIT; ++t) {\n        vector<pair<int, int>> order;\n        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) order.push_back({i,j});\n        shuffle(order.begin(), order.end(), rng);\n        \n        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) rotations[i][j] = rng() % 4;\n        \n        for(auto& p : order) {\n            int i = p.first, j = p.second;\n            int best_r = rotations[i][j];\n            int best_conn = -1;\n            for(int r=0; r<4; ++r) {\n                int t_eff = get_type(grid[i][j], r);\n                int conn = 0;\n                if(i>0 && to[state[i-1][j]][3]!=-1 && to[t_eff][1]!=-1) conn++;\n                if(i<H-1 && to[state[i+1][j]][1]!=-1 && to[t_eff][3]!=-1) conn++;\n                if(j>0 && to[state[i][j-1]][2]!=-1 && to[t_eff][0]!=-1) conn++;\n                if(j<W-1 && to[state[i][j+1]][0]!=-1 && to[t_eff][2]!=-1) conn++;\n                if (conn > best_conn || (conn == best_conn && rng() % 2)) {\n                    best_conn = conn;\n                    best_r = r;\n                }\n            }\n            rotations[i][j] = best_r;\n            state[i][j] = get_type(grid[i][j], best_r);\n        }\n        \n        full_scan();\n        \n        Solution sol;\n        sol.score = current_score;\n        sol.rotations.assign(H, vector<int>(W));\n        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) sol.rotations[i][j] = rotations[i][j];\n        sol.loops = loops;\n        \n        if(top_solutions.size() < TOP_K) {\n            top_solutions.push_back(sol);\n        } else {\n            if(current_score > top_solutions.back().score) {\n                top_solutions.pop_back();\n                top_solutions.push_back(sol);\n                sort(top_solutions.begin(), top_solutions.end(), [](const Solution& a, const Solution& b){ return a.score > b.score; });\n            }\n        }\n    }\n    \n    sort(top_solutions.begin(), top_solutions.end(), [](const Solution& a, const Solution& b){ return a.score > b.score; });\n    \n    // Restore best\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) rotations[i][j] = top_solutions[0].rotations[i][j];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) state[i][j] = get_type(grid[i][j], rotations[i][j]);\n    \n    current_score = top_solutions[0].score;\n    loops = top_solutions[0].loops;\n    \n    long long best_score = current_score;\n    int best_sol_rot[H][W];\n    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n    \n    int current_solution_idx = 0;\n    long long last_improve_time = 0;\n\n    auto start_time = clock();\n    double TIME_LIMIT = 1.95 * CLOCKS_PER_SEC;\n    \n    while((double)(clock() - start_time) < TIME_LIMIT) {\n        double progress = (double)(clock() - start_time) / TIME_LIMIT;\n        \n        // Stuck handling\n        if((double)(clock() - start_time) - last_improve_time > CLOCKS_PER_SEC * 0.4) {\n            // Strategy 1: Sequential Batch Kick\n            bool kicked = false;\n            const int KICK_BATCH_SIZE = 20;\n            \n            for(int k=0; k<KICK_BATCH_SIZE; ++k) {\n                int rr = rng() % H;\n                int cc = rng() % W;\n                int r_rot = rng() % 4;\n                \n                long long kick_score = try_flip(rr, cc, r_rot);\n                \n                if(kick_score > current_score) {\n                    apply_change(rr, cc, r_rot);\n                    kicked = true;\n                    if(current_score > best_score) {\n                        best_score = current_score;\n                        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n                    }\n                }\n            }\n            \n            if(kicked) {\n                last_improve_time = clock();\n            } else {\n                // Restart\n                if(current_solution_idx + 1 < top_solutions.size()) {\n                    current_solution_idx++;\n                    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) rotations[i][j] = top_solutions[current_solution_idx].rotations[i][j];\n                    for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) state[i][j] = get_type(grid[i][j], rotations[i][j]);\n                    current_score = top_solutions[current_solution_idx].score;\n                    loops = top_solutions[current_solution_idx].loops;\n                    last_improve_time = clock();\n                    if(current_score > best_score) {\n                        best_score = current_score;\n                        for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n                    }\n                }\n            }\n            continue; \n        }\n\n        // Annealing Schedule\n        double T = 1000.0 * (1.0 - progress); \n        if(T < 0.1) T = 0.1;\n        \n        int r = rng() % H;\n        int c = rng() % W;\n        int old_rot = rotations[r][c];\n        \n        // Neighbor Selection\n        int new_rot;\n        int dice = rng() % 100;\n        if(dice < 80) new_rot = (old_rot + (rng()%2 ? 1 : 3)) % 4; \n        else new_rot = rng() % 4;\n        \n        if(new_rot == old_rot) continue;\n        \n        long long new_score = try_flip(r, c, new_rot);\n        long long diff = new_score - current_score;\n        \n        if(diff > 0 || (rng() % 1000000 < 1000000 * exp(diff / T))) {\n            apply_change(r, c, new_rot);\n            \n            if(current_score > best_score) {\n                best_score = current_score;\n                for(int i=0; i<H; ++i) for(int j=0; j<W; ++j) best_sol_rot[i][j] = rotations[i][j];\n                last_improve_time = clock();\n            }\n        }\n    }\n    \n    string ans = \"\";\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ans += (char)('0' + best_sol_rot[i][j]);\n        }\n    }\n    cout << ans << endl;\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <set>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <array>\n#include <tuple>\n\nusing namespace std;\n\nconst int LEFT = 1;\nconst int UP = 2;\nconst int RIGHT = 4;\nconst int DOWN = 8;\nconst int MAX_N = 10;\n\nstruct Point {\n    int r, c;\n    Point(int r = 0, int c = 0) : r(r), c(c) {}\n    bool operator==(const Point& p) const { return r == p.r && c == p.c; }\n    bool operator<(const Point& p) const {\n        if (r != p.r) return r < p.r;\n        return c < p.c;\n    }\n};\n\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char MOVE_CHARS[4] = {'U', 'D', 'L', 'R'};\n\nclass Solver {\npublic:\n    int N;\n    int T_limit;\n    vector<vector<int>> board;\n    Point empty_pos;\n    string moves;\n    mt19937 rng;\n    \n    // Static arrays for BFS to avoid allocation\n    Point bfs_parent[MAX_N][MAX_N];\n    int bfs_vis[MAX_N][MAX_N];\n    int bfs_vis_token;\n    \n    vector<Point> tile_positions[16];\n    vector<vector<bool>> in_tree;\n    vector<Point> frontier;\n\n    Solver(int n, int t_limit) : N(n), T_limit(t_limit), bfs_vis_token(0) {\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    void set_board(const vector<vector<int>>& b, Point ep) {\n        board = b;\n        empty_pos = ep;\n        moves = \"\";\n        for(int k=0; k<16; ++k) tile_positions[k].clear();\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                if(board[i][j] != 0) {\n                    tile_positions[board[i][j]].push_back(Point(i, j));\n                }\n            }\n        }\n    }\n\n    bool is_valid(int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    }\n\n    void update_cache(Point p, int old_val, int new_val) {\n        if (old_val == new_val) return;\n        if (old_val != 0) {\n            auto& vec = tile_positions[old_val];\n            vec.erase(remove(vec.begin(), vec.end(), p), vec.end());\n        }\n        if (new_val != 0) {\n            tile_positions[new_val].push_back(p);\n        }\n    }\n\n    // Find best filler on the whole board\n    // Cost = dist(u, filler) + dist(empty, filler)\n    pair<Point, int> find_best_filler(Point u, int bitmask, int max_cost_limit) {\n        Point best_p(-1, -1);\n        int best_cost = max_cost_limit + 1;\n        \n        // Optimization: Calculate u-coord once\n        int ur = u.r, uc = u.c;\n        int er = empty_pos.r, ec = empty_pos.c;\n\n        for (Point f : tile_positions[bitmask]) {\n            if (f.r == ur && f.c == uc) continue;\n            \n            // Manhattan distance\n            int cost = abs(f.r - ur) + abs(f.c - uc) + abs(f.r - er) + abs(f.c - ec);\n            \n            if (cost < best_cost) {\n                best_cost = cost;\n                best_p = f;\n            }\n        }\n        return {best_p, best_cost};\n    }\n\n    // Zero-allocation BFS\n    vector<Point> get_path_for_empty(Point target, Point forbidden = Point(-1, -1)) {\n        if (empty_pos == target) return {};\n        \n        bfs_vis_token++;\n        queue<Point> q;\n        q.push(empty_pos);\n        bfs_vis[empty_pos.r][empty_pos.c] = bfs_vis_token;\n        \n        bool found = false;\n        while(!q.empty()) {\n            Point p = q.front(); q.pop();\n            if(p == target) { found = true; break; }\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) && bfs_vis[nr][nc] != bfs_vis_token) {\n                    if (nr == forbidden.r && nc == forbidden.c) continue; \n                    bfs_vis[nr][nc] = bfs_vis_token;\n                    bfs_parent[nr][nc] = p;\n                    q.push(Point(nr, nc));\n                }\n            }\n        }\n        vector<Point> path;\n        if(found) {\n            Point curr = target;\n            while(curr != empty_pos) {\n                path.push_back(curr);\n                curr = bfs_parent[curr.r][curr.c];\n            }\n            reverse(path.begin(), path.end());\n        }\n        return path;\n    }\n\n    void execute_empty_path(const vector<Point>& path) {\n        for (Point p : path) {\n            if (moves.size() >= static_cast<size_t>(T_limit)) return;\n            \n            int val_p = board[p.r][p.c];\n            int val_e = board[empty_pos.r][empty_pos.c];\n            \n            int dr = p.r - empty_pos.r;\n            int dc = p.c - empty_pos.c;\n            int d = -1;\n            if (dr == -1) d = 0; else if (dr == 1) d = 1;\n            else if (dc == -1) d = 2; else if (dc == 1) d = 3;\n            \n            moves += MOVE_CHARS[d];\n            board[empty_pos.r][empty_pos.c] = val_p;\n            board[p.r][p.c] = val_e;\n            \n            update_cache(empty_pos, val_e, val_p);\n            update_cache(p, val_p, val_e);\n            \n            empty_pos = p;\n        }\n    }\n\n    void move_tile(Point from, Point to) {\n        if (from == to) return;\n        Point cur = from;\n        while (cur != to) {\n            if (moves.size() >= static_cast<size_t>(T_limit)) return;\n            \n            Point diff = Point(to.r - cur.r, to.c - cur.c);\n            vector<int> dirs;\n            if (diff.r > 0) dirs.push_back(1);\n            else if (diff.r < 0) dirs.push_back(0);\n            if (diff.c > 0) dirs.push_back(3);\n            else if (diff.c < 0) dirs.push_back(2);\n            \n            shuffle(dirs.begin(), dirs.end(), rng);\n            bool moved = false;\n            for (int d : dirs) {\n                int nr = cur.r + DR[d];\n                int nc = cur.c + DC[d];\n                Point next_target(nr, nc);\n                vector<Point> path = get_path_for_empty(next_target, cur);\n                if (path.empty()) continue; \n\n                execute_empty_path(path);\n                if (moves.size() >= static_cast<size_t>(T_limit)) return;\n\n                int er = cur.r - empty_pos.r; \n                int ec = cur.c - empty_pos.c;\n                int ed = -1;\n                if (er == -1) ed = 0; else if (er == 1) ed = 1;\n                else if (ec == -1) ed = 2; else if (ec == 1) ed = 3;\n                \n                moves += MOVE_CHARS[ed];\n                \n                int val_cur = board[cur.r][cur.c];\n                int val_e = board[empty_pos.r][empty_pos.c];\n                \n                board[empty_pos.r][empty_pos.c] = val_cur;\n                board[cur.r][cur.c] = val_e;\n                \n                update_cache(empty_pos, val_e, val_cur);\n                update_cache(cur, val_cur, val_e);\n                \n                empty_pos = cur;\n                \n                cur = next_target;\n                moved = true;\n                break;\n            }\n            if (!moved) break;\n        }\n    }\n\n    void solve() {\n        in_tree.assign(N, vector<bool>(N, false));\n        \n        // Initial BFS for Largest Component (using zero-alloc BFS)\n        bfs_vis_token++;\n        vector<vector<Point>> components;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (board[i][j] != 0 && bfs_vis[i][j] != bfs_vis_token) {\n                    queue<Point> q;\n                    vector<Point> comp;\n                    q.push(Point(i, j));\n                    bfs_vis[i][j] = bfs_vis_token;\n                    comp.push_back(Point(i, j));\n\n                    while (!q.empty()) {\n                        Point cur = q.front(); q.pop();\n                        int cr = cur.r, cc = cur.c;\n                        int tile = board[cr][cc];\n                        for (int d = 0; d < 4; ++d) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (is_valid(nr, nc) && board[nr][nc] != 0 && bfs_vis[nr][nc] != bfs_vis_token) {\n                                int neighbor = board[nr][nc];\n                                bool connects = false;\n                                if (d == 0 && (tile & UP) && (neighbor & DOWN)) connects = true;\n                                if (d == 1 && (tile & DOWN) && (neighbor & UP)) connects = true;\n                                if (d == 2 && (tile & LEFT) && (neighbor & RIGHT)) connects = true;\n                                if (d == 3 && (tile & RIGHT) && (neighbor & LEFT)) connects = true;\n                                \n                                if (connects) {\n                                    bfs_vis[nr][nc] = bfs_vis_token;\n                                    comp.push_back(Point(nr, nc));\n                                    q.push(Point(nr, nc));\n                                }\n                            }\n                        }\n                    }\n                    components.push_back(comp);\n                }\n            }\n        }\n        \n        int best_score = 0;\n        for(auto& c : components) if(c.size() > best_score) best_score = c.size();\n        \n        // Set Main Tree\n        for(auto& p : components[0]) in_tree[p.r][p.c] = true;\n\n        // Build Initial Frontier\n        frontier.clear();\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (in_tree[i][j]) continue;\n                if (board[i][j] == 0) continue;\n                for(int d=0; d<4; ++d) {\n                    int nr = i+DR[d], nc = j+DC[d];\n                    if(is_valid(nr, nc) && in_tree[nr][nc]) {\n                        frontier.push_back(Point(i, j));\n                        break;\n                    }\n                }\n            }\n        }\n\n        while (moves.size() < static_cast<size_t>(T_limit)) {\n            bool made_move = false;\n            int max_cost = 25; \n\n            tuple<int, int, int, int, int> best_move = {1e9, -1, -1, -1, -1};\n            bool free_move_found = false;\n\n            for (Point u : frontier) {\n                if (in_tree[u.r][u.c]) continue;\n\n                for(int d=0; d<4; ++d) {\n                    int vr = u.r + DR[d], vc = u.c + DC[d];\n                    Point v(vr, vc);\n                    if(!is_valid(vr, vc) || !in_tree[vr][vc]) continue;\n\n                    int tu = board[u.r][u.c];\n                    int tv = board[vr][vc];\n                    int bu = 0, bv = 0;\n                    if (d == 0) { bu = 2; bv = 8; }\n                    else if (d == 1) { bu = 8; bv = 2; }\n                    else if (d == 2) { bu = 1; bv = 4; }\n                    else if (d == 3) { bu = 4; bv = 1; }\n\n                    if ((tu & bu) && (tv & bv)) {\n                        if (!free_move_found) {\n                            best_move = {0, u.r, u.c, -1, -1};\n                            free_move_found = true;\n                        }\n                        continue;\n                    }\n                    \n                    if (free_move_found) continue; \n\n                    if (!(tu & bu)) {\n                        auto res = find_best_filler(u, bu, max_cost);\n                        if (res.second != -1 && res.second < max_cost) {\n                            if (res.second < get<0>(best_move)) {\n                                best_move = {res.second, u.r, u.c, res.first.r, res.first.c};\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (free_move_found || get<0>(best_move) != 1e9) {\n                auto [cost, ur, uc, fr, fc] = best_move;\n                Point u(ur, uc);\n                if (free_move_found) {\n                    in_tree[u.r][u.c] = true;\n                    made_move = true;\n                } else {\n                    Point filler(fr, fc);\n                    move_tile(filler, u);\n                    if (moves.size() < static_cast<size_t>(T_limit)) {\n                        in_tree[u.r][u.c] = true;\n                        made_move = true;\n                    }\n                }\n            }\n\n            if (made_move) {\n                // Rebuild Frontier\n                frontier.clear();\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (in_tree[i][j]) continue;\n                        if (board[i][j] == 0) continue;\n                        bool is_frontier = false;\n                        for(int d=0; d<4; ++d) {\n                            int nr = i+DR[d], nc = j+DC[d];\n                            if(is_valid(nr, nc) && in_tree[nr][nc]) {\n                                is_frontier = true; break;\n                            }\n                        }\n                        if(is_frontier) frontier.push_back(Point(i, j));\n                    }\n                }\n            } else {\n                break;\n            }\n        }\n        \n        cout << moves << endl;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    \n    vector<vector<int>> board(N, vector<int>(N));\n    Point empty_pos;\n    \n    for (int i = 0; i < N; ++i) {\n        string line;\n        cin >> line;\n        for (int j = 0; j < N; ++j) {\n            char c = line[j];\n            if (c == '0') {\n                board[i][j] = 0;\n                empty_pos = Point(i, j);\n            } else {\n                if (c >= 'a') board[i][j] = 10 + (c - 'a');\n                else board[i][j] = c - '0';\n            }\n        }\n    }\n\n    Solver solver(N, T);\n    solver.set_board(board, empty_pos);\n    solver.solve();\n\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <map>\n#include <cmath>\n#include <chrono>\n#include <cassert>\n\nusing namespace std;\n\ntypedef long long ll;\n\nconst int K_MAX = 100;\n\nstruct Point {\n    ll x, y;\n};\n\nstruct Line {\n    ll x1, y1, x2, y2;\n};\n\n// Signature to uniquely identify a region (bitmask of side of each line)\nstruct Signature {\n    unsigned long long p1; // bits 0-63\n    unsigned long long p2; // bits 64-99 (since K_MAX is 100)\n\n    bool operator<(const Signature& other) const {\n        if (p1 != other.p1) return p1 < other.p1;\n        return p2 < other.p2;\n    }\n    \n    bool operator==(const Signature& other) const {\n        return p1 == other.p1 && p2 == other.p2;\n    }\n};\n\n// Global inputs\nint N, K;\nvector<int> a(11);\nvector<Point> points;\n\n// Random generator\nmt19937 rng(1337);\n\nll rand_ll(ll l, ll r) {\n    uniform_int_distribution<ll> dist(l, r);\n    return dist(rng);\n}\n\nll cross_product(const Point& a, const Point& b, const Point& c) {\n    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);\n}\n\n// Generate a random line that does not pass through any point\nLine generate_random_line() {\n    while (true) {\n        ll x1 = rand_ll(-10000, 10000);\n        ll y1 = rand_ll(-10000, 10000);\n        ll x2 = rand_ll(-10000, 10000);\n        ll y2 = rand_ll(-10000, 10000);\n\n        if (x1 == x2 && y1 == y2) continue;\n\n        Line l{x1, y1, x2, y2};\n        \n        bool hits_point = false;\n        for (const auto& p : points) {\n            if (cross_product({x1, y1}, {x2, y2}, p) == 0) {\n                hits_point = true;\n                break;\n            }\n        }\n        if (!hits_point) {\n            return l;\n        }\n    }\n}\n\n// State of the solver\nstruct State {\n    int k;\n    vector<Line> lines;\n    vector<Signature> signatures; // signature for each point\n    vector<bool> is_dead;\n    \n    map<Signature, int> region_counts; // maps signature -> number of points in that region\n    vector<int> b_counts; // b_counts[d] = number of regions with exactly d points (d=1..10)\n    int score;\n\n    void init(int init_k) {\n        k = init_k;\n        lines.clear();\n        lines.reserve(k);\n        for(int i=0; i<k; ++i) lines.push_back(generate_random_line());\n        \n        is_dead.assign(N, false);\n        signatures.assign(N, {0, 0});\n        region_counts.clear();\n        b_counts.assign(11, 0);\n\n        for (int i = 0; i < N; ++i) {\n            Signature sig{0, 0};\n            bool dead = false;\n            for (int j = 0; j < k; ++j) {\n                ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                if (val == 0) {\n                    dead = true;\n                    break;\n                }\n                if (val > 0) {\n                    if (j < 64) sig.p1 |= (1ULL << j);\n                    else sig.p2 |= (1ULL << (j - 64));\n                }\n            }\n            is_dead[i] = dead;\n            signatures[i] = sig;\n            if (!dead) {\n                region_counts[sig]++;\n            }\n        }\n\n        for (auto& p : region_counts) {\n            int cnt = p.second;\n            if (1 <= cnt && cnt <= 10) {\n                b_counts[cnt]++;\n            }\n        }\n        compute_score();\n    }\n\n    void compute_score() {\n        score = 0;\n        for (int d = 1; d <= 10; ++d) {\n            score += min(a[d], b_counts[d]);\n        }\n    }\n\n    // Replace line at index idx with a new random line\n    void replace(int idx) {\n        Line old_line = lines[idx];\n        Line new_line = generate_random_line();\n        lines[idx] = new_line;\n\n        for (int i = 0; i < N; ++i) {\n            ll old_val = cross_product({old_line.x1, old_line.y1}, {old_line.x2, old_line.y2}, points[i]);\n            ll new_val = cross_product({new_line.x1, new_line.y1}, {new_line.x2, new_line.y2}, points[i]);\n\n            // Since new_line is guaranteed not to pass through points, new_val != 0\n            \n            if (is_dead[i]) {\n                // Point was dead. It becomes alive if the old line was the one killing it.\n                if (old_val == 0) {\n                    // Recalculate signature from scratch\n                    Signature sig{0, 0};\n                    bool still_dead = false;\n                    for (int j = 0; j < k; ++j) {\n                        ll val = cross_product({lines[j].x1, lines[j].y1}, {lines[j].x2, lines[j].y2}, points[i]);\n                        if (val == 0) {\n                            still_dead = true;\n                            break;\n                        }\n                        if (val > 0) {\n                            if (j < 64) sig.p1 |= (1ULL << j);\n                            else sig.p2 |= (1ULL << (j - 64));\n                        }\n                    }\n                    \n                    is_dead[i] = still_dead;\n                    if (!still_dead) {\n                        // Point came alive\n                        int cnt = region_counts[sig]++;\n                        // b_counts update: added 1 to region with (cnt-1) points -> now cnt points\n                        int prev_cnt = cnt - 1;\n                        if (1 <= prev_cnt && prev_cnt <= 10) b_counts[prev_cnt]--;\n                        if (1 <= cnt && cnt <= 10) b_counts[cnt]++;\n                        \n                        signatures[i] = sig;\n                    }\n                }\n                // If dead due to another line, stays dead. No change.\n            } else {\n                // Point was alive. Since new_val != 0, it stays alive.\n                // Check if side changed\n                bool old_pos = (old_val > 0);\n                bool new_pos = (new_val > 0);\n                \n                if (old_pos != new_pos) {\n                    Signature old_sig = signatures[i];\n                    Signature new_sig = old_sig;\n                    // Toggle bit at idx\n                    if (idx < 64) new_sig.p1 ^= (1ULL << idx);\n                    else new_sig.p2 ^= (1ULL << (idx - 64));\n\n                    // Remove from old region\n                    int cnt_old = region_counts[old_sig]--;\n                    // b_counts update: removed 1 from region with cnt_old points -> now cnt_old-1 points\n                    if (1 <= cnt_old && cnt_old <= 10) b_counts[cnt_old]--;\n                    if (1 <= cnt_old - 1 && cnt_old - 1 <= 10) b_counts[cnt_old - 1]++;\n\n                    // Add to new region\n                    int cnt_new = region_counts[new_sig]++;\n                    // b_counts update: added 1 to region with cnt_new-1 points -> now cnt_new points\n                    if (1 <= cnt_new - 1 && cnt_new - 1 <= 10) b_counts[cnt_new - 1]--;\n                    if (1 <= cnt_new && cnt_new <= 10) b_counts[cnt_new]++;\n\n                    signatures[i] = new_sig;\n                }\n            }\n        }\n        compute_score();\n    }\n};\n\nvoid solve() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    cin >> N >> K;\n    for (int i = 1; i <= 10; ++i) cin >> a[i];\n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 2.8; // seconds\n\n    State best_state;\n    best_state.init(0); \n\n    // Try various K values\n    vector<int> k_candidates = {0, 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100};\n    \n    for (int try_k : k_candidates) {\n        if (try_k > K) continue;\n\n        // Check time\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        if (elapsed.count() > time_limit) break;\n\n        State current_state;\n        current_state.init(try_k);\n        if (current_state.score > best_state.score) {\n            best_state = current_state;\n        }\n\n        // Adjust iterations based on N (complexity O(N))\n        // N is roughly sum of d*a[d]. Max ~5000.\n        // 3000 points -> 4000 iterations is safe. \n        // We can afford more if N is smaller.\n        int base_iters = 3000;\n        int max_iters = base_iters; \n        \n        // SA params\n        double start_temp = 50.0;\n        double end_temp = 1.0;\n\n        for (int iter = 0; iter < max_iters; ++iter) {\n            now = chrono::high_resolution_clock::now();\n            elapsed = now - start_time;\n            if (elapsed.count() > time_limit) break;\n\n            double temp = start_temp + (end_temp - start_temp) * iter / max_iters;\n\n            State next_state = current_state;\n            \n            // Move: Replace\n            if (try_k > 0) {\n                int idx = rand_ll(0, try_k - 1);\n                next_state.replace(idx);\n            }\n\n            int delta = next_state.score - current_state.score;\n            \n            // Maximize score\n            if (delta > 0 || exp((double)delta / temp) > (double)rand_ll(0, 10000) / 10000.0) {\n                current_state = next_state;\n                if (current_state.score > best_state.score) {\n                    best_state = current_state;\n                }\n            }\n        }\n    }\n\n    // Output best solution found\n    cout << best_state.lines.size() << endl;\n    for (const auto& l : best_state.lines) {\n        cout << l.x1 << \" \" << l.y1 << \" \" << l.x2 << \" \" << l.y2 << endl;\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n#include <chrono>\n#include <climits>\n\nusing namespace std;\n\nconst int MAX_N = 61;\nint N, M;\nint center;\nbool grid[MAX_N][MAX_N];\n\n// Directions: 0:R, 1:U, 2:L, 3:D, 4:UR, 5:DR, 6:UL, 7:DL\nconst int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};\nconst int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};\n\n// Perpendicular pairs: du -> list of dv\nconst vector<vector<int>> perp_dirs = {\n    {1, 3}, {0, 2}, {1, 3}, {0, 2},\n    {5, 6}, {4, 7}, {4, 7}, {5, 6}\n};\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\nbool time_limit_exceeded = false;\n\nvoid check_time() {\n    auto now = chrono::high_resolution_clock::now();\n    auto duration = chrono::duration_cast<chrono::milliseconds>(now - start_time);\n    if (duration.count() > 4900) {\n        time_limit_exceeded = true;\n    }\n}\n\n// Prefix Sum Managers for validation\ntemplate <int SIZE>\nstruct PrefixManager {\n    int sums[SIZE][MAX_N + 2]; \n\n    void init() {\n        for(int i=0; i<SIZE; ++i) {\n            for(int j=0; j<=N+1; ++j) sums[i][j] = 0;\n        }\n    }\n\n    void update_line(int k, int idx) {\n        for (int i = idx + 1; i <= N + 1; ++i) {\n            sums[k][i]++;\n        }\n    }\n    \n    int query(int k, int l, int r) {\n        if (l >= r) return 0;\n        return sums[k][r] - sums[k][l];\n    }\n};\n\nPrefixManager<MAX_N> grid_rows;\nPrefixManager<MAX_N> grid_cols;\nPrefixManager<2 * MAX_N> grid_d1; \nPrefixManager<2 * MAX_N> grid_d2; \n\nPrefixManager<MAX_N> seg_rows;\nPrefixManager<MAX_N> seg_cols;\nPrefixManager<2 * MAX_N> seg_d1;\nPrefixManager<2 * MAX_N> seg_d2;\n\nvoid init_prefix_structures() {\n    grid_rows.init();\n    grid_cols.init();\n    grid_d1.init();\n    grid_d2.init();\n    \n    seg_rows.init();\n    seg_cols.init();\n    seg_d1.init();\n    seg_d2.init();\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (grid[x][y]) {\n                grid_rows.update_line(y, x);\n                grid_cols.update_line(x, y);\n                int k1 = y - x + (N - 1);\n                grid_d1.update_line(k1, x);\n                int k2 = y + x;\n                grid_d2.update_line(k2, x);\n            }\n        }\n    }\n}\n\nbool is_segment_free(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return true;\n    \n    int lx = min(x1, x2);\n    int ly = min(y1, y2);\n    \n    if (y1 == y2) return seg_rows.query(y1, lx, lx + len) == 0;\n    if (x1 == x2) return seg_cols.query(x1, ly, ly + len) == 0;\n    if (x2 - x1 == y2 - y1) {\n        int k = ly - lx + (N - 1);\n        return seg_d1.query(k, lx, lx + len) == 0;\n    }\n    // D2\n    int k = max(y1, y2) + lx;\n    return seg_d2.query(k, lx, lx + len) == 0;\n}\n\nbool is_perimeter_clean(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && y1 == y2) return true;\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len <= 1) return true;\n    \n    int lx = min(x1, x2);\n    int rx = max(x1, x2);\n    int ly = min(y1, y2);\n    int ry = max(y1, y2);\n\n    if (y1 == y2) return grid_rows.query(y1, lx + 1, rx) == 0;\n    if (x1 == x2) return grid_cols.query(x1, ly + 1, ry) == 0;\n    if (x2 - x1 == y2 - y1) {\n        int k = ly - lx + (N - 1);\n        return grid_d1.query(k, lx + 1, rx) == 0;\n    }\n    int k = ry + lx;\n    return grid_d2.query(k, lx + 1, rx) == 0;\n}\n\nvoid mark_segment(int x1, int y1, int x2, int y2) {\n    int len = max(abs(x2 - x1), abs(y2 - y1));\n    if (len == 0) return;\n    \n    int sx = (x2 - x1) / len;\n    int sy = (y2 - y1) / len;\n    int cx = x1, cy = y1;\n    for (int i = 0; i < len; ++i) {\n        int nx = cx + sx;\n        int ny = cy + sy;\n        int lx = min(cx, nx);\n        int ly = min(cy, ny);\n        \n        if (cy == ny) seg_rows.update_line(cy, lx);\n        else if (cx == nx) seg_cols.update_line(cx, ly);\n        else if (nx == cx + 1 && ny == cy + 1) seg_d1.update_line(ly - lx + (N - 1), lx);\n        else if (nx == cx - 1 && ny == cy - 1) seg_d1.update_line(ly - lx + (N - 1), lx);\n        else if (nx == cx - 1 && ny == cy + 1) seg_d2.update_line(max(cy, ny) + lx, lx);\n        else seg_d2.update_line(max(cy, ny) + lx, lx);\n        \n        cx = nx; cy = ny;\n    }\n}\n\nstruct Point {\n    int x, y;\n    int weight;\n};\n\nvector<tuple<int, int, int, int, int, int, int, int>> ops;\n\nstruct Rectangle {\n    int x2, y2, x3, y3, x4, y4;\n    int perimeter;\n};\n\nbool try_place(int x, int y, Rectangle& best_rect) {\n    if (grid[x][y]) return false;\n    \n    bool found = false;\n    best_rect.perimeter = INT_MAX;\n    \n    const int MAX_LEN = N; \n\n    // Order: Axis-aligned (0-3) then Diagonals (4-7)\n    vector<int> dirs_order = {0, 1, 2, 3, 4, 5, 6, 7};\n\n    for (int du : dirs_order) {\n        for (int len_u = 1; len_u <= MAX_LEN; ++len_u) {\n            int bx = x + dx[du] * len_u;\n            int by = y + dy[du] * len_u;\n            \n            if (bx < 0 || bx >= N || by < 0 || by >= N) break;\n            if (!grid[bx][by]) continue;\n            \n            // Pruning: Smallest possible perimeter for this len_u is 2*len_u + 2.\n            if (2 * len_u + 2 >= best_rect.perimeter) break;\n\n            for (int dv : perp_dirs[du]) {\n                for (int len_v = 1; len_v <= MAX_LEN; ++len_v) {\n                    int dx_coord = x + dx[dv] * len_v;\n                    int dy_coord = y + dy[dv] * len_v;\n                    \n                    if (dx_coord < 0 || dx_coord >= N || dy_coord < 0 || dy_coord >= N) break;\n                    if (!grid[dx_coord][dy_coord]) continue;\n                    \n                    int current_perim = 2 * (len_u + len_v);\n                    if (current_perim >= best_rect.perimeter) break;\n                    \n                    int cx_coord = bx + (dx_coord - x);\n                    int cy_coord = by + (dy_coord - y);\n                    \n                    if (cx_coord < 0 || cx_coord >= N || cy_coord < 0 || cy_coord >= N) break;\n                    if (!grid[cx_coord][cy_coord]) continue;\n\n                    if (!is_segment_free(x, y, bx, by)) continue;\n                    if (!is_segment_free(bx, by, cx_coord, cy_coord)) continue;\n                    if (!is_segment_free(cx_coord, cy_coord, dx_coord, dy_coord)) continue;\n                    if (!is_segment_free(dx_coord, dy_coord, x, y)) continue;\n                    \n                    if (!is_perimeter_clean(x, y, bx, by)) continue;\n                    if (!is_perimeter_clean(bx, by, cx_coord, cy_coord)) continue;\n                    if (!is_perimeter_clean(cx_coord, cy_coord, dx_coord, dy_coord)) continue;\n                    if (!is_perimeter_clean(dx_coord, dy_coord, x, y)) continue;\n\n                    best_rect = {bx, by, cx_coord, cy_coord, dx_coord, dy_coord, current_perim};\n                    found = true;\n                }\n            }\n        }\n    }\n    return found;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    center = (N - 1) / 2;\n    \n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) grid[i][j] = false;\n    \n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        grid[x][y] = true;\n    }\n    \n    init_prefix_structures();\n    \n    auto cmp = [](const Point& a, const Point& b) { return a.weight < b.weight; };\n    priority_queue<Point, vector<Point>, decltype(cmp)> pq(cmp);\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (!grid[i][j]) {\n                int dist_sq = (i - center) * (i - center) + (j - center) * (j - center);\n                pq.push({i, j, dist_sq});\n            }\n        }\n    }\n    \n    while (!pq.empty() && !time_limit_exceeded) {\n        check_time();\n        \n        Point p = pq.top();\n        pq.pop();\n        \n        if (grid[p.x][p.y]) continue;\n        \n        Rectangle best_rect;\n        if (try_place(p.x, p.y, best_rect)) {\n            grid[p.x][p.y] = true;\n            grid_rows.update_line(p.y, p.x);\n            grid_cols.update_line(p.x, p.y);\n            grid_d1.update_line(p.y - p.x + (N - 1), p.x);\n            grid_d2.update_line(p.y + p.x, p.x);\n\n            mark_segment(p.x, p.y, best_rect.x2, best_rect.y2);\n            mark_segment(best_rect.x2, best_rect.y2, best_rect.x3, best_rect.y3);\n            mark_segment(best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4);\n            mark_segment(best_rect.x4, best_rect.y4, p.x, p.y);\n\n            ops.emplace_back(p.x, p.y, best_rect.x2, best_rect.y2, best_rect.x3, best_rect.y3, best_rect.x4, best_rect.y4);\n            \n            // Re-check neighbors. R=15 performed better than R=12 in tests.\n            int R = 15; \n            int x_min = max(0, p.x - R);\n            int x_max = min(N - 1, p.x + R);\n            int y_min = max(0, p.y - R);\n            int y_max = min(N - 1, p.y + R);\n            \n            for (int nx = x_min; nx <= x_max; ++nx) {\n                for (int ny = y_min; ny <= y_max; ++ny) {\n                    if (!grid[nx][ny]) {\n                        int dist_sq = (nx - center) * (nx - center) + (ny - center) * (ny - center);\n                        pq.push({nx, ny, dist_sq});\n                    }\n                }\n            }\n        }\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (auto& op : ops) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \" \"\n             << get<4>(op) << \" \" << get<5>(op) << \" \"\n             << get<6>(op) << \" \" << get<7>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nconst int H = 10;\nconst int W = 10;\n\nstruct Solver {\n    vector<vector<int>> board;\n    vector<int> flavors;\n    int step;\n    \n    // Targets\n    // Most frequent flavor -> Bottom Center (9, 4)\n    // Other flavors -> Top Left (0, 0) and Top Right (0, 9)\n    pair<int, int> T_BC = {9, 4};\n    pair<int, int> T_TL = {0, 0};\n    pair<int, int> T_TR = {0, 9};\n    \n    vector<pair<int, int>> targets;\n    \n    // Dynamic Weight Parameters\n    const double W_START = 4.0; // High penalty initially to enforce separation\n    const double W_END = 2.0;   // Lower penalty at the end to encourage packing\n\n    Solver(vector<int> f) : flavors(f), step(0) {\n        board.assign(H, vector<int>(W, 0));\n        \n        // Count occurrences\n        vector<int> counts(3, 0);\n        for (int x : f) counts[x-1]++;\n        \n        // Sort flavors by count descending\n        vector<pair<int, int>> flavor_counts = {{0, counts[0]}, {1, counts[1]}, {2, counts[2]}};\n        sort(flavor_counts.begin(), flavor_counts.end(), [](const auto& a, const auto& b) {\n            return a.second > b.second;\n        });\n        \n        // Assign targets: Largest -> Bottom Center, Others -> Top Corners\n        targets.resize(3);\n        targets[flavor_counts[0].first] = T_BC;\n        targets[flavor_counts[1].first] = T_TL;\n        targets[flavor_counts[2].first] = T_TR;\n    }\n\n    pair<int, int> get_pos(int p, const vector<vector<int>>& b) {\n        int cnt = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] == 0) {\n                    cnt++;\n                    if (cnt == p) return {i, j};\n                }\n            }\n        }\n        return {-1, -1}; \n    }\n\n    vector<vector<int>> tilt(vector<vector<int>> b, int dir) {\n        if (dir == 0) { // F\n            for (int j = 0; j < W; ++j) {\n                int wi = 0;\n                for (int i = 0; i < H; ++i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // B\n            for (int j = 0; j < W; ++j) {\n                int wi = H - 1;\n                for (int i = H - 1; i >= 0; --i) {\n                    if (b[i][j] != 0) {\n                        b[wi][j] = b[i][j];\n                        if (wi != i) b[i][j] = 0;\n                        wi--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // L\n            for (int i = 0; i < H; ++i) {\n                int wj = 0;\n                for (int j = 0; j < W; ++j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // R\n            for (int i = 0; i < H; ++i) {\n                int wj = W - 1;\n                for (int j = W - 1; j >= 0; --j) {\n                    if (b[i][j] != 0) {\n                        b[i][wj] = b[i][j];\n                        if (wj != j) b[i][j] = 0;\n                        wj--;\n                    }\n                }\n            }\n        }\n        return b;\n    }\n\n    double evaluate(const vector<vector<int>>& b) {\n        // Calculate dynamic weight: linearly decay from W_START to W_END\n        double progress = (double)step / 100.0;\n        double w_dist = W_START - (W_START - W_END) * progress;\n\n        // Component Score\n        int sum_sq = 0;\n        vector<vector<bool>> visited(H, vector<bool>(W, false));\n        \n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0 && !visited[i][j]) {\n                    queue<pair<int,int>> q;\n                    q.push({i,j});\n                    visited[i][j] = true;\n                    int size = 0;\n                    while (!q.empty()) {\n                        auto [r, c] = q.front(); q.pop();\n                        size++;\n                        int dr[] = {0, 0, 1, -1};\n                        int dc[] = {1, -1, 0, 0};\n                        for (int k = 0; k < 4; ++k) {\n                            int nr = r + dr[k];\n                            int nc = c + dc[k];\n                            if (nr >= 0 && nr < H && nc >= 0 && nc < W && !visited[nr][nc] && b[nr][nc] == b[r][c]) {\n                                visited[nr][nc] = true;\n                                q.push({nr,nc});\n                            }\n                        }\n                    }\n                    sum_sq += size * size;\n                }\n            }\n        }\n\n        // Distance Penalty (Manhattan)\n        double penalty_dist = 0;\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W; ++j) {\n                if (b[i][j] != 0) {\n                    int flavor_idx = b[i][j] - 1;\n                    penalty_dist += abs(i - targets[flavor_idx].first) + abs(j - targets[flavor_idx].second);\n                }\n            }\n        }\n        \n        return (double)sum_sq - w_dist * penalty_dist;\n    }\n\n    char solve(int p) {\n        // Place candy\n        auto [r, c] = get_pos(p, board);\n        board[r][c] = flavors[step];\n        \n        int best_move = -1;\n        double best_score = -1e18;\n        \n        // 1-Step Greedy Search\n        for (int d = 0; d < 4; ++d) {\n            auto next_board = tilt(board, d);\n            double score = evaluate(next_board);\n            if (score > best_score) {\n                best_score = score;\n                best_move = d;\n            }\n        }\n        \n        // Apply best move\n        board = tilt(board, best_move);\n        step++;\n        \n        if (best_move == 0) return 'F';\n        if (best_move == 1) return 'B';\n        if (best_move == 2) return 'L';\n        return 'R';\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) cin >> f[i];\n    \n    Solver solver(f);\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        if (t < 99) {\n            char out = solver.solve(p);\n            cout << out << endl;\n            cout.flush();\n        } else {\n            solver.solve(p);\n        }\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nmt19937 rng(42); \n\n// Estimate expected errors E for given N.\n// Uses neighbor-bound (2.5 * p_err).\ndouble estimate_expected_errors(int M, double eps, int N) {\n    int P = N * (N - 1) / 2;\n    if (P < M) return 100.0; \n\n    double step = (double)P / (M - 1);\n    double gap_observed = step * (1.0 - 2.0 * eps);\n    double sigma = sqrt((double)P * eps * (1.0 - eps));\n    \n    if (sigma < 1e-9) return 0.0;\n    \n    double z = (gap_observed / 2.0) / sigma;\n    double p_err = 0.5 * erfc(z / sqrt(2.0));\n    \n    // Estimate expected total errors. \n    // We assume errors mainly occur from neighbors. \n    // 2.5 is a safety multiplier.\n    return 2.5 * p_err * 100.0;\n}\n\nint choose_N(int M, double eps) {\n    int best_N = 100;\n    double best_score = -1.0;\n    \n    int min_N = (int)ceil((1.0 + sqrt(1.0 + 8.0 * M)) / 2.0);\n    if (min_N < 4) min_N = 4;\n\n    for (int N = min_N; N <= 100; ++N) {\n        double E = estimate_expected_errors(M, eps, N);\n        double score = pow(0.9, E) / (double)N;\n        if (score > best_score) {\n            best_score = score;\n            best_N = N;\n        }\n    }\n    return best_N;\n}\n\nstring generate_random_graph(int N, int target_edges) {\n    int P = N * (N - 1) / 2;\n    string graph(P, '0');\n    vector<int> indices(P);\n    iota(indices.begin(), indices.end(), 0);\n    shuffle(indices.begin(), indices.end(), rng);\n    for (int i = 0; i < target_edges; ++i) {\n        graph[indices[i]] = '1';\n    }\n    return graph;\n}\n\nvector<int> get_degrees(int N, const string& s) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (s[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    int M;\n    double eps;\n    cin >> M >> eps;\n    \n    int N = choose_N(M, eps);\n    int P = N * (N - 1) / 2;\n    \n    // Greedy Graph Generation\n    // We try multiple candidates and pick the one farthest from previous graph\n    int num_candidates = 30; \n    \n    vector<string> graphs(M);\n    vector<vector<int>> deg_seqs(M);\n    vector<vector<double>> exp_deg_seq(M);\n    vector<double> exp_wedge_count(M);\n\n    double slope = (1.0 - 2.0 * eps);\n    double intercept = (N - 1) * eps;\n    double var_deg = (N - 1) * eps * (1.0 - eps);\n\n    for (int i = 0; i < M; ++i) {\n        int target_edges = (int)round((double)i * P / (M - 1));\n        \n        string best_graph;\n        vector<int> best_deg;\n        double best_score = -1.0;\n        \n        for (int c = 0; c < num_candidates; ++c) {\n            string g_cand = generate_random_graph(N, target_edges);\n            vector<int> deg_cand = get_degrees(N, g_cand);\n            \n            double score = 0.0;\n            \n            // Calculate distance from previous graph (i-1)\n            if (i > 0) {\n                double dist = 0.0;\n                for (int j = 0; j < N; ++j) {\n                    double diff = deg_cand[j] - deg_seqs[i-1][j];\n                    dist += diff * diff;\n                }\n                score += dist;\n            }\n            \n            // We don't know i+1 yet.\n            // Just picking the one farthest from i-1 helps keep them separated.\n            if (score > best_score) {\n                best_score = score;\n                best_graph = g_cand;\n                best_deg = deg_cand;\n            }\n        }\n        \n        graphs[i] = best_graph;\n        deg_seqs[i] = best_deg;\n        \n        // Compute expected features for decoding\n        exp_deg_seq[i].resize(N);\n        exp_wedge_count[i] = 0.0;\n        for (int j = 0; j < N; ++j) {\n            int d = best_deg[j];\n            double mu = d * slope + intercept;\n            exp_deg_seq[i][j] = mu;\n            exp_wedge_count[i] += 0.5 * (var_deg + mu * mu - mu);\n        }\n    }\n    \n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    cout << flush;\n    \n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        \n        vector<int> deg_H = get_degrees(N, H);\n        \n        long long wedge_H = 0;\n        for (int d : deg_H) {\n            wedge_H += (long long)d * (d - 1) / 2;\n        }\n        \n        int best_k = 0;\n        double min_dist = 1e18;\n        \n        for (int k = 0; k < M; ++k) {\n            double dist_deg = 0.0;\n            for (int j = 0; j < N; ++j) {\n                double diff = deg_H[j] - exp_deg_seq[k][j];\n                dist_deg += diff * diff;\n            }\n            \n            double wedge_diff = wedge_H - exp_wedge_count[k];\n            double dist_total = dist_deg + 0.001 * wedge_diff * wedge_diff;\n            \n            if (dist_total < min_dist) {\n                min_dist = dist_total;\n                best_k = k;\n            }\n        }\n        \n        cout << best_k << endl;\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <climits>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst long long INF = 1e18;\n\n// Global variables\nint N, M, D, K;\nvector<vector<pair<int, int>>> adj; // (neighbor, edge_id)\nvector<int> from;\nvector<int> to;\nvector<long long> weight;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Calculate Edge Usage (Betweenness Centrality)\nvector<long long> calculate_usage() {\n    vector<long long> usage(M, 0);\n    for (int s = 0; s < N; ++s) {\n        vector<long long> dist(N, INF);\n        vector<int> parent_edge(N, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                long long w = weight[eid];\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = eid;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if (i == s) continue;\n            int eid = parent_edge[i];\n            if (eid != -1) usage[eid]++;\n        }\n    }\n    return usage;\n}\n\n// Check connectivity\nbool is_connected(const vector<int>& day_of_edge, int day_k, int check_eid) {\n    vector<int> visited(N, 0);\n    queue<int> q;\n    q.push(0);\n    visited[0] = 1;\n    int count = 1;\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        if (count == N) return true;\n\n        for (auto& [v, eid] : adj[u]) {\n            if (visited[v]) continue;\n            if (day_of_edge[eid] == day_k || eid == check_eid) continue;\n            visited[v] = 1;\n            count++;\n            q.push(v);\n        }\n    }\n    return count == N;\n}\n\n// Evaluate a day using sampling\nlong long evaluate_day_sampled(const vector<bool>& removed, const vector<int>& sources) {\n    long long sum_dist = 0;\n    for (int s : sources) {\n        vector<long long> dist(N, INF);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.emplace(0, s);\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n\n            for (auto& [v, eid] : adj[u]) {\n                if (removed[eid]) continue;\n                long long w = weight[eid];\n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    pq.emplace(dist[v], v);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) {\n            if (i == s) continue;\n            if (dist[i] == INF) sum_dist += INF;\n            else sum_dist += dist[i];\n        }\n    }\n    return sum_dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    cin >> N >> M >> D >> K;\n\n    adj.resize(N);\n    from.resize(M);\n    to.resize(M);\n    weight.resize(M);\n\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        from[i] = u;\n        to[i] = v;\n        weight[i] = w;\n        adj[u].emplace_back(v, i);\n        adj[v].emplace_back(u, i);\n    }\n\n    // Discard coordinates\n    for (int i = 0; i < N; ++i) {\n        double x, y;\n        cin >> x >> y;\n    }\n\n    // 1. Compute Usage\n    vector<long long> usage = calculate_usage();\n\n    // 2. Greedy Assignment\n    vector<int> day_of_edge(M, -1);\n    vector<long long> load(D, 0); \n    vector<int> day_size(D, 0);\n\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return usage[a] > usage[b];\n    });\n\n    auto check_conn = [&](int day_k, int check_eid) {\n        return is_connected(day_of_edge, day_k, check_eid);\n    };\n\n    for (int eid : edge_order) {\n        vector<pair<long long, int>> day_prios;\n        for(int d=0; d<D; ++d) day_prios.push_back({load[d], d});\n        sort(day_prios.begin(), day_prios.end());\n\n        bool assigned = false;\n        for (auto& [_, d] : day_prios) {\n            if (day_size[d] >= K) continue;\n            if (check_conn(d, eid)) {\n                day_of_edge[eid] = d;\n                load[d] += usage[eid];\n                day_size[d]++;\n                assigned = true;\n                break;\n            }\n        }\n        if (!assigned) {\n            for (int d = 0; d < D; ++d) {\n                if (day_size[d] < K) {\n                    day_of_edge[eid] = d;\n                    load[d] += usage[eid];\n                    day_size[d]++;\n                    break;\n                }\n            }\n        }\n    }\n\n    // 3. Local Search\n    vector<int> sources;\n    int sample_size = 40; \n    int step = max(1, N / sample_size);\n    for (int i = 0; i < N; i += step) sources.push_back(i);\n    if (sources.empty()) sources.push_back(0);\n\n    vector<vector<int>> edges_in_day(D);\n    vector<vector<bool>> removed_masks(D, vector<bool>(M, false));\n    vector<long long> day_scores(D);\n\n    for(int i=0; i<M; ++i) {\n        int d = day_of_edge[i];\n        edges_in_day[d].push_back(i);\n        removed_masks[d][i] = true;\n    }\n    for(int d=0; d<D; ++d) {\n        sort(edges_in_day[d].begin(), edges_in_day[d].end(), [&](int a, int b) {\n            return usage[a] > usage[b];\n        });\n        day_scores[d] = evaluate_day_sampled(removed_masks[d], sources);\n    }\n\n    int iter = 0;\n    while (true) {\n        auto curr = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(curr - start_time).count();\n        if (elapsed > 5.3) break; \n        iter++;\n\n        // Identify days and sort by score\n        vector<int> days_by_score(D);\n        iota(days_by_score.begin(), days_by_score.end(), 0);\n        sort(days_by_score.begin(), days_by_score.end(), [&](int a, int b) {\n            return day_scores[a] < day_scores[b]; // Ascending score\n        });\n\n        int worst_day = days_by_score.back(); // Day with highest score\n        \n        bool improved = false;\n        \n        // Try to move an edge from worst_day to a better day\n        // We try the top 3 critical edges in worst_day\n        int try_edges = min(3, (int)edges_in_day[worst_day].size());\n        \n        for(int e_idx = 0; e_idx < try_edges; ++e_idx) {\n            int e_move = edges_in_day[worst_day][e_idx];\n\n            // Iterate over target days (starting from the best days)\n            for (int d_target : days_by_score) {\n                if (d_target == worst_day) continue;\n                if (day_size[d_target] >= K) continue;\n\n                // Check connectivity\n                if (is_connected(day_of_edge, d_target, e_move)) {\n                    \n                    // Evaluate Move\n                    // Worst day without e_move\n                    removed_masks[worst_day][e_move] = false;\n                    long long score_worst_new = evaluate_day_sampled(removed_masks[worst_day], sources);\n                    removed_masks[worst_day][e_move] = true; // Restore\n\n                    // Target day with e_move\n                    removed_masks[d_target][e_move] = true;\n                    long long score_target_new = evaluate_day_sampled(removed_masks[d_target], sources);\n                    removed_masks[d_target][e_move] = false; // Restore\n\n                    long long current_total = day_scores[worst_day] + day_scores[d_target];\n                    long long new_total = score_worst_new + score_target_new;\n\n                    if (new_total < current_total) {\n                        // Accept Move\n                        day_of_edge[e_move] = d_target;\n                        \n                        day_size[worst_day]--;\n                        day_size[d_target]++;\n                        \n                        removed_masks[worst_day][e_move] = false;\n                        removed_masks[d_target][e_move] = true;\n                        \n                        day_scores[worst_day] = score_worst_new;\n                        day_scores[d_target] = score_target_new;\n                        \n                        // Update edge lists\n                        auto it = find(edges_in_day[worst_day].begin(), edges_in_day[worst_day].end(), e_move);\n                        if(it != edges_in_day[worst_day].end()) edges_in_day[worst_day].erase(it);\n                        edges_in_day[d_target].push_back(e_move);\n                        sort(edges_in_day[d_target].begin(), edges_in_day[d_target].end(), [&](int a, int b){\n                            return usage[a] > usage[b];\n                        });\n\n                        improved = true;\n                        break; // Move accepted, stop searching targets\n                    }\n                }\n            }\n            if (improved) break; // Move accepted, stop searching edges\n        }\n\n        // If no improving move found, perform a random move to escape local optima\n        // We pick a random day d1 and try to move a random edge to a random day d2\n        if (!improved) {\n            int d1 = rng() % D;\n            // Only try if d1 has edges\n            if (!edges_in_day[d1].empty()) {\n                int e_rand = edges_in_day[d1][rng() % edges_in_day[d1].size()];\n                \n                // Try a few random targets\n                for(int trial=0; trial<5; ++trial) {\n                    int d2 = rng() % D;\n                    if (d1 == d2 || day_size[d2] >= K) continue;\n                    \n                    if (is_connected(day_of_edge, d2, e_rand)) {\n                        // We accept this random move regardless of score (Simulated Annealing style, T=inf)\n                        // or we check if it improves. Let's check improvement to be safe, \n                        // but if stuck, maybe we need to force it.\n                        // Given Hill Climbing nature, let's check improvement.\n                        \n                        removed_masks[d1][e_rand] = false;\n                        long long s1 = evaluate_day_sampled(removed_masks[d1], sources);\n                        removed_masks[d1][e_rand] = true;\n                        \n                        removed_masks[d2][e_rand] = true;\n                        long long s2 = evaluate_day_sampled(removed_masks[d2], sources);\n                        removed_masks[d2][e_rand] = false;\n                        \n                        if (s1 + s2 < day_scores[d1] + day_scores[d2]) {\n                             day_of_edge[e_rand] = d2;\n                             day_size[d1]--; day_size[d2]++;\n                             removed_masks[d1][e_rand] = false;\n                             removed_masks[d2][e_rand] = true;\n                             day_scores[d1] = s1; day_scores[d2] = s2;\n                             \n                             auto it = find(edges_in_day[d1].begin(), edges_in_day[d1].end(), e_rand);\n                             if(it != edges_in_day[d1].end()) edges_in_day[d1].erase(it);\n                             edges_in_day[d2].push_back(e_rand);\n                             sort(edges_in_day[d2].begin(), edges_in_day[d2].end(), [&](int a, int b){ return usage[a] > usage[b]; });\n                             improved = true;\n                             break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    for(int i=0; i<M; ++i) {\n        if(i>0) cout << \" \";\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst int D_MAX = 14;\nconst int LAYER_SIZE = D_MAX * D_MAX; \n\n// Timer\nclass Timer {\n    chrono::system_clock::time_point start;\npublic:\n    Timer() : start(chrono::system_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::system_clock::now() - start).count();\n    }\n};\n\n// Global RNG\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Input Data\nint D;\nbool f[2][D_MAX][D_MAX]; \nbool r[2][D_MAX][D_MAX]; \n\n// State for a single layer\nstruct LayerState {\n    vector<pair<int, int>> cells; \n    array<int, D_MAX> cnt_y;            \n    bitset<LAYER_SIZE> bits;      \n    \n    LayerState() {\n        cnt_y.fill(0);\n    }\n\n    void clear() {\n        cells.clear();\n        cnt_y.fill(0);\n        bits.reset();\n    }\n\n    void init(int obj_id, int z) {\n        clear();\n        vector<int> xs, ys;\n        for (int x = 0; x < D; ++x) if (f[obj_id][z][x]) xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (r[obj_id][z][y]) ys.push_back(y);\n\n        int kx = xs.size();\n        int ky = ys.size();\n\n        if (kx == 0 || ky == 0) return;\n\n        int limit = min(kx, ky);\n        for (int i = 0; i < limit; ++i) add_cell(xs[i], ys[i]);\n        \n        if (kx > ky) {\n            for (int i = ky; i < kx; ++i) add_cell(xs[i], ys[0]);\n        } else if (ky > kx) {\n            for (int i = kx; i < ky; ++i) add_cell(xs[0], ys[i]);\n        }\n    }\n\n    inline void add_cell(int x, int y) {\n        cells.push_back({x, y});\n        cnt_y[y]++;\n        bits.set(x * D + y);\n    }\n    \n    void force_set_y(int idx, int new_y) {\n        int old_y = cells[idx].second;\n        int x = cells[idx].first;\n        \n        if (old_y == new_y) return;\n\n        cnt_y[old_y]--;\n        cnt_y[new_y]++;\n        \n        bits.reset(x * D + old_y);\n        bits.set(x * D + new_y);\n        \n        cells[idx].second = new_y;\n    }\n};\n\nstruct ObjectState {\n    LayerState layers[D_MAX];\n    int overlap; \n\n    ObjectState() : overlap(0) {}\n    \n    void init(int obj_id) {\n        overlap = 0;\n        for(int z=0; z<D; ++z) layers[z].init(obj_id, z);\n    }\n\n    void calc_overlap(const ObjectState& other) {\n        overlap = 0;\n        for(int z=0; z<D; ++z) {\n            overlap += (layers[z].bits & other.layers[z].bits).count();\n        }\n    }\n};\n\nObjectState states[2];\n\nvoid repair_state(ObjectState& obj, int obj_id) {\n    for (int z = 0; z < D; ++z) {\n        LayerState& layer = obj.layers[z];\n        \n        array<int, D_MAX> true_cnt;\n        true_cnt.fill(0);\n        for(auto& c : layer.cells) true_cnt[c.second]++;\n        \n        vector<int> missing_ys;\n        vector<int> surplus_ys;\n        \n        for(int y=0; y<D; ++y) {\n            if (r[obj_id][z][y]) {\n                if (true_cnt[y] == 0) missing_ys.push_back(y);\n            } else {\n                if (true_cnt[y] > 0) surplus_ys.push_back(y);\n            }\n        }\n        \n        for (int y_target : missing_ys) {\n            int src_y = -1;\n            \n            if (!surplus_ys.empty()) {\n                src_y = surplus_ys.back();\n                surplus_ys.pop_back();\n            } else {\n                for(int y=0; y<D; ++y) {\n                    if (true_cnt[y] > 1) {\n                        src_y = y;\n                        break;\n                    }\n                }\n            }\n            \n            if (src_y != -1) {\n                for(int i=0; i<(int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == src_y) {\n                        layer.force_set_y(i, y_target);\n                        true_cnt[src_y]--;\n                        true_cnt[y_target]++;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        for (int y_bad : surplus_ys) {\n            int y_good = -1;\n            \n            for(int y=0; y<D; ++y) {\n                if (r[obj_id][z][y] && true_cnt[y] > 1) {\n                    y_good = y;\n                    break;\n                }\n            }\n            \n            if (y_good == -1) {\n                for(int y=0; y<D; ++y) {\n                    if (r[obj_id][z][y]) {\n                        y_good = y;\n                        break;\n                    }\n                }\n            }\n            \n            if (y_good != -1) {\n                for(int i=0; i<(int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == y_bad) {\n                        layer.force_set_y(i, y_good);\n                        true_cnt[y_bad]--;\n                        true_cnt[y_good]++;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        layer.cnt_y = true_cnt;\n        layer.bits.reset();\n        for(auto& c : layer.cells) layer.bits.set(c.first * D + c.second);\n    }\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int x = 0; x < D; ++x) f[i][z][x] = (s[x] == '1');\n        }\n        for (int z = 0; z < D; ++z) {\n            string s;\n            cin >> s;\n            for (int y = 0; y < D; ++y) r[i][z][y] = (s[y] == '1');\n        }\n    }\n\n    states[0].init(0);\n    states[1].init(1);\n    states[0].calc_overlap(states[1]);\n\n    Timer timer;\n    // Fine-tuned parameters: Lower temp start (18.0), slightly more time (5.95)\n    double time_limit = 5.95; \n    double current_time = 0;\n    int current_solver = 0; \n    \n    vector<vector<int>> active_ys[2];\n    for(int i=0; i<2; ++i) {\n        active_ys[i].resize(D);\n        for(int z=0; z<D; ++z) {\n            for(int y=0; y<D; ++y) if(r[i][z][y]) active_ys[i][z].push_back(y);\n        }\n    }\n\n    while ((current_time = timer.elapsed()) < time_limit) {\n        int id_opt = current_solver;\n        int id_fix = 1 - current_solver;\n        current_solver = 1 - current_solver; \n\n        ObjectState& opt_state = states[id_opt];\n        const ObjectState& fix_state = states[id_fix];\n        \n        double temp = 18.0 * pow(1e-4 / 18.0, current_time / time_limit);\n        if (temp < 1e-5) temp = 1e-5;\n        \n        int batch = 16000;\n\n        for (int k = 0; k < batch; ++k) {\n            if (k % 1000 == 0 && timer.elapsed() > time_limit) break;\n\n            // Uniform selection of layer z\n            int z = rng() % D;\n            LayerState& layer = opt_state.layers[z];\n            const bitset<LAYER_SIZE>& target_bits = fix_state.layers[z].bits;\n            \n            if (layer.cells.empty()) continue;\n            \n            int idx = rng() % layer.cells.size();\n            int x = layer.cells[idx].first;\n            int old_y = layer.cells[idx].second;\n            \n            const auto& valid_ys = active_ys[id_opt][z];\n            if (valid_ys.empty()) continue;\n            int new_y = valid_ys[rng() % valid_ys.size()];\n            \n            if (old_y == new_y) continue;\n\n            int delta = 0;\n            int pos_old = x * D + old_y;\n            int pos_new = x * D + new_y;\n            \n            if (target_bits.test(pos_old)) delta--;\n            if (target_bits.test(pos_new)) delta++;\n\n            bool valid = false;\n            int swap_idx = -1;\n            \n            if (layer.cnt_y[old_y] > 1) {\n                valid = true;\n            } else {\n                for(int i = 0; i < (int)layer.cells.size(); ++i) {\n                    if (layer.cells[i].second == new_y) {\n                        swap_idx = i;\n                        break;\n                    }\n                }\n                \n                if (swap_idx != -1) {\n                    int x2 = layer.cells[swap_idx].first;\n                    if (target_bits.test(x2 * D + new_y)) delta--;\n                    if (target_bits.test(x2 * D + old_y)) delta++;\n                    valid = true;\n                }\n            }\n\n            if (valid) {\n                if (delta >= 0 || exp(delta / temp) > (double)(rng() % 10000) / 10000.0) {\n                    if (swap_idx != -1) {\n                        int x2 = layer.cells[swap_idx].first;\n                        layer.bits.reset(pos_old);\n                        layer.bits.set(pos_new);\n                        layer.bits.reset(x2 * D + new_y);\n                        layer.bits.set(x2 * D + old_y);\n                        \n                        layer.cells[idx].second = new_y;\n                        layer.cells[swap_idx].second = old_y;\n                        \n                    } else {\n                        layer.cnt_y[old_y]--;\n                        layer.cnt_y[new_y]++;\n                        layer.cells[idx].second = new_y;\n                        layer.bits.reset(pos_old);\n                        layer.bits.set(pos_new);\n                    }\n                    opt_state.overlap += delta;\n                }\n            }\n        }\n        \n        if (timer.elapsed() > time_limit) break;\n    }\n    \n    repair_state(states[0], 0);\n    repair_state(states[1], 1);\n\n    // Output Generation\n    vector<int> b1(D*D*D, 0);\n    vector<int> b2(D*D*D, 0);\n    \n    auto lin = [&](int x, int y, int z) { return x * D * D + y * D + z; };\n    \n    int visited[2][D_MAX][D_MAX][D_MAX]; \n    for(int i=0; i<2; ++i) \n        for(int z=0; z<D; ++z) \n            for(int x=0; x<D; ++x) \n                for(int y=0; y<D; ++y) \n                    visited[i][z][x][y] = 0;\n\n    int current_id = 0;\n    \n    // 1. Shared components\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[0].layers[z].bits.test(x*D + y) && \n                    states[1].layers[z].bits.test(x*D + y) && \n                    visited[0][z][x][y] == 0) {\n                    \n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    visited[1][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b1[lin(cx, cy, cz)] = current_id;\n                        b2[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        \n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[0][nz][nx][ny] == 0 && \n                                    states[0].layers[nz].bits.test(nx*D + ny) && \n                                    states[1].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // 2. Unique to Obj 1\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[0].layers[z].bits.test(x*D + y) && visited[0][z][x][y] == 0) {\n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[0][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b1[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[0][nz][nx][ny] == 0 && states[0].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[0][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // 3. Unique to Obj 2\n    for (int z = 0; z < D; ++z) {\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (states[1].layers[z].bits.test(x*D + y) && visited[1][z][x][y] == 0) {\n                    current_id++;\n                    queue<array<int,3>> q;\n                    q.push({x,y,z});\n                    visited[1][z][x][y] = current_id;\n                    \n                    while(!q.empty()) {\n                        auto p = q.front(); q.pop();\n                        int cx = p[0], cy = p[1], cz = p[2];\n                        b2[lin(cx, cy, cz)] = current_id;\n                        \n                        int dx[6] = {1,-1,0,0,0,0};\n                        int dy[6] = {0,0,1,-1,0,0};\n                        int dz[6] = {0,0,0,0,1,-1};\n                        for(int k=0; k<6; ++k) {\n                            int nx = cx+dx[k], ny = cy+dy[k], nz = cz+dz[k];\n                            if(0<=nx && nx<D && 0<=ny && ny<D && 0<=nz && nz<D) {\n                                if (visited[1][nz][nx][ny] == 0 && states[1].layers[nz].bits.test(nx*D + ny)) {\n                                    visited[1][nz][nx][ny] = current_id;\n                                    q.push({nx,ny,nz});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    cout << current_id << \"\\n\";\n    for(int i=0; i<D*D*D; ++i) {\n        if(i) cout << \" \";\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    for(int i=0; i<D*D*D; ++i) {\n        if(i) cout << \" \";\n        cout << b2[i];\n    }\n    cout << \"\\n\";\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <queue>\n#include <tuple>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Solver {\n    int N, M, K;\n    vector<pair<int, int>> coords;\n    vector<tuple<int, int, long long>> edges;\n    vector<pair<int, int>> residents;\n    vector<vector<long long>> dist_nodes; \n    vector<vector<int>> dist_res_round; \n    vector<vector<int>> dist_res_ceil; \n    vector<int> P;\n    vector<int> B;\n    vector<int> assign;\n    vector<bool> active;\n    vector<vector<int>> cnt; \n    vector<int> max_rad;     \n    vector<vector<int>> resident_order; \n\n    Solver(int n, int m, int k) : N(n), M(m), K(k) {\n        coords.resize(N);\n        edges.resize(M);\n        residents.resize(K);\n        dist_nodes.assign(N, vector<long long>(N, 1e18));\n        dist_res_round.assign(N, vector<int>(K));\n        dist_res_ceil.assign(N, vector<int>(K));\n        P.assign(N, 0);\n        B.assign(M, 0);\n        assign.assign(K, -1);\n        active.assign(N, false);\n        max_rad.assign(N, 0);\n        const int MAX_D = 15001;\n        cnt.assign(N, vector<int>(MAX_D, 0));\n        resident_order.assign(K, vector<int>(N));\n    }\n\n    void solve() {\n        // 1. Floyd-Warshall\n        for (int i = 0; i < N; ++i) dist_nodes[i][i] = 0;\n        for (auto& e : edges) {\n            int u, v;\n            long long w;\n            tie(u, v, w) = e;\n            u--; v--;\n            if (w < dist_nodes[u][v]) {\n                dist_nodes[u][v] = w;\n                dist_nodes[v][u] = w;\n            }\n        }\n        for (int k = 0; k < N; ++k) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (dist_nodes[i][k] + dist_nodes[k][j] < dist_nodes[i][j]) {\n                        dist_nodes[i][j] = dist_nodes[i][k] + dist_nodes[k][j];\n                    }\n                }\n            }\n        }\n\n        // 2. Precompute resident distances (Round and Ceil) and Order\n        vector<int> temp_nodes(N);\n        iota(temp_nodes.begin(), temp_nodes.end(), 0);\n\n        for (int k = 0; k < K; ++k) {\n            for (int i = 0; i < N; ++i) {\n                long long dx = (long long)coords[i].first - residents[k].first;\n                long long dy = (long long)coords[i].second - residents[k].second;\n                long long d_sq = dx*dx + dy*dy;\n                \n                int dr = (int)round(sqrt((double)d_sq));\n                int dc = (int)ceil(sqrt((double)d_sq));\n                \n                dist_res_round[i][k] = dr;\n                dist_res_ceil[i][k] = dc;\n            }\n            // Sort by Round distance for cost optimization\n            sort(temp_nodes.begin(), temp_nodes.end(), [&](int a, int b) {\n                return dist_res_round[a][k] < dist_res_round[b][k];\n            });\n            resident_order[k] = temp_nodes;\n        }\n\n        // 3. Helper: MST Cost\n        auto get_mst_cost = [&](const vector<bool>& act) {\n            long long mst_cost = 0;\n            vector<bool> in_mst(N, false);\n            vector<long long> min_dist(N, 1e18);\n            min_dist[0] = 0; \n            for (int i = 0; i < N; ++i) {\n                int u = -1;\n                for (int j = 0; j < N; ++j) {\n                    if (act[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                        u = j;\n                    }\n                }\n                if (u == -1) break;\n                in_mst[u] = true;\n                mst_cost += min_dist[u];\n                for (int v = 0; v < N; ++v) {\n                    if (act[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                        min_dist[v] = dist_nodes[u][v];\n                    }\n                }\n            }\n            return mst_cost;\n        };\n\n        // 4. Helper: Full Reassign\n        auto reassign = [&]() {\n            for (int i = 0; i < N; ++i) {\n                fill(cnt[i].begin(), cnt[i].end(), 0);\n                max_rad[i] = 0;\n            }\n            for (int k = 0; k < K; ++k) {\n                for (int u : resident_order[k]) {\n                    if (active[u]) {\n                        assign[k] = u;\n                        int d = dist_res_round[u][k];\n                        cnt[u][d]++;\n                        if (d > max_rad[u]) max_rad[u] = d;\n                        break;\n                    }\n                }\n            }\n        };\n\n        // 5. Initial State (Round Logic - Low Cost)\n        active[0] = true;\n        reassign();\n\n        // Add nodes greedily until round-valid\n        while (true) {\n            int worst_k = -1;\n            int worst_d = -1;\n            bool covered = true;\n            \n            for (int k = 0; k < K; ++k) {\n                int owner = assign[k];\n                int d = dist_res_round[owner][k];\n                if (d > 5000) {\n                    covered = false;\n                    if (d > worst_d) {\n                        worst_d = d;\n                        worst_k = k;\n                    }\n                }\n            }\n            \n            if (covered) break;\n            if (worst_k == -1) break;\n            \n            int best_u = -1;\n            int min_d = 15001;\n            for (int u : resident_order[worst_k]) {\n                if (!active[u]) {\n                    min_d = dist_res_round[u][worst_k];\n                    best_u = u;\n                    break;\n                }\n            }\n            \n            if (best_u != -1) {\n                active[best_u] = true;\n                reassign();\n            } else {\n                break; \n            }\n        }\n\n        long long current_edge_cost = get_mst_cost(active);\n        long long current_node_cost = 0;\n        for (int i = 0; i < N; ++i) {\n            current_node_cost += (long long)max_rad[i] * max_rad[i];\n        }\n        long long total_cost = current_edge_cost + current_node_cost;\n\n        // 6. Optimization Loop\n        mt19937 rng(2024);\n        vector<int> order(N-1);\n        iota(order.begin(), order.end(), 1);\n        \n        for (int iter = 0; iter < 50; ++iter) {\n            // --- Remove Pass ---\n            // Strict Validity: only remove if Ceil distance is covered\n            shuffle(order.begin(), order.end(), rng);\n            for (int u : order) {\n                if (!active[u]) continue;\n\n                vector<int> new_owners(K, -1);\n                bool invalid = false;\n                \n                for (int k = 0; k < K; ++k) {\n                    if (assign[k] == u) {\n                        int best_v = -1;\n                        int min_p_round = 15001;\n                        // Sort by Round distance for consistency with cost metric\n                        for (int v : resident_order[k]) {\n                            if (active[v] && v != u) {\n                                min_p_round = dist_res_round[v][k];\n                                best_v = v;\n                                break;\n                            }\n                        }\n                        // CHECK VALIDITY WITH CEIL\n                        if (best_v == -1 || dist_res_ceil[best_v][k] > 5000) {\n                            invalid = true;\n                            break;\n                        }\n                        new_owners[k] = best_v;\n                    }\n                }\n                \n                if (invalid) continue;\n                \n                long long delta = 0;\n                vector<int> saved_max = max_rad;\n                \n                delta -= (long long)max_rad[u] * max_rad[u];\n                max_rad[u] = 0;\n                \n                for (int k = 0; k < K; ++k) {\n                    if (assign[k] == u) {\n                        int v = new_owners[k];\n                        int d = dist_res_round[v][k];\n                        cnt[u][d]--;\n                        cnt[v][d]++;\n                        if (d > max_rad[v]) {\n                            delta += (long long)d*d - (long long)saved_max[v]*saved_max[v];\n                            max_rad[v] = d;\n                        }\n                    }\n                }\n                \n                if (delta >= 0) {\n                    for (int k = 0; k < K; ++k) {\n                        if (assign[k] == u) {\n                            int v = new_owners[k];\n                            int d = dist_res_round[v][k];\n                            cnt[v][d]--;\n                            cnt[u][d]++;\n                        }\n                    }\n                    max_rad = saved_max;\n                    continue;\n                }\n                \n                active[u] = false;\n                long long new_edge_cost = get_mst_cost(active);\n                active[u] = true;\n                \n                if (current_node_cost + delta + new_edge_cost < total_cost) {\n                    active[u] = false;\n                    current_edge_cost = new_edge_cost;\n                    current_node_cost += delta;\n                    total_cost = current_edge_cost + current_node_cost;\n                    for (int k = 0; k < K; ++k) {\n                        if (new_owners[k] != -1) assign[k] = new_owners[k];\n                    }\n                } else {\n                    for (int k = 0; k < K; ++k) {\n                        if (assign[k] == u) {\n                            int v = new_owners[k];\n                            int d = dist_res_round[v][k];\n                            cnt[v][d]--;\n                            cnt[u][d]++;\n                        }\n                    }\n                    max_rad = saved_max;\n                }\n            }\n\n            // --- Add Pass ---\n            // Standard Cost Reduction (Round), Validity Check (Ceil)\n            shuffle(order.begin(), order.end(), rng);\n            for (int u : order) {\n                if (active[u]) continue;\n                \n                vector<int> moved_k;\n                vector<int> old_owners;\n                \n                // Radius-based heuristic (using Round for cost)\n                for (int k = 0; k < K; ++k) {\n                    int cur = assign[k];\n                    int d_cur = dist_res_round[cur][k];\n                    int d_new = dist_res_round[u][k];\n                    if (d_new < max_rad[cur]) {\n                        moved_k.push_back(k);\n                        old_owners.push_back(cur);\n                    }\n                }\n                \n                if (moved_k.empty()) continue;\n                \n                // Check validity of moves using Ceil\n                bool valid = true;\n                for (size_t i = 0; i < moved_k.size(); ++i) {\n                    int k = moved_k[i];\n                    // If moving to u, is it valid?\n                    if (dist_res_ceil[u][k] > 5000) {\n                        valid = false;\n                        break;\n                    }\n                }\n                if (!valid) continue;\n                \n                vector<int> saved_max = max_rad;\n                long long delta = 0;\n                \n                for (size_t i = 0; i < moved_k.size(); ++i) {\n                    int k = moved_k[i];\n                    int v = old_owners[i];\n                    int d_old = dist_res_round[v][k];\n                    cnt[v][d_old]--;\n                    while (max_rad[v] > 0 && cnt[v][max_rad[v]] == 0) max_rad[v]--;\n                }\n                \n                int max_p_u = 0;\n                for (int k : moved_k) {\n                    int d = dist_res_round[u][k];\n                    cnt[u][d]++;\n                    if (d > max_p_u) max_p_u = d;\n                }\n                delta += (long long)max_p_u * max_p_u;\n                max_rad[u] = max_p_u;\n                \n                for (int v : old_owners) {\n                    delta += (long long)max_rad[v] * max_rad[v];\n                    delta -= (long long)saved_max[v] * saved_max[v];\n                }\n                \n                if (max_rad[u] > 5000) valid = false;\n                for (int v : old_owners) {\n                    if (max_rad[v] > 5000) valid = false;\n                }\n                \n                if (!valid || delta >= 0) {\n                    for (int k : moved_k) {\n                        int d = dist_res_round[u][k];\n                        cnt[u][d]--;\n                    }\n                    for (size_t i = 0; i < moved_k.size(); ++i) {\n                        int k = moved_k[i];\n                        int v = old_owners[i];\n                        int d = dist_res_round[v][k];\n                        cnt[v][d]++;\n                    }\n                    max_rad = saved_max;\n                    continue;\n                }\n                \n                active[u] = true;\n                long long new_edge_cost = get_mst_cost(active);\n                active[u] = false;\n                \n                if (current_node_cost + delta + new_edge_cost < total_cost) {\n                    active[u] = true;\n                    current_edge_cost = new_edge_cost;\n                    current_node_cost += delta;\n                    total_cost = current_edge_cost + current_node_cost;\n                    for (size_t i = 0; i < moved_k.size(); ++i) {\n                        assign[moved_k[i]] = u;\n                    }\n                } else {\n                    for (int k : moved_k) {\n                        int d = dist_res_round[u][k];\n                        cnt[u][d]--;\n                    }\n                    for (size_t i = 0; i < moved_k.size(); ++i) {\n                        int k = moved_k[i];\n                        int v = old_owners[i];\n                        int d = dist_res_round[v][k];\n                        cnt[v][d]++;\n                    }\n                    max_rad = saved_max;\n                }\n            }\n            \n            // --- Validity Repair (Force Fix) ---\n            // If still invalid, add one node to fix the worst offender\n            // Use Ceil for strict validity check\n            bool all_valid = true;\n            int worst_k = -1;\n            int worst_d_ceil = -1;\n            \n            for (int k = 0; k < K; ++k) {\n                int owner = assign[k];\n                if (dist_res_ceil[owner][k] > 5000) {\n                    all_valid = false;\n                    int d = dist_res_ceil[owner][k];\n                    if (d > worst_d_ceil) {\n                        worst_d_ceil = d;\n                        worst_k = k;\n                    }\n                }\n            }\n            \n            if (!all_valid && worst_k != -1) {\n                // Find best node to cover worst_k\n                int best_u = -1;\n                int min_p_ceil = 15001;\n                for (int u : resident_order[worst_k]) {\n                    if (!active[u]) {\n                        min_p_ceil = dist_res_ceil[u][worst_k];\n                        best_u = u;\n                        break;\n                    }\n                }\n                if (best_u != -1 && min_p_ceil <= 5000) {\n                    // Add this node\n                    active[best_u] = true;\n                    reassign(); // Reassign to settle everything\n                    current_edge_cost = get_mst_cost(active);\n                    current_node_cost = 0;\n                    for (int i = 0; i < N; ++i) {\n                        current_node_cost += (long long)max_rad[i] * max_rad[i];\n                    }\n                    total_cost = current_edge_cost + current_node_cost;\n                }\n            }\n        }\n\n        // 7. Output Construction\n        for (int i = 0; i < N; ++i) {\n            P[i] = max_rad[i];\n        }\n\n        vector<vector<int>> mst_adj(N, vector<int>(N, 0)); \n        vector<bool> in_mst(N, false);\n        vector<int> parent(N, -1);\n        vector<long long> min_dist(N, 1e18);\n        min_dist[0] = 0;\n        \n        for (int i = 0; i < N; ++i) {\n            int u = -1;\n            for (int j = 0; j < N; ++j) {\n                if (active[j] && !in_mst[j] && (u == -1 || min_dist[j] < min_dist[u])) {\n                    u = j;\n                }\n            }\n            if (u == -1) break;\n            in_mst[u] = true;\n            if (parent[u] != -1) {\n                int s = parent[u];\n                int t = u;\n                vector<long long> d(N, 1e18);\n                vector<int> prev(N, -1);\n                d[s] = 0;\n                priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n                pq.push({0, s});\n                while(!pq.empty()){\n                    auto [dist, v] = pq.top(); pq.pop();\n                    if(dist > d[v]) continue;\n                    if(v == t) break;\n                    for(auto& edge : edges){\n                        int a, b; long long w;\n                        tie(a, b, w) = edge;\n                        a--; b--;\n                        if(v == a && d[a] + w < d[b]){\n                            d[b] = d[a] + w;\n                            prev[b] = a;\n                            pq.push({d[b], b});\n                        } else if (v == b && d[b] + w < d[a]){\n                            d[a] = d[b] + w;\n                            prev[a] = b;\n                            pq.push({d[a], a});\n                        }\n                    }\n                }\n                \n                int curr = t;\n                while (curr != s && curr != -1) {\n                    int p = prev[curr];\n                    if (p == -1) break;\n                    for (int j = 0; j < M; ++j) {\n                        int uj, vj; long long wj;\n                        tie(uj, vj, wj) = edges[j];\n                        uj--; vj--;\n                        if ((uj == p && vj == curr) || (uj == curr && vj == p)) {\n                            B[j] = 1;\n                            break;\n                        }\n                    }\n                    curr = p;\n                }\n            }\n            \n            for (int v = 0; v < N; ++v) {\n                if (active[v] && !in_mst[v] && dist_nodes[u][v] < min_dist[v]) {\n                    min_dist[v] = dist_nodes[u][v];\n                    parent[v] = u;\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            if (i > 0) cout << \" \";\n            cout << P[i];\n        }\n        cout << \"\\n\";\n        for (int j = 0; j < M; ++j) {\n            if (j > 0) cout << \" \";\n            cout << B[j];\n        }\n        cout << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n    \n    Solver solver(N, M, K);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> solver.coords[i].first >> solver.coords[i].second;\n    }\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        solver.edges[i] = {u, v, w};\n    }\n    for (int i = 0; i < K; ++i) {\n        cin >> solver.residents[i].first >> solver.residents[i].second;\n    }\n    \n    solver.solve();\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <map>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> all_vals;\n    map<int, pair<int, int>> pos;\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            grid[x][y] = v;\n            pos[v] = {x, y};\n            all_vals.push_back(v);\n        }\n    }\n\n    sort(all_vals.begin(), all_vals.end());\n    map<int, int> rank_of_val;\n    for (int i = 0; i < (int)all_vals.size(); ++i) {\n        rank_of_val[all_vals[i]] = i;\n    }\n\n    auto get_tier = [&](int rank) -> int {\n        int t = (int)((-1 + sqrt(1 + 8.0 * rank)) / 2);\n        while ((t + 1) * (t + 2) / 2 <= rank) t++;\n        while (t * (t + 1) / 2 > rank) t--;\n        return t;\n    };\n\n    vector<int> target_tier(465);\n    for (int i = 0; i < 465; ++i) {\n        target_tier[i] = get_tier(i);\n    }\n\n    vector<tuple<int, int, int, int>> operations;\n\n    auto dist = [](int x1, int y1, int x2, int y2) -> int {\n        return max(abs(x1 - x2), abs(y1 - y2));\n    };\n\n    // Best performing BFS order: Side, Up, Down\n    vector<pair<int, int>> directions = {\n        {0, -1}, {0, 1}, {-1, 0}, {-1, -1}, {1, 0}, {1, 1}\n    };\n\n    for (int t = N - 1; t >= 0; --t) {\n        int start_rank = t * (t + 1) / 2;\n        int count = t + 1;\n        \n        vector<int> balls_in_tier;\n        for (int i = 0; i < count; ++i) {\n            balls_in_tier.push_back(all_vals[start_rank + i]);\n        }\n\n        // Input Sort: Ascending X (Deepest First).\n        // Rationale: Give \"hard\" balls (far from target) priority to claim the best slots (low dy).\n        // This forces long-distance balls to move straight down (dy=0), minimizing congestion.\n        sort(balls_in_tier.begin(), balls_in_tier.end(), [&](int a, int b) {\n            return pos[a].first < pos[b].first;\n        });\n\n        int node_offset = t + 1;\n        int SRC = (t + 1) * 2;\n        int SNK = (t + 1) * 2 + 1;\n        \n        mcf_graph<int, int> g(SNK + 1);\n\n        for (int i = 0; i < count; ++i) {\n            int val = balls_in_tier[i];\n            auto [cx, cy] = pos[val];\n            g.add_edge(SRC, i, 1, 0); \n            \n            for (int j = 0; j < count; ++j) {\n                int d = dist(cx, cy, t, j);\n                int cost = d * 100 + (cy - j) * (cy - j);\n                g.add_edge(i, node_offset + j, 1, cost);\n            }\n        }\n        \n        for (int j = 0; j < count; ++j) {\n             g.add_edge(node_offset + j, SNK, 1, 0);\n        }\n\n        auto flow_res = g.flow(SRC, SNK);\n        \n        map<int, pair<int, int>> final_targets; \n        \n        auto edges = g.edges();\n        for (auto &e : edges) {\n            if (e.from >= SRC || e.to >= SNK || e.to == SRC || e.from == SNK) continue;\n            if (e.from < t + 1 && e.to >= node_offset && e.to < (t + 1) * 2 && e.flow > 0) {\n                int ball_idx = e.from;\n                int target_y = e.to - node_offset;\n                int val = balls_in_tier[ball_idx];\n                final_targets[val] = {t, target_y};\n            }\n        }\n\n        struct Assignment {\n            int val;\n            int tx;\n            int ty;\n            int d;\n        };\n        vector<Assignment> assigns;\n        for (auto& p : final_targets) {\n            auto [tx, ty] = p.second;\n            auto [sx, sy] = pos[p.first];\n            int d = dist(sx, sy, tx, ty);\n            assigns.push_back({p.first, tx, ty, d});\n        }\n\n        // Placement Order: Edge-in -> Closest First\n        sort(assigns.begin(), assigns.end(), [&](const Assignment& a, const Assignment& b) {\n            int edge_dist_a = min(a.ty, t - a.ty);\n            int edge_dist_b = min(b.ty, t - b.ty);\n            if (edge_dist_a != edge_dist_b) return edge_dist_a < edge_dist_b;\n            \n            if (a.d != b.d) return a.d < b.d;\n            \n            return a.ty < b.ty;\n        });\n\n        for (auto& item : assigns) {\n            int val = item.val;\n            int tx = item.tx;\n            int ty = item.ty;\n            auto [sx, sy] = pos[val];\n\n            if (sx == tx && sy == ty) continue;\n\n            queue<pair<int, int>> q;\n            map<pair<int, int>, pair<int, int>> parent;\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            \n            q.push({sx, sy});\n            visited[sx][sy] = true;\n            \n            bool found = false;\n            \n            while (!q.empty() && !found) {\n                auto [cx, cy] = q.front();\n                q.pop();\n                \n                for (auto [dx, dy] : directions) {\n                    int nx = cx + dx;\n                    int ny = cy + dy;\n                    \n                    if (nx < 0 || nx >= N || ny < 0 || ny > nx) continue;\n                    if (visited[nx][ny]) continue;\n                    \n                    int ball_at_nx = grid[nx][ny];\n                    int b_tier = target_tier[rank_of_val[ball_at_nx]];\n                    \n                    bool is_obstacle = false;\n                    if (b_tier > t) is_obstacle = true;\n                    else if (b_tier == t) {\n                        if (final_targets.count(ball_at_nx)) {\n                             auto [b_tx, b_ty] = final_targets[ball_at_nx];\n                             if (nx == b_tx && ny == b_ty) is_obstacle = true;\n                        }\n                    }\n                    \n                    if (!is_obstacle) {\n                        visited[nx][ny] = true;\n                        parent[{nx, ny}] = {cx, cy};\n                        q.push({nx, ny});\n                        if (nx == tx && ny == ty) {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            vector<pair<int, int>> path;\n            {\n                auto curr = make_pair(tx, ty);\n                while (curr != make_pair(sx, sy)) {\n                    path.push_back(curr);\n                    curr = parent[curr];\n                }\n                path.push_back({sx, sy});\n                reverse(path.begin(), path.end());\n            }\n\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                auto [u1, v1] = path[i];\n                auto [u2, v2] = path[i+1];\n                \n                int val1 = grid[u1][v1];\n                int val2 = grid[u2][v2];\n                \n                swap(grid[u1][v1], grid[u2][v2]);\n                \n                pos[val1] = {u2, v2};\n                pos[val2] = {u1, v1};\n                \n                operations.push_back({u1, v1, u2, v2});\n            }\n        }\n    }\n\n    cout << operations.size() << \"\\n\";\n    for (auto [x1, y1, x2, y2] : operations) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <map>\n#include <set>\n#include <numeric>\n\nusing namespace std;\n\n// Grid configuration\nconst int D = 9;\nconst int INF = 1e9;\n// Entrance\nconst int ER = 0;\nconst int EC = 4;\n\nstruct State {\n    vector<vector<bool>> obstacle;\n    vector<vector<int>> dist;\n    vector<vector<bool>> occupied;\n    int total_containers;\n\n    State(int n, const vector<pair<int, int>>& obs_coords) {\n        obstacle.assign(D, vector<bool>(D, false));\n        occupied.assign(D, vector<bool>(D, false));\n        dist.assign(D, vector<int>(D, -1));\n        \n        // Mark entrance and adjacent as not obstacles (problem guarantee)\n        // But we also treat them as not storage space.\n        \n        // Mark obstacles\n        for (auto p : obs_coords) {\n            obstacle[p.first][p.second] = true;\n        }\n\n        // Calculate distances from entrance\n        queue<pair<int, int>> q;\n        q.push({ER, EC});\n        dist[ER][EC] = 0;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (dist[nr][nc] == -1 && !obstacle[nr][nc]) {\n                        dist[nr][nc] = dist[r][c] + 1;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n        }\n\n        // Count available spots\n        total_containers = 0;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                // Entrance and obstacles are not for storage\n                if ((i == ER && j == EC) || obstacle[i][j]) continue;\n                // Problem statement says entrance and its 3 adjacent are not obstacles\n                // But they are valid storage spots? \n                // \"Each D x D - 1 - N square other than the entrance and obstacles can hold at most 1 container.\"\n                // So adjacent squares (0,3), (0,5), (1,4) ARE valid storage spots.\n                total_containers++;\n            }\n        }\n    }\n    \n    // Find empty cells reachable from entrance via empty cells\n    vector<pair<int, int>> get_reachable_empty() {\n        vector<pair<int, int>> reachable;\n        queue<pair<int, int>> q;\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        \n        // Start from entrance\n        q.push({ER, EC});\n        visited[ER][EC] = true;\n        \n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n\n        while (!q.empty()) {\n            auto curr = q.front(); 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                if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                    if (!visited[nr][nc] && !obstacle[nr][nc] && !occupied[nr][nc]) {\n                        visited[nr][nc] = true;\n                        q.push({nr, nc});\n                        reachable.push_back({nr, nc});\n                    }\n                }\n            }\n        }\n        return reachable;\n    }\n\n    // Check if placing a container at (tr, tc) blocks other empty cells from entrance\n    // It blocks if, after marking (tr, tc) occupied, some previously reachable empty cell becomes unreachable.\n    bool is_safe_placement(int tr, int tc) {\n        // Temporarily mark as occupied\n        occupied[tr][tc] = true;\n        \n        vector<pair<int, int>> new_reachable = get_reachable_empty();\n        \n        // Restore\n        occupied[tr][tc] = false;\n\n        // Count previously reachable (excluding the cell itself)\n        auto prev_reachable = get_reachable_empty();\n        \n        // Actually, we can just compare counts of reachable nodes (excluding the one we are filling)\n        // Since we are adding an obstacle, the set of reachable empty cells can only shrink.\n        // We want it to NOT shrink (except for the cell itself).\n        // Note: get_reachable_empty returns EMPTY cells.\n        // (tr, tc) is empty before placement. It is in prev_reachable.\n        // After placement, it is not in new_reachable.\n        // So we expect |new_reachable| == |prev_reachable| - 1.\n        \n        if (new_reachable.size() == prev_reachable.size() - 1) return true;\n        return false;\n    }\n\n    // Choose best cell for container t\n    pair<int, int> choose_placement(int t) {\n        auto reachable = get_reachable_empty();\n        \n        if (reachable.empty()) {\n            // Should not happen\n            return {-1, -1};\n        }\n\n        // Target distance\n        // Map t from [0, M-1] to a distance range\n        // Max distance is around 15.\n        double ratio = (double)t / total_containers;\n        \n        // We want to sort candidates.\n        // Heuristic: \n        // 1. Is safe (doesn't block).\n        // 2. Distance is close to target.\n        // 3. (Optional) Prefer low degree or corners?\n        \n        vector<tuple<int, int, double>> candidates; // score, r, c\n        // Score > 0 means safe, < 0 unsafe.\n        \n        int max_dist = 0;\n        for(auto& p : reachable) max_dist = max(max_dist, dist[p.first][p.second]);\n        \n        for (auto& p : reachable) {\n            int r = p.first;\n            int c = p.second;\n            int d = dist[r][c];\n            \n            double ideal_d = ratio * max_dist;\n            double dist_error = abs(d - ideal_d);\n            \n            int safe_score = is_safe_placement(r, c) ? 1000 : 0;\n            \n            // Combine: safety is most important. Then distance match.\n            // We maximize score.\n            double final_score = safe_score - dist_error;\n            \n            // If unsafe, we might still want to place it if we have no other choice,\n            // but we pick the one with max_dist_error (least bad? or best distance?).\n            // Let's say if unsafe, score is just -dist_error.\n            // If safe, score is 1000 - dist_error.\n            \n            candidates.push_back({final_score, r, c});\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<tuple<double, int, int>>());\n        \n        // Pick the best one\n        return {get<1>(candidates[0]), get<2>(candidates[0])};\n    }\n\n    void place(int t, int r, int c) {\n        occupied[r][c] = true;\n        cout << r << \" \" << c << endl;\n        // cout << \"# Placed \" << t << \" at \" << r << \" \" << c << endl;\n    }\n\n    // Retrieve phase\n    void retrieve_all(const map<int, pair<int, int>>& id_to_coord) {\n        vector<pair<int, int>> retrieval_order;\n        \n        // Set of remaining IDs\n        set<int> remaining;\n        for (auto p : id_to_coord) remaining.insert(p.first);\n        \n        // While there are containers\n        while (!remaining.empty()) {\n            // Find reachable occupied cells\n            queue<pair<int, int>> q;\n            vector<vector<bool>> visited(D, vector<bool>(D, false));\n            q.push({ER, EC});\n            visited[ER][EC] = true;\n            \n            vector<int> reachable_ids;\n            \n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n\n            while (!q.empty()) {\n                auto curr = q.front(); 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                    if (0 <= nr && nr < D && 0 <= nc && nc < D) {\n                        if (!visited[nr][nc] && !obstacle[nr][nc]) {\n                            // Check if occupied\n                            bool is_occupied = false;\n                            int id_at = -1;\n                            // We need to check if this coordinate has a container that is still in 'remaining'\n                            // We can look up in id_to_coord map (inverse map needed?)\n                            // Actually we have id_to_coord. We need coord_to_id.\n                            // Or just iterate remaining? remaining size is up to 80. O(80*80) is fine.\n                            for (int rid : remaining) {\n                                if (id_to_coord.at(rid) == make_pair(nr, nc)) {\n                                    is_occupied = true;\n                                    id_at = rid;\n                                    break;\n                                }\n                            }\n\n                            if (is_occupied) {\n                                visited[nr][nc] = true; // Can reach this square (but stop here?)\n                                // Actually we pass through it? No.\n                                // Rule: \"passing through adjacent empty squares\".\n                                // Occupied squares are NOT empty.\n                                // So we CANNOT pass through occupied squares.\n                                // We can only reach the occupied square itself if we are adjacent to an empty square.\n                                // But we CANNOT go THROUGH an occupied square.\n                                // However, the square containing the container is the target.\n                                // The rule says: \"The square containing the container to be transported out must be reachable... by passing through adjacent empty squares.\"\n                                // This means the path ends at the square. The square itself is occupied.\n                                // So we just check connectivity via EMPTY squares.\n                                // If (nr, nc) is occupied, we don't push it to queue.\n                                // But we record it as a retrievable target.\n                                reachable_ids.push_back(id_at);\n                            } else {\n                                // Empty, traverse\n                                visited[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            if (reachable_ids.empty()) {\n                // Should not happen\n                break;\n            }\n            \n            // Pick smallest ID\n            sort(reachable_ids.begin(), reachable_ids.end());\n            int to_retrieve = reachable_ids[0];\n            \n            retrieval_order.push_back(id_to_coord.at(to_retrieve));\n            remaining.erase(to_retrieve);\n        }\n        \n        // Output\n        for (auto p : retrieval_order) {\n            cout << p.first << \" \" << p.second << endl;\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    cin.tie(0);\n    ios::sync_with_stdio(false);\n\n    int N;\n    cin >> N;\n    \n    vector<pair<int, int>> obstacles(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> obstacles[i].first >> obstacles[i].second;\n    }\n    \n    State solver(N, obstacles);\n    \n    map<int, pair<int, int>> id_to_coord;\n    \n    for (int i = 0; i < solver.total_containers; ++i) {\n        int t;\n        cin >> t;\n        \n        auto p = solver.choose_placement(t);\n        solver.place(t, p.first, p.second);\n        id_to_coord[t] = p;\n    }\n    \n    solver.retrieve_all(id_to_coord);\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <random>\n\nusing namespace std;\n\n// Constants\nconst int N = 50;\nconst int M = 100;\n\n// Global variables\nint n, m;\nint original_grid[N][N];\nint best_grid[N][N];\nint best_score = -1;\n\nvector<pair<int, int>> original_cells[M + 1];\n\nbool is_boundary_color[M + 1];\nbool is_fixed[N][N];\n\nint dx[4] = {0, 1, 0, -1};\nint dy[4] = {1, 0, -1, 0};\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < n && 0 <= y && y < n;\n}\n\nvoid run_simulation(int seed) {\n    mt19937 rng(seed);\n    \n    int grid[N][N];\n    int color_cnt[M + 1];\n    for(int c=1; c<=m; ++c) color_cnt[c] = 0;\n    \n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            grid[i][j] = original_grid[i][j];\n            if(grid[i][j] != 0) color_cnt[grid[i][j]]++;\n        }\n    }\n\n    vector<pair<int, int>> frontier;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !is_fixed[i][j] && grid[i][j] != 0) {\n                frontier.push_back({i, j});\n            }\n        }\n    }\n\n    while (!frontier.empty()) {\n        int idx = rng() % frontier.size();\n        auto [x, y] = frontier[idx];\n        swap(frontier[idx], frontier.back());\n        frontier.pop_back();\n\n        if (grid[x][y] == 0) continue;\n        if (is_fixed[x][y]) continue;\n\n        int c = grid[x][y];\n        if (color_cnt[c] <= 1) continue;\n\n        // A. Fast Connectivity Check\n        // If the cell has only 1 neighbor of the same color, it is a leaf.\n        // Removing a leaf cannot disconnect the graph.\n        int same_color_neighbors = 0;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && grid[nx][ny] == c) {\n                same_color_neighbors++;\n                if (same_color_neighbors > 1) break;\n            }\n        }\n\n        bool connectivity_ok = true;\n        if (same_color_neighbors > 1) {\n            // Only run expensive BFS if degree > 1\n            int sx = -1, sy = -1;\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k];\n                int ny = y + dy[k];\n                if (in_grid(nx, ny) && grid[nx][ny] == c) {\n                    sx = nx; sy = ny;\n                    break;\n                }\n            }\n\n            if (sx != -1) {\n                queue<pair<int, int>> bq;\n                bq.push({sx, sy});\n                bool visited[N][N] = {false};\n                visited[sx][sy] = true;\n                int count = 0;\n                \n                while (!bq.empty()) {\n                    auto [cx, cy] = bq.front(); bq.pop();\n                    count++;\n                    for (int k = 0; k < 4; ++k) {\n                        int nx = cx + dx[k];\n                        int ny = cy + dy[k];\n                        if (in_grid(nx, ny) && !visited[nx][ny] && grid[nx][ny] == c && (nx != x || ny != y)) {\n                            visited[nx][ny] = true;\n                            bq.push({nx, ny});\n                        }\n                    }\n                }\n                if (count != color_cnt[c] - 1) connectivity_ok = false;\n            } else {\n                connectivity_ok = false;\n            }\n        } \n        // If same_color_neighbors == 1, connectivity_ok is implicitly true (and color_cnt > 1 check ensures it's not the last node)\n\n        if (!connectivity_ok) continue;\n\n        // B. Witness Check\n        vector<int> required_neighbors;\n        bool needs_0 = false;\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny)) {\n                int nc = grid[nx][ny];\n                if (nc == 0) needs_0 = true;\n                else if (nc != c) required_neighbors.push_back(nc);\n            } else {\n                needs_0 = true; \n            }\n        }\n        \n        sort(required_neighbors.begin(), required_neighbors.end());\n        required_neighbors.erase(unique(required_neighbors.begin(), required_neighbors.end()), required_neighbors.end());\n\n        vector<bool> neighbor_mask(M + 1, false);\n        if (needs_0) neighbor_mask[0] = true;\n\n        for (auto [cx, cy] : original_cells[c]) {\n            if (grid[cx][cy] != c) continue; \n            if (cx == x && cy == y) continue; \n\n            for (int k = 0; k < 4; ++k) {\n                int nx = cx + dx[k];\n                int ny = cy + dy[k];\n                if (in_grid(nx, ny)) {\n                    neighbor_mask[grid[nx][ny]] = true;\n                } else {\n                    neighbor_mask[0] = true;\n                }\n            }\n        }\n\n        bool ok = true;\n        if (needs_0 && !neighbor_mask[0]) ok = false;\n        if (ok) {\n            for (int d : required_neighbors) {\n                if (!neighbor_mask[d]) {\n                    ok = false;\n                    break;\n                }\n            }\n        }\n\n        if (!ok) continue; \n\n        // C. Perform Removal\n        grid[x][y] = 0;\n        color_cnt[c]--;\n\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k];\n            int ny = y + dy[k];\n            if (in_grid(nx, ny) && !is_fixed[nx][ny] && grid[nx][ny] != 0) {\n                frontier.push_back({nx, ny});\n            }\n        }\n    }\n\n    int score = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (grid[i][j] == 0) score++;\n        }\n    }\n\n    if (score > best_score) {\n        best_score = score;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                best_grid[i][j] = grid[i][j];\n            }\n        }\n    }\n}\n\nvoid solve() {\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> original_grid[i][j];\n            if(original_grid[i][j] != 0) {\n                original_cells[original_grid[i][j]].push_back({i, j});\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) is_boundary_color[c] = false;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = original_grid[i][j];\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                is_boundary_color[c] = true;\n            }\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = original_grid[i][j];\n            if (!is_boundary_color[c]) {\n                is_fixed[i][j] = true;\n            } else {\n                bool touches_internal = false;\n                for (int k = 0; k < 4; ++k) {\n                    int nx = i + dx[k];\n                    int ny = j + dy[k];\n                    if (in_grid(nx, ny)) {\n                        int nc = original_grid[nx][ny];\n                        if (!is_boundary_color[nc]) {\n                            touches_internal = true;\n                            break;\n                        }\n                    }\n                }\n                is_fixed[i][j] = touches_internal;\n            }\n        }\n    }\n\n    // 1500 iterations with connectivity short-circuit should be fast enough\n    for (int s = 0; s < 1500; ++s) {\n        run_simulation(s);\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << best_grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\n\n// Harmonic numbers for exponential distribution estimation\nvector<double> H;\n\nvoid init_harmonic(int n) {\n    H.resize(n + 2);\n    H[0] = 0.0;\n    for (int i = 1; i <= n + 1; ++i) {\n        H[i] = H[i - 1] + 1.0 / i;\n    }\n}\n\n// Ask the judge\n// Returns 1 if L > R, -1 if L < R, 0 if L = R\nint ask(int l, int r) {\n    if (l == r) return 0;\n    if (query_count >= Q) return 0;\n    \n    cout << 1 << \" \" << 1 << \" \" << l << \" \" << r << \"\\n\";\n    cout.flush();\n    query_count++;\n    \n    string res;\n    cin >> res;\n    if (res == \"<\") return -1;\n    if (res == \">\") return 1;\n    return 0;\n}\n\nbool heavier(int a, int b) {\n    if (query_count >= Q) return false;\n    int res = ask(a, b);\n    return res > 0;\n}\n\nvoid solve() {\n    cin >> N >> D >> Q;\n\n    init_harmonic(N);\n\n    vector<int> heap(N);\n    for(int i=0; i<N; ++i) heap[i] = i;\n    int heap_size = N;\n\n    // Heapify\n    for (int i = N / 2 - 1; i >= 0; --i) {\n        int curr = i;\n        while (true) {\n            int largest = curr;\n            int left = 2 * curr + 1;\n            int right = 2 * curr + 2;\n\n            if (left < heap_size && heavier(heap[left], heap[largest])) largest = left;\n            if (right < heap_size && heavier(heap[right], heap[largest])) largest = right;\n\n            if (largest != curr) {\n                swap(heap[curr], heap[largest]);\n                curr = largest;\n            } else {\n                break;\n            }\n        }\n    }\n\n    vector<int> extracted_indices;\n    \n    // Extract max items greedily.\n    // Reserve 15 queries for tail sorting.\n    while (heap_size > 0) {\n        if (query_count + 15 > Q) break;\n\n        extracted_indices.push_back(heap[0]);\n        heap[0] = heap[heap_size - 1];\n        heap_size--;\n        \n        if (heap_size == 0) break;\n\n        int curr = 0;\n        while (true) {\n            int largest = curr;\n            int left = 2 * curr + 1;\n            int right = 2 * curr + 2;\n\n            if (left < heap_size && heavier(heap[left], heap[largest])) largest = left;\n            if (right < heap_size && heavier(heap[right], heap[largest])) largest = right;\n\n            if (largest != curr) {\n                swap(heap[curr], heap[largest]);\n                curr = largest;\n            } else {\n                break;\n            }\n        }\n    }\n\n    // 1. Merge to form Globally Sorted List (Lightest to Heaviest)\n    // extracted_indices contains [Max, ..., Min_of_extracted] (Descending)\n    // heap contains [Max_of_heap, ..., Min_of_heap] (Approx Descending)\n    \n    // We need [Min_of_heap, ..., Max_of_heap, Min_of_extracted, ..., Max_of_extracted]\n    // because all items in heap are lighter than all items in extracted.\n    \n    // Sort heap ascending (Bubble Sort)\n    // Using remaining queries\n    for (int i = 0; i < heap_size - 1; ++i) {\n        for (int j = 0; j < heap_size - i - 1; ++j) {\n            if (query_count >= Q) break;\n            // We want heap[j] < heap[j+1] for ascending\n            // If heap[j] > heap[j+1], swap\n            int res = ask(heap[j], heap[j+1]);\n            if (res == 1) { // Left > Right\n                swap(heap[j], heap[j+1]);\n            }\n        }\n        if (query_count >= Q) break;\n    }\n\n    // Prepare extracted_indices: [Min_extracted, ..., Max_extracted]\n    reverse(extracted_indices.begin(), extracted_indices.end());\n    \n    // Merge: Heap (Light) + Extracted (Heavy)\n    vector<int> sorted_asc;\n    sorted_asc.insert(sorted_asc.end(), heap.begin(), heap.begin() + heap_size);\n    sorted_asc.insert(sorted_asc.end(), extracted_indices.begin(), extracted_indices.end());\n\n    // 2. Assign Harmonic Weights\n    vector<double> weight_est(N, 0.0);\n    \n    // sorted_asc is Lightest -> Heaviest\n    for (int i = 0; i < N; ++i) {\n        int idx = sorted_asc[i];\n        // Item is (i+1)-th smallest.\n        // E[w] = H_N - H_{N-(i+1)}\n        double est = H[N] - H[N - (i + 1)];\n        weight_est[idx] = est;\n    }\n\n    // 3. LPT Partition\n    vector<pair<double, int>> items;\n    for (int i = 0; i < N; ++i) {\n        items.push_back({weight_est[i], i});\n    }\n    sort(items.begin(), items.end(), greater<pair<double, int>>());\n\n    vector<int> assignment(N);\n    vector<double> bin_sums(D, 0.0);\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n    \n    for (int i = 0; i < D; ++i) {\n        pq.push({0.0, i});\n    }\n    \n    for (auto& p : items) {\n        double w = p.first;\n        int idx = p.second;\n        auto top = pq.top();\n        pq.pop();\n        \n        int bin_idx = top.second;\n        bin_sums[bin_idx] += w;\n        assignment[idx] = bin_idx;\n        pq.push({bin_sums[bin_idx], bin_idx});\n    }\n\n    // Fill remaining queries\n    while (query_count < Q) {\n        ask(0, 1);\n    }\n    \n    // Output assignment\n    for (int i = 0; i < N; ++i) {\n        cout << assignment[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc026":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Global variables for state and parameters\nint N, M;\nvector<vector<int>> stacks;\nvector<pair<int, int>> pos; // 0-indexed stack and height\nvector<pair<int, int>> operations;\n\n// Structure to hold heuristic evaluation results\nstruct DestInfo {\n    int id;\n    long long score;\n    int min_val; // Smallest element in the stack (used for tie-breaking)\n};\n\n// Helper to get the top element of a stack, return large number if empty\nint get_top(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return stacks[stack_id].back();\n}\n\n// Helper to get the minimum element in a stack\nint get_min(int stack_id) {\n    if (stacks[stack_id].empty()) return N + 1;\n    return *min_element(stacks[stack_id].begin(), stacks[stack_id].end());\n}\n\n// Evaluate the cost of moving a segment 'seg' to stack 'dest'\n// Score represents the \"badness\", lower is better.\n// Badness is defined as the number of inversions created.\n// An inversion is a pair (t, s) where t is in destination, s is in segment, and t > s.\n// We also want to prefer keeping segments intact if they are sorted,\n// but the split logic handles that before calling this.\nlong long evaluate_move(int dest, const vector<int>& seg) {\n    if (stacks[dest].empty()) return 0; // No inversions possible with empty stack\n\n    long long inv_count = 0;\n    \n    // Optimization: Since we sum counts of t > s for all s in seg\n    // We can iterate through t in destination and count how many s it is greater than.\n    // Complexity: O(Size(D) * Size(S)). Max 20 * 200 = 4000. Negligible.\n    \n    const vector<int>& dest_stack = stacks[dest];\n    \n    // Pre-calculate prefix sums? Not necessary for N=200.\n    // Just brute force double loop.\n    for (int t : dest_stack) {\n        for (int s : seg) {\n            if (t > s) {\n                inv_count++;\n            }\n        }\n    }\n    return inv_count;\n}\n\n// Execute operation type 1: Move box 'v' (and above it) to stack 'dest'\nvoid move_box(int v, int dest) {\n    // Find current stack\n    int s = pos[v].first;\n    int h = pos[v].second;\n    \n    if (s == dest) return; // Should not happen based on logic\n\n    // Identify segment to move\n    vector<int> boxes_to_move;\n    // stacks[s] has boxes from bottom (0) to top (size-1)\n    // v is at index h. We move h to size-1.\n    for (int i = h; i < stacks[s].size(); ++i) {\n        boxes_to_move.push_back(stacks[s][i]);\n    }\n    \n    // Update Source Stack\n    stacks[s].resize(h);\n    \n    // Update Destination Stack\n    for (int box : boxes_to_move) {\n        stacks[dest].push_back(box);\n    }\n    \n    // Update Positions\n    int new_h = stacks[dest].size() - boxes_to_move.size();\n    for (int i = 0; i < boxes_to_move.size(); ++i) {\n        int box = boxes_to_move[i];\n        pos[box] = {dest, new_h + i};\n    }\n    \n    operations.push_back({v, dest});\n}\n\n// Execute operation type 2: Carry out box 'v'\nvoid carry_out(int v) {\n    int s = pos[v].first;\n    // Check if v is at top (should be guaranteed by caller)\n    if (stacks[s].back() != v) {\n        // Error or should not happen\n        return;\n    }\n    \n    stacks[s].pop_back();\n    // pos[v] is no longer valid, but we won't query v again\n    operations.push_back({v, 0});\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M;\n    stacks.resize(M);\n    pos.resize(N + 1);\n    \n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < N / M; ++j) {\n            int b;\n            cin >> b;\n            stacks[i].push_back(b);\n            pos[b] = {i, j};\n        }\n    }\n\n    // Process boxes 1 to N\n    for (int v = 1; v <= N; ++v) {\n        // While v is not at top of its stack\n        while (true) {\n            int s = pos[v].first;\n            int h = pos[v].second;\n            \n            // If stack has been emptied or v is at top (h == size-1)\n            if (stacks[s].size() == h + 1) {\n                break;\n            }\n            \n            // Identify the top box of the stack containing v\n            int top_box = stacks[s].back();\n            \n            // We want to move segments that are \"inverted\" or simply move the blocking segment.\n            // Strategy:\n            // Look at the box immediately above v. Let's call it 'blocker'.\n            // Or look at the top of the stack.\n            // If the top of the stack is larger than the box below it, it creates an inversion.\n            // Moving just the top box resolves that inversion for the pair (top, below).\n            // Recursively doing this sorts the stack.\n            // Once the stack above v is sorted (small on top), we move the whole block.\n            \n            bool moved = false;\n            \n            // Check for shallow inversion at the top of the current stack\n            if (stacks[s].size() >= 2) {\n                int top = stacks[s].back();\n                int below = stacks[s][stacks[s].size() - 2];\n                \n                // If top > below, moving top alone is usually beneficial to fix the inversion.\n                // However, if 'below' is v, and top is v+1, moving top is bad.\n                // But if top > below, they are not consecutive (unless v, v+1 is inverted which is impossible in sorted 1..N).\n                // So top > below implies they are not in order.\n                if (top > below) {\n                    // Find best destination for 'top_box'\n                    // We want to minimize inversions created by adding 'top_box' to dest.\n                    \n                    vector<DestInfo> candidates;\n                    for (int i = 0; i < M; ++i) {\n                        if (i == s) continue;\n                        \n                        // Segment is just {top_box}\n                        long long inv = evaluate_move(i, {top_box});\n                        candidates.push_back({i, inv, get_min(i)});\n                    }\n                    \n                    // Sort by score (inversions), then by min_val (larger is better buffer)\n                    sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                        if (a.score != b.score) return a.score < b.score;\n                        return a.min_val > b.min_val;\n                    });\n                    \n                    int best_dest = candidates[0].id;\n                    move_box(top_box, best_dest);\n                    moved = true;\n                }\n            }\n            \n            if (!moved) {\n                // No shallow inversion at the top, or we decided not to split.\n                // Move the entire segment above v.\n                // Segment starts at index h+1.\n                vector<int> seg;\n                for (int i = h + 1; i < stacks[s].size(); ++i) {\n                    seg.push_back(stacks[s][i]);\n                }\n                \n                // Find best destination for the whole segment\n                vector<DestInfo> candidates;\n                for (int i = 0; i < M; ++i) {\n                    if (i == s) continue;\n                    \n                    long long inv = evaluate_move(i, seg);\n                    candidates.push_back({i, inv, get_min(i)});\n                }\n                \n                sort(candidates.begin(), candidates.end(), [](const DestInfo& a, const DestInfo& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.min_val > b.min_val;\n                });\n                \n                int best_dest = candidates[0].id;\n                \n                // The segment starts at seg[0], which is the box just above v.\n                move_box(seg[0], best_dest);\n            }\n        }\n        \n        // v is now at top. Carry out.\n        carry_out(v);\n    }\n\n    // Output\n    cout << operations.size() << endl;\n    for (auto op : operations) {\n        cout << op.first << \" \" << op.second << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <numeric>\n#include <functional>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nconst int MAX_N = 40;\nconst int MAX_NODES = MAX_N * MAX_N;\nconst int MAX_MOVES = 99800; \n\nint N;\nint d[MAX_NODES];\nvector<int> adj[MAX_NODES];\nint cnt[MAX_NODES][MAX_NODES];\nlong long k[MAX_NODES];\nlong long total_len = 0;\n\nint to_idx(int i, int j) { return i * N + j; }\n\nvoid from_idx(int idx, int& i, int& j) {\n    i = idx / N;\n    j = idx % N;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Fixed seed for deterministic behavior\n    mt19937 rng(12345);\n    uniform_real_distribution<double> noise_dist(0.0, 0.0001);\n\n    cin >> N;\n    vector<string> h(N-1);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    vector<string> v(N);\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[to_idx(i, j)];\n            k[to_idx(i, j)] = 0;\n        }\n    }\n\n    // Initialize cnt and build adjacency list\n    for (int i = 0; i < N*N; ++i) {\n        for (int j = 0; j < N*N; ++j) {\n            cnt[i][j] = 0;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = to_idx(i, j);\n            if (i < N-1 && h[i][j] == '0') {\n                int v_idx = to_idx(i+1, j);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n            }\n            if (j < N-1 && v[i][j] == '0') {\n                int v_idx = to_idx(i, j+1);\n                adj[u].push_back(v_idx);\n                adj[v_idx].push_back(u);\n            }\n        }\n    }\n\n    // Randomize adjacency lists to generate a random spanning tree structure\n    // This helps escape biases from the grid's natural order (e.g. always going right)\n    for (int u = 0; u < N*N; ++u) {\n        shuffle(adj[u].begin(), adj[u].end(), rng);\n    }\n\n    // Initial DFS to construct a base tour (random spanning tree)\n    vector<bool> visited(N*N, false);\n    \n    function<void(int, int)> dfs = [&](int u, int p) {\n        visited[u] = true;\n        for (int v : adj[u]) {\n            if (!visited[v]) {\n                // Traverse u -> v\n                cnt[u][v]++;\n                k[v]++;\n                dfs(v, u);\n                // Return v -> u\n                cnt[v][u]++;\n                k[u]++;\n            }\n        }\n    };\n\n    dfs(0, -1);\n\n    // Calculate initial total length\n    total_len = 0;\n    for (int u = 0; u < N*N; ++u) {\n        for (int v : adj[u]) {\n            total_len += cnt[u][v];\n        }\n    }\n\n    // Priority queue for greedy detours\n    priority_queue<pair<double, pair<int, int>>> pq;\n\n    auto update_pq = [&](int u) {\n        for (int v : adj[u]) {\n            if (u < v) {\n                double val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n                val += noise_dist(rng);\n                pq.push({val, {u, v}});\n            }\n        }\n    };\n\n    // Initialize priority queue\n    for (int u = 0; u < N*N; ++u) {\n        update_pq(u);\n    }\n\n    // Greedy loop to add detours\n    while (total_len + 2 <= MAX_MOVES) {\n        if (pq.empty()) break;\n        \n        auto item = pq.top();\n        pq.pop();\n        double score = item.first;\n        int u = item.second.first;\n        int v = item.second.second;\n        \n        // Re-calculate current value to check for staleness\n        double current_val = (double)d[u] / (k[u] * k[u]) + (double)d[v] / (k[v] * k[v]);\n        \n        if (current_val < score - 0.1) {\n            continue;\n        }\n        \n        // Add detour: u -> v -> u\n        cnt[u][v]++;\n        cnt[v][u]++;\n        k[u]++;\n        k[v]++;\n        total_len += 2;\n        \n        // Update priority queue for neighbors of u and v\n        update_pq(u);\n        update_pq(v);\n    }\n    \n    // Hierholzer's Algorithm to find the Eulerian circuit\n    vector<char> path;\n    vector<int> stack;\n    stack.push_back(0);\n    \n    while (!stack.empty()) {\n        int u = stack.back();\n        bool found = false;\n        for (int v : adj[u]) {\n            if (cnt[u][v] > 0) {\n                cnt[u][v]--;\n                stack.push_back(v);\n                found = true;\n                break;\n            }\n        }\n        \n        if (!found) {\n            stack.pop_back();\n            if (!stack.empty()) {\n                int prev = stack.back();\n                int i1, j1, i2, j2;\n                from_idx(prev, i1, j1);\n                from_idx(u, i2, j2);\n                \n                char c = ' ';\n                if (i2 > i1) c = 'D';\n                else if (i2 < i1) c = 'U';\n                else if (j2 > j1) c = 'R';\n                else c = 'L';\n                \n                path.push_back(c);\n            }\n        }\n    }\n    \n    // The path is constructed in reverse order\n    reverse(path.begin(), path.end());\n    \n    // Output the route\n    for (char c : path) {\n        cout << c;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconstexpr int M_MAX = 200;\nconstexpr int MAX_N = 15;\nconstexpr int INF = 1e9;\n\nint N = 15;\nint M = 0;\nint N2 = 225;\n\nint grid[MAX_N][MAX_N];\nvector<int> char_pos[26];\nint start_pos;\nvector<string> targets(M_MAX);\n\nint dist[MAX_N * MAX_N][MAX_N * MAX_N];\n\nstd::chrono::system_clock::time_point start_time;\n\nint get_elapsed_ms() {\n    auto now = std::chrono::system_clock::now();\n    return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();\n}\n\nvoid precompute() {\n    N2 = N * N;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = i * N + j;\n            for (int k = 0; k < N; ++k) {\n                for (int l = 0; l < N; ++l) {\n                    int v = k * N + l;\n                    dist[u][v] = abs(i - k) + abs(j - l);\n                }\n            }\n        }\n    }\n}\n\nint calc_overlap(const string& A, const string& B) {\n    int max_ov = 0;\n    int len_A = A.size();\n    int len_B = B.size();\n    int limit = min(len_A, len_B);\n    if (limit > 4) limit = 4;\n    for (int k = 1; k <= limit; ++k) {\n        if (A.compare(len_A - k, k, B, 0, k) == 0) {\n            max_ov = k;\n        }\n    }\n    return max_ov;\n}\n\nint overlap_mat[M_MAX][M_MAX];\n\nvoid build_overlap_matrix() {\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                overlap_mat[i][j] = 0;\n                continue;\n            }\n            overlap_mat[i][j] = calc_overlap(targets[i], targets[j]);\n        }\n    }\n}\n\nstring build_string(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5); \n    s.append(targets[order[0]]);\n    for (size_t i = 1; i < order.size(); ++i) {\n        int u = order[i-1];\n        int v = order[i];\n        int ov = overlap_mat[u][v];\n        const string& t = targets[v];\n        s.append(t.c_str() + ov, t.size() - ov);\n    }\n    return s;\n}\n\nvector<int> dp_buf;\nvector<int> next_dp_buf;\nvector<int> prev_step_buf; \n\nint solve_grid_cost_only(const string& s) {\n    if (s.empty()) return 0;\n    int len = s.size();\n    if (dp_buf.size() != N2) dp_buf.resize(N2);\n    if (next_dp_buf.size() != N2) next_dp_buf.resize(N2);\n\n    fill(dp_buf.begin(), dp_buf.end(), INF);\n    dp_buf[start_pos] = 0;\n    int current_min_cost = 0; \n\n    for (size_t i = 0; i < len; ++i) {\n        char c = s[i];\n        fill(next_dp_buf.begin(), next_dp_buf.end(), INF);\n        int c_idx = c - 'A';\n        if (c_idx < 0 || c_idx >= 26) continue; \n        const vector<int>& target_cells = char_pos[c_idx];\n        \n        int layer_min = INF;\n        for (int u = 0; u < N2; ++u) {\n            if (dp_buf[u] == INF) continue;\n            int base_cost = dp_buf[u] + 1;\n            const int* dist_row = dist[u];\n            for (int v : target_cells) {\n                int cost = base_cost + dist_row[v];\n                if (cost < next_dp_buf[v]) {\n                    next_dp_buf[v] = cost;\n                    if (cost < layer_min) layer_min = cost;\n                }\n            }\n        }\n        swap(dp_buf, next_dp_buf);\n        current_min_cost = layer_min;\n    }\n    return current_min_cost;\n}\n\npair<int, vector<pair<int, int>>> solve_grid(const string& s, bool store_path = false) {\n    if (s.empty()) return {0, {}};\n\n    int len = s.size();\n    if (dp_buf.size() != N2) dp_buf.resize(N2);\n    if (next_dp_buf.size() != N2) next_dp_buf.resize(N2);\n    \n    if (store_path) {\n        size_t required_prev_size = (size_t)len * N2;\n        if (prev_step_buf.size() < required_prev_size) {\n            prev_step_buf.resize(required_prev_size);\n        }\n        fill(prev_step_buf.begin(), prev_step_buf.begin() + required_prev_size, -1);\n    }\n\n    fill(dp_buf.begin(), dp_buf.end(), INF);\n    dp_buf[start_pos] = 0;\n\n    auto get_prev = [&](int step, int u) -> int& {\n        return prev_step_buf[step * N2 + u];\n    };\n\n    for (size_t i = 0; i < len; ++i) {\n        char c = s[i];\n        fill(next_dp_buf.begin(), next_dp_buf.end(), INF);\n        int c_idx = c - 'A';\n        if (c_idx < 0 || c_idx >= 26) continue; \n\n        const vector<int>& target_cells = char_pos[c_idx];\n        \n        for (int u = 0; u < N2; ++u) {\n            if (dp_buf[u] == INF) continue;\n            int base_cost = dp_buf[u] + 1;\n            const int* dist_row = dist[u];\n\n            for (int v : target_cells) {\n                int cost = base_cost + dist_row[v];\n                if (cost < next_dp_buf[v]) {\n                    next_dp_buf[v] = cost;\n                    if (store_path) {\n                        get_prev(i, v) = u;\n                    }\n                }\n            }\n        }\n        swap(dp_buf, next_dp_buf);\n    }\n\n    int min_cost = *min_element(dp_buf.begin(), dp_buf.end());\n    vector<pair<int, int>> path;\n\n    if (store_path && min_cost < INF) {\n        path.resize(len);\n        int end_pos = -1;\n        for (int i = 0; i < N2; ++i) {\n            if (dp_buf[i] == min_cost) {\n                end_pos = i;\n                break;\n            }\n        }\n        \n        if (end_pos != -1) {\n            int curr = end_pos;\n            bool valid_path = true;\n            for (int i = len - 1; i >= 0; --i) {\n                if (curr < 0 || curr >= N2) {\n                    valid_path = false;\n                    break;\n                }\n                path[i] = {curr / N, curr % N};\n                curr = get_prev(i, curr);\n            }\n            if (!valid_path) {\n                path.clear();\n            }\n        }\n    }\n\n    return {min_cost, path};\n}\n\nvector<int> initial_order_greedy(std::mt19937& gen) {\n    vector<int> order;\n    vector<bool> used(M, false);\n    \n    // Smart Start\n    vector<pair<int, int>> init_costs; \n    for(int i=0; i<M; ++i) {\n        char first_c = targets[i][0];\n        int c_idx = first_c - 'A';\n        int min_d = INF;\n        for(int v : char_pos[c_idx]) {\n            int d = dist[start_pos][v] + 1;\n            if (d < min_d) min_d = d;\n        }\n        init_costs.push_back({min_d, i});\n    }\n    \n    sort(init_costs.begin(), init_costs.end());\n    \n    // Pick randomly from top 20 candidates\n    int limit = min(20, M);\n    uniform_int_distribution<> first_dis(0, limit - 1);\n    int first_idx = first_dis(gen);\n    int first_string_idx = init_costs[first_idx].second;\n\n    order.push_back(first_string_idx);\n    used[first_string_idx] = true;\n    \n    // Pure Overlap Greedy\n    for (int count = 1; count < M; ++count) {\n        int last = order.back();\n        int best_next = -1;\n        int max_ov = -1;\n        vector<int> candidates;\n        \n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlap_mat[last][i];\n            if (ov > max_ov) {\n                max_ov = ov;\n                candidates.clear();\n                candidates.push_back(i);\n            } else if (ov == max_ov) {\n                candidates.push_back(i);\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        uniform_int_distribution<> cand_dis(0, (int)candidates.size()-1);\n        best_next = candidates[cand_dis(gen)];\n        \n        order.push_back(best_next);\n        used[best_next] = true;\n    }\n    \n    return order;\n}\n\nvoid solve() {\n    int read_N, read_M;\n    cin >> read_N >> read_M;\n    N = read_N;\n    M = read_M;\n    \n    int si, sj;\n    cin >> si >> sj;\n    start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < N; ++j) {\n            grid[i][j] = row[j];\n            char_pos[row[j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i];\n    }\n    \n    precompute();\n    build_overlap_matrix();\n\n    std::random_device rd;\n    std::mt19937 gen(rd());\n\n    vector<int> best_order;\n    int best_cost = INF;\n\n    // Increased trials for better baseline\n    for(int trial = 0; trial < 100; ++trial) {\n        vector<int> order = initial_order_greedy(gen);\n        string s = build_string(order);\n        int cost = solve_grid_cost_only(s);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n    }\n\n    vector<int> current_order = best_order;\n    string current_s = build_string(current_order);\n    int current_cost = best_cost;\n\n    best_order = current_order;\n    best_cost = current_cost;\n\n    double time_limit = 1990.0; \n    \n    uniform_int_distribution<> idx_dist(0, M-1);\n    uniform_real_distribution<> prob_dist(0.0, 1.0);\n    uniform_real_distribution<> move_type_dist(0.0, 1.0);\n\n    // 30% Swap, 40% Reverse, 30% Insert\n    double start_temp = 2000.0; \n    double end_temp = 1.0; // Lower end temp for better convergence\n\n    while (get_elapsed_ms() < time_limit) {\n        double progress = (double)get_elapsed_ms() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n        \n        vector<int> saved_order = current_order;\n        double r = move_type_dist(gen);\n        \n        if (r < 0.30) {\n            // Swap two elements\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            while(idx1 == idx2) idx2 = idx_dist(gen);\n            swap(current_order[idx1], current_order[idx2]);\n        } else if (r < 0.70) {\n            // Reverse a subarray\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            if (idx1 > idx2) swap(idx1, idx2);\n            reverse(current_order.begin() + idx1, current_order.begin() + idx2 + 1);\n        } else {\n            // Insert\n            int idx1 = idx_dist(gen);\n            int idx2 = idx_dist(gen);\n            if (idx1 != idx2) {\n                int val = current_order[idx1];\n                current_order.erase(current_order.begin() + idx1);\n                if (idx1 < idx2) {\n                    current_order.insert(current_order.begin() + idx2 - 1, val);\n                } else {\n                    current_order.insert(current_order.begin() + idx2, val);\n                }\n            }\n        }\n        \n        string new_s = build_string(current_order);\n        int new_cost = solve_grid_cost_only(new_s);\n        \n        int delta = new_cost - current_cost;\n        bool accept = false;\n        \n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (prob_dist(gen) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_cost = new_cost;\n            current_s = new_s;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_order = current_order;\n            }\n        } else {\n            current_order = saved_order;\n        }\n    }\n    \n    string final_s = build_string(best_order);\n    auto [final_cost, path] = solve_grid(final_s, true);\n    \n    if (!path.empty()) {\n        for (auto p : path) {\n            cout << p.first << \" \" << p.second << \"\\n\";\n        }\n    } else {\n        cout << (start_pos / N) << \" \" << (start_pos % N) << \"\\n\";\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    start_time = std::chrono::system_clock::now();\n    \n    solve();\n    \n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\n#include <atcoder/random>\nusing namespace std;\nusing namespace atcoder;\n\nconst double INF = 1e9;\nconst int MAX_N = 20;\nconst int MAX_M = 20;\n\n// Global variables\nint N, M;\ndouble eps;\nvector<vector<pair<int, int>>> shapes; // Relative coordinates of each shape\nvector<pair<int, int>> shape_sizes;   // (height, width) of each shape\nmap<pair<int, int>, int> fixed_cells; // Known values: (r,c) -> value\n\n// Estimated sums from divination\nvector<double> est_row_sums;\nvector<double> est_col_sums;\n\n// Inverse variances for chi-squared\ndouble inv_var_row;\ndouble inv_var_col;\n\n// Random number generator\nrandom_device rd;\nmt19937 gen(rd());\n\n// Operation cost tracking\ndouble total_cost = 0.0;\n\n// Helper to output and flush\nvoid flush_output() {\n    cout << flush;\n}\n\n// Divination operation\ndouble divine(const vector<pair<int, int>>& cells) {\n    int k = cells.size();\n    cout << \"q \" << k;\n    for (auto [r, c] : cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0 / sqrt(k);\n    \n    // Invert the noise model\n    // y ~ round(max(0, x)), x ~ N(k*eps + T(1-2*eps), k*eps(1-eps))\n    // Estimate T\n    double T_est = (res - k * eps) / (1.0 - 2.0 * eps);\n    if (T_est < 0) T_est = 0; // T must be non-negative\n    return T_est;\n}\n\n// Drilling operation\nint drill(int r, int c) {\n    cout << \"q 1 \" << r << \" \" << c << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    \n    total_cost += 1.0;\n    fixed_cells[{r, c}] = res;\n    return res;\n}\n\n// Answer operation\nbool answer(const vector<pair<int, int>>& pos_cells) {\n    cout << \"a \" << pos_cells.size();\n    for (auto [r, c] : pos_cells) {\n        cout << \" \" << r << \" \" << c;\n    }\n    cout << endl;\n    flush_output();\n    \n    int res;\n    cin >> res;\n    return res == 1;\n}\n\n// State representation for SA\nstruct State {\n    vector<pair<int, int>> pos; // (r, c) for each field\n    int grid[MAX_N][MAX_N];\n    double energy;\n\n    void compute_grid_and_energy() {\n        // Reset grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = 0;\n            }\n        }\n\n        // Place fields\n        for (int k = 0; k < M; ++k) {\n            auto [pr, pc] = pos[k];\n            for (auto [dr, dc] : shapes[k]) {\n                int r = pr + dr;\n                int c = pc + dc;\n                grid[r][c]++;\n            }\n        }\n\n        // Check fixed cells constraint\n        for (auto [p, val] : fixed_cells) {\n            if (grid[p.first][p.second] != val) {\n                energy = INF;\n                return;\n            }\n        }\n\n        // Calculate chi-squared distance to observed row/col sums\n        double err = 0.0;\n        \n        // Row sums\n        for (int i = 0; i < N; ++i) {\n            int sum = 0;\n            for (int j = 0; j < N; ++j) sum += grid[i][j];\n            double diff = sum - est_row_sums[i];\n            err += diff * diff * inv_var_row;\n        }\n\n        // Column sums\n        for (int j = 0; j < N; ++j) {\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += grid[i][j];\n            double diff = sum - est_col_sums[j];\n            err += diff * diff * inv_var_col;\n        }\n\n        energy = err;\n    }\n};\n\n// Simulated Annealing\nState run_sa(int iterations) {\n    State cur, best;\n    cur.pos.resize(M);\n    best.pos.resize(M);\n\n    // Initialize random valid positions\n    for (int k = 0; k < M; ++k) {\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        cur.pos[k] = {dist_r(gen), dist_c(gen)};\n    }\n    cur.compute_grid_and_energy();\n    best = cur;\n\n    double start_temp = 100.0;\n    double end_temp = 0.1;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        double temp = start_temp + (end_temp - start_temp) * iter / iterations;\n        \n        State nxt = cur;\n        \n        // Pick a field to move\n        int k = uniform_int_distribution<>(0, M - 1)(gen);\n        \n        // Generate new position\n        auto [h, w] = shape_sizes[k];\n        uniform_int_distribution<> dist_r(0, N - h);\n        uniform_int_distribution<> dist_c(0, N - w);\n        \n        if (uniform_real_distribution<>(0, 1)(gen) < 0.1) {\n            // Jump\n            nxt.pos[k] = {dist_r(gen), dist_c(gen)};\n        } else {\n            // Small step\n            int dr = uniform_int_distribution<>(-2, 2)(gen);\n            int dc = uniform_int_distribution<>(-2, 2)(gen);\n            int nr = nxt.pos[k].first + dr;\n            int nc = nxt.pos[k].second + dc;\n            \n            // Clamp to valid range\n            nr = max(0, min(N - h, nr));\n            nc = max(0, min(N - w, nc));\n            nxt.pos[k] = {nr, nc};\n        }\n\n        nxt.compute_grid_and_energy();\n\n        if (nxt.energy < cur.energy || uniform_real_distribution<>(0, 1)(gen) < exp((cur.energy - nxt.energy) / max(temp, 0.1))) {\n            cur = nxt;\n        }\n\n        if (cur.energy < best.energy) {\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nvoid solve() {\n    // Input\n    cin >> N >> M >> eps;\n    shapes.resize(M);\n    shape_sizes.resize(M);\n\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        int max_r = 0, max_c = 0;\n        for (int i = 0; i < d; ++i) {\n            int r, c;\n            cin >> r >> c;\n            shapes[k].emplace_back(r, c);\n            max_r = max(max_r, r);\n            max_c = max(max_c, c);\n        }\n        shape_sizes[k] = {max_r, max_c};\n    }\n\n    // Precompute inverse variances\n    // Variance = k * eps * (1 - eps)\n    inv_var_row = 1.0 / (N * eps * (1.0 - eps));\n    inv_var_col = 1.0 / (N * eps * (1.0 - eps));\n    est_row_sums.resize(N);\n    est_col_sums.resize(N);\n\n    // Initial Probing: Rows and Columns\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int, int>> row_cells;\n        for (int j = 0; j < N; ++j) row_cells.emplace_back(i, j);\n        est_row_sums[i] = divine(row_cells);\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int, int>> col_cells;\n        for (int i = 0; i < N; ++i) col_cells.emplace_back(i, j);\n        est_col_sums[j] = divine(col_cells);\n    }\n\n    // Main search loop\n    int max_ops = 2 * N * N;\n    int sa_iters = 3000; // Per iteration\n    \n    // We want to leave some buffer for the answer query\n    while (total_cost < max_ops - 1) {\n        // Run SA\n        State best_state = run_sa(sa_iters);\n\n        // If energy is very low, we might be done\n        // Heuristic: if energy < 10 (which is small for 40 degrees of freedom)\n        if (best_state.energy < 5.0) {\n            // Verify a few random cells or just submit?\n            // Let's try to submit if we are very confident\n            // Or drill one last cell to be safe\n            \n            // Construct answer\n            vector<pair<int, int>> ans;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0) {\n                        ans.emplace_back(i, j);\n                    }\n                }\n            }\n            \n            // Check if we have budget for another drill\n            if (total_cost + 1 + 0.01 > max_ops) {\n                 // Submit\n                if (answer(ans)) return;\n                else {\n                    // If wrong, we shouldn't really get here often if energy is low.\n                    // If we do, we break loop because we can't afford more ops?\n                    // Actually, we just continue if we have time.\n                    // But answer costs 1. So we lost 1 op.\n                }\n            } else {\n                // Try to verify a high-value cell\n                // Find a cell with max v that is not fixed\n                pair<int, int> target = {-1, -1};\n                int max_v = -1;\n                for (int i = 0; i < N; ++i) {\n                    for (int j = 0; j < N; ++j) {\n                        if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                            if (best_state.grid[i][j] > max_v) {\n                                max_v = best_state.grid[i][j];\n                                target = {i, j};\n                            }\n                        }\n                    }\n                }\n\n                if (target.first != -1) {\n                    drill(target.first, target.second);\n                } else {\n                    // All positive cells fixed. Submit.\n                    if (answer(ans)) return;\n                }\n            }\n        } else {\n            // Energy is not low enough. Drill a cell to improve.\n            // Strategy: Drill a cell that is positive in the best model\n            pair<int, int> target = {-1, -1};\n            int max_v = -1;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (best_state.grid[i][j] > 0 && fixed_cells.count({i,j}) == 0) {\n                        if (best_state.grid[i][j] > max_v) {\n                            max_v = best_state.grid[i][j];\n                            target = {i, j};\n                        }\n                    }\n                }\n            }\n\n            // If no positive cell found (all fixed?), check empty?\n            // Or just pick a cell with v=0 that is surrounded by v>0?\n            if (target.first == -1) {\n                 // This case implies model says no undrilled positive cells.\n                 // But energy is high. Means model is wrong (missed some oil).\n                 // We should drill somewhere to find the missing oil.\n                 // Pick a random undrilled cell with v=0 in model.\n                 vector<pair<int,int>> candidates;\n                 for (int i=0; i<N; ++i) {\n                     for (int j=0; j<N; ++j) {\n                         if (best_state.grid[i][j] == 0 && fixed_cells.count({i,j}) == 0) {\n                             candidates.emplace_back(i,j);\n                         }\n                     }\n                 }\n                 if (!candidates.empty()) {\n                     target = candidates[uniform_int_distribution<>(0, candidates.size()-1)(gen)];\n                 } else {\n                     // All cells fixed? Just submit.\n                     vector<pair<int, int>> ans;\n                     for (int i = 0; i < N; ++i) {\n                        for (int j = 0; j < N; ++j) {\n                            if (best_state.grid[i][j] > 0) ans.emplace_back(i, j);\n                        }\n                    }\n                    if (answer(ans)) return;\n                 }\n            }\n            \n            if (target.first != -1) drill(target.first, target.second);\n        }\n    }\n    \n    // Fallback / Time up: Submit current best guess\n    State final_state = run_sa(1000); // Quick last run\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (final_state.grid[i][j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    answer(ans);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <deque>\n#include <map>\n#include <cmath>\n\nusing namespace std;\n\nconst int W_MAX = 1000;\nconst int NUM_GROUPS = 2; \nconst long long INF = 1e18;\n\nint ceil_div(int a, int b) {\n    return (a + b - 1) / b;\n}\n\nstruct GroupSolution {\n    long long cost;\n    vector<int> cuts; \n};\n\n// Global memoization storage for the current day\nvector<map<int, GroupSolution>> day_memo(NUM_GROUPS);\n\nGroupSolution compute_group_dp(\n    int group_idx,\n    int w,\n    const vector<int>& areas, \n    const vector<int>& prev_cuts,\n    int prev_w,\n    bool enable_move_cost\n) {\n    // Check memo\n    if (day_memo[group_idx].count(w)) {\n        return day_memo[group_idx][w];\n    }\n\n    int n = areas.size();\n    GroupSolution sol;\n    sol.cost = INF;\n\n    if (n == 0) {\n        sol.cost = 0;\n        day_memo[group_idx][w] = sol;\n        return sol;\n    }\n    \n    vector<long long> dp_prev(W_MAX + 1, INF);\n    vector<int> choice(W_MAX + 1, -1); \n    dp_prev[0] = 0;\n\n    int num_cuts = n - 1;\n\n    for (int k = 1; k <= n; ++k) {\n        int A = areas[k-1];\n        int min_h = ceil_div(A, w);\n        \n        vector<long long> dp_curr(W_MAX + 1, INF);\n        vector<int> choice_curr(W_MAX + 1, -1);\n\n        vector<long long> pmin(W_MAX + 2, INF);\n        vector<int> parg(W_MAX + 2, -1);\n        for (int i = 0; i <= W_MAX; ++i) {\n            if (dp_prev[i] < pmin[i]) {\n                pmin[i+1] = dp_prev[i];\n                parg[i+1] = i;\n            } else {\n                pmin[i+1] = pmin[i];\n                parg[i+1] = parg[i];\n            }\n        }\n\n        vector<long long> B(W_MAX + 1, INF);\n        for (int i = 0; i <= W_MAX; ++i) {\n            if (dp_prev[i] < INF) B[i] = dp_prev[i] + 100LL * w * i;\n        }\n\n        deque<int> dq;\n        for (int v = 1; v <= W_MAX; ++v) {\n            while(!dq.empty() && B[dq.back()] >= B[v-1]) dq.pop_back();\n            dq.push_back(v-1);\n            while(!dq.empty() && dq.front() < v - min_h + 1) dq.pop_front();\n\n            long long best_cost = INF;\n            int best_u = -1;\n\n            int limit1 = v - min_h;\n            if (limit1 >= 0) {\n                best_cost = pmin[limit1 + 1];\n                best_u = parg[limit1 + 1];\n            }\n\n            if (!dq.empty()) {\n                long long c2 = B[dq.front()] + 100LL * A - 100LL * w * v;\n                if (c2 < best_cost) {\n                    best_cost = c2;\n                    best_u = dq.front();\n                }\n            }\n\n            if (best_cost < INF) {\n                long long move_h_cost = 0;\n                if (enable_move_cost && k < n) { \n                    int prev_y = (k-1 < (int)prev_cuts.size()) ? prev_cuts[k-1] : 0;\n                    move_h_cost = 2LL * w * abs(v - prev_y);\n                }\n                \n                best_cost += move_h_cost;\n                dp_curr[v] = best_cost;\n                choice_curr[v] = best_u;\n            }\n        }\n        dp_prev = dp_curr;\n        choice = choice_curr;\n    }\n\n    int best_v = 0;\n    long long min_c = INF;\n    for(int v = 0; v <= W_MAX; ++v) {\n        if(dp_prev[v] < min_c) {\n            min_c = dp_prev[v];\n            best_v = v;\n        }\n    }\n\n    sol.cost = min_c;\n    \n    if (enable_move_cost) {\n        sol.cost += (long long)num_cuts * abs(w - prev_w);\n    }\n\n    sol.cuts.resize(num_cuts);\n    \n    // Reconstruct\n    vector<vector<int>> all_choices(n + 1, vector<int>(W_MAX + 1, -1));\n    \n    dp_prev.assign(W_MAX + 1, INF);\n    dp_prev[0] = 0;\n\n    for (int k = 1; k <= n; ++k) {\n        int A = areas[k-1];\n        int min_h = ceil_div(A, w);\n        vector<long long> dp_curr(W_MAX + 1, INF);\n\n        vector<long long> pmin(W_MAX + 2, INF);\n        vector<int> parg(W_MAX + 2, -1);\n        for (int i = 0; i <= W_MAX; ++i) {\n            if (dp_prev[i] < pmin[i]) {\n                pmin[i+1] = dp_prev[i];\n                parg[i+1] = i;\n            } else {\n                pmin[i+1] = pmin[i];\n                parg[i+1] = parg[i];\n            }\n        }\n        vector<long long> B(W_MAX + 1, INF);\n        for (int i = 0; i <= W_MAX; ++i) {\n            if (dp_prev[i] < INF) B[i] = dp_prev[i] + 100LL * w * i;\n        }\n\n        deque<int> dq;\n        for (int v = 1; v <= W_MAX; ++v) {\n            while(!dq.empty() && B[dq.back()] >= B[v-1]) dq.pop_back();\n            dq.push_back(v-1);\n            while(!dq.empty() && dq.front() < v - min_h + 1) dq.pop_front();\n            \n            long long best_cost = INF;\n            int best_u = -1;\n            int limit1 = v - min_h;\n            if (limit1 >= 0) {\n                best_cost = pmin[limit1 + 1];\n                best_u = parg[limit1 + 1];\n            }\n            if (!dq.empty()) {\n                long long c2 = B[dq.front()] + 100LL * A - 100LL * w * v;\n                if (c2 < best_cost) {\n                    best_cost = c2;\n                    best_u = dq.front();\n                }\n            }\n            if (best_cost < INF) {\n                long long move_h = 0;\n                if (enable_move_cost && k < n) {\n                    int prev_y = (k-1 < (int)prev_cuts.size()) ? prev_cuts[k-1] : 0;\n                    move_h = 2LL * w * abs(v - prev_y);\n                }\n                best_cost += move_h;\n                dp_curr[v] = best_cost;\n                all_choices[k][v] = best_u;\n            }\n        }\n        dp_prev = dp_curr;\n    }\n    \n    int curr_v = best_v;\n    for (int k = n; k >= 1; --k) {\n        if (k < n) {\n            sol.cuts[k-1] = curr_v;\n        }\n        curr_v = all_choices[k][curr_v];\n    }\n\n    day_memo[group_idx][w] = sol;\n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_input, D, N;\n    cin >> W_input >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    int K = max(2, min(NUM_GROUPS, N)); \n    \n    vector<int> group_limits(K + 1);\n    for (int i = 0; i <= K; ++i) {\n        group_limits[i] = (i * N) / K;\n    }\n    group_limits[K] = N; \n\n    vector<int> current_vert_cuts(K + 1, 0);\n    for(int i=1; i<=K; ++i) current_vert_cuts[i] = (i * W_MAX) / K;\n    \n    vector<vector<int>> current_horiz_cuts(K); \n\n    for (int d = 0; d < D; ++d) {\n        vector<vector<int>> group_areas(K);\n        for (int g = 0; g < K; ++g) {\n            for (int k = group_limits[g]; k < group_limits[g+1]; ++k) {\n                group_areas[g].push_back(a[d][k]);\n            }\n        }\n\n        bool enable_move = (d > 0);\n\n        for(int g=0; g<K; ++g) day_memo[g].clear();\n\n        auto get_total_cost = [&](int w1) {\n            if (w1 <= 0 || w1 >= W_MAX) return INF;\n            \n            int w2 = W_MAX - w1;\n            if (w2 <= 0) return INF;\n\n            long long c1 = compute_group_dp(0, w1, group_areas[0], current_horiz_cuts[0], current_vert_cuts[1]-current_vert_cuts[0], enable_move).cost;\n            if (c1 >= INF) return INF;\n\n            long long c2 = compute_group_dp(1, w2, group_areas[1], current_horiz_cuts[1], current_vert_cuts[2]-current_vert_cuts[1], enable_move).cost;\n            if (c2 >= INF) return INF;\n\n            long long total = c1 + c2;\n\n            if (enable_move) {\n                total += 2000LL * abs(w1 - current_vert_cuts[1]);\n            }\n            return total;\n        };\n\n        int l = 1, r = W_MAX - 1;\n        for (int iter = 0; iter < 40; ++iter) {\n            if (r - l < 4) break;\n            int m1 = l + (r - l) / 3;\n            int m2 = r - (r - l) / 3;\n            long long c1 = get_total_cost(m1);\n            long long c2 = get_total_cost(m2);\n            if (c1 < c2) {\n                r = m2;\n            } else {\n                l = m1;\n            }\n        }\n\n        int best_w1 = l;\n        long long min_cost = INF;\n        for (int w1 = l; w1 <= r; ++w1) {\n            long long c = get_total_cost(w1);\n            if (c < min_cost) {\n                min_cost = c;\n                best_w1 = w1;\n            }\n        }\n        \n        int w1 = best_w1;\n        int w2 = W_MAX - w1;\n\n        auto sol1 = compute_group_dp(0, w1, group_areas[0], current_horiz_cuts[0], current_vert_cuts[1]-current_vert_cuts[0], enable_move);\n        auto sol2 = compute_group_dp(1, w2, group_areas[1], current_horiz_cuts[1], current_vert_cuts[2]-current_vert_cuts[1], enable_move);\n\n        current_vert_cuts[1] = w1;\n        current_vert_cuts[2] = W_MAX;\n        current_horiz_cuts[0] = sol1.cuts;\n        current_horiz_cuts[1] = sol2.cuts;\n\n        // Output Group 0\n        int x_start = 0;\n        int x_end = w1;\n        int y_start = 0;\n        int k_rect = 0;\n        for (int k = group_limits[0]; k < group_limits[1]; ++k) {\n            int y_end;\n            if (k_rect < (int)current_horiz_cuts[0].size()) {\n                y_end = current_horiz_cuts[0][k_rect];\n            } else {\n                y_end = W_MAX; \n            }\n            if (y_end < y_start + 1) y_end = y_start + 1;\n            if (y_end > W_MAX) y_end = W_MAX;\n            if (x_end < x_start + 1) x_end = x_start + 1;\n            if (x_end > W_MAX) x_end = W_MAX;\n\n            cout << y_start << \" \" << x_start << \" \" << y_end << \" \" << x_end << \"\\n\";\n            y_start = y_end;\n            k_rect++;\n        }\n\n        // Output Group 1\n        x_start = w1;\n        x_end = W_MAX;\n        y_start = 0;\n        k_rect = 0;\n        for (int k = group_limits[1]; k < group_limits[2]; ++k) {\n            int y_end;\n            if (k_rect < (int)current_horiz_cuts[1].size()) {\n                y_end = current_horiz_cuts[1][k_rect];\n            } else {\n                y_end = W_MAX; \n            }\n            if (y_end < y_start + 1) y_end = y_start + 1;\n            if (y_end > W_MAX) y_end = W_MAX;\n            if (x_end < x_start + 1) x_end = x_start + 1;\n            if (x_end > W_MAX) x_end = W_MAX;\n\n            cout << y_start << \" \" << x_start << \" \" << y_end << \" \" << x_end << \"\\n\";\n            y_start = y_end;\n            k_rect++;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <array>\n#include <algorithm>\n#include <tuple>\n#include <queue>\n\nusing namespace std;\n\nconst int MOD = 998244353;\n\n// --- Common Structures ---\n\nstruct Board {\n    array<long long, 81> data; // Flattened 9x9\n\n    long long get_score() const {\n        long long s = 0;\n        for (int i = 0; i < 81; ++i) {\n            s += data[i] % MOD;\n        }\n        return s;\n    }\n};\n\nstruct Operation {\n    int m, p, q;\n};\n\n// --- Greedy Solver ---\n\nvector<Operation> solve_greedy(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    Board board = initial_board;\n    \n    // Gains cache\n    array<array<array<long long, 7>, 7>, 20> gains{};\n    \n    auto calc_gain = [&](int m, int p, int q) {\n        long long diff = 0;\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                int idx = (p+i)*9 + (q+j);\n                long long old_v = board.data[idx];\n                long long new_v = old_v + stamps[m][i*3+j];\n                diff += (new_v % MOD) - (old_v % MOD);\n            }\n        }\n        return diff;\n    };\n\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < 7; ++p) {\n            for (int q = 0; q < 7; ++q) {\n                gains[m][p][q] = calc_gain(m, p, q);\n            }\n        }\n    }\n\n    vector<Operation> ops;\n    ops.reserve(K);\n\n    for (int turn = 0; turn < K; ++turn) {\n        long long best_gain = -1;\n        int best_m = -1, best_p = -1, best_q = -1;\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = 0; p < 7; ++p) {\n                for (int q = 0; q < 7; ++q) {\n                    if (gains[m][p][q] > best_gain) {\n                        best_gain = gains[m][p][q];\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_gain <= 0) break;\n\n        ops.push_back({best_m, best_p, best_q});\n\n        // Apply\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                board.data[(best_p+i)*9 + (best_q+j)] += stamps[best_m][i*3+j];\n            }\n        }\n\n        // Update gains\n        int p_min = max(0, best_p - 2);\n        int p_max = min(6, best_p + 2);\n        int q_min = max(0, best_q - 2);\n        int q_max = min(6, best_q + 2);\n\n        for (int m = 0; m < M; ++m) {\n            for (int p = p_min; p <= p_max; ++p) {\n                for (int q = q_min; q <= q_max; ++q) {\n                    gains[m][p][q] = calc_gain(m, p, q);\n                }\n            }\n        }\n    }\n    return ops;\n}\n\n// --- Beam Search Solver (Memory Efficient) ---\n\nstruct HistoryNode {\n    int parent;\n    char m, p, q; // Operation to reach this state. -1 for initial or do-nothing\n};\n\nstruct BeamState {\n    Board board;\n    long long score;\n    int history_idx; // Index in global history\n};\n\nvector<Operation> solve_beam(const Board& initial_board, const vector<vector<long long>>& stamps, int M, int K) {\n    // Parameters\n    const int BEAM_WIDTH = 400;\n    const int BRANCH_FACTOR = 120; \n    const int GREEDY_INIT_DEPTH = 10;\n\n    vector<HistoryNode> history;\n    vector<BeamState> current_beam;\n\n    // 1. Initialize with root state\n    HistoryNode root_node{-1, -1, -1, -1};\n    history.push_back(root_node);\n    current_beam.push_back({initial_board, initial_board.get_score(), 0});\n\n    // 2. Seed with Greedy path\n    Board temp_board = initial_board;\n    vector<Operation> greedy_ops = solve_greedy(initial_board, stamps, M, min(K, GREEDY_INIT_DEPTH));\n    \n    int h_idx = 0;\n    for (auto op : greedy_ops) {\n        h_idx++;\n        HistoryNode node{(int)history.size() - 1, (char)op.m, (char)op.p, (char)op.q};\n        history.push_back(node);\n        \n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                temp_board.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n            }\n        }\n        current_beam.push_back({temp_board, temp_board.get_score(), (int)history.size() - 1});\n    }\n\n    // Beam Search Loop\n    for (int step = 0; step < K; ++step) {\n        vector<BeamState> candidates;\n        // Reserving space helps performance significantly\n        candidates.reserve(current_beam.size() * (BRANCH_FACTOR + 1));\n\n        for (const auto& state : current_beam) {\n            // A. \"Do Nothing\" move\n            // Gain is 0. \n            HistoryNode noop_node{state.history_idx, -1, -1, -1};\n            history.push_back(noop_node);\n            candidates.push_back({state.board, state.score, (int)history.size() - 1});\n\n            // B. Generate Moves\n            // Instead of creating a huge vector, we can process and keep top N?\n            // But sorting requires vector. Given the scale (400 * 1000), creating vector of tuples is fine.\n            // Optimization: Precompute stamp contributions? No, dynamic board.\n            \n            vector<tuple<long long, int, int, int>> potential_moves;\n            potential_moves.reserve(M * 49);\n\n            for (int m = 0; m < M; ++m) {\n                for (int p = 0; p < 7; ++p) {\n                    for (int q = 0; q < 7; ++q) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                long long old_v = state.board.data[(p+i)*9 + (q+j)];\n                                long long new_v = old_v + stamps[m][i*3+j];\n                                gain += (new_v % MOD) - (old_v % MOD);\n                            }\n                        }\n                        potential_moves.emplace_back(gain, m, p, q);\n                    }\n                }\n            }\n\n            // Select top BRANCH_FACTOR\n            int limit = min((int)potential_moves.size(), BRANCH_FACTOR);\n            if (limit > 0) {\n                nth_element(potential_moves.begin(), potential_moves.begin() + limit, potential_moves.end(), \n                    [](const auto& a, const auto& b){ return get<0>(a) > get<0>(b); });\n                \n                // No need to fully sort strictly, but nth_element guarantees first 'limit' are the top ones.\n                // We iterate over them.\n                for (int i = 0; i < limit; ++i) {\n                    auto [gain, m, p, q] = potential_moves[i];\n                    \n                    // Create new state\n                    Board next_board = state.board;\n                    for (int di = 0; di < 3; ++di) {\n                        for (int dj = 0; dj < 3; ++dj) {\n                            next_board.data[(p+di)*9 + (q+dj)] += stamps[m][di*3+dj];\n                        }\n                    }\n                    long long next_score = state.score + gain;\n                    \n                    HistoryNode node{state.history_idx, (char)m, (char)p, (char)q};\n                    history.push_back(node);\n                    candidates.push_back({next_board, next_score, (int)history.size() - 1});\n                }\n            }\n        }\n\n        // Selection\n        int next_limit = min((int)candidates.size(), BEAM_WIDTH);\n        if (next_limit == 0) break;\n\n        auto mid = candidates.begin() + next_limit;\n        nth_element(candidates.begin(), mid, candidates.end(), \n            [](const BeamState& a, const BeamState& b){ return a.score > b.score; });\n\n        current_beam.assign(candidates.begin(), candidates.begin() + next_limit);\n    }\n\n    // Find best state in final beam\n    long long best_score = -1;\n    int best_history_idx = -1;\n    for (const auto& state : current_beam) {\n        if (state.score > best_score) {\n            best_score = state.score;\n            best_history_idx = state.history_idx;\n        }\n    }\n\n    // Reconstruct\n    vector<Operation> ops;\n    int curr = best_history_idx;\n    while (curr != 0) {\n        const HistoryNode& node = history[curr];\n        if (node.m != -1) {\n            ops.emplace_back(node.m, node.p, node.q);\n        }\n        curr = node.parent;\n    }\n    // Reverse\n    reverse(ops.begin(), ops.end());\n    return ops;\n}\n\n// --- Main ---\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    if (!(cin >> N >> M >> K)) return 0;\n\n    Board initial_board;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> initial_board.data[i * 9 + j];\n        }\n    }\n\n    // Read stamps\n    vector<vector<long long>> stamps(M, vector<long long>(9));\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i * 3 + j];\n            }\n        }\n    }\n\n    // 1. Solve Greedy\n    auto ops_greedy = solve_greedy(initial_board, stamps, M, K);\n    \n    // Score Greedy\n    Board b_greedy = initial_board;\n    long long score_greedy = 0;\n    for(auto op : ops_greedy) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_greedy.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_greedy = b_greedy.get_score();\n\n    // 2. Solve Beam Search\n    auto ops_beam = solve_beam(initial_board, stamps, M, K);\n    \n    // Score Beam\n    Board b_beam = initial_board;\n    long long score_beam = 0;\n    for(auto op : ops_beam) {\n        for (int i=0; i<3; ++i) for(int j=0; j<3; ++j) {\n            b_beam.data[(op.p+i)*9 + (op.q+j)] += stamps[op.m][i*3+j];\n        }\n    }\n    score_beam = b_beam.get_score();\n\n    // 3. Output Best\n    if (score_beam > score_greedy) {\n        cout << ops_beam.size() << \"\\n\";\n        for (auto op : ops_beam) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    } else {\n        cout << ops_greedy.size() << \"\\n\";\n        for (auto op : ops_greedy) cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <climits>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\nconst int BUFFER_COL = N - 2; \n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    vector<vector<int>> A(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> A[i][j];\n        }\n    }\n    \n    vector<int> target_row(N * N);\n    for (int c = 0; c < N * N; c++) target_row[c] = c / N;\n    \n    vector<vector<int>> arrival(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++) arrival[i][j] = A[i][j];\n    \n    vector<int> arrived(N, 0);\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_x(N), crane_y(N);\n    vector<int> carrying(N, -1);\n    \n    for (int i = 0; i < N; i++) {\n        crane_x[i] = i;\n        crane_y[i] = 0;\n    }\n    \n    vector<string> actions(N);\n    vector<bool> dispatched(N * N, false);\n    \n    for (int t = 0; t < MAX_TURNS; t++) {\n        bool all_done = true;\n        for(int i=0; i<N*N; ++i) if(!dispatched[i]) all_done = false;\n        if (all_done) break;\n\n        // Step 1: Container arrivals\n        for (int i = 0; i < N; i++) {\n            bool blocked_by_carrying = false;\n            for (int c = 0; c < N; c++) {\n                if (crane_x[c] == i && crane_y[c] == 0 && carrying[c] != -1) {\n                    blocked_by_carrying = true;\n                }\n            }\n            if (grid[i][0] == -1 && !blocked_by_carrying && arrived[i] < N) {\n                grid[i][0] = arrival[i][arrived[i]++];\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        vector<char> act(N, '.');\n        vector<int> nx = crane_x, ny = crane_y;\n        vector<int> ncarry = carrying;\n        \n        for (int c = 0; c < N; c++) {\n            if (c == 0) {\n                // Large Crane\n                if (carrying[c] != -1) {\n                    int tr = target_row[carrying[c]];\n                    \n                    // Strategy for Row 0: Direct Dispatch\n                    // Small cranes handle rows 1-4. Row 0 is only handled by Large Crane.\n                    if (tr == 0) {\n                        if (crane_x[c] > 0) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_x[c] < 0) { act[c] = 'D'; nx[c]++; } // Should not happen\n                        else if (crane_y[c] < N - 1) { act[c] = 'R'; ny[c]++; }\n                        else { act[c] = 'Q'; ncarry[c] = -1; } // Dispatch at (0, N-1)\n                    } else {\n                        // Strategy for Rows 1-4: Buffer at N-2\n                        if (crane_x[c] < tr) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > tr) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < BUFFER_COL) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > BUFFER_COL) { act[c] = 'L'; ny[c]--; }\n                        else {\n                            // At buffer location (tr, N-2)\n                            if (grid[tr][BUFFER_COL] == -1) {\n                                act[c] = 'Q'; ncarry[c] = -1;\n                            } else {\n                                // Buffer occupied. Check for deadlock.\n                                // If Small Crane 'tr' is at (tr, N-3) and wants to come to N-2\n                                // we must move away.\n                                if (tr < N && crane_x[tr] == tr && crane_y[tr] == BUFFER_COL - 1) {\n                                    // Small crane is right behind. Move Left.\n                                    act[c] = 'L'; ny[c]--;\n                                } else {\n                                    act[c] = '.'; // Wait\n                                }\n                            }\n                        }\n                    }\n                } else {\n                    int best_i = -1, best_j = -1, best_score = INT_MIN;\n                    for (int i = 0; i < N; i++) {\n                        for (int j = 0; j < N; j++) {\n                            int cont = grid[i][j];\n                            if (cont != -1 && !dispatched[cont]) {\n                                int tr = target_row[cont];\n                                int wrong = (i != tr);\n                                int dist = abs(i - crane_x[c]) + abs(j - crane_y[c]);\n                                // Heuristic\n                                int score = (wrong ? 100000 : 0) - dist;\n                                if (score > best_score) {\n                                    best_score = score; best_i = i; best_j = j;\n                                }\n                            }\n                        }\n                    }\n                    if (best_i != -1) {\n                        if (crane_x[c] < best_i) { act[c] = 'D'; nx[c]++; }\n                        else if (crane_x[c] > best_i) { act[c] = 'U'; nx[c]--; }\n                        else if (crane_y[c] < best_j) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > best_j) { act[c] = 'L'; ny[c]--; }\n                        else { act[c] = 'P'; ncarry[c] = grid[best_i][best_j]; }\n                    }\n                }\n            } else {\n                // Small Cranes (1-4). Stay in lanes.\n                if (carrying[c] != -1) {\n                    if (crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                    else if (crane_y[c] == N - 1) { act[c] = 'Q'; ncarry[c] = -1; }\n                    else { act[c] = '.'; }\n                } else {\n                    int buffer_cont = grid[c][BUFFER_COL];\n                    bool buffer_valid = (buffer_cont != -1 && !dispatched[buffer_cont] && target_row[buffer_cont] == c);\n                    \n                    int gate_cont = grid[c][0];\n                    bool gate_valid = (gate_cont != -1 && !dispatched[gate_cont] && target_row[gate_cont] == c);\n                    \n                    int target_j = -1;\n                    \n                    if (buffer_valid) target_j = BUFFER_COL;\n                    else if (gate_valid) target_j = 0;\n                    else if (gate_cont != -1 && target_row[gate_cont] != c) {\n                        if (crane_y[c] < N - 1 && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                        target_j = -2; \n                    } else {\n                        // Idle: Move to buffer or patrol\n                        if (crane_y[c] < BUFFER_COL && grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                        else if (crane_y[c] > BUFFER_COL && grid[c][crane_y[c]-1] == -1) { act[c] = 'L'; ny[c]--; }\n                        target_j = -2;\n                    }\n                    \n                    if (target_j != -2 && target_j != -1) {\n                        if (crane_y[c] < target_j) { \n                             if (grid[c][crane_y[c]+1] == -1) { act[c] = 'R'; ny[c]++; }\n                             else { act[c] = '.'; }\n                        }\n                        else if (crane_y[c] > target_j) { \n                             if (grid[c][crane_y[c]-1] == -1) { act[c] = 'L'; ny[c]--; }\n                             else { act[c] = '.'; }\n                        }\n                        else { act[c] = 'P'; ncarry[c] = grid[c][target_j]; }\n                    }\n                }\n            }\n        }\n        \n        // Step 3: Resolve collisions\n        for (int p = 0; p < N; p++) {\n            bool collision = false;\n            for (int i = 0; i < N; i++) {\n                if (i == p) continue;\n                int ox = (i < p) ? nx[i] : crane_x[i];\n                int oy = (i < p) ? ny[i] : crane_y[i];\n                \n                if (nx[p] == ox && ny[p] == oy) {\n                    if (i < p) { collision = true; break; }\n                    else {\n                        if (act[i] == '.' || act[i] == 'P' || act[i] == 'Q') { collision = true; break; }\n                        else {\n                            if (nx[i] == crane_x[p] && ny[i] == crane_y[p]) { collision = true; break; }\n                        }\n                    }\n                }\n            }\n            if (!collision && p != 0 && carrying[p] != -1 && act[p] != 'P' && act[p] != 'Q' && act[p] != '.') {\n                if (grid[nx[p]][ny[p]] != -1) collision = true;\n            }\n            if (collision) {\n                act[p] = '.';\n                nx[p] = crane_x[p];\n                ny[p] = crane_y[p];\n            }\n        }\n        \n        // Step 4: Execute\n        for (int c = 0; c < N; c++) {\n            actions[c] += act[c];\n            if (act[c] == 'P') grid[crane_x[c]][crane_y[c]] = -1;\n            else if (act[c] == 'Q') grid[crane_x[c]][crane_y[c]] = carrying[c];\n            crane_x[c] = nx[c]; crane_y[c] = ny[c]; carrying[c] = ncarry[c];\n        }\n        \n        // Step 5: Dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N - 1] != -1) {\n                dispatched[grid[i][N - 1]] = true;\n                grid[i][N - 1] = -1;\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)actions[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)actions[i].size() < max_len) actions[i] += '.';\n        cout << actions[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Grid dimensions\nconst int N = 20;\nconst int INF = 1e9;\nconst int DX[4] = {0, 0, 1, -1};\nconst int DY[4] = {1, -1, 0, 0};\nconst char DIR_CHAR[4] = {'R', 'L', 'D', 'U'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n;\n    // N is always 20, but we read it just in case\n    if (!(cin >> n)) return 0; \n    \n    vector<int> h(n * n);\n    for (int i = 0; i < n * n; ++i) {\n        cin >> h[i];\n    }\n\n    // 1. Construct Min-Cost Flow Graph\n    // Nodes: 0 to n*n-1 are grid cells.\n    // Source S = n*n, Sink T = n*n + 1.\n    int S = n * n;\n    int T = n * n + 1;\n    mcf_graph<int, long long> graph(n * n + 2);\n    \n    long long total_supply = 0;\n\n    for (int i = 0; i < n * n; ++i) {\n        if (h[i] > 0) {\n            graph.add_edge(S, i, h[i], 0);\n            total_supply += h[i];\n        } else if (h[i] < 0) {\n            graph.add_edge(i, T, -h[i], 0);\n        }\n    }\n\n    // Add grid edges (undirected)\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int u = i * n + j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + DX[k];\n                int nj = j + DY[k];\n                if (0 <= ni && ni < n && 0 <= nj && nj < n) {\n                    int v = ni * n + nj;\n                    // Cost is 1 per unit distance\n                    graph.add_edge(u, v, INF, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min-Cost Flow\n    auto result = graph.flow(S, T, total_supply);\n    // result.second is the min cost (sum of amount * distance)\n    // We don't strictly need the value, just the flow distribution.\n\n    // 3. Extract Flow Graph\n    // adj[u] stores (v, flow) pairs for flow > 0\n    vector<vector<pair<int, int>>> adj(n * n);\n    auto edges = graph.edges();\n    for (const auto& e : edges) {\n        if (e.from < S && e.to < S && e.flow > 0) {\n            adj[e.from].emplace_back(e.to, e.flow);\n        }\n    }\n\n    // 4. Construct Path using DFS simulation\n    vector<string> ops;\n    int current_pos = 0; // Start at (0,0)\n    int current_load = 0;\n    \n    // Helper to perform moves\n    auto move_to = [&](int target_pos) {\n        int cx = current_pos / n;\n        int cy = current_pos % n;\n        int tx = target_pos / n;\n        int ty = target_pos % n;\n        \n        // Simple BFS to find path (since we just need a path, but shortest is best)\n        // For simplicity, just move greedily or BFS.\n        // Given the constraints and the fact that we mostly follow flow edges,\n        // we might just need to connect components. \n        // But here we implement BFS for shortest path.\n        \n        vector<int> prev(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        prev[current_pos] = current_pos;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == target_pos) break;\n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (prev[v] == -1) {\n                        prev[v] = u;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        // Reconstruct path\n        vector<int> path;\n        int curr = target_pos;\n        while (curr != current_pos) {\n            path.push_back(curr);\n            curr = prev[curr];\n        }\n        reverse(path.begin(), path.end());\n        \n        for (int next_pos : path) {\n            int dx = (next_pos / n) - (current_pos / n);\n            int dy = (next_pos % n) - (current_pos % n);\n            for (int k = 0; k < 4; ++k) {\n                if (DX[k] == dx && DY[k] == dy) {\n                    ops.push_back(string(1, DIR_CHAR[k]));\n                    break;\n                }\n            }\n            current_pos = next_pos;\n            // We assume move_to is called with 0 load or correct load.\n            // The cost update is implicit in the operations.\n        }\n    };\n\n    // Helper to load/unload\n    auto check_height = [&]() {\n        if (h[current_pos] > 0) {\n            ops.push_back(\"+\" + to_string(h[current_pos]));\n            current_load += h[current_pos];\n            h[current_pos] = 0;\n        } else if (h[current_pos] < 0) {\n            // We need to unload.\n            // However, we might not have exactly -h[current_pos] available if flow is split weirdly?\n            // In theory, inflow should cover it.\n            int needed = -h[current_pos];\n            if (current_load >= needed) {\n                ops.push_back(\"-\" + to_string(needed));\n                current_load -= needed;\n                h[current_pos] = 0;\n            } else {\n                // Should not happen in optimal flow, but just in case:\n                // This implies we need to carry more soil here.\n                // Or we are processing in a weird order.\n                // With the tree traversal, we should arrive with sufficient load.\n                // If not, it's a logic error in flow construction or traversal.\n                // We will assume it holds.\n            }\n        }\n    };\n\n    // Recursive DFS to cover flow tree\n    // Returns true if we don't need to backtrack (optimized path end)\n    function<bool(int)> dfs = [&](int u) {\n        // 1. Satisfy height at u\n        check_height();\n        \n        // 2. Process children\n        if (adj[u].empty()) {\n            return true; // Leaf\n        }\n        \n        // Optimization: Find the child with the deepest/longest path to process last (to avoid backtrack)\n        // Simple heuristic: just iterate.\n        // To avoid backtrack on the last child:\n        for (size_t i = 0; i < adj[u].size(); ++i) {\n            int v = adj[u][i].first;\n            int flow_amt = adj[u][i].second;\n            \n            // We need to carry `flow_amt` from u to v.\n            // The rest of current_load (if any) should stay at u.\n            // We unload the rest, reload later.\n            int load_to_keep = current_load - flow_amt;\n            \n            if (load_to_keep > 0) {\n                ops.push_back(\"-\" + to_string(load_to_keep));\n                current_load -= load_to_keep;\n                // Height of u increases temporarily. This is fine, we fix it later.\n                h[u] += load_to_keep; \n            }\n            \n            // Move to v\n            move_to(v);\n            // current_load should be flow_amt now\n            if (current_load != flow_amt) {\n                // Logic error\n            }\n            \n            bool should_return = true;\n            if (i == adj[u].size() - 1) {\n                should_return = false; // Last child, don't return\n            }\n            \n            bool child_is_leaf = dfs(v);\n            \n            if (!should_return) {\n                return false; // Propagate \"don't return\" up\n            }\n            \n            // Return from v\n            // At v, we should have 0 load (all deposited at its children/height)\n            // Move back to u\n            move_to(u);\n            \n            // Reload the soil we left at u\n            if (load_to_keep > 0) {\n                ops.push_back(\"+\" + to_string(load_to_keep));\n                current_load += load_to_keep;\n                h[u] -= load_to_keep;\n            }\n            // Now current_load is restored for next child\n        }\n        return true;\n    };\n\n    // Main loop to handle disconnected components\n    while (true) {\n        // Check if any flow remains\n        bool has_flow = false;\n        int best_u = -1;\n        int best_dist = INF;\n        \n        // Find closest node with remaining outflow\n        // Simple BFS from current_pos\n        vector<int> dist(n * n, -1);\n        queue<int> q;\n        q.push(current_pos);\n        dist[current_pos] = 0;\n        \n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            \n            if (!adj[u].empty()) {\n                if (dist[u] < best_dist) {\n                    best_dist = dist[u];\n                    best_u = u;\n                }\n            }\n            \n            int ux = u / n;\n            int uy = u % n;\n            for (int k = 0; k < 4; ++k) {\n                int nx = ux + DX[k];\n                int ny = uy + DY[k];\n                if (0 <= nx && nx < n && 0 <= ny && ny < n) {\n                    int v = nx * n + ny;\n                    if (dist[v] == -1) {\n                        dist[v] = dist[u] + 1;\n                        q.push(v);\n                    }\n                }\n            }\n        }\n        \n        if (best_u == -1) break; // Done\n        \n        if (best_u != current_pos) {\n            // Move to best_u with 0 load (we assume we can reach with 0 load)\n            // We need to ensure we have 0 load to move optimally?\n            // Actually, we might have load if we are in a middle of something.\n            // But this loop handles disconnected components.\n            // So we should be at load 0 when jumping.\n            move_to(best_u);\n        }\n        \n        // Process component starting at best_u\n        dfs(best_u);\n    }\n\n    // Output\n    cout << ops.size() << \"\\n\";\n    for (const auto& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// Random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> rng01(0.0, 1.0);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    int grid_size = N * N;\n    const int MAX_EDGE_SCORE = M * 100; // 1500\n\n    // Precompute neighbor offsets for grid indices\n    vector<vector<int>> neighbors(grid_size);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int idx = r * N + c;\n            if (r > 0) neighbors[idx].push_back(idx - N);\n            if (r < N - 1) neighbors[idx].push_back(idx + N);\n            if (c > 0) neighbors[idx].push_back(idx - 1);\n            if (c < N - 1) neighbors[idx].push_back(idx + 1);\n        }\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // 1. Read Input\n        vector<vector<int>> X(seed_count, vector<int>(M));\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n\n        // 2. Calculate Total Value V for each seed\n        vector<int> V(seed_count);\n        for (int i = 0; i < seed_count; ++i) {\n            V[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // 3. Seed Selection\n        vector<int> max_dim(M, 0);\n        for (int l = 0; l < M; ++l) {\n            for (int i = 0; i < seed_count; ++i) {\n                max_dim[l] = max(max_dim[l], X[i][l]);\n            }\n        }\n\n        vector<pair<double, int>> seed_scores;\n        const double SPECIALIST_BONUS = 10000.0; \n        \n        for (int i = 0; i < seed_count; ++i) {\n            double bonus = 0;\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] == max_dim[l]) {\n                    bonus += SPECIALIST_BONUS;\n                }\n            }\n            seed_scores.push_back({V[i] + bonus, i});\n        }\n\n        sort(seed_scores.begin(), seed_scores.end(), [](const auto& a, const auto& b) {\n            return a.first > b.first;\n        });\n\n        vector<int> pool_indices(grid_size);\n        for (int i = 0; i < grid_size; ++i) {\n            pool_indices[i] = seed_scores[i].second;\n        }\n\n        // 4. Precompute Base Score Matrix S\n        vector<vector<int>> S(grid_size, vector<int>(grid_size, 0));\n        for (int i = 0; i < grid_size; ++i) {\n            for (int j = i + 1; j < grid_size; ++j) {\n                int score = 0;\n                int real_i = pool_indices[i];\n                int real_j = pool_indices[j];\n                for (int l = 0; l < M; ++l) {\n                    score += max(X[real_i][l], X[real_j][l]);\n                }\n                S[i][j] = score;\n                S[j][i] = score;\n            }\n        }\n\n        // 5. Initialization (Max-Edge-First)\n        int u_max = -1, v_max = -1;\n        int s_max = -1;\n        for (int i = 0; i < grid_size; ++i) {\n            for (int j = i + 1; j < grid_size; ++j) {\n                if (S[i][j] > s_max) {\n                    s_max = S[i][j];\n                    u_max = i;\n                    v_max = j;\n                }\n            }\n        }\n\n        vector<int> path;\n        path.push_back(u_max);\n        path.push_back(v_max);\n        vector<bool> in_path(grid_size, false);\n        in_path[u_max] = true;\n        in_path[v_max] = true;\n\n        for (int step = 2; step < grid_size; ++step) {\n            int last = path.back();\n            int best_next = -1;\n            double best_local_score = -1.0;\n            for (int i = 0; i < grid_size; ++i) {\n                if (!in_path[i]) {\n                    double score = (double)S[last][i] + (double)V[pool_indices[i]] * 0.2;\n                    if (score > best_local_score) {\n                        best_local_score = score;\n                        best_next = i;\n                    }\n                }\n            }\n            if (best_next != -1) {\n                path.push_back(best_next);\n                in_path[best_next] = true;\n            } else {\n                for (int i = 0; i < grid_size; ++i) { \n                    if(!in_path[i]){ path.push_back(i); in_path[i]=true; break; } \n                }\n            }\n        }\n        \n        // Map path to Snake Grid\n        vector<int> grid(grid_size);\n        for (int i = 0; i < grid_size; ++i) {\n            int r = i / N;\n            int c = (r % 2 == 0) ? (i % N) : (N - 1 - (i % N));\n            grid[r * N + c] = path[i];\n        }\n\n        // 6. Fast State Initialization for SA\n        vector<int> freq(MAX_EDGE_SCORE + 1, 0);\n        long long current_sum = 0;\n        int current_max = 0;\n\n        for (int i = 0; i < grid_size; ++i) {\n            for (int nb : neighbors[i]) {\n                if (i < nb) {\n                    int score = S[grid[i]][grid[nb]];\n                    current_sum += score;\n                    freq[score]++;\n                    if (score > current_max) current_max = score;\n                }\n            }\n        }\n        \n        // Objective function: Sum + W * Max\n        const double WEIGHT_MAX = 15.0; \n        double current_obj = (double)current_sum + WEIGHT_MAX * (double)current_max;\n\n        // 7. Simulated Annealing\n        double start_temp = 600.0;\n        double end_temp = 0.1;\n        int num_iterations = 400000; \n        double temp = start_temp;\n        double cooling_rate = pow(end_temp / start_temp, 1.0 / num_iterations);\n        \n        for (int it = 0; it < num_iterations; ++it) {\n            int p1 = rng() % grid_size;\n            int p2 = rng() % grid_size;\n            while (p1 == p2) p2 = rng() % grid_size;\n\n            int u = grid[p1];\n            int v = grid[p2];\n\n            // Collect edges to be removed and added\n            // Note: We count each edge once (i < nb)\n            // When swapping p1 and p2, edges (p1, nb) and (p2, nb) are affected.\n            // p1 and p2 might be neighbors? Yes. In that case, the edge (p1, p2) is counted once.\n            \n            vector<int> old_scores;\n            vector<int> new_scores;\n\n            // Helper to process a pair\n            auto process_pair = [&](int a, int b) {\n                if (a < b) { // Only process if we are the \"owner\" of the edge for counting\n                    return make_pair(S[grid[a]][grid[b]], S[grid[a]][grid[b]]);\n                }\n                return make_pair(-1, -1); // Not owner\n            };\n            \n            // Collect old scores and compute their sum\n            long long delta_sum = 0;\n            \n            // p1's neighbors\n            for (int nb : neighbors[p1]) {\n                int s_old = -1;\n                if (p1 < nb) s_old = S[grid[p1]][grid[nb]];\n                else if (nb < p1) s_old = S[grid[nb]][grid[p1]]; // We view it from nb's perspective, but score is symmetric\n                \n                // Wait, S is symmetric. S[u][v] == S[v][u].\n                // We just need the score value.\n                // But we need to know if we counted it in our sum.\n                // Since sum iterates i < nb, for edge (p1, p2), it is counted once.\n                \n                if (nb == p2) continue; // Handle separately\n\n                if (p1 < nb) {\n                    old_scores.push_back(S[u][grid[nb]]);\n                    new_scores.push_back(S[v][grid[nb]]);\n                } else {\n                    // Edge is owned by nb. It changes from S[grid[nb]][u] to S[grid[nb]][v]\n                    // We don't store it here because 'nb' handles it?\n                    // No, we must handle ALL edges connected to p1 and p2.\n                    // The grid state changes. All incident edges change.\n                    // We just need the value.\n                    // We will update freq for ALL these edges.\n                    // But wait, if I update freq for (p1, nb) where p1 > nb, and nb's loop also updates...\n                    // We must be careful not to double count delta sum or freq updates.\n                    \n                    // Let's just collect ALL incident edges to p1 and p2.\n                    // There are deg(p1) + deg(p2) edges. max 4+4=8. \n                    // If p1, p2 adjacent, one edge is shared. Total 7 unique edges.\n                    // This is small enough to handle with a set or just careful logic.\n                    \n                    // Simpler approach: \n                    // Iterate all neighbors of p1.\n                    // Store the OLD score of the edge (p1, nb).\n                    // Store the NEW score (swapped).\n                    // Do this unconditionally. We will fix the \"double counting\" logic?\n                    // Actually, we can't fix it easily if we just iterate neighbors.\n                    // Standard way: \n                    // For p in {p1, p2}:\n                    //   For nb in neighbors[p]:\n                    //     If (p, nb) is an edge in the grid (always true):\n                    //       old_scores.push_back(current_score(p, nb))\n                    //       new_scores.push_back(swapped_score(p, nb))\n                    //\n                    // Problem: Edge (p1, p2) appears twice (once for p1, once for p2).\n                    // We need to handle this.\n                    \n                    // Robust way:\n                    // Iterate neighbors of p1. Record edges.\n                    // Iterate neighbors of p2. Record edges.\n                    // Use a set to deduplicate edge indices (min(id, nb), max(id, nb))?\n                    // Since grid is small, just check if we have seen the pair.\n                }\n            }\n\n            // Let's re-do the collection cleanly.\n            vector<pair<int, int>> edges; // pairs of grid indices\n            auto add_edge = [&](int a, int b) {\n                if (a < b) edges.emplace_back(a, b);\n                else edges.emplace_back(b, a);\n            };\n            for (int nb : neighbors[p1]) if (nb != p2) add_edge(p1, nb);\n            for (int nb : neighbors[p2]) add_edge(p2, nb);\n            \n            // Deduplicate\n            sort(edges.begin(), edges.end());\n            edges.erase(unique(edges.begin(), edges.end()), edges.end());\n\n            // Calculate Sum Delta\n            for (auto& e : edges) {\n                int s_old = S[grid[e.first]][grid[e.second]];\n                // Temporarily swap to calculate new score\n                swap(grid[p1], grid[p2]); \n                int s_new = S[grid[e.first]][grid[e.second]];\n                swap(grid[p1], grid[p2]); // Swap back immediately\n                \n                old_scores.push_back(s_old);\n                new_scores.push_back(s_new);\n                delta_sum += (s_new - s_old);\n            }\n\n            // Perform Swap in Grid\n            swap(grid[p1], grid[p2]);\n\n            // Calculate Max Delta\n            int old_max = current_max;\n            int new_max_candidate = 0;\n            \n            // Update Frequency\n            for (int s : old_scores) {\n                freq[s]--;\n            }\n            for (int s : new_scores) {\n                freq[s]++;\n                if (s > new_max_candidate) new_max_candidate = s;\n            }\n\n            // Recalculate Max\n            if (new_max_candidate > old_max) {\n                current_max = new_max_candidate;\n            } else if (freq[old_max] == 0) {\n                while (current_max > 0 && freq[current_max] == 0) {\n                    current_max--;\n                }\n            }\n            // else current_max remains same\n\n            double delta_obj = (double)delta_sum + WEIGHT_MAX * (double)(current_max - old_max);\n\n            // Acceptance\n            if (delta_obj > 0 || rng01(rng) < exp(delta_obj / temp)) {\n                current_sum += delta_sum;\n                // current_max already updated\n                // current_obj implicitly updated\n            } else {\n                // Revert\n                swap(grid[p1], grid[p2]);\n                // Revert Freq\n                for (int s : old_scores) {\n                    freq[s]++;\n                }\n                for (int s : new_scores) {\n                    freq[s]--;\n                }\n                current_max = old_max;\n            }\n\n            temp *= cooling_rate;\n        }\n\n        // 8. Output\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int idx = grid[r * N + c];\n                cout << pool_indices[idx] << (c < N - 1 ? \" \" : \"\\n\");\n            }\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    // Grid state\n    vector<vector<int>> grid(N, vector<int>(N, 0)); // 0: empty, 1: item present\n    vector<vector<int>> target(N, vector<int>(N, 0));\n\n    string s_row, t_row;\n    for (int i = 0; i < N; ++i) {\n        cin >> s_row;\n        for (int j = 0; j < N; ++j) grid[i][j] = s_row[j] - '0';\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> t_row;\n        for (int j = 0; j < N; ++j) target[i][j] = t_row[j] - '0';\n    }\n\n    // --- 1. Design Robotic Arm ---\n    // Star topology: Root 0, children 1..V-1.\n    // Lengths: 1, 2, ..., V-1.\n    // This provides distinct reach for each arm.\n    cout << V << \"\\n\";\n    vector<int> lengths(V);\n    for (int i = 1; i < V; ++i) {\n        lengths[i] = i;\n        cout << 0 << \" \" << i << \"\\n\";\n    }\n\n    // Initial position: (0, 0)\n    int rx = 0, ry = 0;\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // --- 2. Operate ---\n    vector<int> arm_dirs(V, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(V, 0);  // 0 or 1, whether fingertip i holds an item\n\n    int total_steps = 0;\n    const int MAX_STEPS = 100000;\n\n    // Snake movement state\n    int move_dir = 0; // 0: Right\n    int current_row = 0;\n\n    auto is_finished = [&]() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] != target[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    while (total_steps < MAX_STEPS && !is_finished()) {\n        string S(2 * V, '.');\n\n        // --- A. Determine Movement (Snake) ---\n        if (move_dir == 0) { // Moving Right\n            if (ry + 1 < N) {\n                S[0] = 'R';\n                ry++;\n            } else {\n                // Reached right end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 2; // Switch to Left\n                } else {\n                    S[0] = '.'; // End of grid\n                }\n            }\n        } else if (move_dir == 2) { // Moving Left\n            if (ry - 1 >= 0) {\n                S[0] = 'L';\n                ry--;\n            } else {\n                // Reached left end\n                if (current_row + 1 < N) {\n                    S[0] = 'D';\n                    rx++;\n                    current_row++;\n                    move_dir = 0; // Switch to Right\n                } else {\n                    S[0] = '.';\n                }\n            }\n        }\n\n        // --- B. Determine Rotations (Greedy) ---\n        // For each arm (excluding root), evaluate which direction points to the most valuable square.\n        for (int i = 1; i < V; ++i) {\n            int best_dir = arm_dirs[i];\n            int best_score = -1;\n\n            // Check 4 directions\n            for (int d = 0; d < 4; ++d) {\n                int tx = rx + DX[d] * lengths[i];\n                int ty = ry + DY[d] * lengths[i];\n                int score = 0;\n\n                if (tx >= 0 && tx < N && ty >= 0 && ty < N) {\n                    // Logic: High value if:\n                    // 1. It's a source (grid=1, target=0) and we can pick it.\n                    // 2. It's a target (grid=0, target=1) and we are holding an item to place.\n                    if (grid[tx][ty] == 1 && target[tx][ty] == 0) {\n                        score += 10; // Prioritize picking up sources\n                    } else if (grid[tx][ty] == 0 && target[tx][ty] == 1) {\n                        score += 5;  // Next prioritize filling targets\n                    } else if (grid[tx][ty] == 1 && target[tx][ty] == 1) {\n                        score += 1;   // Already correct\n                    }\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_dir = d;\n                }\n            }\n\n            // Set rotation command\n            if (best_dir != arm_dirs[i]) {\n                int diff = (best_dir - arm_dirs[i] + 4) % 4;\n                if (diff == 1) S[i] = 'R';\n                else if (diff == 3) S[i] = 'L';\n                else if (diff == 2) {\n                    // 180 degree turn, choose L (arbitrary, or shortest path)\n                    S[i] = 'L'; \n                    best_dir = (arm_dirs[i] + 3) % 4; // Update to intermediate state\n                }\n            }\n            \n            // Update internal state for this step (so Action phase uses correct coords)\n            arm_dirs[i] = best_dir;\n        }\n\n        // --- C. Determine Actions (Pick/Put) ---\n        // Loop from 1 to V-1 (Vertex 0 is root/internal, cannot act).\n        for (int i = 1; i < V; ++i) {\n            int cx = rx + DX[arm_dirs[i]] * lengths[i];\n            int cy = ry + DY[arm_dirs[i]] * lengths[i];\n\n            char action_cmd = '.';\n            if (cx >= 0 && cx < N && cy >= 0 && cy < N) {\n                if (holding[i] == 1) {\n                    // Try to Place\n                    if (grid[cx][cy] == 0 && target[cx][cy] == 1) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 1;\n                        holding[i] = 0;\n                    }\n                } else {\n                    // Try to Pick\n                    if (grid[cx][cy] == 1 && target[cx][cy] == 0) {\n                        action_cmd = 'P';\n                        grid[cx][cy] = 0;\n                        holding[i] = 1;\n                    }\n                }\n            }\n            S[V + i] = action_cmd;\n        }\n\n        cout << S << \"\\n\";\n        total_steps++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <unordered_set>\n#include <random>\n#include <cmath>\n#include <chrono>\n#include <climits>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int TYPE_MACKEREL = 1;\nconst int TYPE_SARDINE = -1;\n\n// Optimized parameters for high-performance deep search\nconst int MAX_GREEDY_RESTARTS = 300;   // Reduced to save time for SA\nconst int MAX_GREEDY_STEPS = 40;\nconst int TOP_CANDIDATES = 40;         // Focused refinement\nconst int SA_ITERATIONS = 1000000;     // Doubled for deep search\nconst double START_TEMP = 40.0;         // Higher temp for aggressive exploration\nconst double END_TEMP = 0.1;\n\nstruct Rect {\n    int x1, x2, y1, y2;\n    int score;\n};\n\n// cols[x] stores pairs of {y, cumulative_sum} sorted by y\nvector<vector<pair<int, int>>> cols(MAX_COORD + 1);\n// rows[y] stores pairs of {x, cumulative_sum} sorted by x\nvector<vector<pair<int, int>>> rows(MAX_COORD + 1);\n\nvector<int> next_x(MAX_COORD + 2, -1);\nvector<int> prev_x(MAX_COORD + 2, -1);\nvector<int> next_y(MAX_COORD + 2, -1);\nvector<int> prev_y(MAX_COORD + 2, -1);\n\nint best_global_score = -1;\nRect best_global_rect;\n\n// Random Generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> dist_double(0.0, 1.0);\nuniform_int_distribution<int> dist_int(0, 7);\n\n// Helper to get sum of points in a column segment [y1, y2] using prefix sums\ninline int get_col_sum(int x, int y1, int y2) {\n    if (y1 > y2) return 0;\n    const auto& col = cols[x];\n    if (col.empty()) return 0;\n\n    auto r = upper_bound(col.begin(), col.end(), make_pair(y2, INT_MAX));\n    auto l = lower_bound(col.begin(), col.end(), make_pair(y1, INT_MIN));\n\n    int sum_r = 0;\n    if (r != col.begin()) {\n        sum_r = (r - 1)->second;\n    }\n\n    int sum_l = 0;\n    if (l != col.begin()) {\n        sum_l = (l - 1)->second;\n    }\n\n    return sum_r - sum_l;\n}\n\n// Helper to get sum of points in a row segment [x1, x2] using prefix sums\ninline int get_row_sum(int y, int x1, int x2) {\n    if (x1 > x2) return 0;\n    const auto& row = rows[y];\n    if (row.empty()) return 0;\n\n    auto r = upper_bound(row.begin(), row.end(), make_pair(x2, INT_MAX));\n    auto l = lower_bound(row.begin(), row.end(), make_pair(x1, INT_MIN));\n\n    int sum_r = 0;\n    if (r != row.begin()) {\n        sum_r = (r - 1)->second;\n    }\n\n    int sum_l = 0;\n    if (l != row.begin()) {\n        sum_l = (l - 1)->second;\n    }\n\n    return sum_r - sum_l;\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return;\n\n    vector<pair<int, int>> mackerels;\n    mackerels.reserve(N);\n\n    vector<vector<pair<int, int>>> temp_cols(MAX_COORD + 1);\n    vector<vector<pair<int, int>>> temp_rows(MAX_COORD + 1);\n\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        mackerels.push_back({x, y});\n        temp_cols[x].emplace_back(y, TYPE_MACKEREL);\n        temp_rows[y].emplace_back(x, TYPE_MACKEREL);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n        temp_cols[x].emplace_back(y, TYPE_SARDINE);\n        temp_rows[y].emplace_back(x, TYPE_SARDINE);\n    }\n\n    // Sort and compute prefix sums\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        if (!temp_cols[i].empty()) {\n            sort(temp_cols[i].begin(), temp_cols[i].end());\n            cols[i].resize(temp_cols[i].size());\n            int running_sum = 0;\n            for (size_t j = 0; j < temp_cols[i].size(); ++j) {\n                running_sum += temp_cols[i][j].second;\n                cols[i][j] = {temp_cols[i][j].first, running_sum};\n            }\n        }\n        if (!temp_rows[i].empty()) {\n            sort(temp_rows[i].begin(), temp_rows[i].end());\n            rows[i].resize(temp_rows[i].size());\n            int running_sum = 0;\n            for (size_t j = 0; j < temp_rows[i].size(); ++j) {\n                running_sum += temp_rows[i][j].second;\n                rows[i][j] = {temp_rows[i][j].first, running_sum};\n            }\n        }\n    }\n\n    // Precompute next/prev populated indices\n    int last_x = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_x[i] = last_x;\n        if (!cols[i].empty()) last_x = i;\n    }\n    int next_x_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_x[i] = next_x_val;\n        if (!cols[i].empty()) next_x_val = i;\n    }\n\n    int last_y = -1;\n    for (int i = 0; i <= MAX_COORD; ++i) {\n        prev_y[i] = last_y;\n        if (!rows[i].empty()) last_y = i;\n    }\n    int next_y_val = -1;\n    for (int i = MAX_COORD; i >= 0; --i) {\n        next_y[i] = next_y_val;\n        if (!rows[i].empty()) next_y_val = i;\n    }\n\n    // Phase 1: Fast Greedy Search\n    vector<Rect> candidates;\n    shuffle(mackerels.begin(), mackerels.end(), rng);\n    \n    int restarts = min((int)mackerels.size(), MAX_GREEDY_RESTARTS);\n\n    for (int r = 0; r < restarts; ++r) {\n        const auto& start_pt = mackerels[r];\n        Rect cur;\n        cur.x1 = cur.x2 = start_pt.first;\n        cur.y1 = cur.y2 = start_pt.second;\n        cur.score = 1; \n\n        unordered_set<long long> visited;\n        auto encode = [](int x1, int x2, int y1, int y2) {\n            return ((long long)x1 << 48) | ((long long)x2 << 32) | ((long long)y1 << 16) | y2;\n        };\n        visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n        Rect best_local = cur;\n\n        for (int step = 0; step < MAX_GREEDY_STEPS; ++step) {\n            int best_delta = -2;\n            int best_dir = -1;\n            Rect next_rect;\n\n            if (next_x[cur.x2] != -1) {\n                Rect n = cur; n.x2 = next_x[cur.x2];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x2, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 0; next_rect = n; }\n                }\n            }\n            if (prev_x[cur.x1] != -1) {\n                Rect n = cur; n.x1 = prev_x[cur.x1];\n                if (n.x2 > n.x1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_col_sum(n.x1, n.y1, n.y2);\n                    if (d > best_delta) { best_delta = d; best_dir = 1; next_rect = n; }\n                }\n            }\n            if (next_y[cur.y2] != -1) {\n                Rect n = cur; n.y2 = next_y[cur.y2];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y2, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 2; next_rect = n; }\n                }\n            }\n            if (prev_y[cur.y1] != -1) {\n                Rect n = cur; n.y1 = prev_y[cur.y1];\n                if (n.y2 > n.y1 && 2LL*(n.x2 - n.x1 + n.y2 - n.y1) <= MAX_PERIMETER) {\n                    int d = get_row_sum(n.y1, n.x1, n.x2);\n                    if (d > best_delta) { best_delta = d; best_dir = 3; next_rect = n; }\n                }\n            }\n\n            if (best_dir == -1) break;\n            if (best_delta < 0) break; \n            if (best_delta == 0 && visited.count(encode(next_rect.x1, next_rect.x2, next_rect.y1, next_rect.y2))) break;\n\n            cur = next_rect;\n            cur.score += best_delta;\n            visited.insert(encode(cur.x1, cur.x2, cur.y1, cur.y2));\n\n            if (cur.score > best_local.score) {\n                best_local = cur;\n            }\n        }\n        candidates.push_back(best_local);\n    }\n\n    // Phase 2: Simulated Annealing\n    sort(candidates.begin(), candidates.end(), [](const Rect& a, const Rect& b) {\n        return a.score > b.score;\n    });\n\n    int num_candidates = min((int)candidates.size(), TOP_CANDIDATES);\n\n    for (int i = 0; i < num_candidates; ++i) {\n        Rect cur = candidates[i];\n        Rect best_sa = cur;\n        \n        double temp = START_TEMP;\n        double cooling_rate = pow(END_TEMP / START_TEMP, 1.0 / SA_ITERATIONS);\n\n        for (int iter = 0; iter < SA_ITERATIONS; ++iter) {\n            temp *= cooling_rate;\n\n            int dir = dist_int(rng);\n            Rect next = cur;\n            int delta = 0;\n            bool valid = true;\n\n            if (dir == 0) { // Expand Left\n                if (prev_x[next.x1] != -1) {\n                    int tx = prev_x[next.x1];\n                    if (tx < next.x2 && 2LL * (next.x2 - tx + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x1 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 1) { // Shrink Left\n                if (next_x[next.x1] != -1 && next_x[next.x1] < next.x2) {\n                    int tx = next_x[next.x1];\n                    delta = -get_col_sum(next.x1, next.y1, next.y2);\n                    next.x1 = tx;\n                } else valid = false;\n            } else if (dir == 2) { // Expand Right\n                if (next_x[next.x2] != -1) {\n                    int tx = next_x[next.x2];\n                    if (tx > next.x1 && 2LL * (tx - next.x1 + next.y2 - next.y1) <= MAX_PERIMETER) {\n                        next.x2 = tx;\n                        delta = get_col_sum(tx, next.y1, next.y2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 3) { // Shrink Right\n                if (prev_x[next.x2] != -1 && prev_x[next.x2] > next.x1) {\n                    int tx = prev_x[next.x2];\n                    delta = -get_col_sum(next.x2, next.y1, next.y2);\n                    next.x2 = tx;\n                } else valid = false;\n            } else if (dir == 4) { // Expand Down\n                if (prev_y[next.y1] != -1) {\n                    int ty = prev_y[next.y1];\n                    if (ty < next.y2 && 2LL * (next.x2 - next.x1 + next.y2 - ty) <= MAX_PERIMETER) {\n                        next.y1 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 5) { // Shrink Down\n                if (next_y[next.y1] != -1 && next_y[next.y1] < next.y2) {\n                    int ty = next_y[next.y1];\n                    delta = -get_row_sum(next.y1, next.x1, next.x2);\n                    next.y1 = ty;\n                } else valid = false;\n            } else if (dir == 6) { // Expand Up\n                if (next_y[next.y2] != -1) {\n                    int ty = next_y[next.y2];\n                    if (ty > next.y1 && 2LL * (next.x2 - next.x1 + ty - next.y1) <= MAX_PERIMETER) {\n                        next.y2 = ty;\n                        delta = get_row_sum(ty, next.x1, next.x2);\n                    } else valid = false;\n                } else valid = false;\n            } else if (dir == 7) { // Shrink Up\n                if (prev_y[next.y2] != -1 && prev_y[next.y2] > next.y1) {\n                    int ty = prev_y[next.y2];\n                    delta = -get_row_sum(next.y2, next.x1, next.x2);\n                    next.y2 = ty;\n                } else valid = false;\n            }\n\n            if (valid) {\n                next.score = cur.score + delta;\n                if (delta > 0 || dist_double(rng) < exp((double)delta / temp)) {\n                    cur = next;\n                    if (cur.score > best_sa.score) {\n                        best_sa = cur;\n                    }\n                }\n            }\n        }\n\n        if (best_sa.score > best_global_score) {\n            best_global_score = best_sa.score;\n            best_global_rect = best_sa;\n        }\n    }\n\n    // Handle degenerate output\n    if (best_global_rect.x1 == best_global_rect.x2) {\n        if (best_global_rect.x1 > 0) best_global_rect.x1--;\n        else best_global_rect.x2++;\n    }\n    if (best_global_rect.y1 == best_global_rect.y2) {\n        if (best_global_rect.y1 > 0) best_global_rect.y1--;\n        else best_global_rect.y2++;\n    }\n\n    cout << 4 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y1 << endl;\n    cout << best_global_rect.x2 << \" \" << best_global_rect.y2 << endl;\n    cout << best_global_rect.x1 << \" \" << best_global_rect.y2 << endl;\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nusing ll = long long;\n\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\nstruct Rect {\n    ll w, h;\n    ll x, y;\n    int id; \n};\n\nstruct State {\n    vector<Rect> placed;\n    vector<Op> ops;\n    ll W; \n    ll H; \n    ll score; \n\n    State() : W(0), H(0), score(0) {}\n};\n\nstruct Step {\n    Op op;\n    ll score_inc;\n    Rect new_rect;\n    ll new_W, new_H;\n    ll aspect; \n    ll heuristic; \n};\n\nint N, T;\nll sigma;\nvector<pair<ll, ll>> dims;\n\ninline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nvoid solve_beam_search() {\n    const int BEAM_WIDTH = 80;\n    const int LOCAL_BEAM = 10;\n    const ll ASPECT_WEIGHT = 50; \n    \n    vector<State> beam(1);\n    beam[0].W = 0;\n    beam[0].H = 0;\n    beam[0].score = 0;\n    \n    for (int i = 0; i < N; ++i) {\n        ll w_i = dims[i].first;\n        ll h_i = dims[i].second;\n        \n        vector<State> next_beam;\n        next_beam.reserve(BEAM_WIDTH * LOCAL_BEAM + 10); \n        \n        for (const auto& st : beam) {\n            vector<Step> local_candidates;\n            local_candidates.reserve((st.placed.size() + 1) * 5 + 1);\n            \n            // Option 1: Skip\n            {\n                Step s;\n                s.op = {i, -1, -1, 'X'};\n                s.score_inc = w_i + h_i;\n                s.new_W = st.W;\n                s.new_H = st.H;\n                s.aspect = abs(st.W - st.H);\n                s.heuristic = s.score_inc + s.aspect * ASPECT_WEIGHT;\n                local_candidates.push_back(s);\n            }\n            \n            // Option 2: Place\n            for (int k = -1; k < (int)st.placed.size(); ++k) {\n                for (int r = 0; r < 2; ++r) {\n                    ll cw = (r == 0 ? w_i : h_i);\n                    ll ch = (r == 1 ? w_i : h_i);\n                    int b_id = (k == -1 ? -1 : st.placed[k].id);\n                    \n                    // Direction U\n                    {\n                        ll x = (k == -1 ? 0 : st.placed[k].x + st.placed[k].w);\n                        ll max_bot = 0;\n                        for (const auto& p : st.placed) {\n                            if (overlap(x, x + cw, p.x, p.x + p.w)) {\n                                max_bot = max(max_bot, p.y + p.h);\n                            }\n                        }\n                        ll y = max_bot - ch;\n                        if (y < 0) y = 0;\n                        \n                        ll new_W = max(st.W, x + cw);\n                        ll new_H = max(st.H, y + ch);\n                        ll score_inc = (new_W - st.W) + (new_H - st.H);\n                        \n                        Step s;\n                        s.op = {i, r, b_id, 'U'};\n                        s.score_inc = score_inc;\n                        s.new_W = new_W;\n                        s.new_H = new_H;\n                        s.aspect = abs(new_W - new_H);\n                        s.new_rect = {cw, ch, x, y, i};\n                        s.heuristic = s.score_inc + s.aspect * ASPECT_WEIGHT;\n                        \n                        local_candidates.push_back(s);\n                    }\n                    \n                    // Direction L\n                    {\n                        ll y = (k == -1 ? 0 : st.placed[k].y + st.placed[k].h);\n                        ll max_right = 0;\n                        for (const auto& p : st.placed) {\n                            if (overlap(y, y + ch, p.y, p.y + p.h)) {\n                                max_right = max(max_right, p.x + p.w);\n                            }\n                        }\n                        ll x = max_right - cw;\n                        if (x < 0) x = 0;\n                        \n                        ll new_W = max(st.W, x + cw);\n                        ll new_H = max(st.H, y + ch);\n                        ll score_inc = (new_W - st.W) + (new_H - st.H);\n                        \n                        Step s;\n                        s.op = {i, r, b_id, 'L'};\n                        s.score_inc = score_inc;\n                        s.new_W = new_W;\n                        s.new_H = new_H;\n                        s.aspect = abs(new_W - new_H);\n                        s.new_rect = {cw, ch, x, y, i};\n                        s.heuristic = s.score_inc + s.aspect * ASPECT_WEIGHT;\n                        \n                        local_candidates.push_back(s);\n                    }\n                }\n            }\n            \n            sort(local_candidates.begin(), local_candidates.end(), [](const Step& a, const Step& b) {\n                return a.heuristic < b.heuristic;\n            });\n            \n            int limit = min(LOCAL_BEAM, (int)local_candidates.size());\n            for (int k = 0; k < limit; ++k) {\n                const auto& step = local_candidates[k];\n                State ns = st; \n                ns.W = step.new_W;\n                ns.H = step.new_H;\n                ns.score += step.score_inc;\n                \n                if (step.op.r != -1) {\n                    ns.placed.push_back(step.new_rect);\n                    ns.ops.push_back(step.op);\n                }\n                \n                next_beam.push_back(move(ns));\n            }\n        }\n        \n        sort(next_beam.begin(), next_beam.end(), [](const State& a, const State& b) {\n            return a.score < b.score;\n        });\n        \n        if ((int)next_beam.size() > BEAM_WIDTH) {\n            next_beam.resize(BEAM_WIDTH);\n        }\n        \n        beam = move(next_beam);\n    }\n    \n    for (int t = 0; t < T; ++t) {\n        cout << beam[0].ops.size() << \"\\n\";\n        for (const auto& op : beam[0].ops) {\n            cout << op.p << \" \" << op.r << \" \" << op.d << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma)) return 0;\n    \n    dims.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> dims[i].first >> dims[i].second;\n    }\n    \n    solve_beam_search();\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <queue>\n#include <cmath>\n#include <tuple>\n#include <sys/time.h>\n\nusing namespace std;\n\n// Timer\ndouble get_time() {\n    struct timeval tv;\n    gettimeofday(&tv, NULL);\n    return tv.tv_sec + tv.tv_usec * 1e-6;\n}\n\n// Globals\nint N, M, H;\nvector<int> A;\nvector<vector<int>> G;\nvector<int> X, Y;\nvector<int> degree;\n\nlong long best_score = 0;\nvector<int> best_parent;\n\nrandom_device rd;\nmt19937 rng(rd());\n\n// Safety check: returns true if valid (acyclic and h <= H)\nbool is_valid(const vector<int>& parent) {\n    vector<int> depth(N, -1);\n    // Reconstruct depth to verify constraints\n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) {\n        if (parent[i] != -1) children[parent[i]].push_back(i);\n        else depth[i] = 0;\n    }\n    \n    queue<int> q;\n    for(int i=0; i<N; ++i) if(parent[i] == -1) q.push(i);\n\n    int count = 0;\n    while(!q.empty()) {\n        int v = q.front(); q.pop();\n        count++;\n        if(depth[v] > H) return false;\n        for(int c : children[v]) {\n            depth[c] = depth[v] + 1;\n            q.push(c);\n        }\n    }\n    return count == N; // No cycles means we visited all nodes from roots\n}\n\n// Evaluate parent array: calculate depth and score\nlong long evaluate(const vector<int>& parent, vector<int>& depth) {\n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) {\n        if (parent[i] != -1) children[parent[i]].push_back(i);\n    }\n    \n    queue<int> q;\n    for (int i = 0; i < N; ++i) {\n        if (parent[i] == -1) {\n            depth[i] = 0;\n            q.push(i);\n        }\n    }\n    \n    long long score = 0;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        score += (long long)(depth[v] + 1) * A[v];\n        for (int c : children[v]) {\n            depth[c] = depth[v] + 1;\n            q.push(c);\n        }\n    }\n    return 1 + score;\n}\n\n// Greedy Construction\n// key: 0=A, 1=X, 2=Y, 3=Degree\n// strat: 0=Deepest, 1=Shallowest\npair<vector<int>, long long> greedy_construct(vector<int> order, int key, bool asc, int strat) {\n    if (key == 0) {\n        stable_sort(order.begin(), order.end(), [&](int u, int v) { \n            return asc ? (A[u] < A[v]) : (A[u] > A[v]); \n        });\n    } else if (key == 1) {\n        stable_sort(order.begin(), order.end(), [&](int u, int v) { \n            return asc ? (X[u] < X[v]) : (X[u] > X[v]); \n        });\n    } else if (key == 2) {\n        stable_sort(order.begin(), order.end(), [&](int u, int v) { \n            return asc ? (Y[u] < Y[v]) : (Y[u] > Y[v]); \n        });\n    } else if (key == 3) {\n        stable_sort(order.begin(), order.end(), [&](int u, int v) { \n            return asc ? (degree[u] < degree[v]) : (degree[u] > degree[v]); \n        });\n    }\n\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<bool> processed(N, false);\n    \n    for (int v : order) {\n        int best_u = -1;\n        int target_depth = strat == 0 ? -1 : 15;\n\n        for (int u : G[v]) {\n            if (processed[u] && depth[u] < H) {\n                if (strat == 0) { // Deepest\n                    if (depth[u] > target_depth) { target_depth = depth[u]; best_u = u; }\n                } else { // Shallowest\n                    if (depth[u] < target_depth) { target_depth = depth[u]; best_u = u; }\n                }\n            }\n        }\n\n        if (best_u != -1) {\n            parent[v] = best_u;\n            depth[v] = depth[best_u] + 1;\n        } else {\n            parent[v] = -1;\n            depth[v] = 0;\n        }\n        processed[v] = true;\n    }\n    \n    long long score = 0;\n    for (int i = 0; i < N; ++i) score += (long long)(depth[i] + 1) * A[i];\n    return {parent, 1 + score};\n}\n\n// Hill Climbing (Strictly Improving)\nvoid hill_climb(vector<int>& parent, vector<int>& depth, long long current_score) {\n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) if (parent[i] != -1) children[parent[i]].push_back(i);\n\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> visit_order(N);\n        iota(visit_order.begin(), visit_order.end(), 0);\n        shuffle(visit_order.begin(), visit_order.end(), rng);\n\n        for (int v : visit_order) {\n            vector<int> neighbors = G[v];\n            shuffle(neighbors.begin(), neighbors.end(), rng);\n\n            for (int u : neighbors) {\n                if (u == parent[v]) continue;\n                \n                // Check cycle\n                int curr = u;\n                while (curr != -1 && curr != v) curr = parent[curr];\n                if (curr == v) continue; \n\n                int new_depth_v = depth[u] + 1;\n                if (new_depth_v > H) continue; \n\n                int diff = new_depth_v - depth[v];\n                if (diff <= 0) continue; \n                \n                long long sum_A = 0;\n                vector<int> stack; stack.push_back(v);\n                bool valid = true;\n                while (!stack.empty()) {\n                    int curr_node = stack.back(); stack.pop_back();\n                    if (depth[curr_node] + diff > H) { valid = false; break; }\n                    sum_A += A[curr_node];\n                    for (int c : children[curr_node]) stack.push_back(c);\n                }\n                if (!valid) continue;\n                \n                // Apply Move\n                int old_parent = parent[v];\n                parent[v] = u; depth[v] = new_depth_v;\n                if (old_parent != -1) {\n                    auto it = find(children[old_parent].begin(), children[old_parent].end(), v);\n                    if (it != children[old_parent].end()) children[old_parent].erase(it);\n                }\n                children[u].push_back(v);\n                \n                stack.push_back(v);\n                while (!stack.empty()) {\n                    int curr_node = stack.back(); stack.pop_back();\n                    for (int c : children[curr_node]) { depth[c] += diff; stack.push_back(c); }\n                }\n                \n                current_score += (long long)diff * sum_A;\n                improved = true;\n                \n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_parent = parent;\n                }\n                break; \n            }\n        }\n    }\n}\n\n// Simulated Annealing\nlong long simulated_annealing(vector<int> init_parent, vector<int> init_depth, long long init_score, double time_limit) {\n    double start_time = get_time();\n    \n    vector<int> parent = init_parent;\n    vector<int> depth = init_depth;\n    long long current_score = init_score;\n    \n    vector<vector<int>> children(N);\n    for (int i = 0; i < N; ++i) if (parent[i] != -1) children[parent[i]].push_back(i);\n\n    double temp_start = 500.0; \n    double temp_end = 0.1;\n    uniform_real_distribution<double> dist(0.0, 1.0);\n\n    long long sa_best_score = current_score;\n    vector<int> sa_best_parent = parent;\n\n    while (true) {\n        double elapsed = get_time() - start_time;\n        if (elapsed > time_limit) break;\n        \n        double progress = elapsed / time_limit;\n        double temp = temp_start * (1.0 - progress) + temp_end * progress;\n        \n        for (int iter = 0; iter < 300; ++iter) {\n            int v = rng() % N;\n            vector<int> neighbors = G[v];\n            shuffle(neighbors.begin(), neighbors.end(), rng);\n            \n            for (int u : neighbors) {\n                if (u == parent[v]) continue;\n                int curr = u;\n                while (curr != -1 && curr != v) curr = parent[curr];\n                if (curr == v) continue; \n                \n                int new_depth_v = depth[u] + 1;\n                if (new_depth_v > H) continue; \n                \n                int diff = new_depth_v - depth[v];\n                \n                long long sum_A = 0;\n                vector<int> stack; stack.push_back(v);\n                bool valid = true;\n                while (!stack.empty()) {\n                    int curr_node = stack.back(); stack.pop_back();\n                    if (depth[curr_node] + diff > H) { valid = false; break; }\n                    sum_A += A[curr_node];\n                    for (int c : children[curr_node]) stack.push_back(c);\n                }\n                if (!valid) continue;\n                \n                long long delta = (long long)diff * sum_A;\n                bool accept = false;\n                if (delta > 0) accept = true;\n                else if (exp((double)delta / temp) > dist(rng)) accept = true;\n                \n                if (accept) {\n                    int old_parent = parent[v];\n                    parent[v] = u; depth[v] = new_depth_v;\n                    if (old_parent != -1) {\n                        auto it = find(children[old_parent].begin(), children[old_parent].end(), v);\n                        if (it != children[old_parent].end()) children[old_parent].erase(it);\n                    }\n                    children[u].push_back(v);\n                    stack.push_back(v);\n                    while (!stack.empty()) {\n                        int curr_node = stack.back(); stack.pop_back();\n                        for (int c : children[curr_node]) { depth[c] += diff; stack.push_back(c); }\n                    }\n                    current_score += delta;\n                    \n                    if (current_score > sa_best_score) {\n                        sa_best_score = current_score;\n                        sa_best_parent = parent;\n                    }\n                    break;\n                }\n            }\n        }\n    }\n    \n    if (sa_best_score > best_score) {\n        best_score = sa_best_score;\n        best_parent = sa_best_parent;\n    }\n    return sa_best_score;\n}\n\nint main() {\n    double start_time = get_time();\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> H)) return 0;\n    A.resize(N); for (int i = 0; i < N; ++i) cin >> A[i];\n    G.resize(N);\n    for (int i = 0; i < M; ++i) { int u, v; cin >> u >> v; G[u].push_back(v); G[v].push_back(u); }\n    X.resize(N); Y.resize(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n    degree.resize(N);\n    for(int i=0; i<N; ++i) degree[i] = G[i].size();\n\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n\n    // Initial Best\n    auto [init_parent, init_score] = greedy_construct(indices, 0, true, 0);\n    best_parent = init_parent;\n    best_score = init_score;\n\n    vector<tuple<int, bool, int>> configs;\n    \n    // A based (Asc A + Deep)\n    for(int i=0; i<10; ++i) configs.push_back(make_tuple(0, true, 0));\n    \n    // A based (Asc A + Shallow) -> Chains\n    for(int i=0; i<10; ++i) configs.push_back(make_tuple(0, true, 1));\n    \n    // Desc A\n    configs.push_back(make_tuple(0, false, 0));\n    configs.push_back(make_tuple(0, false, 1));\n    \n    // Spatial\n    configs.push_back(make_tuple(1, true, 0));\n    configs.push_back(make_tuple(1, true, 1));\n    configs.push_back(make_tuple(1, false, 0));\n    configs.push_back(make_tuple(1, false, 1));\n    \n    configs.push_back(make_tuple(2, true, 0));\n    configs.push_back(make_tuple(2, true, 1));\n    configs.push_back(make_tuple(2, false, 0));\n    configs.push_back(make_tuple(2, false, 1));\n    \n    // Degree based\n    configs.push_back(make_tuple(3, true, 0));\n    configs.push_back(make_tuple(3, false, 0));\n    configs.push_back(make_tuple(3, true, 1));\n\n    int trial_idx = 0;\n    while (true) {\n        double elapsed = get_time() - start_time;\n        if (elapsed > 0.6) break;\n        if (trial_idx >= (int)configs.size()) break;\n\n        auto cfg = configs[trial_idx++];\n        int key = get<0>(cfg);\n        bool asc = get<1>(cfg);\n        int strat = get<2>(cfg);\n        \n        vector<int> order = indices;\n        shuffle(order.begin(), order.end(), rng);\n        \n        auto [parent, score] = greedy_construct(order, key, asc, strat);\n        vector<int> depth(N);\n        evaluate(parent, depth);\n        hill_climb(parent, depth, score);\n    }\n\n    // Phase 2: Simulated Annealing\n    if (best_parent.size() > 0 && is_valid(best_parent)) {\n        vector<int> sa_depth(N);\n        evaluate(best_parent, sa_depth);\n        double time_left = 1.95 - (get_time() - start_time);\n        if (time_left > 0.5) {\n            simulated_annealing(best_parent, sa_depth, best_score, time_left);\n        }\n    }\n\n    // Final Safety Check\n    if (!is_valid(best_parent)) {\n        // Fallback\n        auto [fb_parent, fb_score] = greedy_construct(indices, 0, true, 0);\n        best_parent = fb_parent;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << best_parent[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n};\n\nint N;\n\nvector<pair<char, int>> solve_board(const vector<string>& board_grid, bool is_transposed, float multiplier) {\n    vector<Point> onis;\n    vector<bool> removed; \n    vector<vector<bool>> clear_left, clear_right, clear_up, clear_down;\n\n    // Precompute clear paths\n    clear_left.assign(N, vector<bool>(N, false));\n    clear_right.assign(N, vector<bool>(N, false));\n    clear_up.assign(N, vector<bool>(N, false));\n    clear_down.assign(N, vector<bool>(N, false));\n\n    for (int i = 0; i < N; ++i) {\n        bool blocked = false;\n        for (int j = 0; j < N; ++j) {\n            int r = is_transposed ? j : i;\n            int c = is_transposed ? i : j;\n            if (board_grid[r][c] == 'o') blocked = true;\n            clear_left[i][j] = !blocked;\n        }\n        blocked = false;\n        for (int j = N - 1; j >= 0; --j) {\n            int r = is_transposed ? j : i;\n            int c = is_transposed ? i : j;\n            if (board_grid[r][c] == 'o') blocked = true;\n            clear_right[i][j] = !blocked;\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        bool blocked = false;\n        for (int i = 0; i < N; ++i) {\n            int r = is_transposed ? j : i;\n            int c = is_transposed ? i : j;\n            if (board_grid[r][c] == 'o') blocked = true;\n            clear_up[i][j] = !blocked;\n        }\n        blocked = false;\n        for (int i = N - 1; i >= 0; --i) {\n            int r = is_transposed ? j : i;\n            int c = is_transposed ? i : j;\n            if (board_grid[r][c] == 'o') blocked = true;\n            clear_down[i][j] = !blocked;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int r = is_transposed ? j : i;\n            int c = is_transposed ? i : j;\n            if (board_grid[r][c] == 'x') {\n                onis.push_back({i, j});\n            }\n        }\n    }\n\n    removed.assign(onis.size(), false);\n    vector<pair<char, int>> moves;\n\n    // --- PHASE 1: ROW REMOVALS ---\n    for (int r = 0; r < N; ++r) {\n        vector<pair<int, int>> segments;\n        int l = 0;\n        while (l < N) {\n            while (l < N) {\n                int r_grid = is_transposed ? l : r;\n                int c_grid = is_transposed ? r : l;\n                if (board_grid[r_grid][c_grid] == 'o') l++;\n                else break;\n            }\n            if (l >= N) break;\n            int rend = l;\n            while (rend < N) {\n                int r_grid = is_transposed ? rend : r;\n                int c_grid = is_transposed ? r : rend;\n                if (board_grid[r_grid][c_grid] != 'o') rend++;\n                else break;\n            }\n            segments.push_back({l, rend - 1});\n            l = rend;\n        }\n\n        for (auto seg : segments) {\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].r == r && onis[k].c >= seg.first && onis[k].c <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            \n            if (indices.empty()) continue;\n\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].c < onis[b].c;\n            });\n\n            int K = indices.size();\n            vector<int> cols(K);\n            vector<int> savings(K, 0);\n\n            for (int i = 0; i < K; ++i) {\n                int c = onis[indices[i]].c;\n                cols[i] = c;\n                \n                int cost_up = clear_up[r][c] ? 2 * (r + 1) : 2000000000;\n                int cost_down = clear_down[r][c] ? 2 * (N - r) : 2000000000;\n                \n                savings[i] = (int)(min(cost_up, cost_down) * multiplier);\n            }\n\n            vector<int> savings_prefix(K, 0);\n            for(int i=0; i<K; ++i) {\n                savings_prefix[i] = savings[i] + (i>0 ? savings_prefix[i-1] : 0);\n            }\n\n            vector<int> dp(K + 1, 2000000000); \n            vector<pair<int, int>> parent(K + 1, {-1, -1}); \n            dp[0] = 0;\n\n            for (int i = 1; i <= K; ++i) {\n                if (dp[i-1] < dp[i]) {\n                    dp[i] = dp[i-1];\n                    parent[i] = {i-1, -1};\n                }\n\n                for (int j = 1; j <= i; ++j) {\n                    int c_L = cols[j-1];\n                    int c_R = cols[i-1];\n\n                    int costL = 2 * (c_R + 1);\n                    if (!clear_left[r][c_R]) costL = 2000000000;\n\n                    int costR = 2 * (N - c_L);\n                    if (!clear_right[r][c_L]) costR = 2000000000;\n                    \n                    int sum_savings = savings_prefix[i-1] - (j >= 2 ? savings_prefix[j-2] : 0);\n\n                    if (costL < 1000000000) {\n                        int totalL = dp[j-1] + costL - sum_savings;\n                        if (totalL <= dp[i]) {\n                            dp[i] = totalL;\n                            parent[i] = {j-1, 0};\n                        }\n                    }\n                    \n                    if (costR < 1000000000) {\n                        int totalR = dp[j-1] + costR - sum_savings;\n                        if (totalR <= dp[i]) {\n                            dp[i] = totalR;\n                            parent[i] = {j-1, 1};\n                        }\n                    }\n                }\n            }\n\n            vector<pair<int, pair<int, int>>> intervals; \n            int curr = K;\n            while (curr > 0) {\n                int prev = parent[curr].first;\n                int type = parent[curr].second;\n                if (type == -1) {\n                    curr = prev;\n                } else {\n                    intervals.push_back({prev, {curr - 1, type}});\n                    curr = prev;\n                }\n            }\n            reverse(intervals.begin(), intervals.end());\n\n            for (auto iv : intervals) {\n                int s = iv.first;\n                int e = iv.second.first;\n                int type = iv.second.second;\n                \n                if (type == 0) { \n                    int bound = cols[e];\n                    for(int k=0; k<=bound; ++k) moves.push_back({'L', r});\n                    for(int k=0; k<=bound; ++k) moves.push_back({'R', r});\n                    for(int k=s; k<=e; ++k) removed[indices[k]] = true;\n                } else { \n                    int bound = cols[s];\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'R', r});\n                    for(int k=0; k < N-bound; ++k) moves.push_back({'L', r});\n                    for(int k=s; k<=e; ++k) removed[indices[k]] = true;\n                }\n            }\n        }\n    }\n\n    // --- PHASE 2: COLUMN REMOVALS ---\n    for (int c = 0; c < N; ++c) {\n        vector<pair<int, int>> segments;\n        int u = 0;\n        while (u < N) {\n            while (u < N) {\n                int r_grid = is_transposed ? c : u;\n                int c_grid = is_transposed ? u : c;\n                if (board_grid[r_grid][c_grid] == 'o') u++;\n                else break;\n            }\n            if (u >= N) break;\n            int d = u;\n            while (d < N) {\n                int r_grid = is_transposed ? c : d;\n                int c_grid = is_transposed ? d : c;\n                if (board_grid[r_grid][c_grid] != 'o') d++;\n                else break;\n            }\n            segments.push_back({u, d - 1});\n            u = d;\n        }\n\n        for (auto seg : segments) {\n            vector<int> indices;\n            for (size_t k = 0; k < onis.size(); ++k) {\n                if (!removed[k] && onis[k].c == c && onis[k].r >= seg.first && onis[k].r <= seg.second) {\n                    indices.push_back(k);\n                }\n            }\n            if (indices.empty()) continue;\n\n            sort(indices.begin(), indices.end(), [&](int a, int b) {\n                return onis[a].r < onis[b].r;\n            });\n\n            int K = indices.size();\n            vector<int> rows(K);\n            for (int i = 0; i < K; ++i) rows[i] = onis[indices[i]].r;\n\n            vector<int> dp(K, 1e9);\n            vector<pair<int, int>> choice(K, {-1, 0}); \n\n            for (int i = 0; i < K; ++i) {\n                for (int j = 0; j <= i; ++j) {\n                    int prev_cost = (j == 0) ? 0 : dp[j-1];\n                    \n                    int costU = 2000000000;\n                    if (clear_up[rows[i]][c]) {\n                        costU = prev_cost + 2 * (rows[i] + 1);\n                    }\n                    \n                    int costD = 2000000000;\n                    if (clear_down[rows[j]][c]) {\n                        costD = prev_cost + 2 * (N - rows[j]);\n                    }\n\n                    if (costU < dp[i]) {\n                        dp[i] = costU;\n                        choice[i] = {j - 1, 0};\n                    }\n\n                    if (costD < dp[i]) {\n                        dp[i] = costD;\n                        choice[i] = {j - 1, 1};\n                    }\n                }\n            }\n\n            int curr = K - 1;\n            while (curr >= 0) {\n                int prev = choice[curr].first;\n                int type = choice[curr].second;\n\n                if (type == 0) {\n                    int r_end = rows[curr];\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'U', c});\n                    for(int k=0; k<=r_end; ++k) moves.push_back({'D', c});\n                    for(int k=prev+1; k<=curr; ++k) removed[indices[k]] = true;\n                } else {\n                    int r_start = rows[prev + 1];\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'D', c});\n                    for(int k=0; k < N-r_start; ++k) moves.push_back({'U', c});\n                    for(int k=prev+1; k<=curr; ++k) removed[indices[k]] = true;\n                }\n                curr = prev;\n            }\n        }\n    }\n\n    return moves;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    vector<string> original_grid(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> original_grid[i];\n    }\n\n    vector<pair<char, int>> best_moves;\n    int min_size = 2000000000;\n\n    // Try Multipliers 1.15 and 1.2 with Dual Strategy (Row-First, Col-First)\n    for (float m : {1.15f, 1.2f}) {\n        // Row-First\n        vector<pair<char, int>> moves_r = solve_board(original_grid, false, m);\n        if ((int)moves_r.size() < min_size) {\n            min_size = moves_r.size();\n            best_moves = moves_r;\n        }\n\n        // Col-First (Transpose logic handled by flag)\n        vector<pair<char, int>> moves_c = solve_board(original_grid, true, m);\n        \n        // Remap moves back: L<->U, R<->D\n        // Since solve_board with is_transposed=true treats columns as rows,\n        // it emits L/R moves on \"virtual rows\" (which are actually columns).\n        // So if it says (L, 5), it means shift Column 5 Left (Up).\n        // Wait, the solver logic:\n        // Phase 1 shifts \"Rows\". If is_transposed, these are \"Real Columns\".\n        // Shifting a Real Column Up/Down is valid.\n        // The solver generates L/R. \n        // In transposed view, L is shifting \"Row 0\" to \"Left\". \n        // \"Row 0\" is \"Col 0\" of real grid. \n        // \"Left\" is \"Up\" in real grid.\n        // So (L, c) in transposed -> (U, c) in real.\n        // (R, c) in transposed -> (D, c) in real.\n        // Phase 2 shifts \"Cols\". If is_transposed, these are \"Real Rows\".\n        // The solver generates U/D.\n        // Shifting \"Real Row\" Left/Right.\n        // (U, r) in transposed -> (L, r) in real.\n        // (D, r) in transposed -> (R, r) in real.\n\n        for (auto& m : moves_c) {\n            char d = m.first;\n            int p = m.second;\n            if (d == 'L') m.first = 'U';\n            else if (d == 'R') m.first = 'D';\n            else if (d == 'U') m.first = 'L';\n            else if (d == 'D') m.first = 'R';\n        }\n\n        if ((int)moves_c.size() < min_size) {\n            min_size = moves_c.size();\n            best_moves = moves_c;\n        }\n    }\n\n    for (auto m : best_moves) {\n        cout << m.first << \" \" << m.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <random>\n#include <algorithm>\n#include <numeric>\n#include <array>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nmt19937 rng(0);\n\n// Simulation function: returns error and populates cnt\ninline long long simulate(const vector<int>& a, const vector<int>& b, const vector<int>& T, int cnt[N]) {\n    for(int i=0; i<N; ++i) cnt[i] = 0;\n    \n    int cur = 0;\n    cnt[0]++;\n    for (int i = 1; i < L; ++i) {\n        cur = (cnt[cur] & 1) ? a[cur] : b[cur];\n        cnt[cur]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs((long long)cnt[i] - T[i]);\n    }\n    return error;\n}\n\nvoid solve() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_input, l_input;\n    cin >> n_input >> l_input;\n    \n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> global_best_a(N), global_best_b(N);\n    long long global_best_error = 1e18;\n\n    // --- Phase 1: Greedy Construction ---\n    // Reduced iterations to ensure Phase 3 has enough time.\n    const int GREEDY_ITERS = 1500; \n    const int POOL_SIZE = 50;\n    const int REFINE_COUNT = 3;\n    const int REFINE_PASSES = 40;\n\n    struct Solution {\n        vector<int> a, b;\n        long long heuristic_error;\n    };\n    \n    vector<Solution> pool;\n\n    for (int t = 0; t < GREEDY_ITERS; ++t) {\n        vector<int> a(N), b(N);\n        long long assigned[N]; \n        for(int i=0; i<N; ++i) assigned[i] = 0;\n        \n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        \n        for (int x : order) {\n            int base_odd = (T[x] + 1) / 2;\n            int base_even = T[x] / 2;\n            \n            // Reduced noise range slightly for stability, or keep it.\n            int noise = (rng() % 5) - 2; \n            int w_odd = max(0, base_odd + noise);\n            if (w_odd > T[x]) w_odd = T[x];\n            int w_even = T[x] - w_odd; \n\n            auto pick = [&](int w) {\n                long long min_c = 1e18;\n                for(int y=0; y<N; ++y) {\n                    long long c = abs(assigned[y] + w - T[y]);\n                    if(c < min_c) min_c = c;\n                }\n                \n                long long limit = min_c + 20; \n                vector<int> cands;\n                for(int y=0; y<N; ++y) {\n                    long long c = abs(assigned[y] + w - T[y]);\n                    if(c <= limit) cands.push_back(y);\n                }\n                return cands[rng() % cands.size()];\n            };\n            \n            int t1 = pick(w_odd);\n            a[x] = t1;\n            assigned[t1] += w_odd;\n            \n            int t2 = pick(w_even);\n            b[x] = t2;\n            assigned[t2] += w_even;\n        }\n\n        long long h_err = 0;\n        for(int i=0; i<N; ++i) h_err += abs(assigned[i] - T[i]);\n\n        if (pool.size() < POOL_SIZE) {\n            pool.push_back({a, b, h_err});\n        } else {\n            int worst_idx = 0;\n            long long worst_h_err = pool[0].heuristic_error;\n            for(int i=1; i<pool.size(); ++i) {\n                if(pool[i].heuristic_error > worst_h_err) {\n                    worst_h_err = pool[i].heuristic_error;\n                    worst_idx = i;\n                }\n            }\n            if (h_err < worst_h_err) {\n                pool[worst_idx] = {a, b, h_err};\n            }\n        }\n    }\n\n    // --- Phase 2: Simulation and Filtering ---\n    for(auto& sol : pool) {\n        int cnt[N];\n        sol.heuristic_error = simulate(sol.a, sol.b, T, cnt);\n    }\n    \n    sort(pool.begin(), pool.end(), [](const Solution& s1, const Solution& s2){\n        return s1.heuristic_error < s2.heuristic_error;\n    });\n\n    if(pool.size() > REFINE_COUNT) pool.resize(REFINE_COUNT);\n\n    // --- Phase 3: Optimized Local Search ---\n    for(auto& sol : pool) {\n        int cnt[N];\n        long long cur_err = simulate(sol.a, sol.b, T, cnt);\n        \n        auto get_flow = [&](int u) -> pair<long long, long long> {\n            return {(cnt[u] + 1) / 2, cnt[u] / 2};\n        };\n\n        for (int pass = 0; pass < REFINE_PASSES; ++pass) {\n            long long assigned[N];\n            for(int i=0; i<N; ++i) assigned[i] = 0;\n            for(int u=0; u<N; ++u) {\n                auto f = get_flow(u);\n                assigned[sol.a[u]] += f.first;\n                assigned[sol.b[u]] += f.second;\n            }\n\n            // Use Shuffle instead of Sort to reduce overhead and maintain diversity\n            vector<int> node_order(N);\n            iota(node_order.begin(), node_order.end(), 0);\n            shuffle(node_order.begin(), node_order.end(), rng);\n            \n            for (int u : node_order) {\n                if (cnt[u] == 0) continue;\n                auto flow = get_flow(u);\n                \n                // --- Single Variable Change ---\n                // Optimize a[u]\n                {\n                    int old_target = sol.a[u];\n                    long long best_delta = 0;\n                    int best_target = old_target;\n                    \n                    for (int v = 0; v < N; ++v) {\n                        if (v == old_target) continue;\n                        long long delta = \n                            abs(assigned[old_target] - flow.first - T[old_target]) - abs(assigned[old_target] - T[old_target]) +\n                            abs(assigned[v] + flow.first - T[v]) - abs(assigned[v] - T[v]);\n                        \n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_target = v;\n                        }\n                    }\n                    \n                    if (best_delta < 0) {\n                        assigned[old_target] -= flow.first;\n                        assigned[best_target] += flow.first;\n                        sol.a[u] = best_target;\n                    }\n                }\n\n                // Optimize b[u]\n                {\n                    int old_target = sol.b[u];\n                    long long best_delta = 0;\n                    int best_target = old_target;\n                    \n                    for (int v = 0; v < N; ++v) {\n                        if (v == old_target) continue;\n                        long long delta = \n                            abs(assigned[old_target] - flow.second - T[old_target]) - abs(assigned[old_target] - T[old_target]) +\n                            abs(assigned[v] + flow.second - T[v]) - abs(assigned[v] - T[v]);\n                        \n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_target = v;\n                        }\n                    }\n                    \n                    if (best_delta < 0) {\n                        assigned[old_target] -= flow.second;\n                        assigned[best_target] += flow.second;\n                        sol.b[u] = best_target;\n                    }\n                }\n\n                // --- Random Swap Moves ---\n                // Try swapping with 3 random neighbors instead of top 5 to save time\n                for (int k = 0; k < 3; ++k) {\n                    int w = rng() % N;\n                    if (u == w) continue;\n                    auto flow_w = get_flow(w);\n                    \n                    // Swap a[u] with a[w]\n                    {\n                        int v1 = sol.a[u];\n                        int v2 = sol.a[w];\n                        \n                        if (v1 != v2) {\n                            long long old_contrib = \n                                abs(assigned[v1] - T[v1]) + abs(assigned[v2] - T[v2]);\n                            long long new_contrib = \n                                abs(assigned[v1] - flow.first + flow_w.first - T[v1]) + \n                                abs(assigned[v2] - flow_w.first + flow.first - T[v2]);\n                            \n                            if (new_contrib < old_contrib) {\n                                assigned[v1] -= flow.first;\n                                assigned[v2] -= flow_w.first;\n                                sol.a[u] = v2;\n                                sol.a[w] = v1;\n                                assigned[v2] += flow.first;\n                                assigned[v1] += flow_w.first;\n                            }\n                        }\n                    }\n                    \n                    // Swap b[u] with b[w]\n                    {\n                        int v1 = sol.b[u];\n                        int v2 = sol.b[w];\n                        if (v1 != v2) {\n                            long long old_contrib = \n                                abs(assigned[v1] - T[v1]) + abs(assigned[v2] - T[v2]);\n                            long long new_contrib = \n                                abs(assigned[v1] - flow.second + flow_w.second - T[v1]) + \n                                abs(assigned[v2] - flow_w.second + flow.second - T[v2]);\n                            \n                            if (new_contrib < old_contrib) {\n                                assigned[v1] -= flow.second;\n                                assigned[v2] -= flow_w.second;\n                                sol.b[u] = v2;\n                                sol.b[w] = v1;\n                                assigned[v2] += flow.second;\n                                assigned[v1] += flow_w.second;\n                            }\n                        }\n                    }\n                }\n                \n                // Swap a[u] and b[u]\n                {\n                     int v1 = sol.a[u];\n                     int v2 = sol.b[u];\n                     if (v1 != v2) {\n                         long long old_contrib = \n                            abs(assigned[v1] - T[v1]) + abs(assigned[v2] - T[v2]);\n                        long long new_contrib = \n                            abs(assigned[v1] - flow.first + flow.second - T[v1]) + \n                            abs(assigned[v2] - flow.second + flow.first - T[v2]);\n                        \n                        if (new_contrib < old_contrib) {\n                            assigned[v1] -= flow.first;\n                            assigned[v2] -= flow.second;\n                            sol.a[u] = v2;\n                            sol.b[u] = v1;\n                            assigned[v2] += flow.first;\n                            assigned[v1] += flow.second;\n                        }\n                     }\n                }\n            }\n            \n            long long new_err = simulate(sol.a, sol.b, T, cnt);\n            cur_err = new_err;\n            \n            if (cur_err < global_best_error) {\n                global_best_error = cur_err;\n                global_best_a = sol.a;\n                global_best_b = sol.b;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << global_best_a[i] << \" \" << global_best_b[i] << \"\\n\";\n    }\n}\n\nint main() {\n    solve();\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <climits>\n\nusing namespace std;\n\n// DSU implementation\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (rank_[x] < rank_[y]) swap(x, y);\n        parent[y] = x;\n        if (rank_[x] == rank_[y]) rank_[x]++;\n        return true;\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<double> cx, cy;\nvector<int> city_to_group; \n\nint estimated_dist(int i, int j) {\n    double dx = cx[i] - cx[j];\n    double dy = cy[i] - cy[j];\n    return (int)floor(sqrt(dx*dx + dy*dy));\n}\n\nvector<pair<int, int>> ask_query(const vector<int>& cities) {\n    cout << \"? \" << cities.size();\n    for (int c : cities) cout << \" \" << c;\n    cout << endl;\n    cout.flush();\n    \n    vector<pair<int, int>> edges;\n    for (size_t i = 0; i < cities.size() - 1; ++i) {\n        int u, v;\n        cin >> u >> v;\n        if (u > v) swap(u, v);\n        edges.emplace_back(u, v);\n    }\n    return edges;\n}\n\nvoid solve() {\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    cx.resize(N); cy.resize(N);\n    city_to_group.resize(N);\n    \n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2.0;\n        cy[i] = (ly[i] + ry[i]) / 2.0;\n    }\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (cx[i] != cx[j]) return cx[i] < cx[j];\n        return cy[i] < cy[j];\n    });\n    \n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        groups[k].resize(G[k]);\n        for (int i = 0; i < G[k]; ++i) {\n            int city = order[idx++];\n            groups[k][i] = city;\n            city_to_group[city] = k;\n        }\n        sort(groups[k].begin(), groups[k].end(), [&](int i, int j) {\n            if (cx[i] != cx[j]) return cx[i] < cx[j];\n            return cy[i] < cy[j];\n        });\n    }\n\n    set<pair<int, int>> known_edges;\n    int queries_remaining = Q;\n\n    // Phase 1\n    for (int k = 0; k < M; ++k) {\n        if (queries_remaining <= 0) break;\n        int sz = groups[k].size();\n        \n        if (sz >= 2 && sz <= L) {\n            vector<int> subset(groups[k].begin(), groups[k].end());\n            auto res = ask_query(subset);\n            queries_remaining--;\n            for (auto& e : res) known_edges.insert(e);\n        } else if (sz > L) {\n            int stride = (sz <= 2 * L) ? 1 : max(1, L / 2);\n            \n            for (int i = 0; i <= sz - L && queries_remaining > 0; i += stride) {\n                vector<int> subset(groups[k].begin() + i, groups[k].begin() + i + L);\n                auto res = ask_query(subset);\n                queries_remaining--;\n                for (auto& e : res) known_edges.insert(e);\n            }\n        }\n    }\n\n    // Phase 2\n    if (queries_remaining > Q / 10) { \n        vector<int> large_group_indices;\n        for (int k = 0; k < M; ++k) {\n            if (groups[k].size() > 2 * L) {\n                large_group_indices.push_back(k);\n            }\n        }\n        sort(large_group_indices.begin(), large_group_indices.end(), [&](int a, int b) {\n            return groups[a].size() > groups[b].size();\n        });\n        \n        for (int k : large_group_indices) {\n            // Stop if we have very few queries left (safety margin)\n            if (queries_remaining <= 5) break; \n            \n            int sz = groups[k].size();\n            int prev_stride = max(1, L / 2);\n            int target_stride = max(1, L / 4);\n            \n            for (int i = 0; i <= sz - L && queries_remaining > 5; i += target_stride) {\n                if (i % prev_stride != 0) {\n                    vector<int> subset(groups[k].begin() + i, groups[k].begin() + i + L);\n                    auto res = ask_query(subset);\n                    queries_remaining--;\n                    for (auto& e : res) known_edges.insert(e);\n                }\n            }\n        }\n    }\n\n    vector<vector<pair<int, int>>> answer_edges(M);\n    \n    for (int k = 0; k < M; ++k) {\n        auto& vec = groups[k];\n        int sz = vec.size();\n        if (sz <= 1) continue;\n        \n        vector<tuple<int, int, int, int, int>> candidates;\n        \n        for (auto& e : known_edges) {\n            if (city_to_group[e.first] == k && city_to_group[e.second] == k) {\n                int d = estimated_dist(e.first, e.second);\n                auto it_u = find(vec.begin(), vec.end(), e.first);\n                auto it_v = find(vec.begin(), vec.end(), e.second);\n                if (it_u != vec.end() && it_v != vec.end()) {\n                    int idx_u = distance(vec.begin(), it_u);\n                    int idx_v = distance(vec.begin(), it_v);\n                    int idx_diff = abs(idx_u - idx_v);\n                    candidates.push_back({0, d, idx_diff, e.first, e.second});\n                }\n            }\n        }\n        \n        // Spatial Pruning: Only consider estimated edges to nearest 50 neighbors\n        // This drastically reduces candidates for large groups and improves signal-to-noise ratio\n        for (int i = 0; i < sz; ++i) {\n            for (int j = i + 1; j < sz && j < i + 50; ++j) {\n                int u = vec[i];\n                int v = vec[j];\n                if (u > v) swap(u, v);\n                if (known_edges.count({u, v})) continue;\n                int d = estimated_dist(u, v);\n                candidates.push_back({1, d, j - i, u, v});\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end());\n        \n        map<int, int> local_id;\n        for(int i=0; i<sz; ++i) local_id[vec[i]] = i;\n        \n        DSU dsu(sz);\n        int edges_needed = sz - 1;\n        \n        for (auto& item : candidates) {\n            int u = get<3>(item);\n            int v = get<4>(item);\n            int uid = local_id[u];\n            int vid = local_id[v];\n            if (dsu.unite(uid, vid)) {\n                answer_edges[k].push_back({u, v});\n                if (answer_edges[k].size() == edges_needed) break;\n            }\n        }\n    }\n    \n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (size_t i = 0; i < groups[k].size(); ++i) {\n            cout << groups[k][i] << (i == groups[k].size() - 1 ? \"\" : \" \");\n        }\n        cout << endl;\n        for (auto& e : answer_edges[k]) {\n            cout << e.first << \" \" << e.second << endl;\n        }\n    }\n    cout.flush();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    solve();\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nstruct Point {\n    int x;\n    int y;\n};\n\nint N, M;\nvector<Point> targets;\n\nvector<pair<char, char>> actions;\n\nvoid add_action(char a, char d) {\n    actions.push_back({a, d});\n}\n\nvoid add_move(char d, int steps) {\n    for (int i = 0; i < steps; ++i) {\n        add_action('M', d);\n    }\n}\n\nbool isCorner(Point p) {\n    return (p.x == 0 || p.x == N - 1) && (p.y == 0 || p.y == N - 1);\n}\n\nstruct Strategy {\n    int cost;\n    int type; // 0=Walk, 1=Slide U, 2=Slide D, 3=Slide L, 4=Slide R, 5=Corner 1-slide, 6=Corner 2-slide\n    char dir;\n    Point slide_dest; // Relevant for Corner 2-slide to know where to stop\n\n    bool operator<(const Strategy& other) const {\n        return cost < other.cost;\n    }\n};\n\nconst int INF = 1000000000;\n\nStrategy evaluate_strategy(Point cur, Point target, int type) {\n    int dx = abs(cur.x - target.x);\n    int dy = abs(cur.y - target.y);\n    \n    if (type == 0) { // Walk\n        return {dx + dy, 0, ' ', target};\n    }\n    else if (type == 1) { // Slide Up\n        if (cur.y <= target.y) return {INF, 1, 'U', target};\n        int cost = dx + 1 + target.y;\n        return {cost, 1, 'U', target};\n    }\n    else if (type == 2) { // Slide Down\n        if (cur.y >= target.y) return {INF, 2, 'D', target};\n        int cost = dx + 1 + (N - 1 - target.y);\n        return {cost, 2, 'D', target};\n    }\n    else if (type == 3) { // Slide Left\n        if (cur.x <= target.x) return {INF, 3, 'L', target};\n        int cost = dy + 1 + target.x;\n        return {cost, 3, 'L', target};\n    }\n    else if (type == 4) { // Slide Right\n        if (cur.x >= target.x) return {INF, 4, 'R', target};\n        int cost = dy + 1 + (N - 1 - target.x);\n        return {cost, 4, 'R', target};\n    }\n    return {INF, 0, ' ', target};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    targets.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int r, c;\n        cin >> r >> c;\n        targets[i].x = c;\n        targets[i].y = r;\n    }\n\n    Point cur = targets[0];\n\n    for (int k = 1; k < M; ++k) {\n        Point target = targets[k];\n        \n        Strategy best = {INF, 0, ' ', target};\n        \n        // Standard Strategies\n        best = min(best, evaluate_strategy(cur, target, 0));\n        best = min(best, evaluate_strategy(cur, target, 1));\n        best = min(best, evaluate_strategy(cur, target, 2));\n        best = min(best, evaluate_strategy(cur, target, 3));\n        best = min(best, evaluate_strategy(cur, target, 4));\n\n        // Corner Strategies\n        if (isCorner(target)) {\n            // Strategy: Single slide if aligned\n            if (cur.x == target.x) {\n                int cost = 1;\n                if (cur.y == target.y) cost = 0; // Already there\n                char d = (cur.y > target.y) ? 'U' : 'D';\n                best = min(best, {cost, 5, d, target});\n            } else if (cur.y == target.y) {\n                int cost = 1;\n                char d = (cur.x > target.x) ? 'L' : 'R';\n                best = min(best, {cost, 5, d, target});\n            } else {\n                // Strategy: 2-turn corner hop (e.g., Slide U then Slide R)\n                // Valid if we are not on the same row or col, and not already there.\n                // Cost is always 2.\n                best = min(best, {2, 6, ' ', target});\n            }\n        }\n\n        // Tie-breaking: Prefer Walk if costs equal\n        if (best.cost == evaluate_strategy(cur, target, 0).cost && best.type != 0) {\n            best.type = 0;\n        }\n\n        // Execution\n        int dx = target.x - cur.x;\n        int dy = target.y - cur.y;\n\n        if (best.type == 0) {\n            if (dx > 0) add_move('R', dx);\n            else if (dx < 0) add_move('L', -dx);\n            if (dy > 0) add_move('D', dy);\n            else if (dy < 0) add_move('U', -dy);\n        }\n        else if (best.type == 1) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'U');\n            add_move('D', target.y);\n        }\n        else if (best.type == 2) {\n            if (cur.x < target.x) add_move('R', target.x - cur.x);\n            else if (cur.x > target.x) add_move('L', cur.x - target.x);\n            add_action('S', 'D');\n            add_move('U', N - 1 - target.y);\n        }\n        else if (best.type == 3) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'L');\n            add_move('R', target.x);\n        }\n        else if (best.type == 4) {\n            if (cur.y < target.y) add_move('D', target.y - cur.y);\n            else if (cur.y > target.y) add_move('U', cur.y - target.y);\n            add_action('S', 'R');\n            add_move('L', N - 1 - target.x);\n        }\n        else if (best.type == 5) {\n            // Aligned corner slide\n            add_action('S', best.dir);\n        }\n        else if (best.type == 6) {\n            // 2-turn corner hop\n            // We need to slide to the adjacent edge, then slide to the corner.\n            // Order: Slide towards y=0 or y=N-1 (perpendicular to target's y-edge), then x.\n            // Or x then y.\n            // Let's align Y first.\n            char d1, d2;\n            if (target.y == 0) d1 = 'U';\n            else d1 = 'D'; // target.y == N-1\n            \n            if (target.x == N-1) d2 = 'R';\n            else d2 = 'L'; // target.x == 0\n\n            add_action('S', d1);\n            add_action('S', d2);\n        }\n\n        cur = target;\n    }\n\n    for (const auto& act : actions) {\n        cout << act.first << \" \" << act.second << \"\\n\";\n    }\n\n    return 0;\n}"}}}