{"model_name":"gemini-3-pro-preview-high","codes":{"1":{"ahc001":"/**\n * Solution for AtCoder Heuristic Contest 001\n * Algorithm: Randomized Recursive Space Partitioning (k-d tree style) with Area Optimization\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\n// Time limit configuration\nconst double TIME_LIMIT = 4.85; \nauto start_time = chrono::high_resolution_clock::now();\n\n// Function to get elapsed time in seconds\ndouble get_elapsed_time() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nstruct Point {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nint N;\nvector<Point> points;\nvector<Rect> best_rects;\ndouble best_score = -1.0;\n\nvector<Rect> current_rects;\nmt19937 rng(12345);\n\n// Compute the raw score based on problem statement\ndouble compute_score(const vector<Rect>& rects) {\n    double score_sum = 0;\n    for(int i=0; i<N; ++i) {\n        long long w = rects[i].x2 - rects[i].x1;\n        long long h = rects[i].y2 - rects[i].y1;\n        double s = (double)w * h;\n        double r = points[i].r;\n        \n        if (s == 0) continue; \n        \n        // Verify point inclusion (sanity check)\n        if (rects[i].x1 > points[i].x || rects[i].x2 <= points[i].x ||\n            rects[i].y1 > points[i].y || rects[i].y2 <= points[i].y) {\n            return 0;\n        }\n        \n        double val = min(r, s) / max(r, s);\n        score_sum += 1.0 - (1.0 - val) * (1.0 - val);\n    }\n    return 1e9 * score_sum / N;\n}\n\n// Structure to hold split candidate information\nstruct Candidate {\n    int axis; // 0: x-axis (vertical cut), 1: y-axis (horizontal cut)\n    int cut_pos;\n    double cost;\n};\n\n// Recursive function to build the partition tree\nvoid build(const vector<int>& p_idxs, Rect r) {\n    // Base case: single point\n    if (p_idxs.size() == 1) {\n        current_rects[points[p_idxs[0]].id] = r;\n        return;\n    }\n\n    long long total_r = 0;\n    for(int idx : p_idxs) total_r += points[idx].r;\n\n    vector<Candidate> candidates;\n    candidates.reserve(p_idxs.size() * 2);\n\n    // We copy indices to sort them for splitting analysis\n    vector<int> sorted = p_idxs;\n    \n    // --- Try X splits (Vertical cuts) ---\n    sort(sorted.begin(), sorted.end(), [](int a, int b){\n        return points[a].x < points[b].x;\n    });\n    \n    long long current_r = 0;\n    for(size_t i=0; i<sorted.size()-1; ++i) {\n        current_r += points[sorted[i]].r;\n        // The split line must be > max x of left set and <= min x of right set\n        int max_l = points[sorted[i]].x;\n        int min_r = points[sorted[i+1]].x;\n        \n        if (max_l < min_r) {\n            // Ideal position based on area ratio\n            double target_ratio = (double)current_r / total_r;\n            double ideal_x = r.x1 + (r.x2 - r.x1) * target_ratio;\n            \n            // Clamp to valid integer range\n            int pos = round(ideal_x);\n            int valid_min = max_l + 1;\n            int valid_max = min_r;\n            pos = max(valid_min, min(valid_max, pos));\n            \n            double cost = abs(pos - ideal_x);\n            candidates.push_back({0, pos, cost});\n        }\n    }\n\n    // --- Try Y splits (Horizontal cuts) ---\n    sort(sorted.begin(), sorted.end(), [](int a, int b){\n        return points[a].y < points[b].y;\n    });\n    \n    current_r = 0;\n    for(size_t i=0; i<sorted.size()-1; ++i) {\n        current_r += points[sorted[i]].r;\n        int max_l = points[sorted[i]].y;\n        int min_r = points[sorted[i+1]].y;\n        \n        if (max_l < min_r) {\n            double target_ratio = (double)current_r / total_r;\n            double ideal_y = r.y1 + (r.y2 - r.y1) * target_ratio;\n            \n            int pos = round(ideal_y);\n            int valid_min = max_l + 1;\n            int valid_max = min_r;\n            pos = max(valid_min, min(valid_max, pos));\n            \n            double cost = abs(pos - ideal_y);\n            candidates.push_back({1, pos, cost});\n        }\n    }\n    \n    // Fallback for extremely degenerate cases (should not be reached with distinct points)\n    if (candidates.empty()) {\n        return;\n    }\n\n    // --- Selection Strategy ---\n    // Sort candidates by cost (lower is better)\n    sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n        return a.cost < b.cost;\n    });\n    \n    // Pick from top K best candidates to introduce randomness\n    int K = 4; \n    int n_cand = candidates.size();\n    int limit = min(n_cand, K);\n    \n    uniform_int_distribution<int> dist(0, limit - 1);\n    int choice = dist(rng);\n    \n    // Occasionally pick completely random valid cut to escape local optima\n    if (uniform_real_distribution<double>(0,1)(rng) < 0.01) {\n        uniform_int_distribution<int> dist_all(0, n_cand - 1);\n        choice = dist_all(rng);\n    }\n    \n    Candidate best = candidates[choice];\n    \n    // Split points and recurse\n    vector<int> set_l, set_r;\n    set_l.reserve(p_idxs.size()); \n    set_r.reserve(p_idxs.size());\n\n    if (best.axis == 0) { // Vertical cut\n        for(int idx : p_idxs) {\n            if (points[idx].x < best.cut_pos) set_l.push_back(idx);\n            else set_r.push_back(idx);\n        }\n        build(set_l, {r.x1, r.y1, best.cut_pos, r.y2});\n        build(set_r, {best.cut_pos, r.y1, r.x2, r.y2});\n    } else { // Horizontal cut\n        for(int idx : p_idxs) {\n            if (points[idx].y < best.cut_pos) set_l.push_back(idx);\n            else set_r.push_back(idx);\n        }\n        build(set_l, {r.x1, r.y1, r.x2, best.cut_pos});\n        build(set_r, {r.x1, best.cut_pos, r.x2, r.y2});\n    }\n}\n\n// Post-processing: Shrink rectangles that are larger than desired area\nvoid optimize_rects(vector<Rect>& rects) {\n    for(int i=0; i<N; ++i) {\n        long long w = rects[i].x2 - rects[i].x1;\n        long long h = rects[i].y2 - rects[i].y1;\n        long long s = w * h;\n        long long r = points[i].r;\n        \n        // Only shrink if actual area is larger than desired\n        if (s <= r) continue;\n        \n        // Iteratively reduce dimensions while keeping the point inside\n        while (s > r) {\n            bool moved = false;\n            // Heuristic: try to reduce the larger dimension first to maintain aspect ratio\n            bool reduce_w = (rects[i].x2 - rects[i].x1) > (rects[i].y2 - rects[i].y1);\n            \n            // Try preferred dimension first\n            if (reduce_w) {\n                 int dist_l = points[i].x - rects[i].x1;\n                 int dist_r = rects[i].x2 - 1 - points[i].x;\n                 // Trim from the side further from the point\n                 if (dist_l > dist_r) {\n                     if (rects[i].x1 < points[i].x) { rects[i].x1++; moved=true; }\n                     else if (dist_r > 0) { rects[i].x2--; moved=true; }\n                 } else {\n                     if (rects[i].x2 - 1 > points[i].x) { rects[i].x2--; moved=true; }\n                     else if (dist_l > 0) { rects[i].x1++; moved=true; }\n                 }\n            } else {\n                 int dist_t = points[i].y - rects[i].y1;\n                 int dist_b = rects[i].y2 - 1 - points[i].y;\n                 if (dist_t > dist_b) {\n                     if (rects[i].y1 < points[i].y) { rects[i].y1++; moved=true; }\n                     else if (dist_b > 0) { rects[i].y2--; moved=true; }\n                 } else {\n                     if (rects[i].y2 - 1 > points[i].y) { rects[i].y2--; moved=true; }\n                     else if (dist_t > 0) { rects[i].y1++; moved=true; }\n                 }\n            }\n            \n            // If preferred failed, try the other dimension\n            if (!moved) {\n                reduce_w = !reduce_w;\n                if (reduce_w) {\n                     int dist_l = points[i].x - rects[i].x1;\n                     int dist_r = rects[i].x2 - 1 - points[i].x;\n                     if (dist_l > dist_r) {\n                         if (rects[i].x1 < points[i].x) { rects[i].x1++; moved=true; }\n                         else if (dist_r > 0) { rects[i].x2--; moved=true; }\n                     } else {\n                         if (rects[i].x2 - 1 > points[i].x) { rects[i].x2--; moved=true; }\n                         else if (dist_l > 0) { rects[i].x1++; moved=true; }\n                     }\n                } else {\n                     int dist_t = points[i].y - rects[i].y1;\n                     int dist_b = rects[i].y2 - 1 - points[i].y;\n                     if (dist_t > dist_b) {\n                         if (rects[i].y1 < points[i].y) { rects[i].y1++; moved=true; }\n                         else if (dist_b > 0) { rects[i].y2--; moved=true; }\n                     } else {\n                         if (rects[i].y2 - 1 > points[i].y) { rects[i].y2--; moved=true; }\n                         else if (dist_t > 0) { rects[i].y1++; moved=true; }\n                     }\n                }\n            }\n            \n            if (!moved) break; // Cannot shrink further due to point constraints\n            \n            w = rects[i].x2 - rects[i].x1;\n            h = rects[i].y2 - rects[i].y1;\n            s = w * h;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if (!(cin >> N)) return 0;\n    \n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y >> points[i].r;\n    }\n    \n    best_rects.resize(N);\n    current_rects.resize(N);\n    \n    // Initial list of point indices\n    vector<int> p_indices(N);\n    iota(p_indices.begin(), p_indices.end(), 0);\n    \n    int iterations = 0;\n    \n    // Monte Carlo loop\n    while(get_elapsed_time() < TIME_LIMIT) {\n        iterations++;\n        \n        // Build a random valid partition\n        build(p_indices, {0, 0, 10000, 10000});\n        \n        // Shrink rectangles that are too big\n        optimize_rects(current_rects);\n        \n        // Evaluate\n        double score = compute_score(current_rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = current_rects;\n        }\n    }\n    \n    // Output results\n    for(int i=0; i<N; ++i) {\n        cout << best_rects[i].x1 << \" \" << best_rects[i].y1 << \" \" \n             << best_rects[i].x2 << \" \" << best_rects[i].y2 << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst int H = 50;\nconst int W_GRID = 50;\nconst int MAX_TILES = 2500;\nconst int BEAM_WIDTH = 3000; // Beam width adjusted for 2.0s time limit\nconst int MAX_PER_CELL = 4;  // Diversity constraint: max states per cell\nconst double TIME_LIMIT = 1.9; // Safety margin\n\n// Grid Data\nint si, sj;\nint tiles[H][W_GRID];\nint points[H][W_GRID];\n\n// Directions: U, D, L, R\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dchar[4] = {'U', 'D', 'L', 'R'};\n\n// Tree node to reconstruct the path efficiently\nstruct TreeNode {\n    int parent_idx; // Index in the global tree vector\n    char move_char;\n};\n// Global tree to avoid copy overhead. Pre-allocated.\nvector<TreeNode> tree;\n\n// Beam Search State\nstruct State {\n    int coord; // encoded as r * 50 + c\n    int score;\n    int tree_idx; // Index of the last node in the tree\n    bitset<MAX_TILES> visited;\n};\n\n// Time management\nchrono::system_clock::time_point start_time;\nbool check_time() {\n    auto now = chrono::system_clock::now();\n    double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0;\n    return elapsed < TIME_LIMIT;\n}\n\n// Helper for pruning: stores score and index in the candidate list\nstruct CellCand {\n    int score;\n    int candidate_idx;\n};\n// Buckets for filtering top K states per cell\n// Using static/global to avoid reallocation\nvector<CellCand> top_candidates[2500];\n\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::system_clock::now();\n\n    if (!(cin >> si >> sj)) return 0;\n\n    int max_t = 0;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> tiles[i][j];\n            max_t = max(max_t, tiles[i][j]);\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> points[i][j];\n        }\n    }\n\n    // Memory reservations\n    // Tree can grow up to (Number of generated candidates across all steps)\n    // Estimate: 3000 * 4 * 1500 ~ 18M. 20M is safe.\n    tree.reserve(20000000); \n    for(int i=0; i<2500; ++i) top_candidates[i].reserve(MAX_PER_CELL + 1);\n\n    vector<State> current_beam;\n    current_beam.reserve(BEAM_WIDTH);\n\n    // Initial State\n    State start_state;\n    start_state.coord = si * W_GRID + sj;\n    start_state.score = points[si][sj];\n    start_state.tree_idx = -1; // Root of the tree\n    start_state.visited.set(tiles[si][sj]);\n\n    current_beam.push_back(start_state);\n\n    int best_score = start_state.score;\n    int best_end_tree_idx = -1;\n\n    // Buffers for next step\n    vector<State> next_candidates;\n    next_candidates.reserve(BEAM_WIDTH * 4);\n    \n    vector<int> touched_cells;\n    touched_cells.reserve(BEAM_WIDTH * 4);\n    \n    vector<int> survivor_indices;\n    survivor_indices.reserve(BEAM_WIDTH * 4);\n\n    // Main Beam Search Loop\n    for (int step = 0; step < MAX_TILES; ++step) {\n        if (current_beam.empty()) break;\n        // Check time periodically\n        if ((step & 31) == 0 && !check_time()) break;\n\n        next_candidates.clear();\n        touched_cells.clear();\n        \n        // 1. Expand States\n        for (const auto& s : current_beam) {\n            int r = s.coord / W_GRID;\n            int c = s.coord % W_GRID;\n            int current_tile = tiles[r][c];\n\n            for (int i = 0; i < 4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                \n                if (nr >= 0 && nr < H && nc >= 0 && nc < W_GRID) {\n                    int n_tile = tiles[nr][nc];\n                    \n                    // Rule: Must move to a different tile, and that tile must not be visited\n                    if (n_tile != current_tile && !s.visited.test(n_tile)) {\n                        \n                        // Record move in tree\n                        tree.push_back({s.tree_idx, dchar[i]});\n                        int new_tree_idx = (int)tree.size() - 1;\n                        \n                        State ns;\n                        ns.coord = nr * W_GRID + nc;\n                        ns.score = s.score + points[nr][nc];\n                        ns.tree_idx = new_tree_idx;\n                        ns.visited = s.visited; // Copy bitset (fast enough for N=2500)\n                        ns.visited.set(n_tile);\n                        \n                        next_candidates.push_back(ns);\n                    }\n                }\n            }\n        }\n\n        if (next_candidates.empty()) break;\n\n        // 2. Local Pruning (Top K per cell)\n        // Group candidates by their end coordinate and keep only the best few\n        for (int i = 0; i < (int)next_candidates.size(); ++i) {\n            int c = next_candidates[i].coord;\n            int sc = next_candidates[i].score;\n            auto& vec = top_candidates[c];\n\n            if (vec.empty()) {\n                touched_cells.push_back(c);\n                vec.push_back({sc, i});\n            } else {\n                // Insert into small sorted vector\n                bool inserted = false;\n                for (auto it = vec.begin(); it != vec.end(); ++it) {\n                    if (sc > it->score) {\n                        vec.insert(it, {sc, i});\n                        inserted = true;\n                        break;\n                    }\n                }\n                if (!inserted && vec.size() < MAX_PER_CELL) {\n                    vec.push_back({sc, i});\n                }\n                if (vec.size() > MAX_PER_CELL) {\n                    vec.pop_back();\n                }\n            }\n        }\n\n        // 3. Collect survivors and update global best\n        survivor_indices.clear();\n        for (int c : touched_cells) {\n            auto& vec = top_candidates[c];\n            for (const auto& cand : vec) {\n                survivor_indices.push_back(cand.candidate_idx);\n                \n                // Track the best path found so far across all history\n                if (cand.score > best_score) {\n                    best_score = cand.score;\n                    best_end_tree_idx = next_candidates[cand.candidate_idx].tree_idx;\n                }\n            }\n            vec.clear(); // Reset bucket\n        }\n\n        // 4. Global Beam Selection\n        // If we have more candidates than beam width, select the top ones based on score\n        if (survivor_indices.size() > BEAM_WIDTH) {\n            nth_element(survivor_indices.begin(), \n                        survivor_indices.begin() + BEAM_WIDTH, \n                        survivor_indices.end(), \n                        [&](int a, int b) {\n                            return next_candidates[a].score > next_candidates[b].score;\n                        });\n            survivor_indices.resize(BEAM_WIDTH);\n        }\n\n        // 5. Form the new beam\n        current_beam.clear();\n        for (int idx : survivor_indices) {\n            current_beam.push_back(next_candidates[idx]);\n        }\n    }\n\n    // Output the best path found\n    if (best_end_tree_idx != -1) {\n        string path;\n        int curr = best_end_tree_idx;\n        // Backtrack from the best end node to the root\n        while (curr != -1) {\n            path += tree[curr].move_char;\n            curr = tree[curr].parent_idx;\n        }\n        reverse(path.begin(), path.end());\n        cout << path << endl;\n    } else {\n        cout << \"\" << endl;\n    }\n\n    return 0;\n}","ahc003":"/**\n * AtCoder Heuristic Contest Solution\n * Problem: Shortest Path with Unknown Edge Lengths\n * Approach:\n * 1. Model the problem as finding shortest paths in a grid graph with weighted edges.\n * 2. Initially, edge weights are unknown (assume uniform prior).\n * 3. As we traverse paths and receive total length measurements, we update edge estimates.\n * 4. Use Dijkstra's algorithm for pathfinding.\n * 5. Use Stochastic Gradient Descent (Adam) to update edge weights.\n *    - Loss function: Squared Relative Error of predicted vs measured path length.\n *    - Regularization: L2 smoothness on adjacent horizontal edges (row-wise) and vertical edges (column-wise)\n *      to exploit the problem structure where edges are generated with row/column correlations.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst int NUM_H = N * (N - 1); // 30 * 29 = 870\nconst int NUM_V = (N - 1) * N; // 29 * 30 = 870\nconst int NUM_EDGES = NUM_H + NUM_V; // 1740\n\n// Helper to get edge indices\n// Horizontal edges: (r, c) -> (r, c+1)\nint get_h_idx(int r, int c) {\n    return r * (N - 1) + c;\n}\n\n// Vertical edges: (r, c) -> (r+1, c)\nint get_v_idx(int r, int c) {\n    return NUM_H + r * N + c;\n}\n\n// Structure to store query history\nstruct Query {\n    vector<int> path_edges;\n    int measured_dist;\n};\n\nclass Solver {\nprivate:\n    // Estimated weights of edges\n    vector<double> weights;\n    \n    // Adam Optimizer parameters\n    vector<double> m, v; // First and second moment vectors\n    double beta1 = 0.9;\n    double beta2 = 0.999;\n    double epsilon = 1e-8;\n    \n    // Hyperparameters\n    double learning_rate = 150.0;\n    double lambda = 10.0; // Regularization strength for smoothness\n    \n    long long updates_count = 0;\n    vector<Query> history;\n    mt19937 rng;\n\npublic:\n    Solver() {\n        // Initialize weights with expected mean value (approx 5000)\n        weights.assign(NUM_EDGES, 5000.0);\n        m.assign(NUM_EDGES, 0.0);\n        v.assign(NUM_EDGES, 0.0);\n        rng.seed(42);\n    }\n\n    // Dijkstra's algorithm to find the shortest path based on current weight estimates\n    pair<string, vector<int>> find_path(int si, int sj, int ti, int tj) {\n        vector<double> dist(N * N, 1e18);\n        vector<int> parent_edge(N * N, -1);\n        vector<int> parent_node(N * N, -1);\n        \n        auto get_node = [&](int r, int c) { return r * N + c; };\n        \n        int start_node = get_node(si, sj);\n        int target_node = get_node(ti, tj);\n        \n        dist[start_node] = 0;\n        using State = pair<double, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, start_node});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == target_node) break;\n            \n            int r = u / N;\n            int c = u % N;\n            \n            // Explore neighbors\n            // Up\n            if (r > 0) {\n                int nr = r - 1, nc = c;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_v_idx(r - 1, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Down\n            if (r < N - 1) {\n                int nr = r + 1, nc = c;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_v_idx(r, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Left\n            if (c > 0) {\n                int nr = r, nc = c - 1;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_h_idx(r, c - 1);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Right\n            if (c < N - 1) {\n                int nr = r, nc = c + 1;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_h_idx(r, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path = \"\";\n        vector<int> edges;\n        int curr = target_node;\n        while (curr != start_node) {\n            int prev = parent_node[curr];\n            int e_idx = parent_edge[curr];\n            edges.push_back(e_idx);\n            \n            int pr = prev / N, pc = prev % N;\n            int cr = curr / N, cc = curr % N;\n            \n            if (pr == cr + 1) path += 'U';\n            else if (pr == cr - 1) path += 'D';\n            else if (pc == cc + 1) path += 'L';\n            else if (pc == cc - 1) path += 'R';\n            \n            curr = prev;\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges.begin(), edges.end());\n        return {path, edges};\n    }\n\n    // Update estimates using SGD\n    void train(const vector<int>& path_edges, int measured, int k) {\n        history.push_back({path_edges, measured});\n        \n        int batch_size = 32;\n        int iterations = 80; // Number of SGD steps per query\n        \n        vector<double> grad(NUM_EDGES);\n        // Normalizing coefficient for regularization to match magnitude of prediction error\n        double reg_coeff = lambda * 2.0 / (5000.0 * 5000.0);\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            fill(grad.begin(), grad.end(), 0.0);\n            updates_count++;\n            \n            // Select mini-batch (always include the latest query)\n            vector<int> indices;\n            indices.reserve(batch_size + 1);\n            indices.push_back(history.size() - 1);\n            if (history.size() > 1) {\n                for (int b = 0; b < batch_size; ++b) {\n                    indices.push_back(rng() % (history.size() - 1));\n                }\n            }\n\n            // Compute gradients for Prediction Error: ((Pred - Measured)/Measured)^2\n            for (int idx : indices) {\n                const auto& q = history[idx];\n                double pred = 0;\n                for (int e : q.path_edges) pred += weights[e];\n                \n                double y = q.measured_dist;\n                double diff = pred - y;\n                // Derivative w.r.t w_e is 2 * (diff) / y^2\n                double g_factor = 2.0 * diff / (y * y);\n                \n                for (int e : q.path_edges) {\n                    grad[e] += g_factor;\n                }\n            }\n            \n            // Compute gradients for Smoothness Regularization\n            // Horizontal edges: smooth along rows\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N - 2; ++c) {\n                    int e1 = get_h_idx(r, c);\n                    int e2 = get_h_idx(r, c + 1);\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    double g = (w1 - w2) * reg_coeff;\n                    grad[e1] += g;\n                    grad[e2] -= g;\n                }\n            }\n            // Vertical edges: smooth along columns\n            for (int c = 0; c < N; ++c) {\n                for (int r = 0; r < N - 2; ++r) {\n                    int e1 = get_v_idx(r, c);\n                    int e2 = get_v_idx(r + 1, c);\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    double g = (w1 - w2) * reg_coeff;\n                    grad[e1] += g;\n                    grad[e2] -= g;\n                }\n            }\n            \n            // Adam Update Step\n            double bias_corr1 = 1.0 - pow(beta1, updates_count);\n            double bias_corr2 = 1.0 - pow(beta2, updates_count);\n            \n            for (int i = 0; i < NUM_EDGES; ++i) {\n                m[i] = beta1 * m[i] + (1 - beta1) * grad[i];\n                v[i] = beta2 * v[i] + (1 - beta2) * grad[i] * grad[i];\n                \n                double m_hat = m[i] / bias_corr1;\n                double v_hat = v[i] / bias_corr2;\n                \n                weights[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);\n                \n                // Clamp weights to reasonable bounds\n                if (weights[i] < 100.0) weights[i] = 100.0;\n                if (weights[i] > 20000.0) weights[i] = 20000.0;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    Solver solver;\n    \n    // Process 1000 queries\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        \n        // 1. Find and output path\n        auto [path_str, path_edges] = solver.find_path(si, sj, ti, tj);\n        cout << path_str << endl;\n        \n        // 2. Read feedback\n        int measured;\n        cin >> measured;\n        \n        // 3. Update model\n        solver.train(path_edges, measured, k);\n    }\n    \n    return 0;\n}","ahc004":"/**\n * Problem: AHC004 - Genetic Information\n * Approach: Simulated Annealing\n * \n * We approach this problem as an optimization task to find a grid configuration \n * that maximizes the number of satisfied input strings (subsequences).\n * \n * Key Strategy:\n * 1. Representation: The grid is 20x20. Cells contain values 0-7 ('A'-'H') or -1 ('.').\n * 2. Scoring: Maximize the sum of weights of satisfied unique input strings.\n *    - We group identical input strings and sum their occurrences to form weights.\n *    - A string is satisfied if it appears at least once in the grid (horizontally or vertically).\n * 3. Phase 1 (Construction):\n *    - Use Simulated Annealing (SA) to maximize the score.\n *    - State: The grid characters.\n *    - Move: Change a random cell (r, c) to a random character ('A'-'H').\n *    - Optimization: Incremental score update using Rolling Hash.\n *      We only check substrings passing through the modified cell.\n *      Hashes are mapped to string IDs for O(log K) lookup (where K is number of unique strings).\n * 4. Phase 2 (Simplification):\n *    - If we achieve a perfect score (all strings satisfied), we try to replace characters with '.' \n *      to maximize the secondary score component.\n *    - We greedily try to set each cell to '.' and keep it if the primary score (full coverage) is maintained.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <map>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 20;\n\n// Helper structs\nstruct Target {\n    int id;\n    int weight;\n    int length;\n    uint64_t hash;\n};\n\n// Convert character to 0-7 integer\ninline int get_char_code(char c) {\n    return c - 'A';\n}\n\n// Convert 0-7 integer to character, -1 to '.'\ninline char get_code_char(int c) {\n    if (c >= 0 && c < 8) return 'A' + c;\n    return '.';\n}\n\nstruct Solver {\n    int M;\n    vector<Target> unique_targets;\n    // Targets grouped by length for faster lookup. \n    // Index corresponds to length (0-12).\n    vector<vector<Target>> targets_by_len; \n    \n    int grid[N][N];\n    vector<int> occ; // occ[id] stores how many times target[id] appears in the grid\n    int current_satisfied_weight;\n    int max_possible_weight;\n    \n    mt19937 rng;\n    \n    // Masks for rolling hash updates\n    uint64_t high_masks[13];\n\n    Solver() : rng(42) {\n        targets_by_len.resize(13);\n        // Precompute bitmasks for rolling hash\n        for(int l=1; l<=12; ++l) {\n            if (l*3 < 64)\n                high_masks[l] = (1ULL << (3 * (l - 1))) - 1;\n            else\n                high_masks[l] = ~0ULL;\n        }\n    }\n\n    void read_input() {\n        int n_in;\n        if (!(cin >> n_in >> M)) return;\n        map<string, int> counts;\n        \n        for (int i = 0; i < M; ++i) {\n            string s;\n            cin >> s;\n            counts[s]++;\n        }\n        \n        // The maximum possible score from satisfying strings is M (since each s_i contributes 1)\n        max_possible_weight = M;\n        \n        int id_counter = 0;\n        for (auto const& [s, count] : counts) {\n            Target t;\n            t.id = id_counter++;\n            t.weight = count; // Weight is number of copies in input\n            t.length = s.length();\n            \n            // Compute hash\n            uint64_t h = 0;\n            for (char c : s) h = (h << 3) | get_char_code(c);\n            t.hash = h;\n            \n            unique_targets.push_back(t);\n            targets_by_len[t.length].push_back(t);\n        }\n        \n        // Sort for binary search\n        for (int l = 0; l <= 12; ++l) {\n            sort(targets_by_len[l].begin(), targets_by_len[l].end(), [](const Target& a, const Target& b) {\n                return a.hash < b.hash;\n            });\n        }\n        \n        occ.resize(unique_targets.size(), 0);\n    }\n\n    // Initialize grid with random characters and compute initial score\n    void init() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                grid[i][j] = rng() % 8;\n            }\n        }\n        fill(occ.begin(), occ.end(), 0);\n        current_satisfied_weight = 0;\n        \n        // Full scan of the grid to populate occ\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal strings starting at (r,c)\n                for (int l=2; l<=12; ++l) {\n                    if (targets_by_len[l].empty()) continue;\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[r][(c+k)%N];\n                    check_hash(l, h, 1);\n                }\n                // Vertical strings starting at (r,c)\n                for (int l=2; l<=12; ++l) {\n                    if (targets_by_len[l].empty()) continue;\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[(r+k)%N][c];\n                    check_hash(l, h, 1);\n                }\n            }\n        }\n    }\n\n    // Check if a hash exists in targets and update score/occ\n    void check_hash(int len, uint64_t h, int sign) {\n        const auto& vec = targets_by_len[len];\n        auto it = lower_bound(vec.begin(), vec.end(), h, [](const Target& t, uint64_t val) {\n            return t.hash < val;\n        });\n        if (it != vec.end() && it->hash == h) {\n            int id = it->id;\n            if (sign > 0) {\n                if (occ[id] == 0) current_satisfied_weight += it->weight;\n                occ[id]++;\n            } else {\n                if (occ[id] == 1) current_satisfied_weight -= it->weight;\n                occ[id]--;\n            }\n        }\n    }\n    \n    // Helper for incremental update: updates diff instead of global score\n    void check_hash_local(int len, uint64_t h, int sign, int& diff) {\n        const auto& vec = targets_by_len[len];\n        auto it = lower_bound(vec.begin(), vec.end(), h, [](const Target& t, uint64_t val) {\n            return t.hash < val;\n        });\n        if (it != vec.end() && it->hash == h) {\n            int id = it->id;\n            int w = it->weight;\n            if (sign > 0) {\n                if (occ[id] == 0) diff += w;\n                occ[id]++;\n            } else {\n                if (occ[id] == 1) diff -= w;\n                occ[id]--;\n            }\n        }\n    }\n\n    // Calculates the effect of setting grid[r][c] = val\n    // sign = -1 to remove effect of current val, +1 to add effect of val\n    void update_occ_local(int r, int c, int val, int sign, int& diff) {\n        // Horizontal checking using Rolling Hash\n        for (int l = 2; l <= 12; ++l) {\n            if (targets_by_len[l].empty()) continue;\n            \n            // The first window that includes (r,c) starts at c - l + 1\n            int start_c = (c - l + 1 + N) % N;\n            uint64_t h = 0;\n            \n            // Compute hash for the first window fully\n            for (int k = 0; k < l; ++k) {\n                int cc = (start_c + k) % N;\n                // Use `val` if we are at the modified cell, else grid value\n                int char_code = (cc == c) ? val : grid[r][cc];\n                h = (h << 3) | char_code;\n            }\n            check_hash_local(l, h, sign, diff);\n            \n            // Roll the window l-1 times to cover all positions passing through (r,c)\n            uint64_t mask = high_masks[l];\n            for (int step = 0; step < l - 1; ++step) {\n                // Slide window to the right\n                // Remove char at start_c, add char at start_c + l\n                int next_char_pos = (start_c + l) % N;\n                int char_in = (next_char_pos == c) ? val : grid[r][next_char_pos];\n                \n                h = ((h & mask) << 3) | char_in;\n                \n                check_hash_local(l, h, sign, diff);\n                \n                start_c = (start_c + 1) % N;\n            }\n        }\n        \n        // Vertical checking using Rolling Hash\n        for (int l = 2; l <= 12; ++l) {\n            if (targets_by_len[l].empty()) continue;\n            \n            int start_r = (r - l + 1 + N) % N;\n            uint64_t h = 0;\n            \n            for (int k = 0; k < l; ++k) {\n                int rr = (start_r + k) % N;\n                int char_code = (rr == r) ? val : grid[rr][c];\n                h = (h << 3) | char_code;\n            }\n            check_hash_local(l, h, sign, diff);\n            \n            uint64_t mask = high_masks[l];\n            for (int step = 0; step < l - 1; ++step) {\n                int next_char_pos = (start_r + l) % N;\n                int char_in = (next_char_pos == r) ? val : grid[next_char_pos][c];\n                \n                h = ((h & mask) << 3) | char_in;\n                \n                check_hash_local(l, h, sign, diff);\n                \n                start_r = (start_r + 1) % N;\n            }\n        }\n    }\n\n    int calc_move_diff(int r, int c, int old_val, int new_val) {\n        int diff = 0;\n        update_occ_local(r, c, old_val, -1, diff); // remove contribution of old char\n        update_occ_local(r, c, new_val, 1, diff);  // add contribution of new char\n        return diff;\n    }\n\n    void revert_move_occ(int r, int c, int old_val, int new_val) {\n        int dummy = 0;\n        // To revert, we remove new_val and add back old_val\n        update_occ_local(r, c, new_val, -1, dummy);\n        update_occ_local(r, c, old_val, 1, dummy);\n    }\n\n    void solve() {\n        auto start_time = chrono::steady_clock::now();\n        init();\n        \n        // SA Parameters\n        double time_limit = 2.8; \n        double t0 = 5.0;\n        double t1 = 0.0; \n        \n        long long steps = 0;\n        int best_score = current_satisfied_weight;\n        int best_grid[N][N];\n        memcpy(best_grid, grid, sizeof(grid));\n        \n        // Phase 1: Simulated Annealing\n        while (true) {\n            steps++;\n            // Check time every 4096 steps\n            if ((steps & 0xFFF) == 0) {\n                double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n                if (elapsed > time_limit) break;\n            }\n            \n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            double temp = t0 + (t1 - t0) * (elapsed / time_limit);\n            \n            int r = rng() % N;\n            int c = rng() % N;\n            int old_val = grid[r][c];\n            int new_val = rng() % 8; // Only use 'A'-'H' in this phase\n            if (old_val == new_val) continue;\n            \n            int delta = calc_move_diff(r, c, old_val, new_val);\n            \n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else if (temp > 1e-9 && exp(delta / temp) > generate_canonical<double, 10>(rng)) accept = true;\n            \n            if (accept) {\n                current_satisfied_weight += delta;\n                grid[r][c] = new_val;\n                if (current_satisfied_weight > best_score) {\n                    best_score = current_satisfied_weight;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else {\n                // If rejected, we must revert the changes to `occ` made by `calc_move_diff`\n                revert_move_occ(r, c, old_val, new_val);\n            }\n        }\n        \n        // Restore the best grid found\n        memcpy(grid, best_grid, sizeof(grid));\n        \n        // Recalculate occ and score exactly for the best grid (sanitization)\n        fill(occ.begin(), occ.end(), 0);\n        current_satisfied_weight = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int l=2; l<=12; ++l) {\n                    if (targets_by_len[l].empty()) continue;\n                    // Horz\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[r][(c+k)%N];\n                    check_hash(l, h, 1);\n                    // Vert\n                    h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[(r+k)%N][c];\n                    check_hash(l, h, 1);\n                }\n            }\n        }\n        \n        // Phase 2: Dot Optimization\n        // Only performed if we achieved full coverage, as the score boost depends on it.\n        if (current_satisfied_weight == max_possible_weight) {\n            vector<pair<int, int>> cells;\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) cells.push_back({i, j});\n            shuffle(cells.begin(), cells.end(), rng);\n            \n            for(auto p : cells) {\n                int r = p.first;\n                int c = p.second;\n                int old_val = grid[r][c];\n                if (old_val == -1) continue;\n                \n                // Check if replacing with dot maintains the max score.\n                // We simulate removal of old_val. Since dot matches nothing, we don't add anything.\n                // If current_satisfied_weight + diff == max_possible_weight, it means no *required* string was broken.\n                \n                int diff = 0;\n                update_occ_local(r, c, old_val, -1, diff);\n                \n                if (current_satisfied_weight + diff == max_possible_weight) {\n                    // Safe to place dot\n                    current_satisfied_weight += diff;\n                    grid[r][c] = -1; \n                } else {\n                    // Revert (add back old_val)\n                    int dummy = 0;\n                    update_occ_local(r, c, old_val, 1, dummy);\n                }\n            }\n        }\n        \n        // Output Result\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                cout << get_code_char(grid[i][j]);\n            }\n            cout << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver s;\n    s.read_input();\n    s.solve();\n    return 0;\n}","ahc005":"/**\n * Problem Analysis:\n * The problem asks for a minimum cost tour that \"sees\" every road cell on an N x N grid.\n * Visibility is defined by line-of-sight in cardinal directions.\n *\n * Key Insights:\n * 1. Geometric Set Cover:\n *    - We can decompose the road cells into maximal contiguous horizontal (H) and vertical (V) segments.\n *    - Standing on any cell of a segment allows seeing the entire segment.\n *    - Every road cell (r, c) belongs to exactly one H-segment and one V-segment.\n *    - To see cell (r, c), we must visit either its H-segment or its V-segment.\n *    - This structure forms a Bipartite Matching / Vertex Cover problem constraints.\n *      Specifically, we need to select a subset of segments to visit such that every cell (edge in bipartite graph)\n *      is covered by a selected segment (vertex). This is the Vertex Cover problem.\n *\n * 2. Minimum Weight Vertex Cover (MWVC):\n *    - Since we want to minimize travel time, we should prefer visiting segments that are \"close\" to our path.\n *    - We can assign a weight to each segment equal to the cost to reach it from the current position.\n *    - MWVC on a bipartite graph can be solved efficiently using Max-Flow Min-Cut (Konig's theorem extension).\n *\n * 3. Iterative Greedy Strategy:\n *    - The optimal set of segments depends on our current position (dynamic costs).\n *    - We employ an iterative approach:\n *      a. From current position, calculate distances to all segments.\n *      b. Construct the bipartite graph of *unseen* cells.\n *      c. Assign weights to segments based on distance (+ random noise for diversity).\n *      d. Solve MWVC to identify the most efficient set of segments to visit next.\n *      e. Move to the best candidate from the MWVC set.\n *      f. Repeat until all cells are seen, then return to start.\n *\n * 4. Optimization:\n *    - Since the grid is small (N <= 69), we can run many simulations with different random seeds/weights within the time limit.\n *    - We track the best solution found.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <map>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>\n\n// Use AtCoder Library for MaxFlow\n#include <atcoder/maxflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconst int INF = 1e9;\nconst int DX[] = {-1, 1, 0, 0};\nconst int DY[] = {0, 0, -1, 1};\nconst char DIR_CHAR[] = {'U', 'D', 'L', 'R'};\n\n// Global variables\nint N;\nint SI, SJ;\nvector<string> GRID;\nvector<vector<int>> COSTS;\nbool IS_ROAD[70][70];\n\n// Structs\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\nstruct Segment {\n    int id;\n    int type; // 0: Horizontal, 1: Vertical\n    vector<Point> cells;\n};\n\nvector<Segment> H_SEGS, V_SEGS;\nint H_ID[70][70]; // Map cell to H segment ID\nint V_ID[70][70]; // Map cell to V segment ID\n\n// Parsing and Setup\nvoid parse_input() {\n    if (!(cin >> N >> SI >> SJ)) return;\n    GRID.resize(N);\n    COSTS.assign(N, vector<int>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        cin >> GRID[i];\n        for (int j = 0; j < N; ++j) {\n            if (GRID[i][j] != '#') {\n                COSTS[i][j] = GRID[i][j] - '0';\n                IS_ROAD[i][j] = true;\n            } else {\n                IS_ROAD[i][j] = false;\n            }\n        }\n    }\n\n    // Identify Horizontal Segments\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) H_ID[i][j] = -1;\n    }\n    int h_count = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (!IS_ROAD[i][j]) {\n                j++;\n                continue;\n            }\n            int k = j;\n            while (k < N && IS_ROAD[i][k]) k++;\n            Segment seg;\n            seg.id = h_count;\n            seg.type = 0;\n            for (int c = j; c < k; ++c) {\n                seg.cells.push_back({i, c});\n                H_ID[i][c] = h_count;\n            }\n            H_SEGS.push_back(seg);\n            h_count++;\n            j = k;\n        }\n    }\n\n    // Identify Vertical Segments\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) V_ID[i][j] = -1;\n    }\n    int v_count = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (!IS_ROAD[i][j]) {\n                i++;\n                continue;\n            }\n            int k = i;\n            while (k < N && IS_ROAD[k][j]) k++;\n            Segment seg;\n            seg.id = v_count;\n            seg.type = 1;\n            for (int r = i; r < k; ++r) {\n                seg.cells.push_back({r, j});\n                V_ID[r][j] = v_count;\n            }\n            V_SEGS.push_back(seg);\n            v_count++;\n            i = k;\n        }\n    }\n}\n\n// Dijkstra's Algorithm for shortest paths on the grid\nvoid get_dist_matrix(Point start, vector<vector<int>>& dist, vector<vector<int>>& parent_dir) {\n    dist.assign(N, vector<int>(N, INF));\n    parent_dir.assign(N, vector<int>(N, -1));\n    \n    priority_queue<pair<int, pair<int,int>>, vector<pair<int, pair<int,int>>>, greater<pair<int, pair<int,int>>>> pq;\n    \n    dist[start.r][start.c] = 0;\n    pq.push({0, {start.r, start.c}});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        int r = u.first;\n        int c = u.second;\n        \n        if (d > dist[r][c]) continue;\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + DX[k];\n            int nc = c + DY[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && IS_ROAD[nr][nc]) {\n                int weight = COSTS[nr][nc];\n                if (dist[r][c] + weight < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + weight;\n                    parent_dir[nr][nc] = k;\n                    pq.push({dist[nr][nc], {nr, nc}});\n                }\n            }\n        }\n    }\n}\n\n// Reconstruct path string\nstring get_path_str(Point start, Point end, const vector<vector<int>>& parent_dir) {\n    string path = \"\";\n    int r = end.r;\n    int c = end.c;\n    while (r != start.r || c != start.c) {\n        int dir = parent_dir[r][c];\n        if (dir == -1) break; \n        path += DIR_CHAR[dir];\n        r -= DX[dir];\n        c -= DY[dir];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Result {\n    string path;\n    long long score;\n    int time_cost;\n};\n\nmt19937 rng(12345);\n\nResult solve_iterative_mwvc() {\n    // State tracking\n    vector<vector<bool>> is_covered(N, vector<bool>(N, false));\n    int covered_count = 0;\n    int total_road_cells = 0;\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(IS_ROAD[i][j]) total_road_cells++;\n\n    auto see_cell = [&](int r, int c) {\n        if (!is_covered[r][c]) {\n            is_covered[r][c] = true;\n            covered_count++;\n        }\n    };\n\n    auto visit_pos = [&](Point p) {\n        int hid = H_ID[p.r][p.c];\n        if (hid != -1) {\n            for (auto& cell : H_SEGS[hid].cells) see_cell(cell.r, cell.c);\n        }\n        int vid = V_ID[p.r][p.c];\n        if (vid != -1) {\n            for (auto& cell : V_SEGS[vid].cells) see_cell(cell.r, cell.c);\n        }\n    };\n\n    Point current = {SI, SJ};\n    visit_pos(current);\n\n    string full_path = \"\";\n    int total_cost = 0;\n\n    // Random weight perturbation for diversity\n    uniform_real_distribution<double> d_rand(0.85, 1.15);\n\n    while (covered_count < total_road_cells) {\n        // 1. Calculate distances from current\n        vector<vector<int>> dist;\n        vector<vector<int>> parent;\n        get_dist_matrix(current, dist, parent);\n\n        // 2. Precompute min distance to each segment\n        vector<int> dist_h(H_SEGS.size(), INF);\n        vector<Point> closest_h(H_SEGS.size());\n        for (auto& seg : H_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < dist_h[seg.id]) {\n                    dist_h[seg.id] = dist[p.r][p.c];\n                    closest_h[seg.id] = p;\n                }\n            }\n        }\n        vector<int> dist_v(V_SEGS.size(), INF);\n        vector<Point> closest_v(V_SEGS.size());\n        for (auto& seg : V_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < dist_v[seg.id]) {\n                    dist_v[seg.id] = dist[p.r][p.c];\n                    closest_v[seg.id] = p;\n                }\n            }\n        }\n\n        // 3. Build Flow Network for MWVC\n        mf_graph<long long> g(H_SEGS.size() + V_SEGS.size() + 2);\n        int S = H_SEGS.size() + V_SEGS.size();\n        int T_sink = S + 1;\n\n        // Edges S -> H (Capacity = Weight of H segment)\n        for (auto& seg : H_SEGS) {\n            long long w = (long long)(dist_h[seg.id] * d_rand(rng)) + 50; \n            g.add_edge(S, seg.id, w);\n        }\n        // Edges V -> T (Capacity = Weight of V segment)\n        for (auto& seg : V_SEGS) {\n            long long w = (long long)(dist_v[seg.id] * d_rand(rng)) + 50;\n            g.add_edge(H_SEGS.size() + seg.id, T_sink, w);\n        }\n        // Edges H -> V for uncovered cells (Infinite Capacity)\n        bool has_uncovered = false;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (IS_ROAD[r][c] && !is_covered[r][c]) {\n                    int h = H_ID[r][c];\n                    int v = V_ID[r][c];\n                    g.add_edge(h, H_SEGS.size() + v, 1e18);\n                    has_uncovered = true;\n                }\n            }\n        }\n\n        if (!has_uncovered) break;\n\n        // 4. Solve Min Cut\n        g.flow(S, T_sink);\n        auto cut = g.min_cut(S);\n\n        // 5. Extract Vertex Cover\n        // S-side in cut means reachable from S.\n        // VC = (L \\ S_side) U (R \\cap S_side)\n        // cut[i] == true means i is in S_side.\n        vector<int> target_h, target_v;\n        for (int i = 0; i < (int)H_SEGS.size(); ++i) {\n            if (!cut[i]) target_h.push_back(i);\n        }\n        for (int i = 0; i < (int)V_SEGS.size(); ++i) {\n            if (cut[H_SEGS.size() + i]) target_v.push_back(i);\n        }\n\n        // 6. Select Best Target from Cover\n        Point best_p = {-1, -1};\n        double best_score = 1e18;\n\n        // Check H candidates\n        for (int hid : target_h) {\n            Point p = closest_h[hid];\n            double d = (double)dist_h[hid];\n            // Heuristic: if this point also satisfies a V-target, it's better\n            int vid = V_ID[p.r][p.c];\n            bool covers_v = false;\n            for(int t_vid : target_v) if(t_vid == vid) covers_v = true;\n            \n            double score = d;\n            if (covers_v) score *= 0.6; // Discount if double cover\n            \n            if (score < best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        // Check V candidates\n        for (int vid : target_v) {\n            Point p = closest_v[vid];\n            double d = (double)dist_v[vid];\n            int hid = H_ID[p.r][p.c];\n            bool covers_h = false;\n            for(int t_hid : target_h) if(t_hid == hid) covers_h = true;\n            \n            double score = d;\n            if (covers_h) score *= 0.6;\n            \n            if (score < best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n\n        // 7. Move\n        string subpath = get_path_str(current, best_p, parent);\n        full_path += subpath;\n        total_cost += dist[best_p.r][best_p.c];\n\n        // Update coverage along path\n        Point temp = current;\n        for (char c : subpath) {\n            int dir = -1;\n            if (c == 'U') dir = 0;\n            else if (c == 'D') dir = 1;\n            else if (c == 'L') dir = 2;\n            else if (c == 'R') dir = 3;\n            temp.r += DX[dir];\n            temp.c += DY[dir];\n            visit_pos(temp);\n        }\n        current = best_p;\n        visit_pos(current); // Ensure endpoint processed\n    }\n\n    // Return to start\n    if (current.r != SI || current.c != SJ) {\n        vector<vector<int>> dist;\n        vector<vector<int>> parent;\n        get_dist_matrix(current, dist, parent);\n        string subpath = get_path_str(current, {SI, SJ}, parent);\n        full_path += subpath;\n        total_cost += dist[SI][SJ];\n    }\n\n    Result res;\n    res.path = full_path;\n    res.time_cost = (total_cost == 0 ? 1 : total_cost);\n    // Calculate approximate score (assuming full coverage)\n    res.score = 10000 + (long long)(1e7 * N / res.time_cost);\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    parse_input();\n\n    auto start_clock = chrono::high_resolution_clock::now();\n    // Use slightly less than 3.0s to ensure output\n    double time_limit = 2.85;\n\n    Result best_res;\n    best_res.score = -1;\n    best_res.path = \"\";\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_clock;\n        if (elapsed.count() > time_limit) break;\n\n        Result res = solve_iterative_mwvc();\n        if (res.score > best_res.score) {\n            best_res = res;\n        }\n    }\n\n    cout << best_res.path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"/*\n * Solution for F Corporation Project Leader\n * Approach: Greedy scheduling on Critical Path + Online Learning of Skills via Coordinate Descent\n */\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\n// Random number generator\nmt19937 rng(12345);\n\nstruct Task {\n    int id;\n    vector<int> d; // Required skill levels\n    vector<int> dependency_to; // Adjacency list (children)\n    int unresolved_dependencies; // In-degree counter\n    int height; // Critical path length (distance to sink)\n};\n\nstruct Member {\n    int id;\n    vector<int> s; // Estimated skill levels\n    // History of tasks completed: pair<task_id, duration>\n    vector<pair<int, int>> history; \n    int current_task_id; // -1 if free\n    int task_start_day;\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<int> task_status; // 0: not started, 1: started, 2: completed\nvector<int> memo_height;\n\n// Calculate w_{i,j} based on current skill estimate\nint calc_w(int task_idx, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += max(0, tasks[task_idx].d[k] - s[k]);\n    }\n    return w;\n}\n\n// Predict duration days based on current skill estimate\nint predict_days(int task_idx, const vector<int>& s) {\n    int w = calc_w(task_idx, s);\n    if (w == 0) return 1;\n    return max(1, w); // Expected value approx w\n}\n\n// Update skill estimates for a member using local search to fit observations\nvoid update_skills(int member_idx) {\n    Member& m = members[member_idx];\n    int iterations = 1000; // Number of local search steps\n    \n    // Precompute w for all history items to allow incremental updates\n    vector<int> current_w(m.history.size());\n    long long current_sum_s = 0;\n    for (int x : m.s) current_sum_s += x;\n\n    for (size_t i = 0; i < m.history.size(); ++i) {\n        current_w[i] = calc_w(m.history[i].first, m.s);\n    }\n\n    // Helper to calculate error term for a single observation\n    // Actual duration t implies constraints on w\n    auto calc_error_term = [&](int w, int actual) -> long long {\n        int lb, ub;\n        if (actual == 1) {\n            // If t=1, w could be 0, or w+r <= 1. Since r >= -3, w <= 4.\n            lb = 0; ub = 4;\n        } else {\n            // If t > 1, t = w + r => w = t - r. r in [-3, 3].\n            lb = actual - 3;\n            ub = actual + 3;\n        }\n        int diff = 0;\n        if (w < lb) diff = lb - w;\n        else if (w > ub) diff = w - ub;\n        return (long long)diff * diff;\n    };\n\n    // Initial total error\n    long long current_total_err = 0;\n    for (size_t i = 0; i < m.history.size(); ++i) {\n        current_total_err += calc_error_term(current_w[i], m.history[i].second);\n    }\n    \n    // Cost function: minimize prediction error (primary) and skill magnitude (secondary, regularization)\n    // Weight 100000LL ensures error reduction takes precedence over regularization\n    long long current_cost = current_total_err * 100000LL + current_sum_s;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int k = rng() % K;\n        int original_val = m.s[k];\n        \n        // Helper to evaluate and apply a change in s[k]\n        auto try_change = [&](int new_val) -> bool {\n            long long new_total_err = 0;\n            // Incrementally compute new error\n            for (size_t i = 0; i < m.history.size(); ++i) {\n                int t_idx = m.history[i].first;\n                int d_k = tasks[t_idx].d[k];\n                int w_old = current_w[i];\n                // Removing old contribution of k, adding new contribution\n                int term_old = max(0, d_k - original_val);\n                int term_new = max(0, d_k - new_val);\n                int w_new = w_old - term_old + term_new;\n                new_total_err += calc_error_term(w_new, m.history[i].second);\n            }\n            \n            long long new_sum_s = current_sum_s - original_val + new_val;\n            long long new_cost = new_total_err * 100000LL + new_sum_s;\n            \n            if (new_cost < current_cost) {\n                // Accept change\n                m.s[k] = new_val;\n                current_sum_s = new_sum_s;\n                current_total_err = new_total_err;\n                current_cost = new_cost;\n                // Update cached w values\n                for (size_t i = 0; i < m.history.size(); ++i) {\n                    int t_idx = m.history[i].first;\n                    int d_k = tasks[t_idx].d[k];\n                    current_w[i] = current_w[i] - max(0, d_k - original_val) + max(0, d_k - new_val);\n                }\n                return true;\n            }\n            return false;\n        };\n\n        // Try increasing skill\n        if (try_change(original_val + 1)) continue;\n        \n        // Try decreasing skill\n        if (original_val > 0) {\n            try_change(original_val - 1);\n        }\n    }\n}\n\n// Compute critical path height using memoization\nint get_height(int u) {\n    if (memo_height[u] != -1) return memo_height[u];\n    int h = 0;\n    for (int v : tasks[u].dependency_to) {\n        h = max(h, get_height(v));\n    }\n    return memo_height[u] = 1 + h;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) cin >> tasks[i].d[k];\n        tasks[i].unresolved_dependencies = 0;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-based indexing\n        tasks[u].dependency_to.push_back(v);\n        tasks[v].unresolved_dependencies++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].s.assign(K, 0); // Initialize skills to 0\n        members[i].current_task_id = -1;\n        members[i].task_start_day = -1;\n    }\n\n    task_status.assign(N, 0);\n    memo_height.assign(N, -1);\n\n    // Precompute heights for prioritization\n    for (int i = 0; i < N; ++i) get_height(i);\n\n    int day = 0;\n    int tasks_finished_count = 0;\n\n    // Simulation loop\n    while (true) {\n        day++;\n        \n        // 1. Identify available tasks and free members\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 0 && tasks[i].unresolved_dependencies == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        vector<int> free_members;\n        for (int i = 0; i < M; ++i) {\n            if (members[i].current_task_id == -1) {\n                free_members.push_back(i);\n            }\n        }\n\n        // 2. Sort tasks by Importance (Critical Path Height > OutDegree)\n        sort(available_tasks.begin(), available_tasks.end(), [&](int a, int b) {\n            if (tasks[a].height != tasks[b].height) return tasks[a].height > tasks[b].height;\n            return tasks[a].dependency_to.size() > tasks[b].dependency_to.size();\n        });\n\n        // 3. Greedy Assignment\n        vector<pair<int, int>> assignments;\n        vector<bool> member_taken(M, false);\n\n        for (int tid : available_tasks) {\n            int best_m = -1;\n            int min_days = 1e9;\n            long long best_waste = 1e18; \n\n            for (int mid : free_members) {\n                if (member_taken[mid]) continue;\n                \n                int pred = predict_days(tid, members[mid].s);\n                long long current_sum_s = 0;\n                for(int v : members[mid].s) current_sum_s += v;\n\n                // Prioritize minimizing duration. \n                // Tie-break: choose member with lower total skill (saving \"experts\" for harder tasks).\n                if (pred < min_days) {\n                    min_days = pred;\n                    best_m = mid;\n                    best_waste = current_sum_s;\n                } else if (pred == min_days) {\n                    if (current_sum_s < best_waste) {\n                        best_m = mid;\n                        best_waste = current_sum_s;\n                    }\n                }\n            }\n\n            if (best_m != -1) {\n                assignments.push_back({best_m, tid});\n                member_taken[best_m] = true;\n            }\n        }\n\n        // 4. Output Assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n            // Update state\n            members[p.first].current_task_id = p.second;\n            members[p.first].task_start_day = day;\n            task_status[p.second] = 1; \n        }\n        cout << endl; // Flush output\n\n        // 5. Read Completed Tasks\n        int n_completed;\n        cin >> n_completed;\n        if (n_completed == -1) {\n            // End of simulation\n            break;\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_id_1based;\n            cin >> member_id_1based;\n            int mid = member_id_1based - 1;\n            \n            int tid = members[mid].current_task_id;\n            int start_day = members[mid].task_start_day;\n            int duration = day - start_day + 1; \n            \n            // Record history\n            members[mid].history.push_back({tid, duration});\n            members[mid].current_task_id = -1;\n            members[mid].task_start_day = -1;\n            \n            // Learn skills\n            update_skills(mid);\n            \n            // Update dependency graph\n            task_status[tid] = 2;\n            tasks_finished_count++;\n            \n            for (int next_task : tasks[tid].dependency_to) {\n                tasks[next_task].unresolved_dependencies--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconst int NUM_ORDERS = 1000;\nconst int TARGET_ORDERS = 50;\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// Data structures\nstruct Order {\n    int id;\n    int a, b, c, d; // (a,b) pickup, (c,d) delivery\n};\n\nstruct Node {\n    int id; // Internal ID: 0..999 for Pickup, 1000..1999 for Delivery\n    int x, y;\n    bool is_pickup;\n    int order_idx;\n};\n\nstruct Solution {\n    vector<int> route; // Stores node IDs. Does not include Office.\n    bool selected[NUM_ORDERS];\n    int total_dist;\n};\n\n// Globals\nOrder orders[NUM_ORDERS];\n\n// Utils\ninline int dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline Node get_node(int val) {\n    if (val < 1000) {\n        return {val, orders[val].a, orders[val].b, true, val};\n    } else {\n        return {val, orders[val - 1000].c, orders[val - 1000].d, false, val - 1000};\n    }\n}\n\n// Calculate total distance of a route\nint calc_route_dist(const vector<int>& route) {\n    int d = 0;\n    int cx = OFFICE_X;\n    int cy = OFFICE_Y;\n    for (int val : route) {\n        Node n = get_node(val);\n        d += dist(cx, cy, n.x, n.y);\n        cx = n.x;\n        cy = n.y;\n    }\n    d += dist(cx, cy, OFFICE_X, OFFICE_Y);\n    return d;\n}\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        return next() % n;\n    }\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n} rng;\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read Input\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n\n    // Initial Solution Construction\n    Solution curr_sol;\n    fill(curr_sol.selected, curr_sol.selected + NUM_ORDERS, false);\n    \n    // Heuristic: Find order closest to office to start a cluster\n    int start_order = -1;\n    int min_d = 1e9;\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        int d = dist(OFFICE_X, OFFICE_Y, orders[i].a, orders[i].b);\n        if(d < min_d) {\n            min_d = d;\n            start_order = i;\n        }\n    }\n    \n    // Select 50 orders based on proximity to the start_order\n    vector<pair<int,int>> dists;\n    dists.reserve(NUM_ORDERS);\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        // Distance metric: dist(start_P, i_P)\n        int d = dist(orders[start_order].a, orders[start_order].b, orders[i].a, orders[i].b); \n        dists.push_back({d, i});\n    }\n    sort(dists.begin(), dists.end());\n    \n    for(int k=0; k<TARGET_ORDERS; ++k) {\n        int idx = dists[k].second;\n        curr_sol.selected[idx] = true;\n        curr_sol.route.push_back(idx);        // Pickup\n        curr_sol.route.push_back(idx + 1000); // Delivery\n    }\n    \n    curr_sol.total_dist = calc_route_dist(curr_sol.route);\n    Solution best_sol = curr_sol;\n\n    // Simulated Annealing\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95;\n    double temp_start = 200.0;\n    double temp_end = 1.0;\n    \n    int iter = 0;\n    \n    // Pos array for quick lookups in validity checks\n    vector<int> pos_cache(2000); \n\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            chrono::duration<double> diff = now - start_time;\n            if (diff.count() > time_limit) break;\n        }\n        \n        // Temperature Schedule\n        // Simple linear interpolation based on time isn't strictly exponential but works well\n        auto now = chrono::high_resolution_clock::now();\n        double progress = (now - start_time).count() / 1e9 / time_limit; \n        // Actually proper annealing uses exponential decay\n        double cur_time = (double)(iter) / 500000.0; // approximate scaling\n        if (progress > 1.0) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int type = rng.next_int(100);\n        \n        if (type < 15) { \n            // ==========================================\n            // Move Type 1: Swap Order (Remove one, Add one)\n            // ==========================================\n            \n            // 1. Pick random order to remove from route\n            int r_idx = rng.next_int(curr_sol.route.size());\n            int val = curr_sol.route[r_idx];\n            int rem_order = (val < 1000) ? val : val - 1000;\n            \n            // 2. Remove P and D from temporary route\n            vector<int> next_route = curr_sol.route;\n            // Remove larger index first to keep smaller index valid\n            int p_pos = -1, d_pos = -1;\n            for(size_t i=0; i<next_route.size(); ++i) {\n                int ov = next_route[i];\n                if (ov == rem_order) p_pos = i;\n                else if (ov == rem_order + 1000) d_pos = i;\n            }\n            \n            if (d_pos > p_pos) {\n                next_route.erase(next_route.begin() + d_pos);\n                next_route.erase(next_route.begin() + p_pos);\n            } else {\n                next_route.erase(next_route.begin() + p_pos);\n                next_route.erase(next_route.begin() + d_pos);\n            }\n            \n            // 3. Pick random new order\n            int new_order = -1;\n            while(true) {\n                int cand = rng.next_int(NUM_ORDERS);\n                if (!curr_sol.selected[cand]) {\n                    new_order = cand;\n                    break;\n                }\n            }\n            \n            // 4. Greedy Insertion: Find best valid positions for P and D of new_order\n            // We need to insert P at i, D at j (j >= i).\n            \n            // Calculate base distance of the route without the new order\n            int base_dist = calc_route_dist(next_route);\n            \n            Node P = get_node(new_order);\n            Node D = get_node(new_order + 1000);\n            \n            int best_cost = 2e9;\n            int best_i = -1, best_j = -1;\n            \n            int n_size = next_route.size();\n            \n            // Optimization: Pre-calculate node coordinates for fast access\n            // Adding Office at start and end virtually\n            \n            for(int i=0; i<=n_size; ++i) {\n                // Context for P insertion: between (i-1) and (i)\n                int prev_x = (i==0) ? OFFICE_X : get_node(next_route[i-1]).x;\n                int prev_y = (i==0) ? OFFICE_Y : get_node(next_route[i-1]).y;\n                int next_x = (i==n_size) ? OFFICE_X : get_node(next_route[i]).x;\n                int next_y = (i==n_size) ? OFFICE_Y : get_node(next_route[i]).y;\n                \n                // Delta for inserting P\n                int delta_P = dist(prev_x, prev_y, P.x, P.y) + dist(P.x, P.y, next_x, next_y) \n                              - dist(prev_x, prev_y, next_x, next_y);\n                \n                // Pruning: if delta_P alone makes it worse than best known, maybe skip? \n                // No, because D insertion adds cost, so cost always increases.\n                \n                // Try inserting D at j >= i\n                // If j == i, D is inserted immediately after P.\n                // If j > i, D is inserted at position j in the *original* next_route indices\n                // which corresponds to between next_route[j-1] and next_route[j].\n                \n                for(int j=i; j<=n_size; ++j) {\n                    int current_val = base_dist + delta_P;\n                    int delta_D = 0;\n                    \n                    if (j == i) {\n                        // Sequence: prev -> P -> D -> next\n                        // Currently delta_P accounts for prev->P->next.\n                        // We need to change P->next to P->D->next.\n                        delta_D = dist(P.x, P.y, D.x, D.y) + dist(D.x, D.y, next_x, next_y)\n                                  - dist(P.x, P.y, next_x, next_y);\n                    } else {\n                        // Sequence around j (j > i): node[j-1] -> D -> node[j]\n                        int d_prev_x = get_node(next_route[j-1]).x;\n                        int d_prev_y = get_node(next_route[j-1]).y;\n                        int d_next_x = (j==n_size) ? OFFICE_X : get_node(next_route[j]).x;\n                        int d_next_y = (j==n_size) ? OFFICE_Y : get_node(next_route[j]).y;\n                        \n                        delta_D = dist(d_prev_x, d_prev_y, D.x, D.y) + dist(D.x, D.y, d_next_x, d_next_y)\n                                  - dist(d_prev_x, d_prev_y, d_next_x, d_next_y);\n                    }\n                    \n                    if (current_val + delta_D < best_cost) {\n                        best_cost = current_val + delta_D;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            int delta = best_cost - curr_sol.total_dist;\n            if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                curr_sol.selected[rem_order] = false;\n                curr_sol.selected[new_order] = true;\n                curr_sol.route = next_route;\n                curr_sol.route.insert(curr_sol.route.begin() + best_i, new_order);\n                // Since P inserted at i, indices >= i shift by 1. \n                // If j was index in next_route, now it's j+1 relative to new array start\n                // Exception: if j=i, we insert D after P, so at i+1.\n                // If j > i, we insert after original j-1 (now j), so at j+1.\n                curr_sol.route.insert(curr_sol.route.begin() + best_j + 1, new_order + 1000);\n                curr_sol.total_dist = best_cost;\n                \n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 65) {\n            // ==========================================\n            // Move Type 2: 2-opt (Reverse segment)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int l = rng.next_int(sz - 1);\n            int r = rng.next_int(sz - l - 1) + l + 1; // l < r < sz\n            \n            // Validity Check: Reversed segment [l, r] must not contain P_k and D_k for any k.\n            // Efficient check:\n            bool valid = true;\n            \n            // Fill cache for current route positions\n            for(int k=0; k<sz; ++k) pos_cache[curr_sol.route[k]] = k;\n            \n            for(int k=l; k<=r; ++k) {\n                int val = curr_sol.route[k];\n                int partner = (val < 1000) ? val + 1000 : val - 1000;\n                // If partner is also in [l, r], invalid\n                int p_idx = pos_cache[partner];\n                if (p_idx >= l && p_idx <= r) {\n                    valid = false;\n                    break;\n                }\n            }\n            \n            if (valid) {\n                Node n_prev = (l==0) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[l-1]);\n                Node n_l = get_node(curr_sol.route[l]);\n                Node n_r = get_node(curr_sol.route[r]);\n                Node n_next = (r==sz-1) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[r+1]);\n                \n                int cur_seg = dist(n_prev.x, n_prev.y, n_l.x, n_l.y) + dist(n_r.x, n_r.y, n_next.x, n_next.y);\n                int new_seg = dist(n_prev.x, n_prev.y, n_r.x, n_r.y) + dist(n_l.x, n_l.y, n_next.x, n_next.y);\n                \n                int delta = new_seg - cur_seg;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    reverse(curr_sol.route.begin() + l, curr_sol.route.begin() + r + 1);\n                    curr_sol.total_dist += delta;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n\n        } else {\n            // ==========================================\n            // Move Type 3: Relocate (Move single node)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int u = rng.next_int(sz); // Node to move\n            int v = rng.next_int(sz); // Target: insert after v (if v=-1, start)\n            // To simplify, let's say we pick index `ins_idx` in the route *after removal*.\n            // Range 0 to sz-1.\n            \n            if (u == v) continue;\n            \n            // Logic: remove u, insert at v (relative to original indices is tricky).\n            // Let's form candidate vector to check validity/cost simply,\n            // relying on vector speed for small N=100.\n            \n            vector<int> next_route = curr_sol.route;\n            int val = next_route[u];\n            next_route.erase(next_route.begin() + u);\n            \n            // Insert position logic: \n            // We picked random v in range [0, sz-1].\n            // We interpret v as the index to insert *at* in the reduced vector.\n            int ins_idx = v; \n            if (ins_idx > (int)next_route.size()) ins_idx = next_route.size();\n            \n            // Precedence check\n            int partner = (val < 1000) ? val + 1000 : val - 1000;\n            int p_idx = -1;\n            for(int k=0; k<(int)next_route.size(); ++k) {\n                if (next_route[k] == partner) { p_idx = k; break; }\n            }\n            \n            bool ok = true;\n            if (val < 1000) { // Moving Pickup\n                // Must be before Delivery (p_idx)\n                if (ins_idx > p_idx) ok = false;\n            } else { // Moving Delivery\n                // Must be after Pickup (p_idx)\n                if (ins_idx <= p_idx) ok = false;\n            }\n            \n            if (ok) {\n                next_route.insert(next_route.begin() + ins_idx, val);\n                int new_dist = calc_route_dist(next_route);\n                int delta = new_dist - curr_sol.total_dist;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    curr_sol.route = next_route;\n                    curr_sol.total_dist = new_dist;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n        }\n    }\n\n    // Output Formatting\n    // 1. Output m and selected orders\n    vector<int> selected_ids;\n    set<int> seen;\n    for(int val : best_sol.route) {\n        int ord = (val < 1000) ? val : val - 1000;\n        if(seen.find(ord) == seen.end()) {\n            selected_ids.push_back(ord + 1); // 1-based index for output\n            seen.insert(ord);\n        }\n    }\n    \n    cout << selected_ids.size();\n    for(int id : selected_ids) cout << \" \" << id;\n    cout << \"\\n\";\n    \n    // 2. Output route coordinates\n    cout << best_sol.route.size() + 2 << \" \" << OFFICE_X << \" \" << OFFICE_Y;\n    for(int val : best_sol.route) {\n        Node n = get_node(val);\n        cout << \" \" << n.x << \" \" << n.y;\n    }\n    cout << \" \" << OFFICE_X << \" \" << OFFICE_Y << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Global constants and data structures\nconst int N_FIXED = 400;\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    int d;\n    int id;\n};\n\nstruct ContractedEdge {\n    int u_c, v_c; // component leaders\n    int d_val;\n    int original_idx;\n};\n\nint N, M;\nvector<Point> points;\nvector<EdgeInfo> all_edges;\nvector<int> min_d_vals; // Helper for filtering\n\n// Random number generator\nmt19937 rng(12345);\n\n// Custom lightweight DSU for simulation speed\nstruct FastDSU {\n    vector<int> parent;\n    FastDSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    void reset() {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        // Path compression\n        int root = i;\n        while (root != parent[root]) root = parent[root];\n        int curr = i;\n        while (curr != root) {\n            int next = parent[curr];\n            parent[curr] = root;\n            curr = next;\n        }\n        return root;\n    }\n    bool unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n            return true;\n        }\n        return false;\n    }\n};\n\nint calc_dist(int i, int j) {\n    long long dx = points[i].x - points[j].x;\n    long long dy = points[i].y - points[j].y;\n    return (int)round(sqrt(dx*dx + dy*dy));\n}\n\n// Time management\nconst double TIME_LIMIT = 1.85; \nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_elapsed_time() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nint main() {\n    // Setup IO\n    ios_base::sync_with_stdio(false);\n    // cin.tie(NULL); // Interactive problem, but we flush with endl\n\n    if (!(cin >> N >> M)) return 0;\n    \n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n    \n    all_edges.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> all_edges[i].u >> all_edges[i].v;\n        all_edges[i].d = calc_dist(all_edges[i].u, all_edges[i].v);\n        all_edges[i].id = i;\n    }\n\n    // Buffer for filtering edges\n    min_d_vals.assign(N * N, 1000000);\n    \n    // Main DSU for tracking actual connected components\n    dsu main_dsu(N);\n    int components = N;\n    \n    // Reusable DSU for simulations\n    FastDSU sim_dsu(N);\n    \n    // Pre-allocate vectors for simulation\n    vector<pair<int, int>> weighted_edges;\n    weighted_edges.reserve(M);\n    vector<int> spans;\n    spans.reserve(M);\n    \n    // BFS structures for bridge check\n    vector<vector<int>> adj(N);\n    vector<int> q_bfs; q_bfs.reserve(N);\n    vector<bool> visited(N);\n\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        \n        int u = all_edges[i].u;\n        int v = all_edges[i].v;\n        \n        // 1. If u and v are already connected, reject immediately (cycle).\n        if (main_dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // 2. Filter and prepare future edges\n        // We only care about edges that connect different components.\n        // We also prune edges that are strictly worse than others (d > 3*min_d).\n        \n        vector<ContractedEdge> future_edges;\n        future_edges.reserve(M - 1 - i);\n        vector<int> active_pairs;\n        active_pairs.reserve(M - 1 - i);\n        \n        // Pass 1: Find min d for each pair of components\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.leader(all_edges[j].u);\n            int rv = main_dsu.leader(all_edges[j].v);\n            if (ru == rv) continue;\n            if (ru > rv) swap(ru, rv);\n            int idx = ru * N + rv;\n            \n            if (min_d_vals[idx] == 1000000) {\n                active_pairs.push_back(idx);\n            }\n            if (all_edges[j].d < min_d_vals[idx]) {\n                min_d_vals[idx] = all_edges[j].d;\n            }\n        }\n        \n        // Pass 2: Collect valid future edges\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.leader(all_edges[j].u);\n            int rv = main_dsu.leader(all_edges[j].v);\n            if (ru == rv) continue;\n            if (ru > rv) swap(ru, rv);\n            int idx = ru * N + rv;\n            \n            // Pruning heuristic\n            if (all_edges[j].d > 3 * min_d_vals[idx]) continue;\n            \n            future_edges.push_back({ru, rv, all_edges[j].d, j});\n        }\n        \n        // Reset min_d_vals\n        for (int idx : active_pairs) min_d_vals[idx] = 1000000;\n        \n        int ru_curr = main_dsu.leader(u);\n        int rv_curr = main_dsu.leader(v);\n\n        // 3. Bridge Check\n        // Check if connectivity is possible without the current edge using only future edges\n        for(int k=0; k<N; ++k) adj[k].clear();\n        for(const auto& e : future_edges) {\n            adj[e.u_c].push_back(e.v_c);\n            adj[e.v_c].push_back(e.u_c);\n        }\n        \n        fill(visited.begin(), visited.end(), false);\n        q_bfs.clear();\n        q_bfs.push_back(ru_curr);\n        visited[ru_curr] = true;\n        \n        bool connected = false;\n        int head = 0;\n        while(head < (int)q_bfs.size()){\n            int curr = q_bfs[head++];\n            if (curr == rv_curr) {\n                connected = true;\n                break;\n            }\n            for(int nxt : adj[curr]){\n                if(!visited[nxt]){\n                    visited[nxt] = true;\n                    q_bfs.push_back(nxt);\n                }\n            }\n        }\n        \n        if (!connected) {\n            // Must accept to maintain connectivity\n            cout << 1 << endl;\n            main_dsu.merge(u, v);\n            components--;\n            continue;\n        }\n        \n        // 4. Monte Carlo Simulation\n        double elapsed = get_elapsed_time();\n        double rem_time = TIME_LIMIT - elapsed;\n        int steps_left = M - 1 - i;\n        // Allocate time budget for this step\n        double budget = rem_time / (steps_left + 20); \n        \n        long long sum_accept = 0;\n        long long sum_reject = 0;\n        int sims = 0;\n        \n        auto sim_start_t = chrono::high_resolution_clock::now();\n        \n        weighted_edges.resize(future_edges.size());\n        spans.resize(future_edges.size());\n        for(size_t k=0; k<future_edges.size(); ++k) {\n            spans[k] = 2 * future_edges[k].d_val + 1;\n        }\n\n        do {\n            sims++;\n            // Generate random weights for future edges\n            for (size_t k = 0; k < future_edges.size(); ++k) {\n                unsigned int r = rng();\n                int w = future_edges[k].d_val + (r % spans[k]);\n                weighted_edges[k] = {w, (int)k};\n            }\n            \n            // Kruskal's requires sorted edges\n            sort(weighted_edges.begin(), weighted_edges.end());\n            \n            // Calculate MST cost given a starting state (merge_uv or not)\n            auto get_mst_cost = [&](bool merge_uv) {\n                sim_dsu.reset();\n                int edges_needed = components - 1;\n                if (merge_uv) {\n                    sim_dsu.unite(ru_curr, rv_curr);\n                    edges_needed--;\n                }\n                \n                long long cost = 0;\n                int cnt = 0;\n                // If already connected (edges_needed <= 0), cost is 0\n                if (cnt >= edges_needed) return cost;\n\n                for (const auto& p : weighted_edges) {\n                    const auto& e = future_edges[p.second];\n                    if (sim_dsu.unite(e.u_c, e.v_c)) {\n                        cost += p.first;\n                        cnt++;\n                        if (cnt >= edges_needed) break;\n                    }\n                }\n                return cost;\n            };\n            \n            sum_accept += (l_i + get_mst_cost(true));\n            sum_reject += get_mst_cost(false);\n            \n            // Check time every 16 iterations to minimize overhead\n            if ((sims & 15) == 0) {\n                auto now = chrono::high_resolution_clock::now();\n                chrono::duration<double> d_sim = now - sim_start_t;\n                if (d_sim.count() > budget) break;\n            }\n            \n        } while (sims < 500); // Safety cap\n        \n        // Decision\n        if (sum_accept < sum_reject) {\n            cout << 1 << endl;\n            main_dsu.merge(u, v);\n            components--;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"/**\n * AtCoder Heuristic Contest 008\n * Problem: Build partitions to isolate pets and maximize area for humans.\n * Strategy:\n * 1. Layout Strategy:\n *    - We adopt a \"Honeycomb Trap\" strategy. We pre-design a skeleton of walls that divides the 30x30 grid \n *      into 25 smaller regions (approx 5x5 or 6x6 in size).\n *    - The skeleton consists of horizontal and vertical walls at specific intervals.\n *    - Crucially, we designate specific segments of these walls as \"Gates\". These are initially left open \n *      to allow humans to traverse and to keep the \"Clean\" (pet-free) area connected and large.\n *\n * 2. Dynamic Logic (Per Turn):\n *    - We analyze the grid to identify connected components. Components are classified as \"Dirty\" \n *      (contain pets) or \"Clean\" (no pets).\n *    - Humans are assigned tasks based on a priority system:\n *      a. ESCAPE: If a human is in a Dirty component, their top priority is to move to a Clean component.\n *      b. ISOLATE: If a Gate connects a Dirty component to a Clean component, we must build it immediately \n *         to stop the pets from spreading.\n *      c. FRAGMENT: If a Gate connects two Dirty components, we build it to split the pets, making them \n *         easier to contain.\n *      d. CONSTRUCT: If no urgent Gates need closing, humans build the non-Gate skeleton walls to prepare \n *         the trap structure.\n *    - We use a greedy assignment algorithm to match humans to tasks based on distance and priority.\n *\n * 3. Safety & Coordination:\n *    - We strictly adhere to the rule: \"Cannot block a square if a pet is adjacent.\"\n *    - We resolve conflicts to ensure no two humans move to the same square or block a square someone is moving into.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\n// --- Constants ---\nconst int N_ROWS = 30;\nconst int N_COLS = 30;\nconst int MAX_TURNS = 300;\n\n// Directions: Up, Down, Left, Right\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'};\n\n// --- Data Structures ---\nstruct Pet {\n    int id;\n    int r, c; // 0-based coordinates\n    int type;\n};\n\nstruct Human {\n    int id;\n    int r, c; // 0-based coordinates\n};\n\nstruct State {\n    vector<Pet> pets;\n    vector<Human> humans;\n    bool walls[N_ROWS][N_COLS]; // true if wall exists\n};\n\n// --- Global Plan ---\n// We precompute where walls and gates should be.\nbool plan_skeleton[N_ROWS][N_COLS];\nbool plan_gate[N_ROWS][N_COLS];\n\nvoid init_plan() {\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c) {\n            plan_skeleton[r][c] = false;\n            plan_gate[r][c] = false;\n        }\n\n    // Define grid lines for walls\n    // Rows/Cols indices: 5, 11, 17, 23\n    vector<int> lines = {5, 11, 17, 23};\n    \n    // Mark skeleton walls\n    for (int r : lines) {\n        for (int c = 0; c < N_COLS; ++c) plan_skeleton[r][c] = true;\n    }\n    for (int c : lines) {\n        for (int r = 0; r < N_ROWS; ++r) plan_skeleton[r][c] = true;\n    }\n    \n    // Define Gates\n    // Gates are midpoints of the wall segments between intersections.\n    // Segments approximate ranges: 0-4, 6-10, 12-16, 18-22, 24-29.\n    // Midpoints: 2, 8, 14, 20, 27.\n    vector<int> gates_idx = {2, 8, 14, 20, 27};\n    \n    for (int r : lines) {\n        for(int c : gates_idx) plan_gate[r][c] = true;\n    }\n    for (int c : lines) {\n        for(int r : gates_idx) plan_gate[r][c] = true;\n    }\n    \n    // Intersections should be solid walls, not gates\n    for(int r : lines) {\n        for(int c : lines) {\n            plan_gate[r][c] = false;\n        }\n    }\n}\n\n// --- Helper Functions ---\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_ROWS && c >= 0 && c < N_COLS;\n}\n\n// Check if blocking (r,c) is safe regarding pets\n// Rule: Cannot choose a square whose adjacent square contains a pet.\nbool is_safe_to_block(int r, int c, const vector<Pet>& pets) {\n    for(const auto& p : pets) {\n        // Check Manhattan distance <= 1 (Adjacent or Same square)\n        if (abs(p.r - r) + abs(p.c - c) <= 1) return false;\n    }\n    return true;\n}\n\n// Component Analysis\nstruct ComponentInfo {\n    int id;\n    bool has_pet;\n    int size;\n    vector<pair<int,int>> cells;\n};\n\n// BFS to find connected components of free space\nvoid analyze_components(const State& state, vector<vector<int>>& comp_map, vector<ComponentInfo>& comps) {\n    comp_map.assign(N_ROWS, vector<int>(N_COLS, -1));\n    comps.clear();\n    \n    for (int r = 0; r < N_ROWS; ++r) {\n        for (int c = 0; c < N_COLS; ++c) {\n            if (!state.walls[r][c] && comp_map[r][c] == -1) {\n                int cid = comps.size();\n                ComponentInfo info;\n                info.id = cid;\n                info.has_pet = false;\n                info.size = 0;\n                \n                queue<pair<int,int>> q;\n                q.push({r, c});\n                comp_map[r][c] = cid;\n                \n                while(!q.empty()){\n                    auto [curr_r, curr_c] = q.front();\n                    q.pop();\n                    info.cells.push_back({curr_r, curr_c});\n                    info.size++;\n                    \n                    for(int i=0; i<4; ++i){\n                        int nr = curr_r + DR[i];\n                        int nc = curr_c + DC[i];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc] && comp_map[nr][nc] == -1){\n                            comp_map[nr][nc] = cid;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                comps.push_back(info);\n            }\n        }\n    }\n    \n    // Mark components containing pets\n    for(const auto& p : state.pets) {\n        if (comp_map[p.r][p.c] != -1) {\n            comps[comp_map[p.r][p.c]].has_pet = true;\n        }\n    }\n}\n\n// Multi-target BFS for pathfinding\n// Returns direction (0-3) for the first step, or -1 if no path\n// blocked_reserved: walls being built this turn\n// occupied_reserved: squares other humans are moving into\nint get_move_towards_targets(int start_r, int start_c, \n                             const vector<pair<int,int>>& targets, \n                             const bool walls[N_ROWS][N_COLS], \n                             const vector<vector<bool>>& blocked_reserved, \n                             const vector<vector<bool>>& occupied_reserved) {\n    \n    queue<pair<int,int>> q;\n    q.push({start_r, start_c});\n    \n    // dist array\n    vector<vector<int>> dist(N_ROWS, vector<int>(N_COLS, 1e9));\n    // parent array to reconstruct path\n    vector<vector<pair<int,int>>> parent(N_ROWS, vector<pair<int,int>>(N_COLS, {-1, -1}));\n    \n    dist[start_r][start_c] = 0;\n    \n    bool found = false;\n    int found_r = -1, found_c = -1;\n    \n    // Optimization: check if start is target (should move? usually dist=0 implies stay, handled by caller)\n    \n    while(!q.empty()){\n        auto [cr, cc] = q.front();\n        q.pop();\n        \n        // Check if reached any target\n        for(const auto& t : targets){\n            if(t.first == cr && t.second == cc){\n                found = true;\n                found_r = cr; found_c = cc;\n                goto end_bfs;\n            }\n        }\n        \n        for(int i=0; i<4; ++i){\n            int nr = cr + DR[i];\n            int nc = cc + DC[i];\n            \n            // Passable check\n            bool passable = is_valid(nr, nc) && !walls[nr][nc];\n            \n            // Check dynamic reservations only for the immediate next step (dist == 0)\n            if (passable && dist[cr][cc] == 0) {\n                if (blocked_reserved[nr][nc] || occupied_reserved[nr][nc]) passable = false;\n            }\n            \n            if(passable && dist[nr][nc] > dist[cr][cc] + 1){\n                dist[nr][nc] = dist[cr][cc] + 1;\n                parent[nr][nc] = {cr, cc};\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    end_bfs:;\n    \n    if(!found) return -1;\n    if(found_r == start_r && found_c == start_c) return -1; // Already there\n    \n    // Backtrack to find first step\n    int curr_r = found_r;\n    int curr_c = found_c;\n    while(parent[curr_r][curr_c].first != start_r || parent[curr_r][curr_c].second != start_c){\n        auto p = parent[curr_r][curr_c];\n        curr_r = p.first;\n        curr_c = p.second;\n    }\n    \n    // Identify direction\n    for(int i=0; i<4; ++i){\n        if(start_r + DR[i] == curr_r && start_c + DC[i] == curr_c) return i;\n    }\n    return -1;\n}\n\n// --- Main Solver ---\n\nint main() {\n    // Optimization for IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    init_plan();\n    \n    int N;\n    if (!(cin >> N)) return 0;\n    \n    State state;\n    state.pets.resize(N);\n    for(int i=0; i<N; ++i){\n        state.pets[i].id = i;\n        cin >> state.pets[i].r >> state.pets[i].c >> state.pets[i].type;\n        state.pets[i].r--; state.pets[i].c--; // Convert to 0-based\n    }\n    \n    int M;\n    cin >> M;\n    state.humans.resize(M);\n    for(int i=0; i<M; ++i){\n        state.humans[i].id = i;\n        cin >> state.humans[i].r >> state.humans[i].c;\n        state.humans[i].r--; state.humans[i].c--; // Convert to 0-based\n    }\n    \n    // Initialize walls\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c)\n            state.walls[r][c] = false;\n            \n    // Game Loop\n    for(int turn = 0; turn < MAX_TURNS; ++turn){\n        // 1. Analyze Grid\n        vector<vector<int>> comp_map;\n        vector<ComponentInfo> comps;\n        analyze_components(state, comp_map, comps);\n        \n        vector<string> actions(M, \".\");\n        vector<bool> human_busy(M, false);\n        \n        // Reservations prevents collisions\n        vector<vector<bool>> blocked_reserved(N_ROWS, vector<bool>(N_COLS, false));\n        vector<vector<bool>> occupied_reserved(N_ROWS, vector<bool>(N_COLS, false));\n        \n        // Initially mark current human positions as occupied \n        // (will be freed if they move, but important for others not to step on them if they stay)\n        for(const auto& h : state.humans) occupied_reserved[h.r][h.c] = true;\n        \n        // --- Phase 1: Escape ---\n        // If a human is in a component with pets, they must escape to a clean component.\n        for(int i=0; i<M; ++i){\n            int r = state.humans[i].r;\n            int c = state.humans[i].c;\n            int cid = comp_map[r][c];\n            \n            // If in dirty component\n            if(cid != -1 && comps[cid].has_pet){\n                // Collect targets: all cells in all clean components\n                vector<pair<int,int>> targets;\n                for(const auto& comp : comps){\n                    if(!comp.has_pet){\n                        for(auto p : comp.cells) targets.push_back(p);\n                    }\n                }\n                \n                if(targets.empty()) {\n                    // No clean component? Just try to move randomly/away (omitted for simplicity, just stay/wait)\n                    // Or target empty cells in current component to kite pets.\n                } else {\n                    occupied_reserved[r][c] = false; // Temporarily free start to allow path\n                    int dir = get_move_towards_targets(r, c, targets, state.walls, blocked_reserved, occupied_reserved);\n                    occupied_reserved[r][c] = true; \n                    \n                    if(dir != -1){\n                        actions[i] = string(1, MOVE_CHARS[dir]);\n                        occupied_reserved[r][c] = false; // Now really leaving\n                        occupied_reserved[r + DR[dir]][c + DC[dir]] = true; // Occupy dest\n                        human_busy[i] = true;\n                    }\n                }\n            }\n        }\n        \n        // --- Phase 2: Task Generation & Assignment ---\n        struct Task {\n            int r, c; // Wall location\n            int type; // 0 = gate, 1 = skeleton\n            int priority; \n        };\n        vector<Task> all_tasks;\n        \n        for(int r=0; r<N_ROWS; ++r){\n            for(int c=0; c<N_COLS; ++c){\n                // Consider only unbuilt skeleton walls\n                if(!state.walls[r][c] && plan_skeleton[r][c]){\n                    \n                    // Safety check: Pet proximity\n                    if(!is_safe_to_block(r, c, state.pets)) continue;\n                    \n                    // Check if a human is standing on the wall target (cannot build)\n                    bool standing = false;\n                    for(const auto& h : state.humans) if(h.r == r && h.c == c) standing = true;\n                    if(standing) continue;\n\n                    Task t;\n                    t.r = r; t.c = c;\n                    t.type = plan_gate[r][c] ? 0 : 1;\n                    \n                    // Determine Priority\n                    if(t.type == 1) {\n                        // Non-gate skeleton wall. Base priority.\n                        // Slightly higher priority if it helps fragment space? \n                        t.priority = 100; \n                    } else {\n                        // Gate logic\n                        set<int> neighbor_comps;\n                        for(int k=0; k<4; ++k){\n                            int nr = r + DR[k];\n                            int nc = c + DC[k];\n                            if(is_valid(nr,nc) && !state.walls[nr][nc]){\n                                int cid = comp_map[nr][nc];\n                                if(cid != -1) neighbor_comps.insert(cid);\n                            }\n                        }\n                        \n                        bool connects_dirty = false;\n                        bool connects_clean = false;\n                        for(int cid : neighbor_comps){\n                            if(comps[cid].has_pet) connects_dirty = true;\n                            else connects_clean = true;\n                        }\n                        \n                        if(connects_dirty && connects_clean) t.priority = 10000; // Critical: Seal Dirty from Clean\n                        else if(connects_dirty) t.priority = 5000; // High: Fragment Dirty\n                        else t.priority = 10; // Low: Connects Clean-Clean (Keep open unless finished)\n                    }\n                    all_tasks.push_back(t);\n                }\n            }\n        }\n        \n        // Score (Human, Task) pairs\n        struct Candidate {\n            int h_idx;\n            int t_idx;\n            double score;\n        };\n        vector<Candidate> candidates;\n        \n        for(int i=0; i<M; ++i){\n            if(human_busy[i]) continue;\n            \n            for(int j=0; j<(int)all_tasks.size(); ++j){\n                int tr = all_tasks[j].r;\n                int tc = all_tasks[j].c;\n                \n                // Valid build spots are neighbors of the wall\n                int min_dist = 1e9;\n                bool possible = false;\n                \n                for(int k=0; k<4; ++k){\n                    int nr = tr + DR[k];\n                    int nc = tc + DC[k];\n                    if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                        // Simple Manhattan distance as heuristic\n                        int d = abs(state.humans[i].r - nr) + abs(state.humans[i].c - nc);\n                        min_dist = min(min_dist, d);\n                        possible = true;\n                    }\n                }\n                \n                if(possible){\n                    // Score = Priority * K - Distance\n                    // Higher is better\n                    double score = all_tasks[j].priority * 100.0 - min_dist;\n                    candidates.push_back({i, j, score});\n                }\n            }\n        }\n        \n        // Sort candidates by score descending\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.score > b.score;\n        });\n        \n        vector<bool> task_taken(all_tasks.size(), false);\n        \n        // Assign tasks\n        for(const auto& cand : candidates){\n            int h = cand.h_idx;\n            if(human_busy[h]) continue;\n            if(task_taken[cand.t_idx]) continue;\n            \n            int tr = all_tasks[cand.t_idx].r;\n            int tc = all_tasks[cand.t_idx].c;\n            \n            // Identify valid build spots (neighbors)\n            vector<pair<int,int>> build_spots;\n            for(int k=0; k<4; ++k){\n                int nr = tr + DR[k];\n                int nc = tc + DC[k];\n                // Spot must be valid, not a wall, not reserved by other block, not occupied by static human\n                bool ok = is_valid(nr, nc) && !state.walls[nr][nc] && !blocked_reserved[nr][nc];\n                \n                // Static human check (other than self)\n                if(ok) {\n                    for(int other=0; other<M; ++other){\n                        if(other != h && state.humans[other].r == nr && state.humans[other].c == nc) ok = false;\n                    }\n                }\n                \n                if(ok) build_spots.push_back({nr, nc});\n            }\n            \n            if(build_spots.empty()) continue;\n\n            // Move logic\n            occupied_reserved[state.humans[h].r][state.humans[h].c] = false;\n            int dir = get_move_towards_targets(state.humans[h].r, state.humans[h].c, build_spots, state.walls, blocked_reserved, occupied_reserved);\n            occupied_reserved[state.humans[h].r][state.humans[h].c] = true;\n            \n            if(dir != -1){\n                // Moving towards spot\n                actions[h] = string(1, MOVE_CHARS[dir]);\n                occupied_reserved[state.humans[h].r][state.humans[h].c] = false;\n                occupied_reserved[state.humans[h].r + DR[dir]][state.humans[h].c + DC[dir]] = true;\n                human_busy[h] = true;\n                task_taken[cand.t_idx] = true;\n            } else {\n                // Check if already at a build spot\n                bool at_spot = false;\n                for(auto p : build_spots) if(state.humans[h].r == p.first && state.humans[h].c == p.second) at_spot = true;\n                \n                if(at_spot){\n                    // Build!\n                    int b_dir = -1;\n                    for(int k=0; k<4; ++k){\n                        if(state.humans[h].r + DR[k] == tr && state.humans[h].c + DC[k] == tc) b_dir = k;\n                    }\n                    if(b_dir != -1){\n                        actions[h] = string(1, BLOCK_CHARS[b_dir]);\n                        human_busy[h] = true;\n                        task_taken[cand.t_idx] = true;\n                        blocked_reserved[tr][tc] = true;\n                    }\n                }\n            }\n        }\n        \n        // --- Output ---\n        string ans = \"\";\n        for(const auto& s : actions) ans += s;\n        cout << ans << endl; // endl flushes\n        \n        // --- Update State Locally ---\n        // Walls\n        for(int i=0; i<M; ++i){\n            char c = actions[i][0];\n            if(c >= 'a' && c <= 'z'){ // Block\n                for(int k=0; k<4; ++k){\n                    if(BLOCK_CHARS[k] == c){\n                        int tr = state.humans[i].r + DR[k];\n                        int tc = state.humans[i].c + DC[k];\n                        if(is_valid(tr, tc)) state.walls[tr][tc] = true;\n                    }\n                }\n            } else if(c >= 'A' && c <= 'Z'){ // Move\n                for(int k=0; k<4; ++k){\n                    if(MOVE_CHARS[k] == c){\n                        state.humans[i].r += DR[k];\n                        state.humans[i].c += DC[k];\n                    }\n                }\n            }\n        }\n        \n        // Read Pet Moves\n        if(turn < MAX_TURNS) { // Read N strings\n            string pet_input;\n            for(int i=0; i<N; ++i){\n                cin >> pet_input;\n                for(char c : pet_input){\n                    for(int k=0; k<4; ++k){\n                        if(MOVE_CHARS[k] == c){\n                            state.pets[i].r += DR[k];\n                            state.pets[i].c += DC[k];\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_STEPS = 200;\nconst int BEAM_WIDTH = 800; \nconst double EPS = 1e-12;\n\n// Globals\nint Si, Sj, Ti, Tj;\ndouble P;\nint H[N][N-1]; // Horizontal walls\nint V[N-1][N]; // Vertical walls\nint dist_mat[N][N];\nint flat_dist[N*N];\n\n// Directions: U, D, L, R\n// dr, dc\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dchar[4] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    string s;\n    vector<double> probs; // flattened 20x20 probability distribution\n    double score; \n    double heuristic; \n\n    // For descending sort/selection\n    bool operator>(const State& other) const {\n        return heuristic > other.heuristic;\n    }\n};\n\n// Compute shortest path distances from all cells to target using BFS\nvoid bfs_distances() {\n    for(int i=0; i<N; ++i) fill(dist_mat[i], dist_mat[i]+N, 100000);\n    queue<pair<int,int>> q;\n    dist_mat[Ti][Tj] = 0;\n    q.push({Ti, Tj});\n    \n    while(!q.empty()){\n        auto [r, c] = q.front();\n        q.pop();\n        \n        // Check all 4 directions for valid moves (reverse of normal moves)\n        // U: neighbor is (r-1, c), connected via V[r-1][c]\n        if (r > 0 && V[r-1][c] == 0) {\n            if (dist_mat[r-1][c] > dist_mat[r][c] + 1) {\n                dist_mat[r-1][c] = dist_mat[r][c] + 1;\n                q.push({r-1, c});\n            }\n        }\n        // D: neighbor is (r+1, c), connected via V[r][c]\n        if (r < N-1 && V[r][c] == 0) {\n            if (dist_mat[r+1][c] > dist_mat[r][c] + 1) {\n                dist_mat[r+1][c] = dist_mat[r][c] + 1;\n                q.push({r+1, c});\n            }\n        }\n        // L: neighbor is (r, c-1), connected via H[r][c-1]\n        if (c > 0 && H[r][c-1] == 0) {\n            if (dist_mat[r][c-1] > dist_mat[r][c] + 1) {\n                dist_mat[r][c-1] = dist_mat[r][c] + 1;\n                q.push({r, c-1});\n            }\n        }\n        // R: neighbor is (r, c+1), connected via H[r][c]\n        if (c < N-1 && H[r][c] == 0) {\n            if (dist_mat[r][c+1] > dist_mat[r][c] + 1) {\n                dist_mat[r][c+1] = dist_mat[r][c] + 1;\n                q.push({r, c+1});\n            }\n        }\n    }\n    // Flatten for faster access\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            flat_dist[i*N+j] = dist_mat[i][j];\n}\n\nint main(){\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> Si >> Sj >> Ti >> Tj >> P)) return 0;\n\n    // Read Horizontal walls\n    for(int i=0; i<N; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N-1; ++j) H[i][j] = s[j] - '0';\n    }\n    // Read Vertical walls\n    for(int i=0; i<N-1; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) V[i][j] = s[j] - '0';\n    }\n    \n    bfs_distances();\n    \n    double inv_prob = 1.0 / (1.0 - P);\n    int target_idx = Ti*N + Tj;\n\n    State initial;\n    initial.s = \"\";\n    initial.probs.resize(N*N, 0.0);\n    initial.probs[Si*N + Sj] = 1.0;\n    initial.score = 0.0;\n    \n    if(Si == Ti && Sj == Tj) {\n        initial.heuristic = 0; \n    } else {\n        double dist = flat_dist[Si*N + Sj];\n        initial.heuristic = initial.score + 1.0 * (401.0 - (0.0 + dist * inv_prob)); \n    }\n\n    vector<State> beam;\n    beam.reserve(BEAM_WIDTH * 4);\n    beam.push_back(initial);\n    \n    for(int t=0; t<MAX_STEPS; ++t){\n        vector<State> next_beam;\n        next_beam.reserve(beam.size() * 4);\n        \n        for(const auto& st : beam){\n            // Try all 4 directions\n            for(int k=0; k<4; ++k){\n                State nst;\n                nst.s = st.s + dchar[k];\n                nst.probs.assign(N*N, 0.0); \n                nst.score = st.score;\n                \n                // Update distribution based on move\n                for(int idx=0; idx<N*N; ++idx){\n                    if(st.probs[idx] < EPS) continue;\n                    \n                    double p_val = st.probs[idx];\n                    int r = idx / N;\n                    int c = idx % N;\n                    \n                    // 1. Stay with probability P\n                    nst.probs[idx] += p_val * P;\n                    \n                    // 2. Move with probability 1-P\n                    bool blocked = false;\n                    if(k == 0){ // U\n                        if(r == 0 || V[r-1][c] == 1) blocked = true;\n                    } else if(k == 1){ // D\n                        if(r == N-1 || V[r][c] == 1) blocked = true;\n                    } else if(k == 2){ // L\n                        if(c == 0 || H[r][c-1] == 1) blocked = true;\n                    } else if(k == 3){ // R\n                        if(c == N-1 || H[r][c] == 1) blocked = true;\n                    }\n                    \n                    if(blocked){\n                        // Hit wall, stay\n                        nst.probs[idx] += p_val * (1.0 - P);\n                    } else {\n                        // Move success\n                        int nr = r + dr[k];\n                        int nc = c + dc[k];\n                        nst.probs[nr*N + nc] += p_val * (1.0 - P);\n                    }\n                }\n                \n                // Handle probability mass arriving at target\n                if(nst.probs[target_idx] > EPS){\n                    double arrived = nst.probs[target_idx];\n                    // Score for arriving at step t+1 is 401 - (t+1)\n                    nst.score += arrived * (401.0 - (t + 1));\n                    // Remove mass from grid so it's not simulated further\n                    nst.probs[target_idx] = 0.0;\n                }\n                \n                // Compute heuristic efficiently in one pass\n                double M = 0.0; // Remaining mass\n                double Wu = 0.0; // Weighted expected steps\n                for(int idx=0; idx<N*N; ++idx){\n                    if(nst.probs[idx] > EPS){\n                        M += nst.probs[idx];\n                        Wu += nst.probs[idx] * flat_dist[idx];\n                    }\n                }\n                \n                // Heuristic: Score so far + Expected score of remaining mass\n                // Expected arrival time ~ current_time + dist / (1-P)\n                nst.heuristic = nst.score + M * (401.0 - (t + 1)) - Wu * inv_prob;\n                \n                next_beam.push_back(std::move(nst));\n            }\n        }\n        \n        // Select top BEAM_WIDTH candidates\n        if(next_beam.size() > BEAM_WIDTH){\n            nth_element(next_beam.begin(), next_beam.begin() + BEAM_WIDTH, next_beam.end(), \n                [](const State& a, const State& b){\n                    return a.heuristic > b.heuristic;\n                });\n            next_beam.resize(BEAM_WIDTH);\n        }\n        beam = std::move(next_beam);\n    }\n    \n    // Find best solution in the final beam\n    double best_h = -1e18;\n    string best_s = \"\";\n    for(const auto& st : beam){\n        if(st.heuristic > best_h){\n            best_h = st.heuristic;\n            best_s = st.s;\n        }\n    }\n    \n    cout << best_s << endl;\n    \n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// Map (type, entry_dir) -> exit_dir\n// -1 if no connection\nint to[8][4];\n\nvoid init_tables() {\n    // Initialize with -1\n    for(int t=0; t<8; ++t) for(int d=0; d<4; ++d) to[t][d] = -1;\n\n    // 0: Left(0)-Up(1)\n    to[0][0] = 1; to[0][1] = 0;\n    // 1: Left(0)-Down(3)\n    to[1][0] = 3; to[1][3] = 0;\n    // 2: Right(2)-Down(3)\n    to[2][2] = 3; to[2][3] = 2;\n    // 3: Right(2)-Up(1)\n    to[3][2] = 1; to[3][1] = 2;\n    \n    // 4: Left(0)-Up(1) & Right(2)-Down(3)\n    to[4][0] = 1; to[4][1] = 0;\n    to[4][2] = 3; to[4][3] = 2;\n    \n    // 5: Left(0)-Down(3) & Right(2)-Up(1)\n    to[5][0] = 3; to[5][3] = 0;\n    to[5][2] = 1; to[5][1] = 2;\n    \n    // 6: Up(1)-Down(3) (Vertical)\n    to[6][1] = 3; to[6][3] = 1;\n    \n    // 7: Left(0)-Right(2) (Horizontal)\n    to[7][0] = 2; to[7][2] = 0;\n}\n\n// Calculate the effective tile type after r counter-clockwise rotations\nint get_rotated_type(int t, int r) {\n    for (int k = 0; k < r; ++k) {\n        if (t >= 0 && t <= 3) {\n            t = (t + 1) % 4;\n        } else if (t == 4) {\n            t = 5;\n        } else if (t == 5) {\n            t = 4;\n        } else if (t == 6) {\n            t = 7;\n        } else if (t == 7) {\n            t = 6;\n        }\n    }\n    return t;\n}\n\nstruct State {\n    int rots[30][30];\n    int types[30][30]; // Cached actual types for performance\n};\n\nint initial_types[30][30];\nState current_state;\nState best_state;\nlong long best_score_real = -1;\n\n// Random number generator\nmt19937 rng(12345);\n\n// Visited array for loop detection\n// Dimensions: [row][col][entry_direction]\n// We use a generation counter to avoid memset\nint visited[30][30][4];\nint gen = 0;\n\nlong long evaluate(const State& st, vector<int>& loop_lengths) {\n    gen++;\n    // In case of overflow (extremely unlikely), reset\n    if (gen <= 0) {\n        memset(visited, 0, sizeof(visited));\n        gen = 1;\n    }\n\n    loop_lengths.clear();\n    vector<int> path_lengths; \n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int t = st.types[i][j];\n            for (int d = 0; d < 4; ++d) {\n                // Only process if valid entry and not visited\n                if (visited[i][j][d] == gen) continue;\n                if (to[t][d] == -1) continue;\n\n                // Start tracing\n                int curr_i = i;\n                int curr_j = j;\n                int curr_d = d; // Entry direction\n                int len = 0;\n                bool is_loop = false;\n                \n                int start_i = i;\n                int start_j = j;\n                int start_d = d;\n\n                while (true) {\n                    visited[curr_i][curr_j][curr_d] = gen;\n                    \n                    // Determine exit direction from current tile\n                    int out_d = to[st.types[curr_i][curr_j]][curr_d];\n                    \n                    // Mark the reverse direction on this tile as visited too\n                    // effectively marking the track segment\n                    visited[curr_i][curr_j][out_d] = gen; \n\n                    len++;\n                    \n                    // Move to neighbor\n                    int ni = curr_i + di[out_d];\n                    int nj = curr_j + dj[out_d];\n                    \n                    // Check bounds\n                    if (ni < 0 || ni >= 30 || nj < 0 || nj >= 30) {\n                        is_loop = false;\n                        break;\n                    }\n                    \n                    // Determine entry direction into neighbor\n                    // Entering neighbor (ni, nj) from direction opposite to out_d\n                    int next_entry_d = (out_d + 2) % 4;\n                    \n                    // Check if neighbor connects back\n                    if (to[st.types[ni][nj]][next_entry_d] == -1) {\n                        is_loop = false;\n                        break;\n                    }\n\n                    // Check if we hit a visited state\n                    if (visited[ni][nj][next_entry_d] == gen) {\n                        // If we returned to start, it's a loop\n                        if (ni == start_i && nj == start_j && next_entry_d == start_d) {\n                            is_loop = true;\n                        } else {\n                            // We hit the current path somewhere else, or a previously visited component.\n                            // Due to graph degree <= 2, hitting !start means we merged into a previous component.\n                            // Previous components are fully explored, so this is a path ending in a merge.\n                            is_loop = false;\n                        }\n                        break;\n                    }\n                    \n                    curr_i = ni;\n                    curr_j = nj;\n                    curr_d = next_entry_d;\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(len);\n                } else {\n                    path_lengths.push_back(len);\n                }\n            }\n        }\n    }\n    \n    sort(loop_lengths.rbegin(), loop_lengths.rend());\n    \n    long long score = 0;\n    \n    // Primary objective: Maximize product of two longest loops\n    // We use a large multiplier to ensure any valid solution (2 loops) \n    // is strictly better than any invalid solution.\n    if (loop_lengths.size() >= 2) {\n        long long prod = (long long)loop_lengths[0] * loop_lengths[1];\n        score = prod * 1000000LL;\n    }\n    \n    // Secondary objective: Maximize loop lengths (sum of squares)\n    for (int l : loop_lengths) {\n        score += l * l;\n    }\n    \n    // Tertiary objective: Maximize path lengths (encourage connectivity)\n    for (int p : path_lengths) {\n        score += (p * p) / 10; \n    }\n\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_tables();\n    \n    // Input\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            initial_types[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Random initialization\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            current_state.rots[i][j] = rng() % 4;\n            current_state.types[i][j] = get_rotated_type(initial_types[i][j], current_state.rots[i][j]);\n        }\n    }\n    \n    vector<int> loops;\n    best_score_real = -1;\n    \n    auto start_time = chrono::steady_clock::now();\n    // Reserve a small buffer from 2.0s\n    double time_limit = 1.95;\n    \n    long long current_score_aug = evaluate(current_state, loops);\n    best_state = current_state;\n    if (loops.size() >= 2) best_score_real = (long long)loops[0] * loops[1];\n    else best_score_real = 0;\n    \n    // Simulated Annealing parameters\n    double t0 = 50000.0;\n    double t1 = 1.0;\n    double temp = t0;\n    int iter = 0;\n    \n    while (true) {\n        iter++;\n        \n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Exponential cooling\n            double progress = elapsed / time_limit;\n            temp = t0 * pow(t1 / t0, progress);\n        }\n        \n        // Mutation: Rotate one tile\n        int r = rng() % 30;\n        int c = rng() % 30;\n        int old_rot = current_state.rots[r][c];\n        int old_type = current_state.types[r][c];\n        \n        // Pick a random different rotation\n        int new_rot = (old_rot + 1 + (rng() % 3)) % 4;\n        current_state.rots[r][c] = new_rot;\n        current_state.types[r][c] = get_rotated_type(initial_types[r][c], new_rot);\n        \n        long long new_score_aug = evaluate(current_state, loops);\n        \n        double delta = new_score_aug - current_score_aug;\n        \n        // Metropolis criterion\n        if (delta >= 0 || (temp > 1e-9 && exp(delta / temp) > std::uniform_real_distribution<>(0.0, 1.0)(rng))) {\n            current_score_aug = new_score_aug;\n            \n            // Track best valid solution found\n            long long real_score = 0;\n            if (loops.size() >= 2) {\n                real_score = (long long)loops[0] * loops[1];\n            }\n            \n            if (real_score > best_score_real) {\n                best_score_real = real_score;\n                best_state = current_state;\n            }\n        } else {\n            // Revert change\n            current_state.rots[r][c] = old_rot;\n            current_state.types[r][c] = old_type;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            cout << best_state.rots[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <map>\n#include <set>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants for directions and bitmasks\nconst int UP = 2;\nconst int DOWN = 8;\nconst int LEFT = 1;\nconst int RIGHT = 4;\nconst int DIR[4] = {UP, DOWN, LEFT, RIGHT};\nconst int DR[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nint N, T;\nvector<vector<int>> initial_board;\nvector<vector<int>> target_board;\n\n// Timer\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Random number generator\nmt19937 rng(42);\n\n// Helper to check connection\nbool has_dir(int tile, int dir) {\n    return (tile & dir) != 0;\n}\n\nint reverse_dir(int dir) {\n    if (dir == UP) return DOWN;\n    if (dir == DOWN) return UP;\n    if (dir == LEFT) return RIGHT;\n    if (dir == RIGHT) return LEFT;\n    return 0;\n}\n\n// Structure to hold evaluation results\nstruct BoardScore {\n    int mismatches;\n    int max_component;\n    int total_score;\n};\n\n// Evaluate the board: calculate mismatches and largest component size\nBoardScore evaluate(const vector<vector<int>>& board) {\n    int mismatches = 0;\n    int connections = 0;\n    int boundary_penalty = 0;\n\n    // BFS to find max component size\n    int max_comp = 0;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == N-1 && c == N-1) continue; // Expected empty\n            if (visited[r][c]) continue;\n            if (board[r][c] == 0) continue; \n\n            int comp_size = 0;\n            queue<pair<int,int>> q;\n            q.push({r, c});\n            visited[r][c] = true;\n            comp_size++;\n\n            while(!q.empty()) {\n                auto [cr, cc] = q.front();\n                q.pop();\n\n                int tile = board[cr][cc];\n                for (int d = 0; d < 4; ++d) {\n                    if (has_dir(tile, DIR[d])) {\n                        int nr = cr + DR[d];\n                        int nc = cc + DC[d];\n                        \n                        if (nr < 0 || nr >= N || nc < 0 || nc >= N) {\n                            // Handled in loop below\n                        } else {\n                            int neighbor = board[nr][nc];\n                            if (neighbor != 0 && has_dir(neighbor, reverse_dir(DIR[d]))) {\n                                if (!visited[nr][nc]) {\n                                    visited[nr][nc] = true;\n                                    q.push({nr, nc});\n                                    comp_size++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if (comp_size > max_comp) max_comp = comp_size;\n        }\n    }\n\n    // Check local connections and boundaries\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (r == N-1 && c == N-1) continue; \n            int tile = board[r][c];\n            \n            if (has_dir(tile, UP)) {\n                if (r == 0) boundary_penalty++;\n                else {\n                    int n = board[r-1][c];\n                    if (n == 0) boundary_penalty++; \n                    else if (!has_dir(n, DOWN)) mismatches++;\n                    else connections++; \n                }\n            }\n            if (has_dir(tile, DOWN)) {\n                if (r == N-1) boundary_penalty++;\n                else {\n                    int n = board[r+1][c];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, UP)) mismatches++;\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, LEFT)) {\n                if (c == 0) boundary_penalty++;\n                else {\n                    int n = board[r][c-1];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, RIGHT)) mismatches++;\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, RIGHT)) {\n                if (c == N-1) boundary_penalty++;\n                else {\n                    int n = board[r][c+1];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, LEFT)) mismatches++;\n                    else connections++;\n                }\n            }\n        }\n    }\n\n    // Score calculation: prioritise max component, penalise mismatches/boundaries heavily\n    int score = max_comp * 100 - mismatches * 50 - boundary_penalty * 50;\n    return {mismatches + boundary_penalty, max_comp, score};\n}\n\n// Simulated Annealing to find optimal target board configuration\nvoid find_target_configuration() {\n    vector<int> tiles;\n    for(int r=0; r<N; ++r)\n        for(int c=0; c<N; ++c)\n            tiles.push_back(initial_board[r][c]);\n    \n    // Ensure '0' is at the last position (N-1, N-1) initially\n    auto it = find(tiles.begin(), tiles.end(), 0);\n    if(it != tiles.end()) {\n        iter_swap(it, tiles.end() - 1);\n    }\n\n    target_board.assign(N, vector<int>(N));\n    auto tiles_vec = tiles; \n\n    // Initial configuration\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            target_board[r][c] = tiles_vec[r*N + c];\n        }\n    }\n    \n    BoardScore current_eval = evaluate(target_board);\n    int current_score = current_eval.total_score;\n    \n    vector<vector<int>> best_board = target_board;\n    int best_score = current_score;\n\n    double start_temp = 1000.0;\n    double end_temp = 0.1;\n    double time_limit = 2.5; \n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            double t = get_time();\n            if (t > time_limit) break;\n        }\n\n        double t = get_time();\n        double progress = t / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, progress);\n\n        // Propose swap, keeping (N-1, N-1) fixed as '0'\n        int r1 = rng() % N;\n        int c1 = rng() % N;\n        if (r1 == N-1 && c1 == N-1) { \n            int idx = rng() % (N*N-1);\n            r1 = idx / N; c1 = idx % N;\n        }\n\n        int r2 = rng() % N;\n        int c2 = rng() % N;\n        if (r2 == N-1 && c2 == N-1) { \n             do {\n                r2 = rng() % N;\n                c2 = rng() % N;\n             } while (r2 == N-1 && c2 == N-1);\n        }\n        \n        if (r1 == r2 && c1 == c2) continue;\n\n        swap(target_board[r1][c1], target_board[r2][c2]);\n        \n        BoardScore next_eval = evaluate(target_board);\n        int next_score = next_eval.total_score;\n        \n        if (next_score > current_score) {\n            current_score = next_score;\n            if (next_score > best_score) {\n                best_score = next_score;\n                best_board = target_board;\n            }\n        } else {\n            double prob = exp((next_score - current_score) / temp);\n            if (uniform_real_distribution<>(0,1)(rng) < prob) {\n                current_score = next_score;\n            } else {\n                swap(target_board[r1][c1], target_board[r2][c2]); // Revert\n            }\n        }\n    }\n    \n    target_board = best_board;\n}\n\n// Puzzle Solver Globals\nstring moves = \"\";\npair<int, int> empty_pos;\n\nvoid apply_move(char c) {\n    moves += c;\n    int dr = 0, dc = 0;\n    if (c == 'U') dr = -1; // 'U' means slide UP tile into empty. Empty moves UP.\n    if (c == 'D') dr = 1;\n    if (c == 'L') dc = -1;\n    if (c == 'R') dc = 1;\n    \n    int nr = empty_pos.first + dr;\n    int nc = empty_pos.second + dc;\n    \n    swap(initial_board[empty_pos.first][empty_pos.second], initial_board[nr][nc]);\n    empty_pos = {nr, nc};\n}\n\n// Pathfinding for empty square\nbool bfs_empty(int tr, int tc, const vector<vector<bool>>& locked) {\n    if (empty_pos.first == tr && empty_pos.second == tc) return true;\n    \n    queue<pair<int,int>> q;\n    q.push(empty_pos);\n    \n    map<pair<int,int>, char> parent_move;\n    map<pair<int,int>, pair<int,int>> parent_pos;\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vis[empty_pos.first][empty_pos.second] = true;\n    \n    bool found = false;\n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            found = true;\n            break;\n        }\n        \n        for (int i=0; i<4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n            char move_char = DIR_CHAR[i]; \n            \n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !locked[nr][nc] && !vis[nr][nc]) {\n                vis[nr][nc] = true;\n                parent_pos[{nr,nc}] = {r,c};\n                parent_move[{nr,nc}] = move_char;\n                q.push({nr,nc});\n            }\n        }\n    }\n    \n    if (!found) return false;\n    \n    vector<char> path_vec;\n    pair<int,int> curr = {tr, tc};\n    pair<int,int> start = empty_pos;\n    \n    while (curr != start) {\n        char m = parent_move[curr];\n        path_vec.push_back(m);\n        curr = parent_pos[curr];\n    }\n    reverse(path_vec.begin(), path_vec.end());\n    \n    for(char c : path_vec) apply_move(c);\n    return true;\n}\n\n// Main Solver Logic\nvoid solve_puzzle() {\n    // Assign IDs to tiles to track them through moves\n    vector<vector<int>> tile_ids(N, vector<int>(N));\n    int id_counter = 0;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            tile_ids[r][c] = id_counter++;\n        }\n    }\n    \n    // Find empty pos\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c] == 0) empty_pos = {r,c};\n    \n    vector<bool> id_used(N*N, false);\n    vector<vector<bool>> locked(N, vector<bool>(N, false));\n    \n    // Solve rows 0 to N-3\n    for (int r = 0; r <= N - 3; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (c < N - 2) {\n                // --- Normal Piece ---\n                int needed_type = target_board[r][c];\n                int best_id = -1;\n                int min_dist = 10000;\n                \n                // Find closest unused tile of type\n                for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                    int id = tile_ids[i][j];\n                    if (!id_used[id] && initial_board[i][j] == needed_type) {\n                        int dist = abs(r - i) + abs(c - j);\n                        if (dist < min_dist) { min_dist = dist; best_id = id; }\n                    }\n                }\n                id_used[best_id] = true;\n                \n                // Move piece loop\n                auto get_pos = [&](int id) {\n                    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n                    return make_pair(-1,-1);\n                };\n\n                pair<int,int> curr = get_pos(best_id);\n                while (curr.first != r || curr.second != c) {\n                    int dr = 0, dc = 0;\n                    if (curr.first < r) dr = 1;\n                    else if (curr.first > r) dr = -1;\n                    else if (curr.second < c) dc = 1;\n                    else if (curr.second > c) dc = -1;\n                    \n                    int nr = curr.first + dr;\n                    int nc = curr.second + dc;\n                    \n                    locked[curr.first][curr.second] = true;\n                    bfs_empty(nr, nc, locked);\n                    locked[curr.first][curr.second] = false;\n                    \n                    char m = ' ';\n                    if (curr.first == nr + 1) m = 'D';\n                    if (curr.first == nr - 1) m = 'U';\n                    if (curr.second == nc + 1) m = 'R';\n                    if (curr.second == nc - 1) m = 'L';\n                    apply_move(m);\n                    swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                    curr = {nr, nc};\n                }\n                locked[r][c] = true;\n\n            } else {\n                // --- Last Two Pieces of Row (Macro) ---\n                int t1_type = target_board[r][N-2];\n                int t2_type = target_board[r][N-1];\n                \n                int t1_id = -1, t2_id = -1;\n                int min_dist = 10000;\n\n                // Find T1\n                for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                     int id = tile_ids[i][j];\n                     if (!id_used[id] && initial_board[i][j] == t1_type) { t1_id = id; break; } \n                }\n                id_used[t1_id] = true;\n\n                // Find T2\n                for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                     int id = tile_ids[i][j];\n                     if (!id_used[id] && initial_board[i][j] == t2_type && id != t1_id) { t2_id = id; break; }\n                }\n                id_used[t2_id] = true;\n                \n                auto get_pos = [&](int id) {\n                    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n                    return make_pair(-1,-1);\n                };\n                \n                auto move_p = [&](int id, int tr, int tc, int avoid_id = -1) {\n                    pair<int,int> curr = get_pos(id);\n                    while(curr.first != tr || curr.second != tc) {\n                        int dr = 0, dc = 0;\n                        if (curr.first < tr) dr = 1; else if (curr.first > tr) dr = -1;\n                        else if (curr.second < tc) dc = 1; else if (curr.second > tc) dc = -1;\n                        int nr = curr.first + dr; int nc = curr.second + dc;\n                        pair<int,int> avoid_pos = {-1,-1};\n                        if (avoid_id != -1) { avoid_pos = get_pos(avoid_id); locked[avoid_pos.first][avoid_pos.second] = true; }\n                        locked[curr.first][curr.second] = true;\n                        bfs_empty(nr, nc, locked);\n                        locked[curr.first][curr.second] = false;\n                        if (avoid_id != -1) locked[avoid_pos.first][avoid_pos.second] = false;\n                        char m = ' ';\n                        if (curr.first == nr + 1) m = 'D'; if (curr.first == nr - 1) m = 'U';\n                        if (curr.second == nc + 1) m = 'R'; if (curr.second == nc - 1) m = 'L';\n                        apply_move(m);\n                        swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                        curr = {nr, nc};\n                    }\n                };\n                \n                // 1. Move T2 to (r+1, N-1)\n                move_p(t2_id, r+1, N-1, t1_id);\n                \n                // 2. Move T1 to (r, N-1)\n                pair<int,int> p = get_pos(t2_id); locked[p.first][p.second] = true;\n                move_p(t1_id, r, N-1);\n                locked[p.first][p.second] = false;\n                \n                // 3. Empty to (r, N-2)\n                pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n                pair<int,int> p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n                bfs_empty(r, N-2, locked);\n                \n                // 4. Exec Macro\n                apply_move('R'); // Empty -> r, N-1. T1 -> r, N-2\n                swap(tile_ids[r][N-2], tile_ids[r][N-1]);\n                apply_move('D'); // Empty -> r+1, N-1. T2 -> r, N-1\n                swap(tile_ids[r][N-1], tile_ids[r+1][N-1]);\n                \n                locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n                locked[r][N-2] = true; locked[r][N-1] = true;\n                break; // Inner loop finished\n            }\n        }\n    }\n    \n    // Solve columns 0 to N-3 for last 2 rows\n    for(int c=0; c <= N-3; ++c) {\n        int t1_type = target_board[N-2][c];\n        int t2_type = target_board[N-1][c];\n        \n        int t1_id = -1, t2_id = -1;\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n             int id = tile_ids[i][j];\n             if(!id_used[id] && initial_board[i][j] == t1_type) { t1_id = id; break; }\n        }\n        id_used[t1_id] = true;\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n             int id = tile_ids[i][j];\n             if(!id_used[id] && initial_board[i][j] == t2_type && id != t1_id) { t2_id = id; break; }\n        }\n        id_used[t2_id] = true;\n        \n        auto get_pos = [&](int id) { for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j); return make_pair(-1,-1); };\n        auto move_p = [&](int id, int tr, int tc, int avoid_id = -1) {\n            pair<int,int> curr = get_pos(id);\n            while(curr.first != tr || curr.second != tc) {\n                int dr = 0, dc = 0;\n                if (curr.first < tr) dr = 1; else if (curr.first > tr) dr = -1;\n                else if (curr.second < tc) dc = 1; else if (curr.second > tc) dc = -1;\n                int nr = curr.first + dr; int nc = curr.second + dc;\n                pair<int,int> avoid_pos = {-1,-1};\n                if (avoid_id != -1) { avoid_pos = get_pos(avoid_id); locked[avoid_pos.first][avoid_pos.second] = true; }\n                locked[curr.first][curr.second] = true;\n                bfs_empty(nr, nc, locked);\n                locked[curr.first][curr.second] = false;\n                if (avoid_id != -1) locked[avoid_pos.first][avoid_pos.second] = false;\n                char m = ' ';\n                if (curr.first == nr + 1) m = 'D'; if (curr.first == nr - 1) m = 'U';\n                if (curr.second == nc + 1) m = 'R'; if (curr.second == nc - 1) m = 'L';\n                apply_move(m);\n                swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                curr = {nr, nc};\n            }\n        };\n        \n        move_p(t2_id, N-1, c+1, t1_id);\n        pair<int,int> p = get_pos(t2_id); locked[p.first][p.second] = true;\n        move_p(t1_id, N-1, c);\n        locked[p.first][p.second] = false;\n        \n        pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n        pair<int,int> p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n        bfs_empty(N-2, c, locked);\n        \n        apply_move('D'); swap(tile_ids[N-2][c], tile_ids[N-1][c]);\n        apply_move('R'); swap(tile_ids[N-1][c], tile_ids[N-1][c+1]);\n        \n        locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n        locked[N-2][c] = true; locked[N-1][c] = true;\n    }\n    \n    // Final 3x2 area BFS\n    locked[N-2][N-3] = false; locked[N-1][N-3] = false;\n    \n    vector<pair<int,int>> pos_map = {{N-2, N-3}, {N-2, N-2}, {N-2, N-1}, {N-1, N-3}, {N-1, N-2}, {N-1, N-1}};\n    \n    auto get_state = [&]() {\n        vector<int> s(6);\n        for(int i=0; i<6; ++i) s[i] = initial_board[pos_map[i].first][pos_map[i].second];\n        return s;\n    };\n    \n    vector<int> target_state(6);\n    for(int i=0; i<6; ++i) target_state[i] = target_board[pos_map[i].first][pos_map[i].second];\n    \n    queue<vector<int>> q;\n    map<vector<int>, char> move_map;\n    map<vector<int>, vector<int>> parent_map;\n    \n    vector<int> start_s = get_state();\n    q.push(start_s);\n    move_map[start_s] = 0; \n    \n    bool solved = false;\n    vector<int> final_s;\n    int steps = 0;\n    \n    while(!q.empty()) {\n        vector<int> curr = q.front();\n        q.pop();\n        if (curr == target_state) { solved = true; final_s = curr; break; }\n        \n        int z = -1;\n        for(int i=0; i<6; ++i) if(curr[i] == 0) z = i;\n        int r = pos_map[z].first;\n        int c = pos_map[z].second;\n        \n        for(int d=0; d<4; ++d) {\n            int nr = r + DR[d];\n            int nc = c + DC[d];\n            if (nr >= N-2 && nr <= N-1 && nc >= N-3 && nc <= N-1) {\n                int nz = -1;\n                for(int k=0; k<6; ++k) if(pos_map[k].first == nr && pos_map[k].second == nc) nz = k;\n                vector<int> next_s = curr;\n                swap(next_s[z], next_s[nz]);\n                if (move_map.find(next_s) == move_map.end()) {\n                    move_map[next_s] = DIR_CHAR[d];\n                    parent_map[next_s] = curr;\n                    q.push(next_s);\n                }\n            }\n        }\n        if(++steps > 100000) break;\n    }\n    \n    if (solved) {\n        string path = \"\";\n        vector<int> curr = final_s;\n        while (curr != start_s) {\n            path += move_map[curr];\n            curr = parent_map[curr];\n        }\n        reverse(path.begin(), path.end());\n        for(char c : path) apply_move(c);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    cin >> N >> T;\n    initial_board.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') initial_board[i][j] = c - '0';\n            else initial_board[i][j] = c - 'a' + 10;\n        }\n    }\n\n    find_target_configuration();\n    solve_puzzle();\n    \n    cout << moves << endl;\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst double PI = std::acos(-1.0);\nconst int MAX_K = 100;\n\nstruct Point {\n    int id;\n    long long x, y;\n    double px, py; // projected coordinates\n};\n\n// Global variables\nint N;\nint K_limit;\nint A[11];\nvector<Point> points;\nmt19937 rng(42);\n\n// Global buffers for score calculation to avoid allocation overhead\n// Max cuts 100 implies max 101 bins in each dimension.\nint counts_grid[105][105];\n\nclass Timer {\n    chrono::high_resolution_clock::time_point start;\npublic:\n    Timer() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(now - start).count();\n    }\n};\n\n// Helper to get unique coordinates with epsilon tolerance\n// This prevents cutting between points that are too close in projection,\n// which ensures the integer line construction is robust.\nvector<double> get_unique_coords(const vector<double>& coords) {\n    vector<double> uniq;\n    if (coords.empty()) return uniq;\n    vector<double> sorted = coords;\n    sort(sorted.begin(), sorted.end());\n    uniq.push_back(sorted[0]);\n    for (size_t i = 1; i < sorted.size(); ++i) {\n        // Use a tolerance of 0.01 to ensure physical gap for cuts\n        if (sorted[i] - uniq.back() > 0.01) {\n            uniq.push_back(sorted[i]);\n        }\n    }\n    return uniq;\n}\n\nstruct Solver {\n    vector<Point> current_points;\n    vector<double> uniq_x, uniq_y;\n    vector<int> pt_x_rank, pt_y_rank;\n    double angle;\n    \n    vector<int> best_cx, best_cy; // Stores indices of cuts in uniq_x/uniq_y\n    int best_score = -1;\n\n    void init(double ang) {\n        angle = ang;\n        current_points = points;\n        double rad = angle * PI / 180.0;\n        double c = cos(rad), s = sin(rad);\n        \n        for(auto& p : current_points) {\n            p.px = p.x * c + p.y * s;\n            p.py = -p.x * s + p.y * c;\n        }\n        \n        vector<double> raw_x, raw_y;\n        raw_x.reserve(N);\n        raw_y.reserve(N);\n        for(const auto& p : current_points) {\n            raw_x.push_back(p.px);\n            raw_y.push_back(p.py);\n        }\n        \n        uniq_x = get_unique_coords(raw_x);\n        uniq_y = get_unique_coords(raw_y);\n        \n        pt_x_rank.resize(N);\n        pt_y_rank.resize(N);\n        \n        // Precompute ranks: which interval in the unique sorted list each point belongs to\n        for(int i=0; i<N; ++i) {\n            auto it = lower_bound(uniq_x.begin(), uniq_x.end(), current_points[i].px - 1e-5);\n            pt_x_rank[i] = (int)distance(uniq_x.begin(), it);\n        }\n        for(int i=0; i<N; ++i) {\n            auto it = lower_bound(uniq_y.begin(), uniq_y.end(), current_points[i].py - 1e-5);\n            pt_y_rank[i] = (int)distance(uniq_y.begin(), it);\n        }\n    }\n    \n    // Evaluate current configuration of cuts\n    // cx/cy are sorted lists of indices in uniq_x/uniq_y where cuts are placed.\n    int eval(const vector<int>& cx, const vector<int>& cy) {\n        int nx = (int)cx.size() + 1;\n        int ny = (int)cy.size() + 1;\n        \n        // Reset grid counts\n        for(int i=0; i<nx; ++i) {\n            memset(counts_grid[i], 0, sizeof(int) * ny);\n        }\n        \n        // Assign points to bins and count\n        for(int i=0; i<N; ++i) {\n            int r_x = pt_x_rank[i];\n            int r_y = pt_y_rank[i];\n            \n            // Find which bin the point falls into\n            auto it_x = upper_bound(cx.begin(), cx.end(), r_x);\n            int bx = (int)distance(cx.begin(), it_x);\n            \n            auto it_y = upper_bound(cy.begin(), cy.end(), r_y);\n            int by = (int)distance(cy.begin(), it_y);\n            \n            counts_grid[bx][by]++;\n        }\n        \n        // Aggregate piece counts\n        int piece_b[11] = {0};\n        for(int i=0; i<nx; ++i) {\n            for(int j=0; j<ny; ++j) {\n                int c = counts_grid[i][j];\n                if(c >= 1 && c <= 10) {\n                    piece_b[c]++;\n                }\n            }\n        }\n        \n        // Calculate score\n        long long num = 0;\n        long long den = 0;\n        for(int d=1; d<=10; ++d) {\n            num += min(A[d], piece_b[d]);\n            den += A[d];\n        }\n        \n        if (den == 0) return 0;\n        return (int)(1000000.0 * num / den + 0.5);\n    }\n    \n    void run_sa(double duration) {\n        Timer t;\n        // Initial solution\n        vector<int> cx, cy;\n        int uxs = (int)uniq_x.size();\n        int uys = (int)uniq_y.size();\n        \n        // Helper to generate unique random cuts\n        auto gen_cuts = [&](int n_cuts, int max_idx) {\n            vector<int> res;\n            if (max_idx <= 0) return res;\n            for(int i=0; i<n_cuts; ++i) {\n                res.push_back(rng() % max_idx);\n            }\n            sort(res.begin(), res.end());\n            res.erase(unique(res.begin(), res.end()), res.end());\n            return res;\n        };\n        \n        // Initialize with some random cuts if starting fresh\n        if (best_score == -1) {\n            int init_cuts = min(K_limit, 60); \n            cx = gen_cuts(init_cuts / 2, uxs - 1);\n            cy = gen_cuts(init_cuts - cx.size(), uys - 1);\n        } else {\n            cx = best_cx;\n            cy = best_cy;\n        }\n        \n        int current_score = eval(cx, cy);\n        if(current_score > best_score) {\n            best_score = current_score;\n            best_cx = cx;\n            best_cy = cy;\n        }\n        \n        double start_temp = 2000;\n        double end_temp = 0;\n        \n        while(t.elapsed() < duration) {\n            double progress = t.elapsed() / duration;\n            double temp = start_temp * (1.0 - progress);\n            \n            vector<int> ncx = cx;\n            vector<int> ncy = cy;\n            \n            int type = rng() % 6;\n            bool changed = false;\n            \n            // Mutations: Add, Delete, Move for X and Y\n            if (type == 0) { // Add X\n                if ((int)(ncx.size() + ncy.size()) < K_limit && uxs > 1) {\n                    int val = rng() % (uxs - 1);\n                    bool exists = false;\n                    for(int v : ncx) if(v == val) exists = true;\n                    if(!exists) {\n                        ncx.push_back(val);\n                        sort(ncx.begin(), ncx.end());\n                        changed = true;\n                    }\n                }\n            } else if (type == 1) { // Del X\n                if (!ncx.empty()) {\n                    int idx = rng() % ncx.size();\n                    ncx.erase(ncx.begin() + idx);\n                    changed = true;\n                }\n            } else if (type == 2) { // Mov X\n                if (!ncx.empty() && uxs > 1) {\n                    int idx = rng() % ncx.size();\n                    int old_val = ncx[idx];\n                    // Move locally or globally? Global is easier for now.\n                    int new_val = rng() % (uxs - 1);\n                    bool exists = false;\n                    for(int v : ncx) if(v == new_val && v != old_val) exists = true;\n                    if(!exists) {\n                        ncx[idx] = new_val;\n                        sort(ncx.begin(), ncx.end());\n                        changed = true;\n                    }\n                }\n            } else if (type == 3) { // Add Y\n                if ((int)(ncx.size() + ncy.size()) < K_limit && uys > 1) {\n                    int val = rng() % (uys - 1);\n                    bool exists = false;\n                    for(int v : ncy) if(v == val) exists = true;\n                    if(!exists) {\n                        ncy.push_back(val);\n                        sort(ncy.begin(), ncy.end());\n                        changed = true;\n                    }\n                }\n            } else if (type == 4) { // Del Y\n                if (!ncy.empty()) {\n                    int idx = rng() % ncy.size();\n                    ncy.erase(ncy.begin() + idx);\n                    changed = true;\n                }\n            } else if (type == 5) { // Mov Y\n                if (!ncy.empty() && uys > 1) {\n                    int idx = rng() % ncy.size();\n                    int old_val = ncy[idx];\n                    int new_val = rng() % (uys - 1);\n                    bool exists = false;\n                    for(int v : ncy) if(v == new_val && v != old_val) exists = true;\n                    if(!exists) {\n                        ncy[idx] = new_val;\n                        sort(ncy.begin(), ncy.end());\n                        changed = true;\n                    }\n                }\n            }\n            \n            if (changed) {\n                int new_score = eval(ncx, ncy);\n                int diff = new_score - current_score;\n                // Maximize score\n                if (diff >= 0 || exp(diff / (temp + 1e-9)) > (double(rng()) / mt19937::max())) {\n                    cx = ncx;\n                    cy = ncy;\n                    current_score = new_score;\n                    if (current_score > best_score) {\n                        best_score = current_score;\n                        best_cx = cx;\n                        best_cy = cy;\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> K_limit)) return 0;\n    for(int i=1; i<=10; ++i) {\n        cin >> A[i];\n    }\n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y;\n    }\n    \n    // Explore multiple rotation angles\n    vector<double> angles;\n    angles.push_back(0.0);\n    for(int i=0; i<19; ++i) {\n        angles.push_back(std::uniform_real_distribution<double>(0.0, 90.0)(rng));\n    }\n    \n    int n_angles = angles.size();\n    vector<Solver> solvers(n_angles);\n    \n    Timer total_timer;\n    double time_limit = 2.8;\n    \n    // Pass 1: Short exploration for each angle\n    double pass1_time = 0.8; \n    double t_per_angle = pass1_time / n_angles;\n    \n    int best_idx = -1;\n    \n    for(int i=0; i<n_angles; ++i) {\n        solvers[i].init(angles[i]);\n        solvers[i].run_sa(t_per_angle);\n        if (best_idx == -1 || solvers[i].best_score > solvers[best_idx].best_score) {\n            best_idx = i;\n        }\n    }\n    \n    // Pass 2: Deep optimization on the best angle\n    double remaining = time_limit - total_timer.elapsed();\n    if (remaining > 0 && best_idx != -1) {\n        solvers[best_idx].run_sa(remaining);\n    }\n    \n    const Solver& S = solvers[best_idx];\n    cout << S.best_cx.size() + S.best_cy.size() << endl;\n    \n    double rad = S.angle * PI / 180.0;\n    double c = cos(rad), s = sin(rad);\n    \n    // Helper to output line defined by: x_proj = val => x*c + y*s = val\n    // or y_proj = val => -x*s + y*c = val\n    auto print_line = [&](double A, double B, double C) {\n        // Line equation: Ax + By = C\n        // Center point M on the line closest to origin: M = C * (A, B) / (A^2+B^2) = (C*A, C*B)\n        // Direction vector along the line: D = (-B, A)\n        // Endpoints P1, P2 far away: M +/- Scale * D\n        \n        double Mx = C * A;\n        double My = C * B;\n        double Dx = -B;\n        double Dy = A;\n        \n        long long scale = 500000000LL; // 5*10^8\n        \n        long long x1 = round(Mx - scale * Dx);\n        long long y1 = round(My - scale * Dy);\n        long long x2 = round(Mx + scale * Dx);\n        long long y2 = round(My + scale * Dy);\n        \n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << endl;\n    };\n    \n    for(int idx : S.best_cx) {\n        // Cut is between uniq_x[idx] and uniq_x[idx+1]\n        double val = (S.uniq_x[idx] + S.uniq_x[idx+1]) / 2.0;\n        print_line(c, s, val);\n    }\n    for(int idx : S.best_cy) {\n        // Cut is between uniq_y[idx] and uniq_y[idx+1]\n        double val = (S.uniq_y[idx] + S.uniq_y[idx+1]) / 2.0;\n        print_line(-s, c, val);\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double TIME_LIMIT = 4.8;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n};\n\nint N, M;\nint C; \nlong long weights[65][65];\n\nusing Mask = unsigned long long;\n\ninline void set_bit(Mask& m, int i) {\n    m |= (1ULL << i);\n}\n\n// Check if bits in range [l, r) are all 0\n// Range is inclusive of l, exclusive of r.\ninline bool check_range_empty(Mask m, int l, int r) {\n    if (l >= r) return true;\n    if (l >= 64) return true; \n    unsigned long long mask_r = (r >= 64) ? (~0ULL) : ((1ULL << r) - 1);\n    unsigned long long mask_l = (1ULL << l) - 1;\n    Mask mask = mask_r ^ mask_l;\n    return (m & mask) == 0;\n}\n\nstruct Move {\n    Point p1, p2, p3, p4;\n};\n\nstruct State {\n    Mask row_dots[62];\n    Mask col_dots[62];\n    Mask d1_dots[130]; \n    Mask d2_dots[130]; \n\n    Mask h_edges[62]; \n    Mask v_edges[62];\n    Mask d1_edges[130];\n    Mask d2_edges[130];\n\n    long long current_score_w;\n    vector<Move> history;\n\n    State() {\n        for(int i=0; i<62; ++i) row_dots[i] = col_dots[i] = h_edges[i] = v_edges[i] = 0;\n        for(int i=0; i<130; ++i) d1_dots[i] = d2_dots[i] = d1_edges[i] = d2_edges[i] = 0;\n        current_score_w = 0;\n    }\n\n    bool has_dot(int x, int y) const {\n        return (row_dots[y] >> x) & 1;\n    }\n\n    void add_dot(int x, int y) {\n        set_bit(row_dots[y], x);\n        set_bit(col_dots[x], y);\n        set_bit(d1_dots[x + y], x);\n        set_bit(d2_dots[x - y + N], x);\n        current_score_w += weights[x][y];\n    }\n    \n    void add_edges(Point p1, Point p2, Point p3, Point p4) {\n        auto mark = [&](Point a, Point b) {\n            if (a.y == b.y) { \n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                for (int x = l; x < r; ++x) set_bit(h_edges[y], x);\n            } else if (a.x == b.x) { \n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                for (int y = l; y < r; ++y) set_bit(v_edges[x], y);\n            } else {\n                if ((a.x + a.y) == (b.x + b.y)) { \n                    int k = a.x + a.y;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d1_edges[k], x);\n                } else { \n                    int k = a.x - a.y + N;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d2_edges[k], x);\n                }\n            }\n        };\n        mark(p1, p2);\n        mark(p2, p3);\n        mark(p3, p4);\n        mark(p4, p1);\n    }\n};\n\nconst int pairs90[8][2] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0}, \n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\nstruct Solver {\n    vector<State> beam;\n    vector<Point> initial_dots;\n\n    Point find_neighbor(const State& s, Point p, int dir) {\n        int x = p.x, y = p.y;\n        if (dir == 0) { // R\n            Mask m = s.row_dots[y];\n            m &= (~0ULL << (x + 1)); \n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, y};\n        } else if (dir == 2) { // L\n            Mask m = s.row_dots[y];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, y};\n        } else if (dir == 1) { // U\n            Mask m = s.col_dots[x];\n            m &= (~0ULL << (y + 1));\n            if (m == 0) return {-1, -1};\n            int ny = __builtin_ctzll(m);\n            return {x, ny};\n        } else if (dir == 3) { // D\n            Mask m = s.col_dots[x];\n            m &= ((1ULL << y) - 1);\n            if (m == 0) return {-1, -1};\n            int ny = 63 - __builtin_clzll(m);\n            return {x, ny};\n        } else if (dir == 4) { // NE (d2 const, x inc)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 6) { // SW (d2 const, x dec)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 5) { // NW (d1 const, x dec)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, k - nx};\n        } else if (dir == 7) { // SE (d1 const, x inc)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, k - nx};\n        }\n        return {-1, -1};\n    }\n\n    bool check_edges_free(const State& s, Point p1, Point p2, Point p3, Point p4) {\n        auto check = [&](Point a, Point b) {\n            if (a.y == b.y) {\n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.h_edges[y], l, r);\n            } else if (a.x == b.x) {\n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                return check_range_empty(s.v_edges[x], l, r);\n            } else if ((a.x + a.y) == (b.x + b.y)) {\n                int k = a.x + a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d1_edges[k], l, r);\n            } else {\n                int k = a.x - a.y + N;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d2_edges[k], l, r);\n            }\n        };\n        return check(p1, p2) && check(p2, p3) && check(p3, p4) && check(p4, p1);\n    }\n    \n    bool check_perimeter_dots(const State& s, Point p1, Point p2) {\n         if (p1.y == p2.y) {\n             int y = p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.row_dots[y], l, r);\n         } else if (p1.x == p2.x) {\n             int x = p1.x;\n             int l = min(p1.y, p2.y) + 1;\n             int r = max(p1.y, p2.y);\n             return check_range_empty(s.col_dots[x], l, r);\n         } else if ((p1.x + p1.y) == (p2.x + p2.y)) {\n             int k = p1.x + p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d1_dots[k], l, r);\n         } else {\n             int k = p1.x - p1.y + N;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d2_dots[k], l, r);\n         }\n    }\n\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        State s0;\n        for (auto p : initial_dots) {\n            s0.add_dot(p.x, p.y);\n        }\n        beam.push_back(s0);\n        \n        // Beam width adjustment based on N\n        int BEAM_WIDTH = 80;\n        if (N > 45) BEAM_WIDTH = 50;\n        if (N > 55) BEAM_WIDTH = 30; \n\n        struct NextStateInfo {\n            int parent_idx;\n            Move move;\n            long long new_score;\n            double heuristic; \n        };\n        vector<NextStateInfo> candidates;\n        candidates.reserve(BEAM_WIDTH * 50);\n\n        int turn = 0;\n        static vector<Point> dots;\n\n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            candidates.clear();\n            bool any_move = false;\n\n            for (int i = 0; i < beam.size(); ++i) {\n                const State& s = beam[i];\n                \n                dots.clear();\n                for(int y=0; y<N; ++y) {\n                    Mask m = s.row_dots[y];\n                    while(m) {\n                        int x = __builtin_ctzll(m);\n                        dots.push_back({x, y});\n                        m &= (m - 1);\n                    }\n                }\n\n                for (const auto& p3 : dots) {\n                    for (int pair_idx = 0; pair_idx < 8; ++pair_idx) {\n                        int d_idx1 = pairs90[pair_idx][0];\n                        int d_idx2 = pairs90[pair_idx][1];\n\n                        Point p2 = find_neighbor(s, p3, d_idx1);\n                        if (p2.x == -1) continue;\n                        Point p4 = find_neighbor(s, p3, d_idx2);\n                        if (p4.x == -1) continue;\n\n                        Point p1 = {p2.x + p4.x - p3.x, p2.y + p4.y - p3.y};\n                        \n                        if (p1.x < 0 || p1.x >= N || p1.y < 0 || p1.y >= N) continue;\n                        if (s.has_dot(p1.x, p1.y)) continue;\n\n                        if (!check_perimeter_dots(s, p1, p2)) continue;\n                        if (!check_perimeter_dots(s, p1, p4)) continue;\n                        if (!check_edges_free(s, p1, p2, p3, p4)) continue;\n\n                        long long gain = weights[p1.x][p1.y];\n                        long long new_total = s.current_score_w + gain;\n                        \n                        // Heuristic is simple greedy gain\n                        candidates.push_back({i, {p1, p2, p3, p4}, new_total, (double)gain});\n                        any_move = true;\n                    }\n                }\n            }\n\n            if (!any_move) break;\n\n            if (candidates.size() > BEAM_WIDTH) {\n                 nth_element(candidates.begin(), candidates.begin() + BEAM_WIDTH, candidates.end(),\n                    [](const NextStateInfo& a, const NextStateInfo& b) {\n                        return a.heuristic > b.heuristic;\n                    });\n                 candidates.resize(BEAM_WIDTH);\n            }\n            \n            sort(candidates.begin(), candidates.end(), \n                 [](const NextStateInfo& a, const NextStateInfo& b) {\n                     return a.heuristic > b.heuristic;\n                 });\n\n            vector<State> next_beam;\n            next_beam.reserve(candidates.size());\n            \n            for (const auto& cand : candidates) {\n                State ns = beam[cand.parent_idx];\n                ns.add_dot(cand.move.p1.x, cand.move.p1.y);\n                ns.add_edges(cand.move.p1, cand.move.p2, cand.move.p3, cand.move.p4);\n                ns.history.push_back(cand.move);\n                next_beam.push_back(ns);\n            }\n\n            beam = move(next_beam);\n            turn++;\n        }\n\n        if (beam.empty()) return;\n        auto best_it = max_element(beam.begin(), beam.end(), [](const State& a, const State& b){\n            return a.current_score_w < b.current_score_w;\n        });\n        \n        const auto& history = best_it->history;\n        cout << history.size() << \"\\n\";\n        for (const auto& m : history) {\n            cout << m.p1.x << \" \" << m.p1.y << \" \" \n                 << m.p2.x << \" \" << m.p2.y << \" \" \n                 << m.p3.x << \" \" << m.p3.y << \" \" \n                 << m.p4.x << \" \" << m.p4.y << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if (!(cin >> N >> M)) return 0;\n\n    C = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            weights[x][y] = 1LL * (x - C) * (x - C) + 1LL * (y - C) * (y - C) + 1;\n        }\n    }\n\n    Solver solver;\n    solver.initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> solver.initial_dots[i].x >> solver.initial_dots[i].y;\n    }\n\n    solver.solve();\n\n    return 0;\n}","ahc015":"/**\n * Solution for AtCoder Heuristic Contest (AHC015) - Halloween Candy\n * \n * Strategy:\n * 1. Modeling:\n *    - The problem is to maximize the clustering of same-flavored candies.\n *    - We model the board state and the 4 tilting operations (Forward, Backward, Left, Right).\n *    - Since the candy positions are random but flavors are known, this is a stochastic optimization problem.\n * \n * 2. Algorithm: Monte Carlo Search\n *    - At each step t, we need to choose a direction.\n *    - We consider all 4 possible moves.\n *    - For each candidate move, we run multiple random simulations (playouts) to estimate the expected final score.\n * \n * 3. Simulation Strategy:\n *    - From the state after the candidate move, we simulate the remaining steps (t+1 to 100).\n *    - In the simulation, future candy positions are chosen uniformly at random from empty cells.\n *    - To make the simulation effective within the time limit, we use a \"Greedy Playout Policy\":\n *      At each step of the simulation, we choose the tilt direction that maximizes the number of \n *      adjacent same-flavor pairs immediately. This is a fast proxy for the final objective.\n *    - At the end of the simulation, we calculate the true score (sum of squares of connected component sizes).\n * \n * 4. Time Management:\n *    - We have 2.0 seconds total.\n *    - We allocate time dynamically: `time_for_current_step = remaining_time / remaining_steps`.\n *    - This ensures we use the available time efficiently, performing more simulations when time permits.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\n// Constants\nconst int N = 10;\nconst int MAX_T = 100;\n\n// Global input flavors\nint flavors[MAX_T];\n\n// Directions: 0=F, 1=B, 2=L, 3=R\nconst char DIRS[] = {'F', 'B', 'L', 'R'};\n\n// Fast Random Number Generator (Xorshift128)\nstruct XorShift128 {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    \n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    \n    inline int next_int(int n) {\n        if (n <= 0) return 0;\n        return next() % n;\n    }\n} rng;\n\nstruct State {\n    int board[N][N]; // 0: empty, 1-3: flavor\n    \n    State() {\n        memset(board, 0, sizeof(board));\n    }\n\n    // Tilts the board in the given direction.\n    // Returns true if the board state changed.\n    bool tilt(int dir) {\n        bool changed = false;\n        if (dir == 0) { // Forward (Up)\n            for (int c = 0; c < N; ++c) {\n                int p = 0;\n                for (int r = 0; r < N; ++r) {\n                    if (board[r][c] != 0) {\n                        if (p != r) {\n                            board[p][c] = board[r][c];\n                            board[r][c] = 0;\n                            changed = true;\n                        }\n                        p++;\n                    }\n                }\n            }\n        } else if (dir == 1) { // Backward (Down)\n            for (int c = 0; c < N; ++c) {\n                int p = N - 1;\n                for (int r = N - 1; r >= 0; --r) {\n                    if (board[r][c] != 0) {\n                        if (p != r) {\n                            board[p][c] = board[r][c];\n                            board[r][c] = 0;\n                            changed = true;\n                        }\n                        p--;\n                    }\n                }\n            }\n        } else if (dir == 2) { // Left\n            for (int r = 0; r < N; ++r) {\n                int p = 0;\n                for (int c = 0; c < N; ++c) {\n                    if (board[r][c] != 0) {\n                        if (p != c) {\n                            board[r][p] = board[r][c];\n                            board[r][c] = 0;\n                            changed = true;\n                        }\n                        p++;\n                    }\n                }\n            }\n        } else if (dir == 3) { // Right\n            for (int r = 0; r < N; ++r) {\n                int p = N - 1;\n                for (int c = N - 1; c >= 0; --c) {\n                    if (board[r][c] != 0) {\n                        if (p != c) {\n                            board[r][p] = board[r][c];\n                            board[r][c] = 0;\n                            changed = true;\n                        }\n                        p--;\n                    }\n                }\n            }\n        }\n        return changed;\n    }\n\n    // Fast heuristic: count adjacent pairs of the same flavor.\n    // Used during simulation to choose moves quickly.\n    int eval_adj() const {\n        int score = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int f = board[r][c];\n                if (f == 0) continue;\n                // Check right\n                if (c + 1 < N && board[r][c+1] == f) score++;\n                // Check down\n                if (r + 1 < N && board[r+1][c] == f) score++;\n            }\n        }\n        return score;\n    }\n\n    // Full evaluation: Sum of squares of connected component sizes.\n    // Used at the end of simulations to get the true score.\n    long long eval_full() const {\n        bool visited[N][N] = {false};\n        long long score = 0;\n        \n        // Static queue to avoid allocation\n        static pair<int,int> q[N*N];\n\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (board[r][c] != 0 && !visited[r][c]) {\n                    int f = board[r][c];\n                    int size = 0;\n                    \n                    int head = 0, tail = 0;\n                    q[tail++] = {r, c};\n                    visited[r][c] = true;\n                    size++;\n                    \n                    while(head < tail){\n                        pair<int,int> curr = q[head++];\n                        int cr = curr.first;\n                        int cc = curr.second;\n                        \n                        const int dr[] = {0, 0, 1, -1};\n                        const int dc[] = {1, -1, 0, 0};\n                        \n                        for(int i=0; i<4; ++i){\n                            int nr = cr + dr[i];\n                            int nc = cc + dc[i];\n                            if(nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc] && board[nr][nc] == f){\n                                visited[nr][nc] = true;\n                                size++;\n                                q[tail++] = {nr, nc};\n                            }\n                        }\n                    }\n                    score += (long long)size * size;\n                }\n            }\n        }\n        return score;\n    }\n\n    void place(int r, int c, int f) {\n        board[r][c] = f;\n    }\n\n    // Finds the k-th empty cell (1-based index)\n    pair<int,int> get_kth_empty(int k) const {\n        int count = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (board[r][c] == 0) {\n                    count++;\n                    if (count == k) return {r, c};\n                }\n            }\n        }\n        return {-1, -1};\n    }\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read all flavors in advance\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    State current_state;\n    auto start_time = chrono::high_resolution_clock::now();\n    // Using 1.95s to be safe within 2.0s limit\n    double total_time_limit = 1.95; \n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // 1. Place the t-th candy at the p-th empty position\n        pair<int,int> pos = current_state.get_kth_empty(p);\n        current_state.place(pos.first, pos.second, flavors[t]);\n\n        // 2. Decide the best tilt direction\n        int best_dir = 0;\n        \n        // Calculate time budget for this move\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        double time_left = total_time_limit - elapsed.count();\n        double time_for_move = time_left / (100 - t);\n        if (time_for_move < 0.0005) time_for_move = 0.0005; // Minimum budget\n        \n        // Special case for the last move (no uncertainty)\n        if (t == 99) {\n            long long max_score = -1;\n            for (int d = 0; d < 4; ++d) {\n                State next = current_state;\n                next.tilt(d);\n                long long s = next.eval_full();\n                if (s > max_score) {\n                    max_score = s;\n                    best_dir = d;\n                }\n            }\n        } else {\n            // Monte Carlo Simulations\n            long long total_scores[4] = {0};\n            int counts[4] = {0};\n            \n            auto move_start = chrono::high_resolution_clock::now();\n            int iter = 0;\n            \n            // Run simulations until time budget is exhausted\n            while (true) {\n                iter++;\n                // Check time every 32 iterations to reduce overhead\n                if ((iter & 31) == 0) {\n                    auto curr = chrono::high_resolution_clock::now();\n                    chrono::duration<double> step_elapsed = curr - move_start;\n                    if (step_elapsed.count() > time_for_move) break;\n                }\n\n                // Round-robin selection of the initial move to evaluate\n                int d = (iter - 1) % 4;\n                \n                State s = current_state;\n                s.tilt(d);\n                \n                // Simulate the rest of the game\n                for (int k = t + 1; k < 100; ++k) {\n                    // Pick a random empty cell for the next candy\n                    // At start of step k (0-based), there are k candies on board.\n                    // Empty cells = 100 - k.\n                    int empty_count = 100 - k;\n                    int rnd_idx = rng.next_int(empty_count) + 1;\n                    \n                    pair<int,int> rnd_pos = s.get_kth_empty(rnd_idx);\n                    s.place(rnd_pos.first, rnd_pos.second, flavors[k]);\n                    \n                    // Choose a move using Greedy Policy (maximize immediate adjacencies)\n                    int max_adj = -1;\n                    int candidates[4];\n                    int cand_count = 0;\n                    \n                    for (int dd = 0; dd < 4; ++dd) {\n                        State temp = s;\n                        temp.tilt(dd);\n                        int adj = temp.eval_adj();\n                        if (adj > max_adj) {\n                            max_adj = adj;\n                            cand_count = 0;\n                            candidates[cand_count++] = dd;\n                        } else if (adj == max_adj) {\n                            candidates[cand_count++] = dd;\n                        }\n                    }\n                    \n                    // Random tie-breaking among best moves\n                    int selected = candidates[rng.next_int(cand_count)];\n                    s.tilt(selected);\n                }\n                \n                // Evaluate final state\n                total_scores[d] += s.eval_full();\n                counts[d]++;\n            }\n            \n            // Choose direction with highest average score\n            double best_avg = -1.0;\n            // Tie-breaker preference: F, L, B, R (arbitrary but consistent)\n            for (int d = 0; d < 4; ++d) {\n                if (counts[d] == 0) continue;\n                double avg = (double)total_scores[d] / counts[d];\n                if (avg > best_avg) {\n                    best_avg = avg;\n                    best_dir = d;\n                }\n            }\n        }\n        \n        // 3. Output and update state\n        cout << DIRS[best_dir] << endl; // Automatic flush due to endl\n        current_state.tilt(best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <map>\n#include <set>\n#include <numeric>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Global RNG\nmt19937 rng(12345);\n\n// Utils\nint rand_int(int l, int r) {\n    return uniform_int_distribution<int>(l, r)(rng);\n}\n\ndouble rand_double() {\n    return uniform_real_distribution<double>(0.0, 1.0)(rng);\n}\n\n// Graph representation: Adjacency Matrix\ntypedef vector<vector<int>> Graph;\n\n// Convert binary string to Graph\nGraph from_string(int N, const string& s) {\n    Graph g(N, vector<int>(N, 0));\n    int k = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if(s[k] == '1') {\n                g[i][j] = g[j][i] = 1;\n            }\n            k++;\n        }\n    }\n    return g;\n}\n\n// Convert Graph to binary string\nstring to_string_repr(const Graph& g) {\n    int N = g.size();\n    string s = \"\";\n    s.reserve(N*(N-1)/2);\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            s += (g[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Generate random matrix KxK with given row sums\n// Returns empty if failed\nGraph generate_valid_matrix(int K, const vector<int>& row_sums) {\n    Graph mat(K, vector<int>(K, 0));\n    vector<int> current_sums(K, 0);\n    \n    // List all possible positions (including diagonal)\n    vector<pair<int, int>> pos;\n    pos.reserve(K*(K+1)/2);\n    for(int i=0; i<K; ++i) {\n        for(int j=i; j<K; ++j) {\n            pos.push_back({i, j});\n        }\n    }\n    shuffle(pos.begin(), pos.end(), rng);\n    \n    for(auto& p : pos) {\n        int u = p.first;\n        int v = p.second;\n        // Check if adding edge (u,v) is valid\n        bool ok = true;\n        if(current_sums[u] + 1 > row_sums[u]) ok = false;\n        if(u != v && current_sums[v] + 1 > row_sums[v]) ok = false;\n        \n        if(ok) {\n            mat[u][v] = mat[v][u] = 1;\n            current_sums[u]++;\n            if(u != v) current_sums[v]++;\n        }\n    }\n    \n    if(current_sums == row_sums) return mat;\n    return {};\n}\n\n// Calculate Hamming distance between upper triangles of two KxK matrices\nint hamming_dist(const Graph& A, const Graph& B) {\n    int K = A.size();\n    int d = 0;\n    for(int i=0; i<K; ++i) {\n        for(int j=i; j<K; ++j) {\n            if(A[i][j] != B[i][j]) d++;\n        }\n    }\n    return d;\n}\n\nstruct Config {\n    int N;\n    int K;\n    int S;\n    vector<Graph> codebook; // size M, each KxK\n    double score; // estimated score (higher is better, stored as 1/N if E=0, else negative)\n};\n\n// Generate the large graph from small graph\nGraph expand_graph(const Graph& small, int N, int K, int S) {\n    Graph g(N, vector<int>(N, 0));\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            int g1 = i / S;\n            int g2 = j / S;\n            if (g1 >= K) g1 = K - 1; \n            if (g2 >= K) g2 = K - 1;\n            \n            if(small[g1][g2]) {\n                g[i][j] = g[j][i] = 1;\n            }\n        }\n    }\n    return g;\n}\n\n// Apply channel noise and shuffle\nGraph apply_channel(const Graph& original, double epsilon) {\n    int N = original.size();\n    Graph noisy = original;\n    // Noise\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if(rand_double() < epsilon) {\n                noisy[i][j] = 1 - noisy[i][j];\n                noisy[j][i] = noisy[i][j];\n            }\n        }\n    }\n    // Shuffle\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    shuffle(p.begin(), p.end(), rng);\n    \n    Graph shuffled(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            shuffled[i][j] = noisy[p[i]][p[j]];\n        }\n    }\n    return shuffled;\n}\n\n// Decode\nint decode(const Graph& H, int K, int S, const vector<Graph>& codebook, double eps) {\n    int N = H.size();\n    // 1. Calculate degrees\n    vector<pair<int, int>> degrees(N);\n    for(int i=0; i<N; ++i) {\n        int d = 0;\n        for(int x : H[i]) d += x;\n        degrees[i] = {d, i};\n    }\n    sort(degrees.begin(), degrees.end());\n    \n    // 2. Partition based on rank\n    vector<int> map_node_to_group(N);\n    for(int i=0; i<N; ++i) {\n        int original_idx = degrees[i].second;\n        int group = i / S;\n        if(group >= K) group = K - 1;\n        map_node_to_group[original_idx] = group;\n    }\n    \n    // 3. Estimate block matrix Y (soft)\n    double denom = (1.0 - 2.0 * eps);\n    if(abs(denom) < 1e-9) denom = 1e-9; \n    \n    vector<vector<double>> Z(K, vector<double>(K));\n    \n    for(int a=0; a<K; ++a) {\n        for(int b=a; b<K; ++b) {\n            int edges = 0;\n            int possible = 0;\n            for(int u=0; u<N; ++u) {\n                if(map_node_to_group[u] != a) continue;\n                for(int v=0; v<N; ++v) {\n                    if(map_node_to_group[v] != b) continue;\n                    if(a == b && u >= v) continue; \n                    \n                    possible++;\n                    if(H[u][v]) edges++;\n                }\n            }\n            \n            double density = (possible > 0) ? (double)edges / possible : 0.0; \n            Z[a][b] = (density - eps) / denom;\n        }\n    }\n    \n    // Find closest code\n    int best_idx = -1;\n    double min_dist = 1e18;\n    \n    for(int m=0; m<(int)codebook.size(); ++m) {\n        double dist = 0;\n        for(int a=0; a<K; ++a) {\n            for(int b=a; b<K; ++b) {\n                double val = (double)codebook[m][a][b];\n                double diff = Z[a][b] - val;\n                dist += diff * diff;\n            }\n        }\n        if(dist < min_dist) {\n            min_dist = dist;\n            best_idx = m;\n        }\n    }\n    return best_idx;\n}\n\nvoid solve() {\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return;\n    \n    // Case eps == 0 (trivial)\n    if(eps < 1e-5) {\n        int N = 4;\n        while(N*(N-1)/2 < M) N++;\n        \n        cout << N << endl;\n        // Graph k has k edges\n        for(int k=0; k<M; ++k) {\n            int edges = k;\n            string s = \"\";\n            int count = 0;\n            int total = N*(N-1)/2;\n            for(int i=0; i<total; ++i) {\n                if(count < edges) { s += '1'; count++; }\n                else s += '0';\n            }\n            cout << s << endl;\n        }\n        \n        for(int q=0; q<100; ++q) {\n            string s; cin >> s;\n            int cnt = 0;\n            for(char c : s) if(c=='1') cnt++;\n            cout << cnt << endl;\n        }\n        return;\n    }\n    \n    // Case eps > 0: Search for best config\n    vector<int> Ks = {4, 5, 6, 7};\n    \n    Config best_conf;\n    best_conf.score = -1.0;\n    best_conf.N = 100; \n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    for(int K : Ks) {\n        // Check capacity\n        int capacity_bits = K*(K-1)/2; \n        if (pow(2, capacity_bits) < M) continue;\n        \n        // Determine row sums for \"sorting\" invariant\n        vector<int> row_sums(K);\n        iota(row_sums.begin(), row_sums.end(), 0); // 0, 1, ..., K-1\n        \n        // Generate pool of valid matrices\n        vector<Graph> pool;\n        int attempts = 0;\n        while(pool.size() < 500 && attempts < 3000) {\n            Graph g = generate_valid_matrix(K, row_sums);\n            if(!g.empty()) {\n                bool unique = true;\n                for(const auto& ex : pool) {\n                    if(hamming_dist(g, ex) == 0) { unique = false; break; }\n                }\n                if(unique) pool.push_back(g);\n            }\n            attempts++;\n        }\n        \n        if((int)pool.size() < M) continue; \n        \n        // Select M furthest matrices (MaxMin)\n        vector<Graph> selected;\n        selected.push_back(pool[0]);\n        vector<int> min_dists(pool.size(), 1e9);\n        \n        for(size_t i=0; i<pool.size(); ++i) {\n            min_dists[i] = hamming_dist(pool[i], selected[0]);\n        }\n        \n        while((int)selected.size() < M) {\n            int best_idx = -1;\n            int max_min_dist = -1;\n            \n            for(size_t i=0; i<pool.size(); ++i) {\n                if(min_dists[i] < 0) continue;\n                if(min_dists[i] > max_min_dist) {\n                    max_min_dist = min_dists[i];\n                    best_idx = i;\n                }\n            }\n            \n            if(best_idx == -1) break; \n            \n            selected.push_back(pool[best_idx]);\n            for(size_t i=0; i<pool.size(); ++i) {\n                if(min_dists[i] < 0) continue;\n                int d = hamming_dist(pool[i], pool[best_idx]);\n                min_dists[i] = min(min_dists[i], d);\n            }\n            min_dists[best_idx] = -1; \n        }\n        \n        // Try different S (N = S*K)\n        for(int S = 1; S <= 100/K; ++S) {\n            int N = S * K;\n            // If we already have a perfect solution with smaller N, skip larger N\n            if(best_conf.score > 0 && N >= best_conf.N) break;\n            \n            int errors = 0;\n            int trials = 200; // Simulation count\n            \n            for(int t=0; t<trials; ++t) {\n                int target = rand_int(0, M-1);\n                Graph expanded = expand_graph(selected[target], N, K, S);\n                Graph obs = apply_channel(expanded, eps);\n                int pred = decode(obs, K, S, selected, eps);\n                if(pred != target) {\n                    errors++;\n                    if(errors > 0) break; // Strict E=0 requirement for optimization\n                }\n            }\n            \n            if(errors == 0) {\n                best_conf.N = N;\n                best_conf.K = K;\n                best_conf.S = S;\n                best_conf.codebook = selected;\n                best_conf.score = 1.0 / N; \n                break; // Found minimal S for this K\n            } \n        }\n        \n        // Time Check\n        auto curr = chrono::high_resolution_clock::now();\n        if(chrono::duration_cast<chrono::milliseconds>(curr - start_time).count() > 3000) break;\n    }\n    \n    // Fallback if no perfect config found\n    if(best_conf.score < 0) {\n        best_conf.N = 100;\n        best_conf.K = 5;\n        best_conf.S = 20;\n        vector<int> row_sums(5); iota(row_sums.begin(), row_sums.end(), 0);\n        vector<Graph> pool;\n        int attempts = 0;\n        while((int)pool.size() < M && attempts < 10000) {\n            Graph g = generate_valid_matrix(5, row_sums);\n            if(!g.empty()) pool.push_back(g);\n            attempts++;\n        }\n        // Fill with random if still not enough\n        while((int)pool.size() < M) {\n             Graph g(5, vector<int>(5));\n             for(int i=0;i<5;++i) for(int j=i;j<5;++j) g[i][j] = g[j][i] = rand_int(0,1);\n             pool.push_back(g);\n        }\n        best_conf.codebook = pool;\n    }\n    \n    // Output Graphs\n    cout << best_conf.N << endl;\n    for(int m=0; m<M; ++m) {\n        Graph g = expand_graph(best_conf.codebook[m], best_conf.N, best_conf.K, best_conf.S);\n        cout << to_string_repr(g) << endl;\n    }\n    \n    // Answer Queries\n    for(int q=0; q<100; ++q) {\n        string s; cin >> s;\n        Graph H = from_string(best_conf.N, s);\n        int pred = decode(H, best_conf.K, best_conf.S, best_conf.codebook, eps);\n        cout << pred << endl;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants\nconst long long INF_DIST = 1e18;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Point {\n    int x, y;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<Point> coords;\nvector<vector<pair<int, int>>> adj; // u -> {v, edge_index}\n\n// Precomputed data\nvector<vector<int16_t>> edge_hop_dist; // MxM matrix storing hop distances between edges\nvector<double> edge_importance; // size M, stores approximate betweenness centrality\n\n// Solution state\nvector<int> assignment; // edge_id -> day (1-based)\nvector<vector<int>> day_edges; // day (1-based) -> list of edge_ids\n\n// Random number generator\nmt19937 rng(12345);\n\n// Time management\nauto start_time = chrono::steady_clock::now();\ndouble get_time() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Union Find for connectivity checks\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n + 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) parent[rootX] = rootY;\n    }\n};\n\n// Preprocessing: Hop distances between all pairs of nodes and then edges\nvoid compute_hop_distances() {\n    // node_hop_dist[u][v]: min hops between node u and node v\n    vector<vector<int16_t>> node_dist(N + 1, vector<int16_t>(N + 1, 0));\n\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        vector<int> d(N + 1, -1);\n        queue<int> q;\n        \n        d[start_node] = 0;\n        q.push(start_node);\n        \n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            for (auto& edge : adj[u]) {\n                int v = edge.first;\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        for(int i=1; i<=N; ++i) node_dist[start_node][i] = (int16_t)d[i];\n    }\n\n    // Compute edge_hop_dist[i][j]: min hops between any endpoint of edge i and any endpoint of edge j\n    edge_hop_dist.assign(M, vector<int16_t>(M));\n    for (int i = 0; i < M; ++i) {\n        for (int j = i; j < M; ++j) {\n            if (i == j) {\n                edge_hop_dist[i][j] = 0;\n            } else {\n                int u1 = edges[i].u;\n                int v1 = edges[i].v;\n                int u2 = edges[j].u;\n                int v2 = edges[j].v;\n                \n                int d1 = node_dist[u1][u2];\n                int d2 = node_dist[u1][v2];\n                int d3 = node_dist[v1][u2];\n                int d4 = node_dist[v1][v2];\n                \n                int min_d = min({d1, d2, d3, d4});\n                edge_hop_dist[i][j] = min_d;\n                edge_hop_dist[j][i] = min_d;\n            }\n        }\n    }\n}\n\n// Preprocessing: Importance (Betweenness Centrality approximation)\nvoid compute_importance() {\n    edge_importance.assign(M, 0.0);\n    \n    // Run Dijkstra from each node to count how often an edge is part of a Shortest Path Tree\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, INF_DIST);\n        vector<int> parent_edge(N + 1, -1);\n        \n        dist[start_node] = 0;\n        pq.push({0, start_node});\n        \n        while (!pq.empty()) {\n            long long d = pq.top().first;\n            int u = pq.top().second;\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            \n            for (auto& e : adj[u]) {\n                int v = e.first;\n                int idx = e.second;\n                int w = edges[idx].w;\n                \n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        // Backtrack to increment counts\n        for (int i = 1; i <= N; ++i) {\n            if (i == start_node) continue;\n            int curr = i;\n            while (curr != start_node && parent_edge[curr] != -1) {\n                int e_idx = parent_edge[curr];\n                edge_importance[e_idx] += 1.0;\n                \n                int u = edges[e_idx].u;\n                int v = edges[e_idx].v;\n                // Determine which node is closer to start_node\n                if (dist[u] < dist[v]) curr = u;\n                else curr = v;\n            }\n        }\n    }\n    \n    // Normalize\n    double max_imp = 0;\n    for (double v : edge_importance) max_imp = max(max_imp, v);\n    if (max_imp > 0) {\n        for (auto& v : edge_importance) v /= max_imp;\n    }\n}\n\n// Initial Solution Generation\nvoid initial_solution() {\n    assignment.assign(M, 0);\n    day_edges.assign(D + 1, vector<int>());\n    \n    // Use BFS on the dual-like structure or just BFS on edges starting from center\n    // to ensure nearby edges get consecutive indices.\n    vector<bool> visited(M, false);\n    queue<int> q;\n    \n    // Find node closest to center (500, 500)\n    int center_node = 1;\n    int min_dist = 1e9;\n    if (!coords.empty()) {\n        for(int i=1; i<=N; ++i) {\n            int d = (coords[i-1].x - 500)*(coords[i-1].x - 500) + (coords[i-1].y - 500)*(coords[i-1].y - 500);\n            if (d < min_dist) {\n                min_dist = d;\n                center_node = i;\n            }\n        }\n    }\n    \n    // Push edges of center node\n    for(auto& p : adj[center_node]) {\n        q.push(p.second);\n        visited[p.second] = true;\n    }\n    if(q.empty()) { q.push(0); visited[0] = true; }\n\n    vector<int> ordered_edges;\n    ordered_edges.reserve(M);\n    \n    while(ordered_edges.size() < M) {\n        if (q.empty()) {\n            for(int i=0; i<M; ++i) if(!visited[i]) { q.push(i); visited[i]=true; break; }\n        }\n        \n        while(!q.empty()){\n            int e_idx = q.front();\n            q.pop();\n            ordered_edges.push_back(e_idx);\n            \n            int u = edges[e_idx].u;\n            int v = edges[e_idx].v;\n            \n            for(auto& p : adj[u]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n            for(auto& p : adj[v]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n        }\n    }\n    \n    // Assign days in a round-robin fashion to spatially separate edges on the same day\n    vector<int> counts(D + 1, 0);\n    int current_day = 1;\n    for(int e_idx : ordered_edges) {\n        // Ensure we don't exceed K\n        while(counts[current_day] >= K) {\n            current_day = (current_day % D) + 1;\n        }\n        assignment[e_idx] = current_day;\n        day_edges[current_day].push_back(e_idx);\n        counts[current_day]++;\n        current_day = (current_day % D) + 1;\n    }\n}\n\n// Cost Function for SA\n// Calculate contribution of a pair of removed edges (i, j)\ninline double pair_cost(int i, int j) {\n    double dist = edge_hop_dist[i][j];\n    // Penalty is high if distance is small.\n    // Penalty is scaled by importance: removing two important edges nearby is very bad.\n    double imp_factor = 1.0 + 10.0 * edge_importance[i] * edge_importance[j]; \n    return imp_factor / ((dist + 1.0) * (dist + 1.0));\n}\n\n// Calculate total dispersion cost for a day\ndouble calculate_day_cost(int d) {\n    double cost = 0;\n    const auto& es = day_edges[d];\n    for (size_t i = 0; i < es.size(); ++i) {\n        for (size_t j = i + 1; j < es.size(); ++j) {\n            cost += pair_cost(es[i], es[j]);\n        }\n    }\n    return cost;\n}\n\n// Check if graph remains connected when edges of day 'd' are removed\nbool check_connectivity(int d) {\n    DSU dsu(N);\n    int components = N;\n    for(int i=0; i<M; ++i) {\n        if (assignment[i] != d) {\n            if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                dsu.unite(edges[i].u, edges[i].v);\n                components--;\n            }\n        }\n    }\n    return components == 1;\n}\n\n// Try to fix connectivity issues greedily\nbool fix_connectivity() {\n    bool changed = false;\n    for (int d = 1; d <= D; ++d) {\n        if (!check_connectivity(d)) {\n            // Identify components\n            DSU dsu(N);\n            for(int i=0; i<M; ++i) {\n                if (assignment[i] != d) {\n                    dsu.unite(edges[i].u, edges[i].v);\n                }\n            }\n            \n            // Find an edge currently scheduled for day 'd' that connects two different components\n            // If we move this edge to another day, it will be present on day 'd', fixing connectivity.\n            int best_edge = -1;\n            \n            for (int e_idx : day_edges[d]) {\n                if (dsu.find(edges[e_idx].u) != dsu.find(edges[e_idx].v)) {\n                    best_edge = e_idx;\n                    break; // Found a bridging edge\n                }\n            }\n            \n            if (best_edge != -1) {\n                // Move best_edge to a day with capacity < K\n                for (int target = 1; target <= D; ++target) {\n                    if (target != d && day_edges[target].size() < K) {\n                        // Perform move\n                        vector<int>& vec_d = day_edges[d];\n                        vec_d.erase(remove(vec_d.begin(), vec_d.end(), best_edge), vec_d.end());\n                        \n                        day_edges[target].push_back(best_edge);\n                        assignment[best_edge] = target;\n                        changed = true;\n                        break; \n                    }\n                }\n            }\n        }\n    }\n    return changed;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> D >> K)) return 0;\n    \n    adj.resize(N + 1);\n    edges.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        edges.push_back({u, v, w, i});\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n    \n    coords.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n\n    // 1. Preprocessing\n    compute_hop_distances();\n    compute_importance();\n    \n    // 2. Initial Assignment\n    initial_solution();\n\n    // Calculate initial costs\n    vector<double> day_costs(D + 1);\n    double total_cost = 0;\n    for (int d = 1; d <= D; ++d) {\n        day_costs[d] = calculate_day_cost(d);\n        total_cost += day_costs[d];\n    }\n\n    // 3. Simulated Annealing\n    double time_limit = 5.6; \n    double t0 = 5.0;\n    double t1 = 0.0001;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) { \n            if (get_time() > time_limit) break;\n        }\n        \n        double temp = t0 + (t1 - t0) * (get_time() / time_limit);\n        \n        // Swap Move: Pick two different days and swap an edge\n        int d1 = uniform_int_distribution<int>(1, D)(rng);\n        int d2 = uniform_int_distribution<int>(1, D)(rng);\n        if (d1 == d2) continue;\n        \n        if (day_edges[d1].empty() || day_edges[d2].empty()) continue;\n\n        int idx1 = uniform_int_distribution<int>(0, day_edges[d1].size() - 1)(rng);\n        int idx2 = uniform_int_distribution<int>(0, day_edges[d2].size() - 1)(rng);\n        \n        int e1 = day_edges[d1][idx1];\n        int e2 = day_edges[d2][idx2];\n        \n        // Calculate cost delta incrementally\n        double d1_old = day_costs[d1];\n        double d2_old = day_costs[d2];\n        \n        // Remove e1 from d1, add e2 to d1\n        double cost_e1_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e1_in_d1 += pair_cost(e1, other);\n        }\n        double cost_e2_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e2_in_d1 += pair_cost(e2, other);\n        }\n        \n        // Remove e2 from d2, add e1 to d2\n        double cost_e2_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e2_in_d2 += pair_cost(e2, other);\n        }\n        double cost_e1_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e1_in_d2 += pair_cost(e1, other);\n        }\n        \n        double d1_new = d1_old - cost_e1_in_d1 + cost_e2_in_d1;\n        double d2_new = d2_old - cost_e2_in_d2 + cost_e1_in_d2;\n        \n        double delta = (d1_new + d2_new) - (d1_old + d2_old);\n        \n        if (delta < 0 || bernoulli_distribution(exp(-delta / temp))(rng)) {\n            // Accept swap\n            day_edges[d1][idx1] = e2;\n            day_edges[d2][idx2] = e1;\n            assignment[e1] = d2;\n            assignment[e2] = d1;\n            day_costs[d1] = d1_new;\n            day_costs[d2] = d2_new;\n            total_cost += delta;\n        }\n    }\n    \n    // 4. Ensure Connectivity\n    // Keep trying to fix until valid or time is up (allow slight over time if needed, but keep safe)\n    while (get_time() < 5.9) {\n        if (!fix_connectivity()) break; \n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        cout << assignment[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cstring>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Timing management\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Constants\nconst int MAX_D = 14;\nint D;\n\n// Silhouette Inputs\nvector<string> f1_in, r1_in, f2_in, r2_in;\n\n// Point structure for 3D coordinates\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y, z + other.z};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y, z - other.z};\n    }\n};\n\n// Rotation handling\nstruct Rotation {\n    int p[3]; // Permutation of axes {0, 1, 2}\n    int s[3]; // Signs {1, -1}\n};\n\nvector<Rotation> rotations;\n\nvoid init_rotations() {\n    int perms[6][3] = {\n        {0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}\n    };\n    for (int i = 0; i < 6; ++i) {\n        for (int mask = 0; mask < 8; ++mask) {\n            Rotation r;\n            for (int j = 0; j < 3; ++j) {\n                r.p[j] = perms[i][j];\n                r.s[j] = (mask & (1 << j)) ? -1 : 1;\n            }\n            // Check determinant to ensure proper rotation (det = 1)\n            int mat[3][3] = {0};\n            for(int j=0; j<3; ++j) mat[j][r.p[j]] = r.s[j];\n            \n            int det = mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1])\n                    - mat[0][1]*(mat[1][0]*mat[2][2] - mat[1][2]*mat[2][0])\n                    + mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]);\n            \n            if (det == 1) {\n                rotations.push_back(r);\n            }\n        }\n    }\n}\n\nPoint apply(const Point& pt, int rot_idx) {\n    const Rotation& r = rotations[rot_idx];\n    int coords[3] = {pt.x, pt.y, pt.z};\n    return {\n        coords[r.p[0]] * r.s[0],\n        coords[r.p[1]] * r.s[1],\n        coords[r.p[2]] * r.s[2]\n    };\n}\n\n// Helper to read silhouette bit\nbool get_bit(const vector<string>& bits, int r, int c) {\n    return bits[r][c] == '1';\n}\n\nusing VoxelSet = vector<Point>;\n\n// Construct the set of all valid voxels given silhouettes\nVoxelSet get_maximal(const vector<string>& f, const vector<string>& r_sil) {\n    VoxelSet voxels;\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                // f is indexed as f(z, x), r as r(z, y)\n                if (get_bit(f, z, x) && get_bit(r_sil, z, y)) {\n                    voxels.push_back({x, y, z});\n                }\n            }\n        }\n    }\n    return voxels;\n}\n\n// Trim voxels that are not essential for maintaining the silhouette\n// Randomly removes valid candidates\nVoxelSet trim_voxels(const VoxelSet& input, mt19937& rng) {\n    // Track occupancy\n    int grid[15][15][15];\n    memset(grid, 0, sizeof(grid));\n    for (const auto& p : input) grid[p.x][p.y][p.z] = 1;\n\n    // Count how many blocks support each silhouette pixel\n    int czx[15][15], czy[15][15];\n    memset(czx, 0, sizeof(czx));\n    memset(czy, 0, sizeof(czy));\n\n    for (const auto& p : input) {\n        czx[p.z][p.x]++;\n        czy[p.z][p.y]++;\n    }\n\n    VoxelSet current = input;\n    shuffle(current.begin(), current.end(), rng);\n\n    VoxelSet result;\n    for (const auto& p : current) {\n        // If more than one block supports both silhouettes at this position, we can remove it\n        if (czx[p.z][p.x] > 1 && czy[p.z][p.y] > 1) {\n            czx[p.z][p.x]--;\n            czy[p.z][p.y]--;\n            grid[p.x][p.y][p.z] = 0;\n        }\n    }\n\n    for(int x=0; x<D; ++x)\n        for(int y=0; y<D; ++y)\n            for(int z=0; z<D; ++z)\n                if(grid[x][y][z]) result.push_back({x,y,z});\n    \n    return result;\n}\n\n// Finds the largest common connected block between subsets of V1 and V2\n// Returns indices of voxels in the input vectors that form the block\npair<vector<int>, vector<int>> find_common_block(\n    const VoxelSet& v1, const VoxelSet& v2, int threshold\n) {\n    if(v1.empty() || v2.empty()) return {{}, {}};\n\n    int best_score = -1;\n    int best_rot = -1;\n    Point best_shift = {0,0,0};\n\n    // Vote array for finding best translation\n    static int votes[30*30*30]; \n    int offset_base = D;\n    int dim = 2 * D + 1;\n    int dim_sq = dim * dim;\n\n    // Optimization: Subsample for voting if datasets are huge, \n    // but typically D <= 14 makes |V| small enough.\n    int step1 = 1, step2 = 1;\n    if (v1.size() * v2.size() > 150000) {\n        step1 = 2; step2 = 2;\n    }\n\n    for (int rot = 0; rot < 24; ++rot) {\n        // Reset votes\n        memset(votes, 0, sizeof(int) * dim * dim * dim);\n\n        // Transform v2\n        vector<Point> v2_rot(v2.size());\n        for(size_t i=0; i<v2.size(); ++i) v2_rot[i] = apply(v2[i], rot);\n\n        // Vote for shift = p1 - p2\n        for (size_t i = 0; i < v1.size(); i += step1) {\n            for (size_t j = 0; j < v2.size(); j += step2) {\n                Point d = v1[i] - v2_rot[j];\n                if (abs(d.x) < D && abs(d.y) < D && abs(d.z) < D) {\n                    int idx = (d.x + offset_base) * dim_sq + (d.y + offset_base) * dim + (d.z + offset_base);\n                    votes[idx]++;\n                }\n            }\n        }\n\n        // Find max vote\n        int max_v = 0;\n        int best_idx = -1;\n        for(int i=0; i<dim*dim*dim; ++i) {\n            if(votes[i] > max_v) {\n                max_v = votes[i];\n                best_idx = i;\n            }\n        }\n\n        if (max_v > best_score) {\n            best_score = max_v;\n            best_rot = rot;\n            int dz = best_idx % dim;\n            int dy = (best_idx / dim) % dim;\n            int dx = (best_idx / dim_sq);\n            best_shift = {dx - offset_base, dy - offset_base, dz - offset_base};\n        }\n    }\n\n    if (best_score < threshold) return {{}, {}};\n\n    // Reconstruct Intersection\n    map<Point, int> v2_map;\n    for(size_t i=0; i<v2.size(); ++i) {\n        Point p = apply(v2[i], best_rot) + best_shift;\n        v2_map[p] = i;\n    }\n\n    VoxelSet intersection;\n    map<Point, int> p_to_v1;\n\n    for(size_t i=0; i<v1.size(); ++i) {\n        if (v2_map.count(v1[i])) {\n            intersection.push_back(v1[i]);\n            p_to_v1[v1[i]] = i;\n        }\n    }\n\n    if (intersection.empty()) return {{}, {}};\n\n    // Find largest connected component in intersection\n    set<Point> int_set(intersection.begin(), intersection.end());\n    set<Point> visited;\n    vector<Point> best_comp;\n\n    for(const auto& p : intersection) {\n        if (visited.count(p)) continue;\n        \n        vector<Point> comp;\n        queue<Point> q;\n        q.push(p);\n        visited.insert(p);\n        comp.push_back(p);\n        \n        while(!q.empty()){\n            Point u = q.front(); q.pop();\n            \n            int dx[] = {1, -1, 0, 0, 0, 0};\n            int dy[] = {0, 0, 1, -1, 0, 0};\n            int dz[] = {0, 0, 0, 0, 1, -1};\n            \n            for(int k=0; k<6; ++k){\n                Point v = {u.x + dx[k], u.y + dy[k], u.z + dz[k]};\n                if(int_set.count(v) && visited.find(v) == visited.end()){\n                    visited.insert(v);\n                    q.push(v);\n                    comp.push_back(v);\n                }\n            }\n        }\n        \n        if (comp.size() > best_comp.size()) {\n            best_comp = comp;\n        }\n    }\n\n    if ((int)best_comp.size() < threshold) return {{}, {}};\n\n    vector<int> res1, res2;\n    for(const auto& p : best_comp) {\n        res1.push_back(p_to_v1[p]);\n        res2.push_back(v2_map[p]);\n    }\n\n    return {res1, res2};\n}\n\nstruct BlockDef {\n    int id;\n    int vol;\n};\n\nstruct Solution {\n    vector<int> b1_grid;\n    vector<int> b2_grid;\n    int num_blocks;\n    double score;\n};\n\ndouble calculate_score(const vector<BlockDef>& blocks, \n                       const vector<int>& unused1,\n                       const vector<int>& unused2) {\n    double term1 = 0;\n    for(int v : unused1) term1 += v;\n    double term2 = 0;\n    for(int v : unused2) term2 += v;\n    double term3 = 0;\n    for(const auto& b : blocks) {\n        term3 += 1.0 / b.vol;\n    }\n    return round(1e9 * (term1 + term2 + term3));\n}\n\nvoid solve() {\n    cin >> D;\n    f1_in.resize(D); r1_in.resize(D);\n    f2_in.resize(D); r2_in.resize(D);\n    for(int i=0; i<D; ++i) cin >> f1_in[i];\n    for(int i=0; i<D; ++i) cin >> r1_in[i];\n    for(int i=0; i<D; ++i) cin >> f2_in[i];\n    for(int i=0; i<D; ++i) cin >> r2_in[i];\n\n    init_rotations();\n\n    VoxelSet M1 = get_maximal(f1_in, r1_in);\n    VoxelSet M2 = get_maximal(f2_in, r2_in);\n\n    mt19937 rng(0); // Deterministic seeding for reproducible results\n\n    Solution best_sol;\n    best_sol.score = 1e18;\n\n    int iterations = 0;\n    // Time constrained loop\n    while (get_time() < 5.5) {\n        iterations++;\n        \n        // Generate reduced valid sets\n        VoxelSet V1 = trim_voxels(M1, rng);\n        VoxelSet V2 = trim_voxels(M2, rng);\n\n        vector<bool> used1(V1.size(), false);\n        vector<bool> used2(V2.size(), false);\n        int rem1 = V1.size();\n        int rem2 = V2.size();\n\n        vector<BlockDef> common_blocks;\n        vector<int> grid1(D*D*D, 0);\n        vector<int> grid2(D*D*D, 0);\n        int block_idx_counter = 1;\n\n        // Greedy phase: Find large common blocks\n        while (rem1 > 0 && rem2 > 0) {\n            VoxelSet sub1, sub2;\n            vector<int> map1, map2;\n            for(size_t i=0; i<V1.size(); ++i) if(!used1[i]) { sub1.push_back(V1[i]); map1.push_back(i); }\n            for(size_t i=0; i<V2.size(); ++i) if(!used2[i]) { sub2.push_back(V2[i]); map2.push_back(i); }\n\n            // Prioritize blocks with volume >= 2, fallback to 1\n            int threshold = 2;\n            if (sub1.size() < 2 || sub2.size() < 2) threshold = 1;\n\n            auto res = find_common_block(sub1, sub2, threshold);\n            if (res.first.empty()) {\n                if (threshold > 1) {\n                    res = find_common_block(sub1, sub2, 1);\n                }\n            }\n\n            if (res.first.empty()) break;\n\n            int vol = res.first.size();\n            BlockDef b;\n            b.id = block_idx_counter++;\n            b.vol = vol;\n            common_blocks.push_back(b);\n\n            for (int idx : res.first) {\n                int orig_idx = map1[idx];\n                used1[orig_idx] = true;\n                rem1--;\n                Point p = V1[orig_idx];\n                grid1[p.x*D*D + p.y*D + p.z] = b.id;\n            }\n            for (int idx : res.second) {\n                int orig_idx = map2[idx];\n                used2[orig_idx] = true;\n                rem2--;\n                Point p = V2[orig_idx];\n                grid2[p.x*D*D + p.y*D + p.z] = b.id;\n            }\n        }\n\n        // Cleanup phase: Match remaining 1x1 blocks\n        vector<int> rem_idx1, rem_idx2;\n        for(size_t i=0; i<V1.size(); ++i) if(!used1[i]) rem_idx1.push_back(i);\n        for(size_t i=0; i<V2.size(); ++i) if(!used2[i]) rem_idx2.push_back(i);\n\n        int common_ones = min(rem_idx1.size(), rem_idx2.size());\n        for(int i=0; i<common_ones; ++i) {\n            BlockDef b;\n            b.id = block_idx_counter++;\n            b.vol = 1;\n            common_blocks.push_back(b);\n            \n            int idx1 = rem_idx1[i];\n            Point p1 = V1[idx1];\n            grid1[p1.x*D*D + p1.y*D + p1.z] = b.id;\n\n            int idx2 = rem_idx2[i];\n            Point p2 = V2[idx2];\n            grid2[p2.x*D*D + p2.y*D + p2.z] = b.id;\n        }\n\n        // Penalty phase: Unmatched blocks\n        vector<int> u1_vols, u2_vols;\n        for(size_t i=common_ones; i<rem_idx1.size(); ++i) {\n            int idx = rem_idx1[i];\n            Point p = V1[idx];\n            int id = block_idx_counter++;\n            grid1[p.x*D*D + p.y*D + p.z] = id;\n            u1_vols.push_back(1);\n        }\n        for(size_t i=common_ones; i<rem_idx2.size(); ++i) {\n            int idx = rem_idx2[i];\n            Point p = V2[idx];\n            int id = block_idx_counter++;\n            grid2[p.x*D*D + p.y*D + p.z] = id;\n            u2_vols.push_back(1);\n        }\n\n        double score = calculate_score(common_blocks, u1_vols, u2_vols);\n        if (score < best_sol.score) {\n            best_sol.score = score;\n            best_sol.b1_grid = grid1;\n            best_sol.b2_grid = grid2;\n            best_sol.num_blocks = block_idx_counter - 1;\n        }\n        \n        if (iterations >= 150) break;\n    }\n\n    cout << best_sol.num_blocks << endl;\n    for(int i=0; i<(int)best_sol.b1_grid.size(); ++i) cout << best_sol.b1_grid[i] << (i==best_sol.b1_grid.size()-1 ? \"\" : \" \");\n    cout << endl;\n    for(int i=0; i<(int)best_sol.b2_grid.size(); ++i) cout << best_sol.b2_grid[i] << (i==best_sol.b2_grid.size()-1 ? \"\" : \" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc020":"/**\n * Problem: AHC020 - Broadcasting\n * Approach: Simulated Annealing to optimize resident-to-station assignment.\n * 1. Precompute all-pairs shortest paths on the graph G to support Steiner Tree heuristics.\n * 2. Represent the state by the assignment of each resident to a station.\n *    - The power P_i of station i is determined by the farthest resident assigned to it.\n *    - The active stations (terminals) are those with at least one resident assigned, plus station 1.\n * 3. The cost function is sum(P_i^2) + ApproximateSteinerTreeCost(active_stations).\n * 4. Use Simulated Annealing to move residents between nearby stations.\n *    - A move updates P_i and P_j incrementally.\n *    - If a station becomes empty or non-empty, the Steiner Tree cost is re-evaluated.\n * 5. Post-process to generate the exact edge set:\n *    - Construct the tree using the union of shortest paths between terminals (MST on metric closure).\n *    - Prune unnecessary leaves to minimize edge cost.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 105;\nconst int MAX_K = 5005;\nconst int MAX_M = 305;\nconst long long INF = 1e18;\n\n// Structures\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Station {\n    int x, y;\n    int id;\n};\n\n// Global Inputs\nint N, M, K;\nStation stations[MAX_N];\nEdge edges[MAX_M];\nPoint residents[MAX_K];\n\n// Precomputed Data\nlong long adj_dist[MAX_N][MAX_N];      // Shortest path distance in G\nint next_node[MAX_N][MAX_N];           // Next node in shortest path\nint edge_index[MAX_N][MAX_N];          // Edge ID connecting two nodes\nint resident_ceil_dist[MAX_K][MAX_N];  // Required P for resident k at station i\nvector<int> nearby_stations[MAX_K];    // List of stations sorted by distance for each resident\n\n// Random number generator\nmt19937 rng(12345);\n\n// Helper Functions\nlong long distSq(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint get_P(long long sq_dist) {\n    if (sq_dist == 0) return 0;\n    return (int)ceil(sqrt((double)sq_dist));\n}\n\n// State Management\nstruct State {\n    vector<int> assignment;                 // resident k -> station index\n    vector<multiset<int>> station_radii;    // station i -> set of required radii (P values)\n    vector<int> active_residents_count;     // station i -> number of assigned residents\n    \n    long long power_cost;\n    long long network_cost;\n    long long total_cost;\n\n    State() {\n        assignment.resize(K);\n        station_radii.resize(N);\n        active_residents_count.assign(N, 0);\n        power_cost = 0;\n        network_cost = 0;\n        total_cost = 0;\n    }\n};\n\nvoid precompute_paths() {\n    // Initialize\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            adj_dist[i][j] = (i == j ? 0 : INF);\n            next_node[i][j] = -1;\n            edge_index[i][j] = -1;\n        }\n    }\n\n    // Load edges\n    for(int i=0; i<M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int w = edges[i].w;\n        // Graph is simple, but standard check\n        if(w < adj_dist[u][v] || adj_dist[u][v] == INF) {\n            adj_dist[u][v] = adj_dist[v][u] = w;\n            next_node[u][v] = v;\n            next_node[v][u] = u;\n            edge_index[u][v] = edge_index[v][u] = i;\n        }\n    }\n\n    // Floyd-Warshall with path reconstruction\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(adj_dist[i][k] != INF && adj_dist[k][j] != INF) {\n                    if(adj_dist[i][k] + adj_dist[k][j] < adj_dist[i][j]) {\n                        adj_dist[i][j] = adj_dist[i][k] + adj_dist[k][j];\n                        next_node[i][j] = next_node[i][k];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate Approximate Steiner Tree Cost\n// This constructs a tree covering the active terminals (stations with residents + station 0).\n// It uses the union of shortest paths from the MST on the metric closure.\nlong long calc_steiner_cost(const vector<bool>& is_terminal) {\n    vector<int> terminals;\n    for(int i=0; i<N; ++i) {\n        if(is_terminal[i] || i == 0) terminals.push_back(i);\n    }\n    \n    if(terminals.size() <= 1) return 0;\n\n    // 1. MST on metric closure (complete graph of terminals)\n    int T = terminals.size();\n    vector<long long> min_dist(T, INF);\n    vector<int> parent(T, -1);\n    vector<bool> visited(T, false);\n    \n    min_dist[0] = 0;\n    \n    // Prim's Algorithm\n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_dist[j] < best) {\n                best = min_dist[j];\n                u = j;\n            }\n        }\n        if (u == -1) break;\n        visited[u] = true;\n        \n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[terminals[u]][terminals[v]];\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    \n    // 2. Map MST edges back to original graph paths and sum unique edge weights\n    bitset<MAX_M> used_edges;\n    long long total_w = 0;\n    \n    for(int i=1; i<T; ++i) {\n        if (parent[i] == -1) continue; \n        int u = terminals[i];\n        int v = terminals[parent[i]];\n        \n        int curr = u;\n        while(curr != v) {\n            int nxt = next_node[curr][v];\n            int idx = edge_index[curr][nxt];\n            if(idx != -1 && !used_edges[idx]) {\n                used_edges[idx] = 1;\n                total_w += edges[idx].w;\n            }\n            curr = nxt;\n        }\n    }\n    \n    return total_w;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    if (!(cin >> N >> M >> K)) return 0;\n    for(int i=0; i<N; ++i) {\n        cin >> stations[i].x >> stations[i].y;\n        stations[i].id = i;\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--; // 0-indexed\n        edges[i].id = i;\n    }\n    for(int i=0; i<K; ++i) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n\n    // Initialization\n    precompute_paths();\n\n    // Precompute distances and sort nearby stations for each resident\n    for(int k=0; k<K; ++k) {\n        vector<pair<int, int>> dists;\n        for(int i=0; i<N; ++i) {\n            long long sq = distSq(residents[k].x, residents[k].y, stations[i].x, stations[i].y);\n            int P = get_P(sq);\n            resident_ceil_dist[k][i] = P;\n            dists.push_back({P, i});\n        }\n        // Sort by distance\n        sort(dists.begin(), dists.end());\n        for(auto& p : dists) nearby_stations[k].push_back(p.second);\n    }\n\n    // Initial State: Assign each resident to the closest station\n    State current_state;\n    vector<bool> is_terminal(N, false);\n    \n    for(int k=0; k<K; ++k) {\n        int st_idx = nearby_stations[k][0]; \n        current_state.assignment[k] = st_idx;\n        current_state.station_radii[st_idx].insert(resident_ceil_dist[k][st_idx]);\n        current_state.active_residents_count[st_idx]++;\n    }\n\n    for(int i=0; i<N; ++i) {\n        if(current_state.active_residents_count[i] > 0) {\n            int P = *current_state.station_radii[i].rbegin();\n            current_state.power_cost += (long long)P * P;\n            is_terminal[i] = true;\n        }\n    }\n    \n    current_state.network_cost = calc_steiner_cost(is_terminal);\n    current_state.total_cost = current_state.power_cost + current_state.network_cost;\n\n    State best_state = current_state;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95; \n    double start_temp = 2000000.0; // Tuned based on cost magnitude\n    double end_temp = 100.0;\n\n    int iter = 0;\n    while(true) {\n        iter++;\n        if((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if(elapsed > time_limit) break;\n        }\n\n        // 1. Pick a random resident\n        int k = rng() % K;\n        int old_u = current_state.assignment[k];\n        \n        // 2. Pick a new station (biased towards nearby ones)\n        // Consider top 15 closest stations\n        int rank = rng() % min(N, 15);\n        int new_v = nearby_stations[k][rank];\n        \n        if(old_u == new_v) continue;\n\n        // 3. Calculate Delta Power Cost\n        long long old_P_u_sq = 0;\n        if(!current_state.station_radii[old_u].empty()) {\n            int r = *current_state.station_radii[old_u].rbegin();\n            old_P_u_sq = (long long)r * r;\n        }\n        \n        long long old_P_v_sq = 0;\n        if(!current_state.station_radii[new_v].empty()) {\n            int r = *current_state.station_radii[new_v].rbegin();\n            old_P_v_sq = (long long)r * r;\n        }\n\n        // New P_u if k is removed\n        long long new_P_u_sq = old_P_u_sq;\n        int r_k_u = resident_ceil_dist[k][old_u];\n        bool u_becomes_empty = (current_state.active_residents_count[old_u] == 1);\n        \n        if (u_becomes_empty) {\n            new_P_u_sq = 0;\n        } else {\n            int current_max = *current_state.station_radii[old_u].rbegin();\n            if (r_k_u == current_max) {\n                // Check if there are other residents with the same max radius\n                if (current_state.station_radii[old_u].count(r_k_u) == 1) {\n                     // Find the second largest\n                     auto it = current_state.station_radii[old_u].find(r_k_u);\n                     if (it != current_state.station_radii[old_u].begin()) {\n                         auto prev_it = prev(it);\n                         new_P_u_sq = (long long)(*prev_it) * (*prev_it);\n                     } else {\n                         // Should not happen if count > 1, but technically possible if data inconsistent\n                         new_P_u_sq = 0; \n                     }\n                }\n                // If count > 1, removing one doesn't change the max\n            }\n        }\n\n        // New P_v if k is added\n        int r_k_v = resident_ceil_dist[k][new_v];\n        long long new_P_v_sq = old_P_v_sq;\n        bool v_becomes_active = (current_state.active_residents_count[new_v] == 0);\n\n        if (v_becomes_active) {\n            new_P_v_sq = (long long)r_k_v * r_k_v;\n        } else {\n            int current_max = *current_state.station_radii[new_v].rbegin();\n            if (r_k_v > current_max) {\n                new_P_v_sq = (long long)r_k_v * r_k_v;\n            }\n        }\n\n        long long power_delta = (new_P_u_sq - old_P_u_sq) + (new_P_v_sq - old_P_v_sq);\n        long long network_delta = 0;\n        long long new_network_cost = current_state.network_cost;\n\n        // 4. Calculate Delta Network Cost (only if active set changes)\n        if (u_becomes_empty || v_becomes_active) {\n            if (u_becomes_empty) is_terminal[old_u] = false;\n            if (v_becomes_active) is_terminal[new_v] = true;\n            \n            new_network_cost = calc_steiner_cost(is_terminal);\n            network_delta = new_network_cost - current_state.network_cost;\n            \n            // Revert for now\n            if (u_becomes_empty) is_terminal[old_u] = true;\n            if (v_becomes_active) is_terminal[new_v] = false;\n        }\n\n        long long total_delta = power_delta + network_delta;\n\n        // 5. Accept or Reject\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        double temp = start_temp + (end_temp - start_temp) * (elapsed / time_limit);\n        \n        bool accept = (total_delta <= 0);\n        if (!accept) {\n            double prob = exp(-total_delta / temp);\n            if (generate_canonical<double, 10>(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            // Apply changes\n            current_state.assignment[k] = new_v;\n            \n            auto it = current_state.station_radii[old_u].find(r_k_u);\n            current_state.station_radii[old_u].erase(it);\n            current_state.active_residents_count[old_u]--;\n            \n            current_state.station_radii[new_v].insert(r_k_v);\n            current_state.active_residents_count[new_v]++;\n            \n            current_state.power_cost += power_delta;\n            current_state.network_cost = new_network_cost;\n            current_state.total_cost += total_delta;\n            \n            if (u_becomes_empty) is_terminal[old_u] = false;\n            if (v_becomes_active) is_terminal[new_v] = true;\n            \n            if (current_state.total_cost < best_state.total_cost) {\n                best_state = current_state;\n            }\n        }\n    }\n\n    // Final Output Generation\n    \n    // 1. Identify final terminals\n    fill(is_terminal.begin(), is_terminal.end(), false);\n    vector<int> P_vals(N, 0);\n    vector<int> terminals;\n    \n    for(int i=0; i<N; ++i) {\n        if(best_state.active_residents_count[i] > 0) {\n            is_terminal[i] = true;\n            P_vals[i] = *best_state.station_radii[i].rbegin();\n        }\n    }\n    // Add root and all active stations to terminals list\n    for(int i=0; i<N; ++i) if(is_terminal[i] || i==0) terminals.push_back(i);\n    \n    // 2. Construct the network (Union of shortest paths)\n    bitset<MAX_M> used_edges_bs;\n    int T = terminals.size();\n    if (T > 1) {\n         vector<long long> min_dist(T, INF);\n         vector<int> parent(T, -1);\n         vector<bool> visited(T, false);\n         min_dist[0] = 0;\n         \n         for(int i=0; i<T; ++i) {\n            int u = -1;\n            long long best = INF;\n            for(int j=0; j<T; ++j) {\n                if(!visited[j] && min_dist[j] < best) {\n                    best = min_dist[j];\n                    u = j;\n                }\n            }\n            visited[u] = true;\n            for(int v=0; v<T; ++v) {\n                if(!visited[v]) {\n                    long long d = adj_dist[terminals[u]][terminals[v]];\n                    if(d < min_dist[v]) {\n                        min_dist[v] = d;\n                        parent[v] = u;\n                    }\n                }\n            }\n         }\n         \n         for(int i=1; i<T; ++i) {\n             int u = terminals[i];\n             int v = terminals[parent[i]];\n             int curr = u;\n             while(curr != v) {\n                 int nxt = next_node[curr][v];\n                 int idx = edge_index[curr][nxt];\n                 if(idx != -1) used_edges_bs[idx] = 1;\n                 curr = nxt;\n             }\n         }\n    }\n    \n    // 3. Pruning: Use Kruskal's on the induced subgraph and remove non-terminal leaves\n    vector<int> subgraph_edges;\n    for(int i=0; i<M; ++i) if(used_edges_bs[i]) subgraph_edges.push_back(i);\n    \n    // Sort edges by weight for Kruskal's\n    sort(subgraph_edges.begin(), subgraph_edges.end(), [](int a, int b){\n        return edges[a].w < edges[b].w;\n    });\n    \n    struct DSU {\n        vector<int> p;\n        DSU(int n) : p(n) { iota(p.begin(), p.end(), 0); }\n        int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n        bool unite(int x, int y) {\n            x = find(x); y = find(y);\n            if(x == y) return false;\n            p[x] = y; return true;\n        }\n    };\n    \n    DSU dsu(N);\n    vector<int> tree_edges;\n    vector<vector<pair<int,int>>> tree_adj(N);\n    vector<int> degree(N, 0);\n    \n    for(int id : subgraph_edges) {\n        if(dsu.unite(edges[id].u, edges[id].v)) {\n            tree_edges.push_back(id);\n            tree_adj[edges[id].u].push_back({edges[id].v, id});\n            tree_adj[edges[id].v].push_back({edges[id].u, id});\n            degree[edges[id].u]++;\n            degree[edges[id].v]++;\n        }\n    }\n    \n    // Leaf Pruning\n    queue<int> q;\n    for(int i=0; i<N; ++i) {\n        if(degree[i] == 1 && !is_terminal[i] && i != 0) {\n            q.push(i);\n        }\n    }\n    \n    vector<bool> final_edges(M, false);\n    for(int id : tree_edges) final_edges[id] = true;\n    \n    while(!q.empty()) {\n        int u = q.front(); q.pop();\n        for(auto& edge : tree_adj[u]) {\n            int v = edge.first;\n            int id = edge.second;\n            if(final_edges[id]) {\n                final_edges[id] = false;\n                degree[u]--;\n                degree[v]--;\n                if(degree[v] == 1 && !is_terminal[v] && v != 0) {\n                    q.push(v);\n                }\n                break; \n            }\n        }\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) cout << P_vals[i] << (i == N-1 ? \"\" : \" \");\n    cout << \"\\n\";\n    for(int i=0; i<M; ++i) cout << (final_edges[i] ? 1 : 0) << (i == M-1 ? \"\" : \" \");\n    cout << \"\\n\";\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n\nusing namespace std;\n\nconst int N = 30;\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\n// Function to solve using a specific strategy\n// strategy_type: 0=TD, 1=BU, 2=Mixed(TD->BU), 3=Mixed(BU->TD), 4=Random\nvector<Move> solve(vector<vector<int>> a, int strategy_type, int seed = 0) {\n    vector<Move> ops;\n    mt19937 rng(seed);\n    vector<pair<int,int>> coords;\n    if (strategy_type == 4) {\n        for(int x=0; x<N-1; ++x) for(int y=0; y<=x; ++y) coords.push_back({x,y});\n    }\n\n    int pass = 0;\n    while (true) {\n        bool changed = false;\n        \n        auto process = [&](int x, int y) {\n            int val = a[x][y];\n            int l = a[x+1][y];\n            int r = a[x+1][y+1];\n            \n            if (val > l || val > r) {\n                changed = true;\n                if (l < r) { // Swap with left (smaller)\n                    swap(a[x][y], a[x+1][y]);\n                    ops.push_back({x, y, x+1, y});\n                } else { // Swap with right (smaller)\n                    swap(a[x][y], a[x+1][y+1]);\n                    ops.push_back({x, y, x+1, y+1});\n                }\n            }\n        };\n\n        if (strategy_type == 0) { // Top-Down\n            for (int x = 0; x < N - 1; ++x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n        } else if (strategy_type == 1) { // Bottom-Up\n            for (int x = N - 2; x >= 0; --x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n        } else if (strategy_type == 2) { // Mixed TD then BU\n            for (int x = 0; x < N - 1; ++x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n            for (int x = N - 2; x >= 0; --x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n        } else if (strategy_type == 3) { // Mixed BU then TD\n            for (int x = N - 2; x >= 0; --x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n            for (int x = 0; x < N - 1; ++x) {\n                for (int y = 0; y <= x; ++y) process(x, y);\n            }\n        } else if (strategy_type == 4) { // Random\n            shuffle(coords.begin(), coords.end(), rng);\n            for (auto p : coords) process(p.first, p.second);\n        }\n\n        if (!changed) break;\n        if (ops.size() > 10000) break; \n        pass++;\n    }\n    return ops;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<Move> best_ops;\n    size_t min_k = 10001;\n\n    auto update = [&](vector<Move> ops) {\n        if (ops.size() < min_k) {\n            min_k = ops.size();\n            best_ops = ops;\n        }\n    };\n\n    // Try different greedy strategies\n    update(solve(a, 0)); // TD\n    update(solve(a, 1)); // BU\n    update(solve(a, 2)); // Mixed 1\n    update(solve(a, 3)); // Mixed 2\n    \n    // Try random strategies with different seeds\n    for(int s=0; s<20; ++s) {\n        update(solve(a, 4, s));\n    }\n\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nconst int D = 9;\nint N;\nint grid_data[D][D]; // 0: empty, 1: obstacle, 2: container\n// Entrance is at (0, 4)\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// BFS optimization variables\nint visited_token[D][D];\nint dist_map[D][D];\nint bfs_token = 0;\nint q_r[D * D], q_c[D * D];\n\n// Directions\nint dr[] = {0, 0, 1, -1};\nint dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// Optimized BFS to get distances and count reachable empty cells\n// Returns count of reachable empty cells (excluding entrance if empty)\nint fast_bfs() {\n    bfs_token++;\n    int head = 0, tail = 0;\n    \n    // Start at entrance\n    q_r[tail] = 0; q_c[tail] = 4; tail++;\n    visited_token[0][4] = bfs_token;\n    dist_map[0][4] = 0;\n    \n    int count = 0;\n    while(head < tail){\n        int r = q_r[head];\n        int c = q_c[head];\n        head++;\n        \n        int d_next = dist_map[r][c] + 1;\n        \n        for(int i=0; i<4; ++i){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if(is_valid(nr, nc) && grid_data[nr][nc] == 0 && visited_token[nr][nc] != bfs_token){\n                visited_token[nr][nc] = bfs_token;\n                dist_map[nr][nc] = d_next;\n                q_r[tail] = nr; q_c[tail] = nc; tail++;\n                \n                // Count valid storage cells (entrance is not storage)\n                if(nr != 0 || nc != 4) {\n                    count++;\n                }\n            }\n        }\n    }\n    return count;\n}\n\n// Helper to get distance of a cell after running fast_bfs\n// Returns -1 if not reachable or blocked\nint get_dist(int r, int c) {\n    if (visited_token[r][c] == bfs_token) return dist_map[r][c];\n    return -1;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int d_in;\n    if (!(cin >> d_in)) return 0;\n    cin >> N;\n    \n    // Init grid\n    for(int r=0; r<D; ++r)\n        for(int c=0; c<D; ++c)\n            grid_data[r][c] = 0;\n            \n    for(int i=0; i<N; ++i){\n        int r, c;\n        cin >> r >> c;\n        grid_data[r][c] = 1;\n    }\n    \n    // Reset BFS token\n    for(int r=0; r<D; ++r)\n        for(int c=0; c<D; ++c)\n            visited_token[r][c] = 0;\n\n    int K = D*D - 1 - N;\n    vector<bool> id_seen(D*D, false);\n    vector<Point> final_pos(D*D);\n    \n    for(int step=0; step<K; ++step){\n        int t;\n        cin >> t;\n        \n        // Calculate percentile of the current ID t among remaining IDs\n        // Count how many available IDs are smaller than t\n        int rem_count = 0;\n        int rank_t = 0;\n        // The ID t is \"available\" until we place it, but id_seen tracks past placements.\n        // We iterate all possible IDs\n        for(int i=0; i<K; ++i){\n            if(!id_seen[i] || i == t) { // if not seen yet (including t)\n                rem_count++;\n                if(i < t) rank_t++;\n            }\n        }\n        \n        double P = 0.5;\n        if(rem_count > 1) P = (double)rank_t / (rem_count - 1);\n        \n        id_seen[t] = true; // Mark as seen for next steps\n        \n        // Run BFS to analyze current empty space\n        int reachable_cnt = fast_bfs();\n        \n        vector<int> all_dists;\n        vector<Point> empty_cells;\n        all_dists.reserve(rem_count);\n        empty_cells.reserve(rem_count);\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_data[r][c] == 0 && (r!=0 || c!=4)){\n                    int d = get_dist(r, c);\n                    if(d != -1){\n                        all_dists.push_back(d);\n                        empty_cells.push_back({r, c});\n                    }\n                }\n            }\n        }\n        \n        sort(all_dists.begin(), all_dists.end());\n        double target_dist = 0;\n        if(!all_dists.empty()){\n            int idx = (int)round(P * (all_dists.size() - 1));\n            target_dist = all_dists[idx];\n        }\n        \n        // Identify Candidates\n        // A cell is a candidate if it's empty, reachable, and placing a container there\n        // does not disconnect other empty cells from the entrance.\n        // Connectivity check: reachable count decreases by exactly 1.\n        vector<Point> candidates;\n        candidates.reserve(empty_cells.size());\n        \n        for(auto p : empty_cells){\n            grid_data[p.r][p.c] = 2; // Temporarily place\n            int cnt = fast_bfs();\n            grid_data[p.r][p.c] = 0; // Restore\n            \n            if(cnt == reachable_cnt - 1){\n                candidates.push_back(p);\n            }\n        }\n        \n        // Score Candidates\n        // Heuristic: Minimize squared distance error + maximize future candidates count\n        double best_score = -1e18;\n        Point best_p = candidates[0];\n        \n        for(auto p : candidates){\n            // Need dist from the ORIGINAL BFS state (before temp placement)\n            // We can't use get_dist() because fast_bfs was run inside loop.\n            // Need to re-run or cache?\n            // Actually we can just re-run or use cached values if we stored them.\n            // Since fast_bfs overwrites dist_map, we must re-calculate or look up carefully.\n            // Better: Store dists in empty_cells loop.\n            // Let's find dist of p from all_dists logic? No, lookup by coord.\n            // We need to run BFS on the *original* grid again to get dist(p)?\n            // Or just store dist in a separate map before candidate loop.\n            \n            // Optimization: We ran BFS at start of step. We can copy dist_map or store dists.\n            // But fast_bfs overwrites global dist_map.\n            // Let's just run BFS for connectivity check anyway.\n            // We can grab distance from a saved structure.\n            \n            // To avoid complexity, let's just re-run BFS on clean grid to get dist\n            // But that's slow inside loop.\n            // Correct approach: Save dists of all empty cells in a vector/map before candidate loop.\n            // But since we iterate `empty_cells`, we can store dist in Point or parallel vector.\n        }\n        \n        // Let's redo data gathering properly\n        // Restore distances of current state\n        fast_bfs(); \n        vector<vector<int>> current_dists(D, vector<int>(D));\n        for(int r=0; r<D; ++r) for(int c=0; c<D; ++c) current_dists[r][c] = get_dist(r, c);\n        \n        for(auto p : candidates){\n            double dist = current_dists[p.r][p.c];\n            double match_err = (dist - target_dist) * (dist - target_dist);\n            \n            // Calculate Future Freedom (c_prime)\n            grid_data[p.r][p.c] = 2;\n            int cnt2 = fast_bfs();\n            \n            // Count how many candidates exist in this new state\n            // This requires another nested check.\n            // To be fast, we only check cells that are reachable in new state.\n            int c_prime = 0;\n            \n            // Collect empty cells in new state\n            vector<Point> next_empty; \n            next_empty.reserve(cnt2);\n            for(int r=0; r<D; ++r){\n                for(int c=0; c<D; ++c){\n                    if(grid_data[r][c] == 0 && (r!=0 || c!=4) && get_dist(r, c) != -1){\n                        next_empty.push_back({r, c});\n                    }\n                }\n            }\n            \n            // Check candidacy for each\n            for(auto np : next_empty){\n                grid_data[np.r][np.c] = 2;\n                int cnt3 = fast_bfs();\n                if(cnt3 == cnt2 - 1) c_prime++;\n                grid_data[np.r][np.c] = 0;\n            }\n            \n            grid_data[p.r][p.c] = 0; // Restore\n            \n            // Weighted score\n            // Weight A=100 for distance match, B=1 for freedom.\n            double score = -100.0 * match_err + (double)c_prime;\n            \n            if(score > best_score){\n                best_score = score;\n                best_p = p;\n            }\n        }\n        \n        // Output and Commit\n        cout << best_p.r << \" \" << best_p.c << endl;\n        grid_data[best_p.r][best_p.c] = 2;\n        final_pos[t] = best_p;\n    }\n    \n    // Retrieval Phase\n    // Map coordinates to IDs\n    vector<vector<int>> grid_ids(D, vector<int>(D, -1));\n    for(int i=0; i<K; ++i){\n        grid_ids[final_pos[i].r][final_pos[i].c] = i;\n    }\n    \n    // Greedily retrieve smallest available ID\n    for(int step=0; step<K; ++step){\n        fast_bfs(); // Updates dist_map to show what is reachable from entrance\n        \n        int best_id = 1000000;\n        Point best_loc = {-1, -1};\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_data[r][c] == 2){\n                    // Check if reachable: adjacent to visited empty cell (or entrance)\n                    bool reachable = false;\n                    for(int i=0; i<4; ++i){\n                        int nr = r + dr[i];\n                        int nc = c + dc[i];\n                        if(is_valid(nr, nc)){\n                            // Entrance is (0,4), always visited/available source\n                            if((nr == 0 && nc == 4) || get_dist(nr, nc) != -1){\n                                reachable = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if(reachable){\n                        int id = grid_ids[r][c];\n                        if(id < best_id){\n                            best_id = id;\n                            best_loc = {r, c};\n                        }\n                    }\n                }\n            }\n        }\n        \n        cout << best_loc.r << \" \" << best_loc.c << endl;\n        grid_data[best_loc.r][best_loc.c] = 0; // Remove container\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <algorithm>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int N = 50;\nconst int M = 100;\nconst int TIME_LIMIT_MS = 1950;\n\n// Directions\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\n// State\nint grid[N][N];\nint best_grid[N][N];\nint current_score = 0;\nint best_score = 0;\n\n// Adjacency tracking\n// adj_count[i][j] stores number of boundary edges between color i and j\n// i, j in [0, M]\nint adj_count[M + 1][M + 1];\nbool is_required[M + 1][M + 1];\n\n// Connectivity Check Helpers\nint visited_grid[N][N];\nint visited_token = 0;\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to check if 'color' is connected after removing (rem_r, rem_c)\n// Special handling for color 0: must reach boundary\nbool check_global_connectivity(int rem_r, int rem_c, int color) {\n    visited_token++;\n    int start_r = -1, start_c = -1;\n    int neighbor_count = 0;\n\n    // Find a starting neighbor\n    for (int i = 0; i < 4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) {\n                if (start_r == -1) { start_r = nr; start_c = nc; }\n                neighbor_count++;\n            }\n        } else if (color == 0) {\n            // If color is 0, out-of-bounds is part of the region.\n            // We can treat out-of-bounds as a single virtual node.\n            // If we have neighbors that are 0, they must be able to reach out-of-bounds.\n            // Effectively, we can start BFS from \"outside\".\n            // But to keep it simple, we just check if all in-bound 0-neighbors can reach \n            // either the boundary or each other and one of them touches boundary.\n            neighbor_count++; \n        }\n    }\n\n    if (neighbor_count == 0) return true; // Removing the last cell or isolated cell\n\n    // If color is 0, we need to ensure all neighbors can reach the boundary (or virtual outside).\n    // Simplified: Run BFS from one neighbor. Count how many neighbors we reach.\n    // Also track if we reached the boundary.\n    // If start_r is -1, it means all neighbors are out-of-bounds (which are connected).\n    if (start_r == -1) return true;\n\n    queue<pair<int, int>> q;\n    q.push({start_r, start_c});\n    visited_grid[start_r][start_c] = visited_token;\n    \n    int reached_neighbors = 1; // We start at one\n    bool reached_boundary = false;\n\n    // Check if start node is on boundary\n    if (start_r == 0 || start_r == N - 1 || start_c == 0 || start_c == N - 1) reached_boundary = true;\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n\n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n\n            if (!is_valid(nr, nc)) {\n                reached_boundary = true;\n                continue;\n            }\n\n            if (nr == rem_r && nc == rem_c) continue;\n\n            if (grid[nr][nc] == color && visited_grid[nr][nc] != visited_token) {\n                visited_grid[nr][nc] = visited_token;\n                q.push({nr, nc});\n                \n                // Check if this node is one of the original neighbors of (rem_r, rem_c)\n                // A simple check is manhattan distance == 1, but we iterate all anyway.\n                // Optimization: count how many neighbors of the removed cell we visited.\n                if (abs(nr - rem_r) + abs(nc - rem_c) == 1) {\n                    reached_neighbors++;\n                }\n                \n                if (color == 0 && !reached_boundary) {\n                    if (nr == 0 || nr == N - 1 || nc == 0 || nc == N - 1) reached_boundary = true;\n                }\n            }\n        }\n    }\n\n    // If color is 0, we MUST reach boundary (because 0 is rooted outside).\n    if (color == 0 && !reached_boundary) return false;\n\n    // Verify we reached all in-grid neighbors\n    int actual_grid_neighbors = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if(is_valid(nr, nc) && grid[nr][nc] == color) actual_grid_neighbors++;\n    }\n    \n    return reached_neighbors == actual_grid_neighbors;\n}\n\n// Fast local check. Returns true if definitely connected, false if uncertain/disconnected locally.\nbool check_local_connectivity(int r, int c, int color) {\n    int neighbors[4]; \n    int k = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        // For color 0, out of bounds is considered a neighbor of color 0\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) neighbors[k++] = i;\n        } else if (color == 0) {\n            neighbors[k++] = i;\n        }\n    }\n\n    if (k <= 1) return true;\n\n    // Check connectivity in 3x3 window (including virtual outside for 0)\n    // We use a tiny BFS or hardcoded paths.\n    // Vertices 0..3 represent the 4 neighbors.\n    // Adjacency matrix for these 4 neighbors based on paths through diagonals.\n    // Diagonal (r+dr[a]+dr[b], c+dc[a]+dc[b]) connects neighbor a and b if grid value matches\n    // BUT only if a and b are orthogonal (e.g. Up and Right).\n    \n    // A simplified Union-Find for the k neighbors.\n    int parent[4] = {0, 1, 2, 3};\n    auto find = [&](int i) { while(i != parent[i]) i = parent[i]; return i; };\n    auto unite = [&](int i, int j) { parent[find(i)] = find(j); };\n\n    // Neighbors are 0:Up, 1:Down, 2:Left, 3:Right\n    // Adjacent pairs in circle: (0,2), (2,1), (1,3), (3,0) -> (Up, Left), (Left, Down), ...\n    // Indices in dr/dc: 0:(-1,0)Up, 1:(1,0)Down, 2:(0,-1)Left, 3:(0,1)Right\n    \n    // Pairs checking\n    // 0 (Up) and 2 (Left): connect via (-1, -1)\n    // 0 (Up) and 3 (Right): connect via (-1, 1)\n    // 1 (Down) and 2 (Left): connect via (1, -1)\n    // 1 (Down) and 3 (Right): connect via (1, 1)\n    \n    auto check_diag = [&](int d1, int d2) {\n        int nr = r + dr[d1] + dr[d2];\n        int nc = c + dc[d1] + dc[d2];\n        bool connected = false;\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) connected = true;\n        } else if (color == 0) {\n            connected = true;\n        }\n        if (connected) unite(d1, d2);\n    };\n\n    // We map our neighbor indices to the direction indices 0..3\n    // But 'neighbors' array stores the direction indices directly.\n    // We need to check which ones are present and unite them.\n    // Actually we iterate all pairs of present neighbors.\n    \n    for (int i = 0; i < k; ++i) {\n        for (int j = i + 1; j < k; ++j) {\n            int d1 = neighbors[i];\n            int d2 = neighbors[j];\n            // Check if they are adjacent directions (not opposite)\n            if (dr[d1] + dr[d2] == 0 && dc[d1] + dc[d2] == 0) continue; // Opposite\n            // Check diagonal\n            check_diag(d1, d2);\n        }\n    }\n\n    int root = find(neighbors[0]);\n    for (int i = 1; i < k; ++i) {\n        if (find(neighbors[i]) != root) return false;\n    }\n    return true;\n}\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // 1. Input\n    int n_in, m_in;\n    if (!(cin >> n_in >> m_in)) return 0;\n    \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    // 2. Init Adjacencies\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = grid[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int nr = i + dr[k];\n                int nc = j + dc[k];\n                int v = 0; // Default outside color\n                if (is_valid(nr, nc)) {\n                    v = grid[nr][nc];\n                }\n                \n                if (u != v) {\n                    // Store undirected as directed for both u->v and v->u to simplify logic\n                    // But careful not to double count when iterating?\n                    // We update both entries.\n                    // But we need unique pairs for constraints.\n                    // Let's store symmetric: adj_count[u][v] == adj_count[v][u]\n                    // Note: we will encounter edge (u,v) from u's side and v's side.\n                    // To avoid double counting initial scan, only count when looking at u side?\n                    // No, grid logic is simpler: iterate all cells, look at right/down neighbors?\n                    // But boundary (outside) edges?\n                    // Let's stick to: iterate all cells, look at 4 neighbors.\n                    // This counts each edge TWICE (once from u, once from v).\n                    // So real count = adj_count / 2.\n                    // Thresholds 0 and >0 work same.\n                    adj_count[u][v]++;\n                }\n            }\n        }\n    }\n    \n    // Set requirements based on initial map\n    for (int i = 0; i <= M; ++i) {\n        for (int j = 0; j <= M; ++j) {\n            if (adj_count[i][j] > 0) {\n                is_required[i][j] = true;\n            }\n        }\n    }\n\n    // Score init (count 0s)\n    // Initially 0.\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) best_grid[i][j] = grid[i][j];\n\n    // 3. Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    mt19937 rng(123);\n    \n    double start_temp = 2.0;\n    double end_temp = 0.0;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0xFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        // Pick random cell\n        int r = rng() % N;\n        int c = rng() % N;\n        int current_color = grid[r][c];\n        \n        // Pick a neighbor's color (or 0 from outside)\n        int k = rng() % 4;\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n        int target_color = 0;\n        if (is_valid(nr, nc)) {\n            target_color = grid[nr][nc];\n        }\n        \n        if (current_color == target_color) continue;\n\n        // Calculate Delta Score\n        // Score = number of 0s.\n        int score_diff = 0;\n        if (current_color == 0) score_diff--;\n        if (target_color == 0) score_diff++;\n        \n        // Acceptance probability\n        // If score improves (diff > 0), accept.\n        // If neutral (diff == 0), accept.\n        // If worse (diff < 0), accept with prob.\n        // We want to maximize score.\n        if (score_diff < 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            double temp = start_temp + (end_temp - start_temp) * (elapsed / TIME_LIMIT_MS);\n            double prob = exp(score_diff / temp); // e.g. exp(-1 / 1.0) ~= 0.36\n            if (elapsed > TIME_LIMIT_MS) break;\n            if (std::uniform_real_distribution<>(0,1)(rng) > prob) continue;\n        }\n\n        // Check Validity\n        \n        // 1. Adjacency Constraints\n        bool adj_ok = true;\n        for (int i = 0; i < 4; ++i) {\n            int nnr = r + dr[i];\n            int nnc = c + dc[i];\n            int neighbor_col = 0;\n            if (is_valid(nnr, nnc)) neighbor_col = grid[nnr][nnc];\n            \n            // Removing edge (current_color, neighbor_col)\n            if (neighbor_col != current_color) {\n                // We count edges twice (u->v and v->u), so threshold is 2?\n                // No, my init loop counted each edge twice in the array.\n                // Removing this cell removes ONE instance of the edge from (r,c)->neighbor\n                // And the neighbor->(r,c) edge is also conceptually removed/changed.\n                // My update logic below decrements [u][v] and [v][u].\n                // So threshold is 1?\n                // Let's simulate the update.\n                // Edge (current, neighbor) count decreases by 2 (one for each direction in loop).\n                if (adj_count[current_color][neighbor_col] <= 2 && is_required[current_color][neighbor_col]) {\n                    adj_ok = false; break;\n                }\n            }\n            \n            // Adding edge (target_color, neighbor_col)\n            if (neighbor_col != target_color) {\n                if (adj_count[target_color][neighbor_col] == 0 && !is_required[target_color][neighbor_col]) {\n                    adj_ok = false; break;\n                }\n            }\n        }\n        if (!adj_ok) continue;\n\n        // 2. Connectivity of Old Color\n        if (!check_local_connectivity(r, c, current_color)) {\n            if (!check_global_connectivity(r, c, current_color)) continue;\n        }\n\n        // 3. Connectivity of New Color\n        // When adding a cell adjacent to target_color, connectivity is usually preserved.\n        // Exception: target_color is 0, and we might isolate a part of 0 from boundary?\n        // Wait, we pick target_color from a neighbor. So we are extending an existing connected component.\n        // For non-0, this is always safe (merging/extending).\n        // For 0, extending the \"outside\" component inwards is safe.\n        // The only risk for 0 is if we somehow create a ring of 0s? No, that's fine.\n        // The risk is splitting 0s, handled in step 2 (if current_color was 0).\n        // So adding to target is always safe connectivity-wise if picked from neighbor.\n        \n        // Apply Change\n        // Update Adjacency Counts\n        for (int i = 0; i < 4; ++i) {\n            int nnr = r + dr[i];\n            int nnc = c + dc[i];\n            int neighbor_col = 0;\n            if (is_valid(nnr, nnc)) neighbor_col = grid[nnr][nnc];\n            \n            if (neighbor_col != current_color) {\n                adj_count[current_color][neighbor_col]--;\n                adj_count[neighbor_col][current_color]--;\n            }\n            if (neighbor_col != target_color) {\n                adj_count[target_color][neighbor_col]++;\n                adj_count[neighbor_col][target_color]++;\n            }\n        }\n        \n        grid[r][c] = target_color;\n        current_score += score_diff;\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) best_grid[i][j] = grid[i][j];\n        }\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    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <iomanip>\n#include <random>\n#include <set>\n#include <map>\n#include <cassert>\n\nusing namespace std;\n\n// Global variables for problem context\nint N, D, Q;\nint query_count = 0;\nbool query_limit_reached = false;\n\n// Memoization for item comparisons: 0 = unknown, 1 = less (<), -1 = greater (>), 2 = equal (=)\nvector<vector<int>> memo;\n\n// Perform a query using the balance scale\n// L, R: vectors of item indices for the left and right pans\nvoid ask(const vector<int>& L, const vector<int>& R) {\n    if (query_count >= Q) {\n        query_limit_reached = true;\n        return;\n    }\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    query_count++;\n}\n\n// Read the judge's response\nint get_response() {\n    if (query_limit_reached) return 0; \n    string res;\n    cin >> res;\n    if (res == \"<\") return 1;\n    if (res == \">\") return -1;\n    if (res == \"=\") return 2;\n    return 0; \n}\n\n// Compare two items a and b.\n// Returns 1 if a < b, -1 if a > b, 0 if a == b.\n// Uses memoization to save queries.\nint compare_items(int a, int b) {\n    if (a == b) return 0;\n    if (memo[a][b] != 0) return (memo[a][b] == 2 ? 0 : memo[a][b]);\n\n    // Simple cache check is O(1). Transitive inference could be added but N is small.\n    // We perform a direct query.\n    ask({a}, {b});\n    \n    if (query_limit_reached) return 0; \n    \n    int res = get_response();\n    if (res == 1) {\n        memo[a][b] = 1;\n        memo[b][a] = -1;\n        return 1;\n    } else if (res == -1) {\n        memo[a][b] = -1;\n        memo[b][a] = 1;\n        return -1;\n    } else {\n        memo[a][b] = 2;\n        memo[b][a] = 2;\n        return 0;\n    }\n}\n\n// Compute expected values of order statistics for Exponential Distribution\nvector<double> compute_expected_weights(int n) {\n    vector<double> w(n);\n    double current = 0;\n    // E[X_(i)] = sum_{j=1}^{i} 1/(N - j + 1)\n    for (int i = 0; i < n; ++i) {\n        current += 1.0 / (n - i);\n        w[i] = current;\n    }\n    return w;\n}\n\n// Isotonic Regression using Pool Adjacent Violators Algorithm (PAVA)\n// Adjusts values in y to be monotonically non-decreasing while minimizing mean squared error.\nvector<double> isotonic_regression(const vector<double>& y) {\n    vector<pair<double, double>> stack; // {value, weight}\n    for (double val : y) {\n        double current_val = val;\n        double current_w = 1.0;\n        while (!stack.empty() && stack.back().first >= current_val) {\n            double prev_val = stack.back().first;\n            double prev_w = stack.back().second;\n            stack.pop_back();\n            current_val = (prev_val * prev_w + current_val * current_w) / (prev_w + current_w);\n            current_w += prev_w;\n        }\n        stack.push_back({current_val, current_w});\n    }\n    vector<double> res;\n    for (auto p : stack) {\n        for (int i = 0; i < (int)p.second; ++i) res.push_back(p.first);\n    }\n    return res;\n}\n\nint main() {\n    // Optimize I/O operations? Not strictly necessary due to flush requirement but good practice.\n    // However, cin/cout with flush is required.\n    cin >> N >> D >> Q;\n\n    memo.assign(N, vector<int>(N, 0));\n    srand(123); // Fixed seed for deterministic local behavior\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // Strategy: \n    // 1. Sort items to estimate weights.\n    // 2. Partition based on estimates.\n    // 3. Refine partition by comparing sets.\n\n    // Determine how many queries to reserve for the refinement phase.\n    // We need roughly D*log(D) queries to sort sets once. \n    // We want to do this at least a few times if possible.\n    int reserve_queries = 0;\n    if (Q > N * 4) {\n        // If Q is large enough, reserve some for set balancing.\n        // Heuristic: Reserve enough for ~3 rounds of set sorting + overhead.\n        reserve_queries = min(Q / 3, 400);\n    }\n    \n    // 1. Sort Items\n    try {\n        stable_sort(p.begin(), p.end(), [&](int a, int b) {\n            if (query_count >= Q - reserve_queries) return false; // Stop sorting if limit near\n            int res = compare_items(a, b);\n            return res == 1; // a < b\n        });\n    } catch (...) {\n        // Fallback if anything goes wrong\n    }\n\n    // 2. Initial Partition (In Silico)\n    // Assign expected weights based on the rank obtained from sorting.\n    vector<double> exp_w_sorted = compute_expected_weights(N);\n    vector<double> item_w(N);\n    for (int i = 0; i < N; ++i) {\n        item_w[p[i]] = exp_w_sorted[i];\n    }\n\n    // Greedy initialization: Sort items by expected weight descending\n    vector<int> p_desc = p;\n    reverse(p_desc.begin(), p_desc.end());\n\n    vector<vector<int>> sets(D);\n    vector<double> set_sums(D, 0.0);\n\n    for (int idx : p_desc) {\n        // Assign to the current lightest set\n        int best_s = -1;\n        double min_sum = 1e18;\n        for (int s = 0; s < D; ++s) {\n            if (set_sums[s] < min_sum) {\n                min_sum = set_sums[s];\n                best_s = s;\n            }\n        }\n        sets[best_s].push_back(idx);\n        set_sums[best_s] += item_w[idx];\n    }\n\n    // Local Search to optimize variance (using expected weights)\n    auto calc_variance = [&](const vector<double>& sums) {\n        double mean = 0;\n        for(double x : sums) mean += x;\n        mean /= D;\n        double var = 0;\n        for(double x : sums) var += (x - mean)*(x - mean);\n        return var;\n    };\n\n    int iter = 0;\n    double current_var = calc_variance(set_sums);\n    while (iter < 15000) {\n        iter++;\n        int s1 = rand() % D;\n        int s2 = rand() % D;\n        if (s1 == s2) continue;\n        if (sets[s1].empty()) continue;\n\n        // Type 0: Move, Type 1: Swap\n        int type = (sets[s2].empty() ? 0 : rand() % 2);\n        \n        int idx1 = rand() % sets[s1].size();\n        int item1 = sets[s1][idx1];\n\n        if (type == 0) { // Move s1 -> s2\n            set_sums[s1] -= item_w[item1];\n            set_sums[s2] += item_w[item1];\n            double new_var = calc_variance(set_sums);\n            if (new_var < current_var) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(item1);\n                current_var = new_var;\n            } else {\n                set_sums[s1] += item_w[item1];\n                set_sums[s2] -= item_w[item1];\n            }\n        } else { // Swap\n            int idx2 = rand() % sets[s2].size();\n            int item2 = sets[s2][idx2];\n            \n            set_sums[s1] -= item_w[item1];\n            set_sums[s1] += item_w[item2];\n            set_sums[s2] -= item_w[item2];\n            set_sums[s2] += item_w[item1];\n            \n            double new_var = calc_variance(set_sums);\n            if (new_var < current_var) {\n                sets[s1][idx1] = item2;\n                sets[s2][idx2] = item1;\n                current_var = new_var;\n            } else {\n                set_sums[s1] -= item_w[item2];\n                set_sums[s1] += item_w[item1];\n                set_sums[s2] -= item_w[item1];\n                set_sums[s2] += item_w[item2];\n            }\n        }\n    }\n\n    // 3. Refinement Loop\n    // We rely on physical queries to correct the belief about set sums.\n    while (Q - query_count > D * 2) {\n        // 3.1 Sort the sets physically\n        vector<int> set_indices(D);\n        iota(set_indices.begin(), set_indices.end(), 0);\n        \n        bool stop_sorting = false;\n        sort(set_indices.begin(), set_indices.end(), [&](int a, int b) {\n            if (stop_sorting) return false;\n            if (query_count >= Q) { stop_sorting = true; return false; }\n            \n            // Compare set a and set b\n            ask(sets[a], sets[b]);\n            int res = get_response();\n            return res == 1; // a < b\n        });\n        if (stop_sorting || query_count >= Q) break;\n\n        // 3.2 Update estimated sums using PAV\n        vector<double> sorted_estimates;\n        sorted_estimates.reserve(D);\n        for (int idx : set_indices) sorted_estimates.push_back(set_sums[idx]);\n        \n        vector<double> pav_res = isotonic_regression(sorted_estimates);\n        \n        // Enforce small separation to drive optimization if they are flattend by PAV\n        for (int i = 1; i < D; ++i) {\n            if (pav_res[i] <= pav_res[i-1] + 1e-9) {\n                pav_res[i] = pav_res[i-1] + 1e-6;\n            }\n        }\n\n        // Update set_sums with corrected values\n        for (int i = 0; i < D; ++i) {\n            set_sums[set_indices[i]] = pav_res[i];\n        }\n\n        // 3.3 Attempt to balance Heaviest vs Lightest\n        int light_idx = set_indices[0];\n        int heavy_idx = set_indices.back();\n\n        double diff = set_sums[heavy_idx] - set_sums[light_idx];\n        if (diff < 1e-9) break; \n\n        double target_change = diff / 2.0;\n        int best_type = -1; // 0: move, 1: swap\n        int best_u_idx = -1, best_v_idx = -1;\n        double best_err = 1e18;\n\n        // Try Move: Heavy -> Light\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            int u = sets[heavy_idx][i];\n            double val = item_w[u];\n            double err = abs(val - target_change);\n            if (err < best_err) {\n                best_err = err;\n                best_type = 0;\n                best_u_idx = i;\n            }\n        }\n\n        // Try Swap: u in Heavy, v in Light. We want u > v.\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            for (int j = 0; j < (int)sets[light_idx].size(); ++j) {\n                int u = sets[heavy_idx][i];\n                int v = sets[light_idx][j];\n                double val = item_w[u] - item_w[v];\n                if (val <= 0) continue;\n                double err = abs(val - target_change);\n                if (err < best_err) {\n                    best_err = err;\n                    best_type = 1;\n                    best_u_idx = i;\n                    best_v_idx = j;\n                }\n            }\n        }\n\n        // Apply best change if it looks reasonable (we don't check against old variance here, \n        // we trust the PAV corrected target)\n        if (best_type == 0) {\n            int u = sets[heavy_idx][best_u_idx];\n            sets[heavy_idx].erase(sets[heavy_idx].begin() + best_u_idx);\n            sets[light_idx].push_back(u);\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[light_idx] += item_w[u];\n        } else if (best_type == 1) {\n            int u = sets[heavy_idx][best_u_idx];\n            int v = sets[light_idx][best_v_idx];\n            sets[heavy_idx][best_u_idx] = v;\n            sets[light_idx][best_v_idx] = u;\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[heavy_idx] += item_w[v];\n            set_sums[light_idx] -= item_w[v];\n            set_sums[light_idx] += item_w[u];\n        } else {\n            // Cannot improve\n            break; \n        }\n    }\n\n    // Output final division\n    vector<int> ans(N);\n    for (int i = 0; i < D; ++i) {\n        for (int x : sets[i]) ans[x] = i;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"/**\n * Heuristic solution for \"Stack of Boxes\" problem.\n * \n * Strategy:\n * We process the boxes in the order they need to be carried out (1 to N).\n * If the target box is not at the top of its stack, we must move the boxes covering it.\n * We greedily choose the best move to clear the covering boxes.\n * \n * A move consists of picking a \"chunk\" of boxes from the top of the source stack\n * and moving them to a destination stack.\n * We evaluate possible moves based on a cost function:\n * Cost = Energy Cost + Penalty\n * \n * Penalties are assigned to avoid \"bad\" states:\n * 1. Placing a larger box on top of a smaller box (Bad Link).\n *    This blocks the smaller box, forcing an extra move later.\n *    Penalty is high if the blocked box is needed soon.\n * 2. Moving a chunk that is internally \"unsorted\" (top > bottom inside chunk).\n *    We effectively forbid this by giving infinite penalty, forcing us to split\n *    such chunks into sorted runs. This minimizes future work.\n * 3. Using an empty stack.\n *    We penalize using empty stacks for small numbers, reserving them for\n *    holding large numbers or emergency situations.\n * \n * The parameters for penalties are tuned to balance immediate energy usage\n * against future convenience.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Move {\n    int v;\n    int i;\n};\n\nint N = 200;\nint M = 10;\nvector<vector<int>> stacks;\nvector<Move> result;\nint op_count = 0;\n\n// Find the stack index and position (0-indexed from bottom) of a box v\npair<int, int> find_box(int v) {\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<(int)stacks[i].size(); ++j) {\n            if(stacks[i][j] == v) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Execute a move: chunk starting at stack[src][idx] to to_stack_idx\nvoid do_move(int v, int to_stack_idx) {\n    pair<int, int> loc = find_box(v);\n    int src = loc.first;\n    int idx = loc.second; \n    \n    vector<int> moving_boxes;\n    for(int k=idx; k<(int)stacks[src].size(); ++k) {\n        moving_boxes.push_back(stacks[src][k]);\n    }\n    \n    stacks[src].resize(idx);\n    \n    for(int x : moving_boxes) {\n        stacks[to_stack_idx].push_back(x);\n    }\n    \n    result.push_back({v, to_stack_idx + 1});\n    op_count++;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<N/M; ++j) {\n            int val;\n            cin >> val;\n            stacks[i].push_back(val);\n        }\n    }\n\n    for (int target = 1; target <= N; ++target) {\n        pair<int, int> loc = find_box(target);\n        if (loc.first == -1) continue; \n        \n        int src = loc.first;\n        int idx = loc.second;\n        \n        // If target is already at top\n        if (idx == (int)stacks[src].size() - 1) {\n            result.push_back({target, 0});\n            stacks[src].pop_back();\n            op_count++;\n            continue;\n        }\n        \n        // Repeatedly move covering chunks until target is at top\n        while (true) {\n            loc = find_box(target);\n            src = loc.first;\n            idx = loc.second;\n            if (idx == (int)stacks[src].size() - 1) break;\n            \n            // Boxes to move: stacks[src][idx+1 ... end]\n            int cover_start = idx + 1;\n            int top_idx = (int)stacks[src].size() - 1;\n            \n            double min_score = 1e18;\n            int best_k = -1;\n            int best_dst = -1;\n            \n            // Try all possible split points k\n            for (int k = cover_start; k <= top_idx; ++k) {\n                int chunk_bottom = stacks[src][k];\n                int chunk_size = top_idx - k + 1;\n                \n                // Check for internal inversions in the chunk\n                // We want stack to be descending from bottom to top (b_i > b_{i+1}).\n                // If b_{i+1} > b_i, it's a \"bad\" internal link.\n                bool internal_bad = false;\n                for (int p = k; p < top_idx; ++p) {\n                    if (stacks[src][p+1] > stacks[src][p]) {\n                        internal_bad = true;\n                        break;\n                    }\n                }\n                if (internal_bad) continue; \n\n                double base_cost = (double)(chunk_size + 1);\n                \n                // Try all destinations\n                for (int dst = 0; dst < M; ++dst) {\n                    if (dst == src) continue;\n                    \n                    double penalty = 0;\n                    bool dst_empty = stacks[dst].empty();\n                    // If empty, treat top as infinity\n                    int dst_top = dst_empty ? 10000 : stacks[dst].back();\n                    \n                    // Evaluate link (chunk_bottom on dst_top)\n                    if (chunk_bottom > dst_top) {\n                        // Bad link: creating a blocking configuration\n                        // Ideally we want chunk_bottom < dst_top\n                        \n                        // Urgency factor: how soon will we need the blocked box (dst_top)?\n                        // Higher urgency -> higher penalty\n                        double urgency = 0;\n                        if (!dst_empty) {\n                            urgency = 1.0 / (dst_top - target + 5.0); \n                        }\n                        // Base penalty for bad link + urgency scaling\n                        penalty += chunk_size * (5.0 + 1000.0 * urgency);\n                    } else {\n                        // Good link: we can remove chunk_bottom before dst_top needed\n                        // Reward tight fit (minimize gap)\n                        double diff = dst_top - chunk_bottom;\n                        penalty += diff * 0.01; \n                    }\n                    \n                    if (dst_empty) {\n                        // Penalty for using up an empty stack\n                        // We prefer to put large values into empty stacks (as bases)\n                        // So penalty decreases as chunk_bottom increases\n                        penalty += 20.0 - 0.1 * chunk_bottom; \n                    }\n                    \n                    double total_score = base_cost + penalty;\n                    if (total_score < min_score) {\n                        min_score = total_score;\n                        best_k = k;\n                        best_dst = dst;\n                    }\n                }\n            }\n            \n            // If no valid sorted chunk found (unlikely since size 1 is always sorted),\n            // fallback to moving top box.\n            if (best_k == -1) {\n                best_k = top_idx;\n                // Pick best dest for single box\n                // Simple search for fallback\n                double fb_min = 1e18;\n                for(int dst=0; dst<M; ++dst) {\n                    if(dst == src) continue;\n                    bool de = stacks[dst].empty();\n                    int dt = de ? 10000 : stacks[dst].back();\n                    int val = stacks[src][top_idx];\n                    double pen = 0;\n                    if(val > dt) pen = 1000; // Bad\n                    else pen = (dt - val) * 0.01;\n                    if(de) pen += 10;\n                    if(pen < fb_min) { fb_min = pen; best_dst = dst; }\n                }\n            }\n            \n            do_move(stacks[src][best_k], best_dst);\n        }\n        \n        // Carry out\n        result.push_back({target, 0});\n        stacks[src].pop_back();\n        op_count++;\n    }\n    \n    for(const auto &m : result) {\n        cout << m.v << \" \" << m.i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\n// Timer class to manage execution time\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    Timer() { reset(); }\n    void reset() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto end = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end - start).count() / 1000.0;\n    }\n};\n\n// Global variables\nint N;\nvector<string> h_walls, v_walls;\nvector<vector<int>> D_grid;\nint dist_mat[1600][1600]; // N=40 -> 1600 nodes\nconst int INF = 1e9;\n\n// Directions\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dc_char[] = {'U', 'D', 'L', 'R'};\n\n// Function to check if a move is valid\nbool can_move(int r, int c, int dir) {\n    if (dir == 0) { // U\n        if (r == 0) return false;\n        return h_walls[r-1][c] == '0';\n    }\n    if (dir == 1) { // D\n        if (r == N-1) return false;\n        return h_walls[r][c] == '0';\n    }\n    if (dir == 2) { // L\n        if (c == 0) return false;\n        return v_walls[r][c-1] == '0';\n    }\n    if (dir == 3) { // R\n        if (c == N-1) return false;\n        return v_walls[r][c] == '0';\n    }\n    return false;\n}\n\n// Compute All-Pairs Shortest Paths using BFS\nvoid compute_apsp() {\n    // Initialize with INF\n    for (int i = 0; i < N * N; ++i) {\n        for (int j = 0; j < N * N; ++j) {\n            dist_mat[i][j] = INF;\n        }\n        dist_mat[i][i] = 0;\n    }\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // BFS from u\n            // Using a simple queue and array for distances\n            static int q_arr[2000]; // Sufficient for 1600\n            static int d_local[1600];\n            for(int k=0; k<N*N; ++k) d_local[k] = INF;\n            \n            int head = 0, tail = 0;\n            q_arr[tail++] = u;\n            d_local[u] = 0;\n            \n            dist_mat[u][u] = 0;\n            \n            while(head < tail){\n                int curr = q_arr[head++];\n                int d_curr = d_local[curr];\n                dist_mat[u][curr] = d_curr; // Store in global matrix\n                \n                int cr = curr / N;\n                int cc = curr % N;\n                \n                for(int k=0; k<4; ++k){\n                    if(can_move(cr, cc, k)){\n                        int nr = cr + dr[k];\n                        int nc = cc + dc[k];\n                        int v = nr * N + nc;\n                        if(d_local[v] == INF){\n                            d_local[v] = d_curr + 1;\n                            q_arr[tail++] = v;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate score for a given path based on average dirtiness\nlong long calculate_score(const string& path) {\n    if (path.empty()) return 2e18;\n    long long L = path.length();\n    vector<vector<int>> visit_times(N*N);\n    \n    // Start at (0,0) which corresponds to time 0.\n    int r = 0, c = 0;\n    visit_times[0].push_back(0);\n    \n    for(int t=1; t<=L; ++t){\n        char move = path[t-1];\n        if(move == 'U') r--;\n        else if(move == 'D') r++;\n        else if(move == 'L') c--;\n        else if(move == 'R') c++;\n        \n        int u = r*N + c;\n        visit_times[u].push_back(t);\n    }\n    \n    double total_weighted_sq_sum = 0;\n    \n    for(int u=0; u<N*N; ++u){\n        if(visit_times[u].empty()) return 2e18; // Unvisited node\n        \n        long long sq_sum = 0;\n        \n        // Calculate sum of delta*(delta-1) for intervals\n        if (u == 0) {\n            // For (0,0), visits include 0 and L (if path returns to 0).\n            // Intervals are simply adjacent differences.\n            for(size_t k=0; k<visit_times[u].size()-1; ++k){\n                long long delta = visit_times[u][k+1] - visit_times[u][k];\n                sq_sum += delta * (delta - 1);\n            }\n        } else {\n            // For other nodes, wrap around from last visit to first visit\n            for(size_t k=0; k<visit_times[u].size()-1; ++k){\n                long long delta = visit_times[u][k+1] - visit_times[u][k];\n                sq_sum += delta * (delta - 1);\n            }\n            // Wrap around interval\n            long long delta = (visit_times[u][0] + L) - visit_times[u].back();\n            sq_sum += delta * (delta - 1);\n        }\n        \n        total_weighted_sq_sum += (double)D_grid[u/N][u%N] * sq_sum;\n    }\n    \n    // Score is round(Sum / 2L)\n    return (long long)round(total_weighted_sq_sum / (2.0 * L));\n}\n\nint main() {\n    Timer timer;\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N)) return 0;\n    h_walls.resize(N-1);\n    for(int i=0; i<N-1; ++i) cin >> h_walls[i];\n    v_walls.resize(N);\n    for(int i=0; i<N; ++i) cin >> v_walls[i];\n    D_grid.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) cin >> D_grid[i][j];\n\n    compute_apsp();\n\n    // Parameters to try for the gravity decay power\n    vector<double> powers = {2.0, 1.0, 3.0, 1.5, 4.0, 0.5};\n    \n    long long best_score = -1;\n    string best_path = \"\";\n    mt19937 rng(42);\n    \n    int p_idx = 0;\n    \n    // Time buffer: stop searching a bit before 2.0s\n    while(timer.elapsed() < 1.85) {\n        double power;\n        if(p_idx < powers.size()) power = powers[p_idx];\n        else {\n             uniform_real_distribution<double> dist_pow(0.5, 4.0);\n             power = dist_pow(rng);\n        }\n        \n        // Precompute weights for the current power\n        vector<double> weight_lookup(2 * N * N);\n        for(int d=0; d<2*N*N; ++d) {\n            weight_lookup[d] = 1.0 / pow(d + 1, power);\n        }\n        \n        // Scores storage\n        vector<double> static_score(N*N, 0.0);\n        vector<double> dynamic_score(N*N, 0.0);\n        vector<long long> last_visit(N*N, -1000000); // Init to unvisited state\n        \n        // Init static and dynamic scores\n        for(int v=0; v<N*N; ++v) {\n            double s = 0, d = 0;\n            for(int u=0; u<N*N; ++u) {\n                double w = weight_lookup[dist_mat[v][u]];\n                double val = D_grid[u/N][u%N] * w;\n                s += val;\n                d += val * last_visit[u];\n            }\n            static_score[v] = s;\n            dynamic_score[v] = d;\n        }\n        \n        // Initial position 0\n        int curr = 0;\n        // Register visit at (0,0) at t=0\n        {\n            int d_u = D_grid[0][0];\n            long long diff = 0 - last_visit[0];\n            last_visit[0] = 0;\n            for(int v=0; v<N*N; ++v) {\n                dynamic_score[v] += d_u * diff * weight_lookup[dist_mat[v][0]];\n            }\n        }\n        \n        string path;\n        path.reserve(100005);\n        int L_target = 100000;\n        \n        for(int t=1; t<=L_target; ++t) {\n            int best_next = -1;\n            \n            // Check if we need to return to 0 to close the cycle\n            if(dist_mat[curr][0] + t >= L_target) {\n                int curr_dist = dist_mat[curr][0];\n                // Pick any neighbor closer to 0\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        if(dist_mat[next_node][0] < curr_dist) {\n                            best_next = next_node;\n                            break;\n                        }\n                    }\n                }\n            } else {\n                // Greedy choice based on heuristic\n                double max_score = -1e18;\n                \n                // Iterate neighbors\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        \n                        // Score calculation: (current_time * static) - dynamic\n                        double sc = (double)t * static_score[next_node] - dynamic_score[next_node];\n                        // Add small noise for tie-breaking\n                        sc += uniform_real_distribution<double>(0.0, 1e-6)(rng);\n                        \n                        if(sc > max_score) {\n                            max_score = sc;\n                            best_next = next_node;\n                        }\n                    }\n                }\n            }\n            \n            if(best_next == -1) break; \n            \n            // Append move\n            int cr = curr/N, cc = curr%N;\n            int nr = best_next/N, nc = best_next%N;\n            for(int k=0; k<4; ++k){\n                if(cr+dr[k] == nr && cc+dc[k] == nc){\n                    path += dc_char[k];\n                    break;\n                }\n            }\n            \n            curr = best_next;\n            \n            // Update state\n            int d_u = D_grid[nr][nc];\n            long long old_last = last_visit[curr];\n            long long diff = t - old_last;\n            last_visit[curr] = t;\n            \n            // Update dynamic scores efficiently\n            for(int v=0; v<N*N; ++v) {\n                dynamic_score[v] += d_u * diff * weight_lookup[dist_mat[v][curr]];\n            }\n        }\n        \n        if(curr == 0 && !path.empty()) {\n            long long sc = calculate_score(path);\n            if(best_score == -1 || sc < best_score) {\n                best_score = sc;\n                best_path = path;\n            }\n        }\n        \n        p_idx++;\n    }\n    \n    cout << best_path << endl;\n    return 0;\n}","ahc028":"/**\n * Solution for AtCoder Heuristic Contest 028\n * Problem: Kakizome\n * \n * Strategy:\n * 1. Construct a superstring by ordering the input strings t_k.\n *    - Maximize overlaps (Shortest Common Superstring).\n *    - Minimize physical movement distance between string segments.\n * 2. Use Greedy initialization with spatial heuristics.\n * 3. Refine the ordering using Simulated Annealing.\n *    - Cost function: Exact physical cost computed via DP.\n * 4. DP finds the optimal sequence of key presses for a fixed superstring.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <iomanip>\n\nusing namespace std;\n\n// -------------------- Constants & Globals --------------------\nint N, M;\nint start_r, start_c;\nvector<string> A;\nvector<string> T;\nvector<pair<int, int>> char_positions[26];\npair<double, double> char_avg_pos[26];\n\n// overlaps[i][j] = length of longest suffix of T[i] matching prefix of T[j]\nint overlaps[205][205];\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// -------------------- Helper Functions --------------------\n\n// Character to integer index (0-25)\ninline int c2i(char c) {\n    return c - 'A';\n}\n\n// Manhattan distance\ninline int dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Calculate overlap between s1 and s2\nint calc_overlap(const string& s1, const string& s2) {\n    // Max overlap is 4 since strings are distinct and length 5\n    for (int len = 4; len >= 1; --len) {\n        bool match = true;\n        for (int k = 0; k < len; ++k) {\n            if (s1[5 - len + k] != s2[k]) {\n                match = false;\n                break;\n            }\n        }\n        if (match) return len;\n    }\n    return 0;\n}\n\n// Construct the sequence of character indices for a given permutation of strings\nvoid build_superstring_vec(const vector<int>& p, vector<int>& s_out) {\n    s_out.clear();\n    s_out.reserve(1200); // Reserve sufficient memory\n    \n    // Append first string fully\n    for (char c : T[p[0]]) s_out.push_back(c2i(c));\n    \n    // Append subsequent strings skipping the overlap\n    for (size_t i = 1; i < p.size(); ++i) {\n        int u = p[i-1];\n        int v = p[i];\n        int ov = overlaps[u][v];\n        const string& t = T[v];\n        for (int k = ov; k < 5; ++k) {\n            s_out.push_back(c2i(t[k]));\n        }\n    }\n}\n\n// Calculate the exact minimum movement cost for a given character sequence S using DP\n// Returns the minimum total cost\nint get_cost(const vector<int>& S) {\n    int L = S.size();\n    if (L == 0) return 0;\n\n    // Static buffers to reuse memory, reducing allocation overhead\n    static vector<int> dp_prev;\n    static vector<int> dp_curr;\n    \n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp_prev.resize(pos0.size());\n    \n    // Initialize first character costs (from start position)\n    for (size_t j = 0; j < pos0.size(); ++j) {\n        dp_prev[j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    // DP transitions\n    for (int i = 1; i < L; ++i) {\n        int c_curr = S[i];\n        const auto& pos_curr = char_positions[c_curr];\n        const auto& pos_prev = char_positions[S[i-1]];\n        \n        dp_curr.resize(pos_curr.size());\n        \n        for (size_t j = 0; j < pos_curr.size(); ++j) {\n            int r = pos_curr[j].first;\n            int c = pos_curr[j].second;\n            int min_val = INT_MAX;\n            \n            for (size_t k = 0; k < pos_prev.size(); ++k) {\n                int prev_val = dp_prev[k];\n                // Cost = prev_cost + movement + 1 (type)\n                int d = abs(r - pos_prev[k].first) + abs(c - pos_prev[k].second);\n                if (prev_val + d + 1 < min_val) {\n                    min_val = prev_val + d + 1;\n                }\n            }\n            dp_curr[j] = min_val;\n        }\n        dp_prev = dp_curr;\n    }\n    \n    // Find minimum cost at the end\n    int ans = INT_MAX;\n    for (int v : dp_prev) if (v < ans) ans = v;\n    return ans;\n}\n\n// Run DP again to reconstruct and print the path\nvoid solve_final(const vector<int>& S) {\n    int L = S.size();\n    vector<vector<int>> parent(L);\n    vector<vector<int>> dp(L);\n    \n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp[0].resize(pos0.size());\n    parent[0].resize(pos0.size(), -1);\n    \n    for (size_t j = 0; j < pos0.size(); ++j) {\n        dp[0][j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    for (int i = 1; i < L; ++i) {\n        int c_curr = S[i];\n        const auto& pos_curr = char_positions[c_curr];\n        const auto& pos_prev = char_positions[S[i-1]];\n        \n        dp[i].resize(pos_curr.size());\n        parent[i].resize(pos_curr.size());\n        \n        for (size_t j = 0; j < pos_curr.size(); ++j) {\n            int r = pos_curr[j].first;\n            int c = pos_curr[j].second;\n            int min_val = INT_MAX;\n            int best_p = -1;\n            \n            for (size_t k = 0; k < pos_prev.size(); ++k) {\n                int d = abs(r - pos_prev[k].first) + abs(c - pos_prev[k].second);\n                int total = dp[i-1][k] + d + 1;\n                if (total < min_val) {\n                    min_val = total;\n                    best_p = k;\n                }\n            }\n            dp[i][j] = min_val;\n            parent[i][j] = best_p;\n        }\n    }\n    \n    int min_total = INT_MAX;\n    int curr_idx = -1;\n    for (size_t j = 0; j < dp[L-1].size(); ++j) {\n        if (dp[L-1][j] < min_total) {\n            min_total = dp[L-1][j];\n            curr_idx = j;\n        }\n    }\n    \n    // Backtrack to find coordinates\n    vector<pair<int,int>> path;\n    for (int i = L - 1; i >= 0; --i) {\n        path.push_back(char_positions[S[i]][curr_idx]);\n        curr_idx = parent[i][curr_idx];\n    }\n    reverse(path.begin(), path.end());\n    \n    for (auto& p : path) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n}\n\n// -------------------- Main --------------------\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    if (!(cin >> N >> M)) return 0;\n    cin >> start_r >> start_c;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    T.resize(M);\n    for (int i = 0; i < M; ++i) cin >> T[i];\n    \n    // Preprocess map positions and calculate average position per char\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int c = c2i(A[i][j]);\n            char_positions[c].push_back({i, j});\n            char_avg_pos[c].first += i;\n            char_avg_pos[c].second += j;\n        }\n    }\n    for (int c = 0; c < 26; ++c) {\n        if (!char_positions[c].empty()) {\n            char_avg_pos[c].first /= char_positions[c].size();\n            char_avg_pos[c].second /= char_positions[c].size();\n        }\n    }\n    \n    // Precompute overlaps\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) overlaps[i][j] = 0;\n            else overlaps[i][j] = calc_overlap(T[i], T[j]);\n        }\n    }\n    \n    // --- Phase 1: Greedy Construction ---\n    // Try starting from every node to find the best greedy path.\n    vector<int> best_p;\n    int best_score = INT_MAX;\n    vector<int> s_vec;\n    \n    for (int start_node = 0; start_node < M; ++start_node) {\n        vector<int> p;\n        p.reserve(M);\n        vector<bool> visited(M, false);\n        \n        p.push_back(start_node);\n        visited[start_node] = true;\n        \n        int curr = start_node;\n        for (int step = 1; step < M; ++step) {\n            int best_next = -1;\n            double max_h_score = -1e18;\n            \n            int last_c = c2i(T[curr].back());\n            \n            // Find best next string\n            for (int next = 0; next < M; ++next) {\n                if (!visited[next]) {\n                    int ov = overlaps[curr][next];\n                    \n                    // Heuristic: Maximize overlap, minimize spatial distance.\n                    // Distance is estimated using average key positions.\n                    int first_new_c = c2i(T[next][ov]);\n                    double d = abs(char_avg_pos[last_c].first - char_avg_pos[first_new_c].first) + \n                               abs(char_avg_pos[last_c].second - char_avg_pos[first_new_c].second);\n                    \n                    // Weighting: overlap is very important (saves ~6 cost), distance is secondary.\n                    double score = ov * 10.0 - d * 0.1;\n                    \n                    if (score > max_h_score) {\n                        max_h_score = score;\n                        best_next = next;\n                    }\n                }\n            }\n            \n            visited[best_next] = true;\n            p.push_back(best_next);\n            curr = best_next;\n        }\n        \n        build_superstring_vec(p, s_vec);\n        int cost = get_cost(s_vec);\n        if (cost < best_score) {\n            best_score = cost;\n            best_p = p;\n        }\n    }\n    \n    // --- Phase 2: Simulated Annealing ---\n    double T_start = 10.0;\n    double T_end = 0.5;\n    double TL = 1.90; // Time limit\n    \n    vector<int> curr_p = best_p;\n    int curr_cost = best_score;\n    \n    int iters = 0;\n    while (true) {\n        iters++;\n        // Check time periodically\n        if ((iters & 127) == 0) {\n            double el = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (el > TL) break;\n        }\n        \n        // Calculate Temperature\n        double el = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n        double progress = el / TL;\n        double Temp = T_start * pow(T_end/T_start, progress);\n        \n        // Generate Neighbor\n        int type = rng() % 100;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) j = (i + 1) % M;\n        if (i > j) swap(i, j);\n        \n        vector<int> next_p = curr_p;\n        \n        if (type < 40) { \n            // Swap\n            swap(next_p[i], next_p[j]);\n        } else if (type < 70) { \n            // 2-opt (Reverse segment)\n            reverse(next_p.begin() + i, next_p.begin() + j + 1);\n        } else { \n            // Insert (Move i to j)\n            int val = next_p[i];\n            next_p.erase(next_p.begin() + i);\n            next_p.insert(next_p.begin() + j, val);\n        }\n        \n        // Evaluate\n        build_superstring_vec(next_p, s_vec);\n        int next_cost = get_cost(s_vec);\n        \n        int diff = next_cost - curr_cost;\n        // Acceptance criteria\n        if (diff <= 0 || bernoulli_distribution(exp(-diff / Temp))(rng)) {\n            curr_p = next_p;\n            curr_cost = next_cost;\n            if (curr_cost < best_score) {\n                best_score = curr_cost;\n                best_p = curr_p;\n            }\n        }\n    }\n    \n    // Final Output\n    build_superstring_vec(best_p, s_vec);\n    solve_final(s_vec);\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <map>\n#include <iomanip>\n\nusing namespace std;\n\n// ---------------------- Utilities ----------------------\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool is_time_over() {\n        return elapsed() > limit;\n    }\n};\n\nmt19937 rng(12345);\n\n// ---------------------- Problem Data ----------------------\n\nint N, M;\ndouble EPS;\nstruct Point { int r, c; };\nstruct Polyomino {\n    vector<Point> shape;\n};\nvector<Polyomino> fields;\n\nstruct Operation {\n    int type; // 0: drill, 1: divine\n    int r, c; // for drill\n    vector<Point> set_points; // for divine\n    int result_drill;\n    int result_divine;\n};\nvector<Operation> history;\n\nstruct ValidPos {\n    int id;\n    int dr, dc;\n    vector<Point> cells;\n};\nvector<vector<ValidPos>> possible_positions; // possible_positions[field_idx]\nvector<vector<int>> active_indices; // indices into possible_positions\n\n// Grid knowledge: -1 unknown, >=0 exact value\nvector<vector<int>> grid_known;\n\n// ---------------------- Core Functions ----------------------\n\n// Precompute all valid translations for each polyomino\nvoid precompute_positions() {\n    possible_positions.resize(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& poly = fields[k].shape;\n        int max_r = 0, max_c = 0;\n        for (auto& p : poly) {\n            max_r = max(max_r, p.r);\n            max_c = max(max_c, p.c);\n        }\n        for (int r = 0; r < N - max_r; ++r) {\n            for (int c = 0; c < N - max_c; ++c) {\n                ValidPos vp;\n                vp.dr = r;\n                vp.dc = c;\n                vp.id = (int)possible_positions[k].size();\n                for (auto& p : poly) {\n                    vp.cells.push_back({p.r + r, p.c + c});\n                }\n                possible_positions[k].push_back(vp);\n            }\n        }\n    }\n}\n\nvoid update_knowledge() {\n    grid_known.assign(N, vector<int>(N, -1));\n    for (const auto& op : history) {\n        if (op.type == 0) {\n            grid_known[op.r][op.c] = op.result_drill;\n        }\n    }\n}\n\n// Prune positions that cover a square known to be 0\nvoid prune_positions() {\n    active_indices.assign(M, {});\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < (int)possible_positions[k].size(); ++i) {\n            bool ok = true;\n            for (auto& p : possible_positions[k][i].cells) {\n                if (grid_known[p.r][p.c] == 0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                active_indices[k].push_back(i);\n            }\n        }\n    }\n}\n\n// Calculate energy (negative log-likelihood-ish score)\ndouble calc_energy(const vector<int>& config, const vector<vector<int>>& current_counts) {\n    double energy = 0.0;\n    \n    for (const auto& op : history) {\n        if (op.type == 0) { // Drill\n            int val = current_counts[op.r][op.c];\n            if (val != op.result_drill) {\n                // Strong penalty for mismatching exact drill results\n                energy += 10000.0 * abs(val - op.result_drill);\n            }\n        } else if (op.type == 1) { // Divine\n            int sum_v = 0;\n            for (const auto& p : op.set_points) {\n                sum_v += current_counts[p.r][p.c];\n            }\n            int k_sz = op.set_points.size();\n            // Mean = (k - v)eps + v(1-eps) = v(1-2eps) + k*eps\n            double mean = sum_v * (1.0 - 2.0 * EPS) + k_sz * EPS;\n            double var = k_sz * EPS * (1.0 - EPS);\n            double diff = op.result_divine - mean;\n            energy += (diff * diff) / (2.0 * var);\n        }\n    }\n    return energy;\n}\n\n// Run Simulated Annealing to find plausible configurations\nvector<vector<int>> solve(int num_solutions, double time_limit) {\n    vector<vector<int>> solutions;\n    Timer sa_timer(time_limit);\n    \n    while (solutions.size() < (size_t)num_solutions && !sa_timer.is_time_over()) {\n        vector<int> config(M);\n        vector<vector<int>> counts(N, vector<int>(N, 0));\n        bool possible = true;\n        \n        // Initialize with random valid positions\n        for (int k = 0; k < M; ++k) {\n            if (active_indices[k].empty()) {\n                possible = false; break;\n            }\n            int idx = active_indices[k][rng() % active_indices[k].size()];\n            config[k] = idx;\n            for (auto& p : possible_positions[k][idx].cells) {\n                counts[p.r][p.c]++;\n            }\n        }\n        \n        if (!possible) break;\n\n        double current_energy = calc_energy(config, counts);\n        double T = 20.0;\n        double min_T = 0.05;\n        double decay = 0.92;\n        \n        int iter = 0;\n        int max_iter = 2500;\n        \n        while (T > min_T && iter < max_iter) {\n            iter++;\n            int k = rng() % M;\n            if (active_indices[k].size() <= 1) continue;\n            \n            int old_idx = config[k];\n            int new_idx = active_indices[k][rng() % active_indices[k].size()];\n            \n            if (old_idx == new_idx) continue;\n            \n            // Incremental update\n            for (auto& p : possible_positions[k][old_idx].cells) counts[p.r][p.c]--;\n            for (auto& p : possible_positions[k][new_idx].cells) counts[p.r][p.c]++;\n            \n            double new_energy = calc_energy(config, counts);\n            \n            if (new_energy < current_energy || exp((current_energy - new_energy) / T) > (double)rng() / 4294967296.0) {\n                config[k] = new_idx;\n                current_energy = new_energy;\n            } else {\n                // Revert\n                for (auto& p : possible_positions[k][new_idx].cells) counts[p.r][p.c]--;\n                for (auto& p : possible_positions[k][old_idx].cells) counts[p.r][p.c]++;\n            }\n            \n            T *= decay;\n        }\n        solutions.push_back(config);\n    }\n    return solutions;\n}\n\n// ---------------------- Main ----------------------\n\nint main() {\n    cin.tie(nullptr);\n    ios_base::sync_with_stdio(false);\n\n    if (!(cin >> N >> M >> EPS)) return 0;\n\n    fields.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int d; cin >> d;\n        fields[i].shape.resize(d);\n        for (int j = 0; j < d; ++j) {\n            cin >> fields[i].shape[j].r >> fields[i].shape[j].c;\n        }\n    }\n\n    precompute_positions();\n    grid_known.assign(N, vector<int>(N, -1));\n    \n    // 1. Initial Scan using Divine on blocks\n    // Use block size based on N. For N=10-20, ~4 is good cost/info trade-off.\n    int block_size = max(2, N / 5);\n    vector<vector<Point>> divine_sets;\n    for(int r=0; r<N; r+=block_size) {\n        for(int c=0; c<N; c+=block_size) {\n            vector<Point> pts;\n            for(int rr=r; rr<min(N, r+block_size); ++rr) {\n                for(int cc=c; cc<min(N, c+block_size); ++cc) {\n                    pts.push_back({rr, cc});\n                }\n            }\n            // Divine requires at least 2 squares\n            if(pts.size() >= 2) {\n                divine_sets.push_back(pts);\n            }\n        }\n    }\n    \n    for(auto& pts : divine_sets) {\n        cout << \"q \" << pts.size();\n        for(auto& p : pts) cout << \" \" << p.r << \" \" << p.c;\n        cout << endl;\n        int res; cin >> res;\n        history.push_back({1, 0, 0, pts, 0, res});\n    }\n\n    Timer global_timer(2.85);\n    int max_ops = 2 * N * N;\n    \n    // 2. Iterative Refinement\n    while (!global_timer.is_time_over() && (int)history.size() < max_ops) {\n        update_knowledge();\n        prune_positions();\n        \n        // Generate multiple diverse, valid configurations\n        // Budget ~50ms per iteration\n        vector<vector<int>> solutions = solve(15, 0.05); \n        \n        if (solutions.empty()) {\n             // If constraint solver fails (rare), drill a random unknown square\n             int r = rng()%N, c = rng()%N;\n             while(grid_known[r][c] != -1) { r = rng()%N; c = rng()%N; }\n             cout << \"q 1 \" << r << \" \" << c << endl;\n             int val; cin >> val;\n             history.push_back({0, r, c, {}, val, 0});\n             continue;\n        }\n\n        // Aggregate results\n        vector<vector<int>> pos_counts(N, vector<int>(N, 0));\n        \n        for(int i=0; i<(int)solutions.size(); ++i) {\n            vector<vector<int>> counts(N, vector<int>(N, 0));\n            for(int k=0; k<M; ++k) {\n                int idx = solutions[i][k];\n                for(auto& p : possible_positions[k][idx].cells) {\n                    counts[p.r][p.c]++;\n                }\n            }\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    if(counts[r][c] > 0) pos_counts[r][c]++;\n                }\n            }\n        }\n\n        // Check consensus\n        bool all_agree = true;\n        vector<Point> answer_set;\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                bool has_oil = (pos_counts[r][c] > 0);\n                // Disagreement if some say oil and some say no oil\n                if (pos_counts[r][c] != 0 && pos_counts[r][c] != (int)solutions.size()) {\n                    all_agree = false;\n                }\n                if (has_oil) answer_set.push_back({r, c});\n            }\n        }\n\n        // If all samples agree, verify against hard constraints and answer\n        if (all_agree && solutions.size() >= 5) {\n            bool consistent = true;\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    bool in_set = false;\n                    for(auto& p : answer_set) if(p.r == r && p.c == c) in_set = true;\n                    \n                    if (grid_known[r][c] == 0 && in_set) consistent = false;\n                    if (grid_known[r][c] > 0 && !in_set) consistent = false;\n                }\n            }\n            \n            if (consistent) {\n                cout << \"a \" << answer_set.size();\n                for(auto& p : answer_set) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                int res; cin >> res;\n                if (res == 1) return 0; \n                // If incorrect (res==0), continue loop (cost penalty applied by system)\n            }\n        }\n        \n        // Select next square to drill based on maximum disagreement\n        int best_r = -1, best_c = -1;\n        int max_disagreement = -1;\n        \n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                if (grid_known[r][c] != -1) continue; \n                int c_yes = pos_counts[r][c];\n                int c_no = (int)solutions.size() - c_yes;\n                int disagreement = min(c_yes, c_no);\n                if (disagreement > max_disagreement) {\n                    max_disagreement = disagreement;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        if (best_r != -1 && max_disagreement > 0) {\n            cout << \"q 1 \" << best_r << \" \" << best_c << endl;\n            int val; cin >> val;\n            history.push_back({0, best_r, best_c, {}, val, 0});\n        } else {\n            // Fallback: Random unknown square\n            vector<Point> undrilled;\n            for(int r=0; r<N; ++r)\n                for(int c=0; c<N; ++c)\n                    if(grid_known[r][c] == -1) undrilled.push_back({r, c});\n            \n            if(undrilled.empty()) break; \n            \n            int idx = rng() % undrilled.size();\n            cout << \"q 1 \" << undrilled[idx].r << \" \" << undrilled[idx].c << endl;\n            int val; cin >> val;\n            history.push_back({0, undrilled[idx].r, undrilled[idx].c, {}, val, 0});\n        }\n    }\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int W_GRID = 1000;\nconst int SHORTAGE_PENALTY = 100;\n\n// Data structures\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nint D, N;\nvector<vector<int>> A; // A[d][k] stores the area demand\n\n// Timer\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\n// Result of solving one column for all days\nstruct ColumnResult {\n    long long cost;\n    vector<vector<int>> cuts; // cuts[d][k] is the bottom coordinate of the k-th item in the column\n};\n\n// Solve the 1D problem for a specific column\n// items: indices of reservations in this column\n// width: width of this column\nColumnResult solve_column(const vector<int>& items, int width) {\n    if (items.empty()) return {0, vector<vector<int>>(D)};\n    \n    // If width is too small, cost is effectively infinite (huge shortage)\n    if (width <= 0) return {1000000000000LL, {}};\n\n    int m = items.size();\n    vector<vector<int>> cuts(D, vector<int>(m));\n    long long total_cost = 0;\n    \n    // State: positions of cuts from the previous day\n    vector<int> prev_cuts(m);\n    \n    for (int d = 0; d < D; ++d) {\n        // 1. Calculate required height for each item\n        vector<int> needs(m);\n        for(int i=0; i<m; ++i) {\n            needs[i] = (A[d][items[i]] + width - 1) / width;\n        }\n\n        // 2. Calculate strict Lower Bounds (L) and Upper Bounds (R)\n        // L[i]: minimum position of cut i to satisfy items 0..i\n        // R[i]: maximum position of cut i to satisfy items i+1..m-1 (counting from bottom)\n        vector<int> L(m), R(m);\n        \n        long long current_L = 0;\n        for(int i=0; i<m; ++i) {\n            current_L += needs[i];\n            L[i] = (int)min((long long)W_GRID, current_L);\n        }\n\n        R[m-1] = W_GRID; // The last cut is always the bottom of the grid\n        long long current_R = W_GRID;\n        for(int i=m-2; i>=0; --i) {\n            current_R -= needs[i+1];\n            R[i] = (int)max(0LL, current_R);\n        }\n\n        vector<int> curr_cuts(m);\n        curr_cuts[m-1] = W_GRID;\n\n        // 3. Determine cuts for items 0 to m-2\n        for(int i=0; i<m-1; ++i) {\n            int lower = L[i];\n            int upper = R[i];\n            \n            if (lower > upper) {\n                // Unavoidable shortage (demand > supply).\n                // We prioritize satisfying the current item (and those above).\n                curr_cuts[i] = lower; \n            } else {\n                // Valid range [lower, upper] exists.\n                if (d == 0) {\n                    // For day 0, pick the lower bound to pack tightly to the top.\n                    // This leaves maximum space at the bottom for potential future expansion or new items.\n                    curr_cuts[i] = lower;\n                } else {\n                    // Try to maintain the position from the previous day to avoid move cost.\n                    int p = prev_cuts[i];\n                    if (p < lower) curr_cuts[i] = lower;      // Must move down to satisfy demand\n                    else if (p > upper) curr_cuts[i] = upper; // Must move up (rare, if demand shrinks significantly and others grow)\n                    else curr_cuts[i] = p;                    // Stay put\n                }\n            }\n            // Clamp to grid\n            if (curr_cuts[i] > W_GRID) curr_cuts[i] = W_GRID;\n        }\n        \n        // 4. Calculate Cost\n        long long d_cost = 0;\n        \n        // Shortage cost\n        int prev_y = 0;\n        for(int i=0; i<m; ++i) {\n            int h = curr_cuts[i] - prev_y;\n            int area = h * width;\n            int req = A[d][items[i]];\n            if (area < req) {\n                d_cost += (long long)(req - area) * SHORTAGE_PENALTY;\n            }\n            prev_y = curr_cuts[i];\n        }\n        \n        // Partition move cost\n        // L0=0 implies no cost for day 0 configuration relative to \"empty\".\n        // The problem defines L_d based on change from d-1.\n        if (d > 0) {\n            for(int i=0; i<m-1; ++i) {\n                if (curr_cuts[i] != prev_cuts[i]) {\n                    // A horizontal line segment of length 'width' is removed and added elsewhere\n                    d_cost += 2 * width;\n                }\n            }\n        }\n        \n        total_cost += d_cost;\n        cuts[d] = curr_cuts;\n        prev_cuts = curr_cuts;\n    }\n    \n    return {total_cost, cuts};\n}\n\nstruct Solution {\n    vector<vector<int>> partition; // partition[c] contains the list of item indices for column c\n    vector<int> widths;            // width of each column\n    long long score;\n};\n\nmt19937 rng(42);\n\n// Evaluate a given partition of items into columns\nSolution evaluate_partition(const vector<vector<int>>& part) {\n    int K = part.size();\n    vector<int> widths(K);\n    \n    // Calculate widths based on maximum demand across all days\n    vector<long long> max_demands(K, 0);\n    long long total_demand = 0;\n    for(int c=0; c<K; ++c) {\n        for(int d=0; d<D; ++d) {\n            long long d_sum = 0;\n            for(int idx : part[c]) d_sum += A[d][idx];\n            if (d_sum > max_demands[c]) max_demands[c] = d_sum;\n        }\n        total_demand += max_demands[c];\n    }\n    \n    if (total_demand == 0) total_demand = 1;\n    \n    // Assign widths proportionally\n    int current_w = 0;\n    for(int c=0; c<K; ++c) {\n        if (c == K-1) {\n            widths[c] = W_GRID - current_w;\n        } else {\n            long long w = (long long)W_GRID * max_demands[c] / total_demand;\n            if (w < 1) w = 1;\n            widths[c] = (int)w;\n            current_w += widths[c];\n        }\n    }\n    \n    // Safety check for the last column width\n    if (widths[K-1] < 1) {\n        widths[K-1] = 1;\n        // Adjust previous widths to make space\n        current_w = 0;\n        for(int c=0; c<K-1; ++c) current_w += widths[c];\n        if (current_w >= W_GRID) {\n             for(int c=0; c<K-1; ++c) {\n                 if (widths[c] > 1) {\n                     widths[c]--;\n                     if (current_w - 1 < W_GRID) break;\n                 }\n             }\n        }\n    }\n\n    long long total_score = 0;\n    for(int c=0; c<K; ++c) {\n        ColumnResult res = solve_column(part[c], widths[c]);\n        total_score += res.cost;\n    }\n    \n    return {part, widths, total_score};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> W_GRID >> D >> N)) return 0;\n\n    A.resize(D, vector<int>(N));\n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            cin >> A[d][k];\n        }\n    }\n    \n    long long start_time = get_time_ms();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    // Try different numbers of columns K\n    // N is up to 50. sqrt(50) approx 7. We try up to 10 or N.\n    int max_k = min(N, 10); \n    \n    for(int K=1; K<=max_k; ++K) {\n        // Initialize with uniform partitioning of sorted indices\n        vector<int> cuts(K+1);\n        cuts[0] = 0;\n        cuts[K] = N;\n        for(int i=1; i<K; ++i) cuts[i] = (N * i) / K;\n        \n        vector<vector<int>> part(K);\n        for(int c=0; c<K; ++c) {\n            for(int i=cuts[c]; i<cuts[c+1]; ++i) part[c].push_back(i);\n        }\n        \n        Solution sol = evaluate_partition(part);\n        if (best_sol.score == -1 || sol.score < best_sol.score) {\n            best_sol = sol;\n        }\n        \n        // Hill Climbing on partition boundaries\n        // We limit iterations to manage time\n        int iters = 0;\n        while (iters < 1000) { \n            if (get_time_ms() - start_time > 2800) break; // 2.8s soft limit\n            iters++;\n            \n            if (K == 1) break; // No boundaries to move for K=1\n\n            vector<int> next_cuts = cuts;\n            int idx = uniform_int_distribution<int>(1, K-1)(rng);\n            int dir = uniform_int_distribution<int>(0, 1)(rng) ? 1 : -1;\n            \n            next_cuts[idx] += dir;\n            \n            // Check validity: cuts must be strictly increasing\n            if (next_cuts[idx] <= next_cuts[idx-1] || next_cuts[idx] >= next_cuts[idx+1]) continue;\n            \n            vector<vector<int>> next_part(K);\n            for(int c=0; c<K; ++c) {\n                for(int i=next_cuts[c]; i<next_cuts[c+1]; ++i) next_part[c].push_back(i);\n            }\n            \n            Solution next_sol = evaluate_partition(next_part);\n            if (next_sol.score < sol.score) {\n                sol = next_sol;\n                cuts = next_cuts;\n                if (sol.score < best_sol.score) best_sol = sol;\n            }\n        }\n    }\n    \n    // Reconstruct the final rectangles from the best solution\n    vector<vector<Rect>> final_rects(D, vector<Rect>(N));\n    int current_x = 0;\n    for(int c=0; c<best_sol.partition.size(); ++c) {\n        int w = best_sol.widths[c];\n        ColumnResult res = solve_column(best_sol.partition[c], w);\n        \n        for(int d=0; d<D; ++d) {\n            int prev_y = 0;\n            for(int i=0; i<best_sol.partition[c].size(); ++i) {\n                int item_idx = best_sol.partition[c][i];\n                int y = res.cuts[d][i];\n                // Output format: r0 c0 r1 c1\n                // r is vertical (0..1000), c is horizontal (0..1000)\n                final_rects[d][item_idx] = {prev_y, current_x, y, current_x + w};\n                prev_y = y;\n            }\n        }\n        current_x += w;\n    }\n    \n    // Print output\n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            Rect r = final_rects[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\n\n// Problem Constraints\nconstexpr int N = 9;\nconstexpr long long MOD = 998244353;\n\n// Fast RNG using Xorshift128\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Global Variables\nint M, K;\nlong long initial_board[81];\nlong long stamps[20][9]; // Flattened 3x3 stamps\nint move_indices[49][9]; // Affected board indices for each top-left position\n\nstruct MoveDef {\n    int m;       // Stamp ID\n    int pos_idx; // Position ID (0..48)\n    int p, q;    // Coordinates\n};\nvector<MoveDef> all_moves;\n\n// State Variables\nint current_ops[81]; // Stores index in all_moves, or -1 for empty\nlong long board[81];\nlong long current_score;\n\n// Best Solution Tracking\nint best_ops[81];\nlong long best_score = -1;\n\n// Undo System for efficient rollback\nstruct Undo {\n    int idx;\n    long long val;\n};\nUndo undo_log[20]; // Buffer for changes (max 18 per step)\nint undo_ptr = 0;\n\n// Apply or remove a stamp operation. \n// If adding=true, adds stamp values. If adding=false, subtracts stamp values.\n// Records old values to undo_log.\ninline void apply_change(int move_id, bool adding) {\n    if (move_id == -1) return;\n    const auto& mv = all_moves[move_id];\n    int m = mv.m;\n    int pos = mv.pos_idx;\n    \n    // Unroll loop manually or let compiler optimize. 9 iterations is small.\n    for (int i = 0; i < 9; ++i) {\n        int idx = move_indices[pos][i];\n        long long old_val = board[idx];\n        long long s_val = stamps[m][i];\n        \n        // Record for undo\n        undo_log[undo_ptr++] = {idx, old_val};\n        \n        // Update Score (remove old value contribution)\n        current_score -= old_val;\n        \n        // Calculate new value\n        long long new_val;\n        if (adding) {\n            new_val = old_val + s_val;\n            if (new_val >= MOD) new_val -= MOD;\n        } else {\n            new_val = old_val - s_val;\n            if (new_val < 0) new_val += MOD;\n        }\n        \n        // Apply update\n        board[idx] = new_val;\n        current_score += new_val;\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    int n_in;\n    if (!(cin >> n_in >> M >> K)) return 0;\n    \n    for (int i = 0; i < 81; ++i) cin >> initial_board[i];\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 9; ++i) cin >> stamps[m][i];\n    }\n    \n    // Precompute moves and affected indices\n    // Positions are 0 <= p, q <= N-3 (=6). 7x7 = 49 positions.\n    int pos_cnt = 0;\n    for (int p = 0; p <= N - 3; ++p) {\n        for (int q = 0; q <= N - 3; ++q) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    move_indices[pos_cnt][i * 3 + j] = (p + i) * N + (q + j);\n                }\n            }\n            for (int m = 0; m < M; ++m) {\n                all_moves.push_back({m, pos_cnt, p, q});\n            }\n            pos_cnt++;\n        }\n    }\n    int num_valid_moves = all_moves.size();\n    \n    // Initialize state\n    for (int i = 0; i < 81; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < 81; ++i) current_score += board[i];\n    for (int i = 0; i < K; ++i) current_ops[i] = -1;\n    \n    best_score = current_score;\n    for (int i = 0; i < K; ++i) best_ops[i] = -1;\n    \n    // Greedy Initialization\n    // Sequentially fill slots if it improves the score\n    for (int k = 0; k < K; ++k) {\n        long long best_local_score = current_score;\n        int best_move = -1;\n        \n        // Try all possible moves for this slot\n        for (int mv = 0; mv < num_valid_moves; ++mv) {\n            undo_ptr = 0;\n            long long prev_score = current_score;\n            \n            apply_change(mv, true);\n            \n            if (current_score > best_local_score) {\n                best_local_score = current_score;\n                best_move = mv;\n            }\n            \n            // Revert\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n            current_score = prev_score;\n        }\n        \n        // If we found a beneficial move, apply it permanently\n        if (best_move != -1) {\n            current_ops[k] = best_move;\n            undo_ptr = 0;\n            apply_change(best_move, true);\n        }\n    }\n    \n    // Update global best after greedy\n    if (current_score > best_score) {\n        best_score = current_score;\n        for(int i=0; i<K; ++i) best_ops[i] = current_ops[i];\n    }\n    \n    // Simulated Annealing\n    auto start_clock = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double t0 = 2e8;     // Initial temperature\n    double t1 = 1.0;     // Final temperature\n    \n    long long iter = 0;\n    double current_temp = t0;\n    \n    while (true) {\n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_clock).count();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            current_temp = t0 * pow(t1 / t0, progress);\n        }\n        iter++;\n        \n        // Pick a random slot and a random new move (or empty)\n        int slot = rng.next_int(K);\n        int old_move = current_ops[slot];\n        // Generate new move in range [-1, num_valid_moves-1]\n        int new_move = rng.next_int(num_valid_moves + 1) - 1;\n        \n        if (old_move == new_move) continue;\n        \n        long long prev_score = current_score;\n        undo_ptr = 0;\n        \n        // Apply transition: Remove old move, Add new move\n        apply_change(old_move, false); // Remove old\n        apply_change(new_move, true);  // Add new\n        \n        long long delta = current_score - prev_score;\n        bool accept = false;\n        \n        if (delta >= 0) {\n            accept = true;\n        } else {\n            if (rng.next_double() < exp(delta / current_temp)) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_ops[slot] = new_move;\n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int i = 0; i < K; ++i) best_ops[i] = current_ops[i];\n            }\n        } else {\n            // Revert changes using log (in reverse order)\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n        }\n    }\n    \n    // Output results\n    vector<MoveDef> result_moves;\n    for (int i = 0; i < K; ++i) {\n        if (best_ops[i] != -1) {\n            result_moves.push_back(all_moves[best_ops[i]]);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& mv : result_moves) {\n        cout << mv.m << \" \" << mv.p << \" \" << mv.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <deque>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Crane {\n    int id;\n    Coord pos;\n    bool holding;\n    int container_id; // -1 if none\n    bool dead;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    deque<int> queues[N];\n    Crane cranes[N];\n    int containers_dispatched;\n    vector<string> history;\n    \n    State() {\n        for(int i=0; i<N; ++i)\n            for(int j=0; j<N; ++j)\n                grid[i][j] = -1;\n        containers_dispatched = 0;\n        history.resize(N);\n    }\n};\n\nint dist(Coord a, Coord b) {\n    return std::abs(a.r - b.r) + std::abs(a.c - b.c);\n}\n\nint main() {\n    // Optimize I/O operations\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Input\n    int n_in;\n    if (!(cin >> n_in)) return 0;\n    // N is fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Initialize State\n    State st;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            st.queues[i].push_back(A[i][j]);\n        }\n        st.cranes[i] = {i, {i, 0}, false, -1, false};\n    }\n\n    // Track next needed container for each row\n    // Dispatch gate i needs containers 5*i, 5*i+1, ... in order\n    vector<int> next_needed(N);\n    for(int i=0; i<N; ++i) next_needed[i] = i * N;\n\n    // Main simulation loop\n    for (int turn = 1; turn <= MAX_TURNS; ++turn) {\n        if (st.containers_dispatched == N*N) break;\n\n        // 1. Refill Receiving Gates (Step 1 of turn)\n        for(int i=0; i<N; ++i) {\n            if (!st.queues[i].empty()) {\n                bool empty_sq = (st.grid[i][0] == -1);\n                bool crane_holding = false;\n                // Check if any crane is holding a container at this gate (blocks refill)\n                for(int k=0; k<N; ++k) {\n                    if (!st.cranes[k].dead && st.cranes[k].pos.r == i && st.cranes[k].pos.c == 0 && st.cranes[k].holding) {\n                        crane_holding = true;\n                        break;\n                    }\n                }\n                if (empty_sq && !crane_holding) {\n                    st.grid[i][0] = st.queues[i].front();\n                    st.queues[i].pop_front();\n                }\n            }\n        }\n\n        // 2. Crane Actions (Step 2 of turn)\n        for(int i=0; i<N; ++i) {\n            char act = '.';\n            if (i > 0) {\n                // Small cranes bomb themselves on turn 1 to clear the way\n                if (turn == 1) {\n                    act = 'B';\n                    st.cranes[i].dead = true;\n                } else {\n                    act = '.';\n                }\n            } else {\n                // Large Crane (0) Logic\n                Crane& c = st.cranes[0];\n                \n                auto is_needed = [&](int id) {\n                    if (id == -1) return false;\n                    int row = id / N;\n                    // Only the exact next one is \"needed\" to enforce order\n                    if (next_needed[row] == id) return true;\n                    return false;\n                };\n                \n                char my_act = '.';\n                \n                if (c.holding) {\n                    int held = c.container_id;\n                    if (is_needed(held)) {\n                        // DELIVER: Move to dispatch gate\n                        int row = held / N;\n                        Coord dest = {row, N-1};\n                        \n                        if (c.pos == dest) {\n                            // Drop if square is empty (it will be dispatched in step 3)\n                            if (st.grid[dest.r][dest.c] == -1) {\n                                my_act = 'Q';\n                            } else {\n                                my_act = '.'; // Wait for space\n                            }\n                        } else {\n                            // Move towards destination\n                            if (c.pos.r < dest.r) my_act = 'D';\n                            else if (c.pos.r > dest.r) my_act = 'U';\n                            else if (c.pos.c < dest.c) my_act = 'R';\n                            else if (c.pos.c > dest.c) my_act = 'L';\n                        }\n                    } else {\n                        // STORE: Move garbage to buffer\n                        // Prefer columns 1, 2, 3. Column 0 is last resort.\n                        int best_dist = 999;\n                        Coord best_spot = {-1, -1};\n                        \n                        for(int c_idx : {1, 2, 3, 0}) { \n                             for(int r_idx=0; r_idx<N; ++r_idx) {\n                                 // Skip Dispatch column 4\n                                 if (st.grid[r_idx][c_idx] == -1) {\n                                     int d = dist(c.pos, {r_idx, c_idx});\n                                     if (d < best_dist) {\n                                         best_dist = d;\n                                         best_spot = {r_idx, c_idx};\n                                     }\n                                 }\n                             }\n                        }\n                        \n                        if (best_spot.r != -1) {\n                            if (c.pos == best_spot) {\n                                my_act = 'Q';\n                            } else {\n                                if (c.pos.r < best_spot.r) my_act = 'D';\n                                else if (c.pos.r > best_spot.r) my_act = 'U';\n                                else if (c.pos.c < best_spot.c) my_act = 'R';\n                                else if (c.pos.c > best_spot.c) my_act = 'L';\n                            }\n                        } else {\n                             my_act = '.'; // Stuck (should not happen with N=5)\n                        }\n                    }\n                } else {\n                    // PICK: Find something to pick\n                    int best_dist = 999;\n                    Coord target = {-1, -1};\n                    \n                    // Priority 1: Look for exposed needed items on the grid\n                    for(int r=0; r<N; ++r) {\n                        for(int c_idx=0; c_idx<N; ++c_idx) {\n                            int id = st.grid[r][c_idx];\n                            if (is_needed(id)) {\n                                // Ignore if already at correct dispatch gate (will be auto-dispatched)\n                                int needed_row = id / N;\n                                if (r == needed_row && c_idx == N-1) continue; \n                                \n                                int d = dist(c.pos, {r, c_idx});\n                                if (d < best_dist) {\n                                    best_dist = d;\n                                    target = {r, c_idx};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (target.r != -1) {\n                        // Go pick the visible needed item\n                        if (c.pos == target) {\n                            my_act = 'P';\n                        } else {\n                             if (c.pos.r < target.r) my_act = 'D';\n                             else if (c.pos.r > target.r) my_act = 'U';\n                             else if (c.pos.c < target.c) my_act = 'R';\n                             else if (c.pos.c > target.c) my_act = 'L';\n                        }\n                    } else {\n                        // Priority 2: Dig for buried needed items in queues\n                        int best_depth = 999;\n                        int target_q = -1;\n                        \n                        for(int q=0; q<N; ++q) {\n                            for(int k=0; k<(int)st.queues[q].size(); ++k) {\n                                if (is_needed(st.queues[q][k])) {\n                                    if (k < best_depth) {\n                                        best_depth = k;\n                                        target_q = q;\n                                    }\n                                    break; \n                                }\n                            }\n                        }\n                        \n                        if (target_q != -1) {\n                            // Go to the queue to clear the blocker\n                            Coord t = {target_q, 0};\n                            if (c.pos == t) {\n                                if (st.grid[t.r][t.c] != -1) my_act = 'P';\n                                else my_act = '.'; // Wait for refill\n                            } else {\n                                 if (c.pos.r < t.r) my_act = 'D';\n                                 else if (c.pos.r > t.r) my_act = 'U';\n                                 else if (c.pos.c < t.c) my_act = 'R';\n                                 else if (c.pos.c > t.c) my_act = 'L';\n                            }\n                        } else {\n                            my_act = '.';\n                        }\n                    }\n                }\n                \n                act = my_act;\n                \n                // Update Crane 0 state based on action\n                if (act == 'U') st.cranes[0].pos.r--;\n                else if (act == 'D') st.cranes[0].pos.r++;\n                else if (act == 'L') st.cranes[0].pos.c--;\n                else if (act == 'R') st.cranes[0].pos.c++;\n                else if (act == 'P') {\n                    st.cranes[0].holding = true;\n                    st.cranes[0].container_id = st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c];\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = -1;\n                }\n                else if (act == 'Q') {\n                    st.cranes[0].holding = false;\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = st.cranes[0].container_id;\n                    st.cranes[0].container_id = -1;\n                }\n            }\n            st.history[i] += act;\n        }\n        \n        // 3. Dispatch (Step 3 of turn)\n        for(int i=0; i<N; ++i) {\n            int cid = st.grid[i][N-1];\n            if (cid != -1) {\n                // Item at dispatch gate is removed from grid\n                st.grid[i][N-1] = -1;\n                st.containers_dispatched++;\n                \n                // Update needed index if correct one was dispatched\n                int row = cid / N;\n                if (row == i && cid == next_needed[i]) {\n                    next_needed[i]++;\n                }\n            }\n        }\n    }\n\n    // Output results\n    for(int i=0; i<N; ++i) {\n        cout << st.history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Directions: 0:U, 1:D, 2:L, 3:R\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint N = 20;\nlong long grid_h[20][20];\nlong long current_h[20][20];\n\n// flow_plan[r][c][k] stores the remaining flow needed from (r,c) in direction k\nlong long flow_plan[20][20][4]; \n\nstruct State {\n    int r, c;\n    long long load;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (cin >> N) {} // Read N\n    \n    // 1. Construct Min Cost Flow Network\n    // Nodes 0..(N*N-1) represent grid cells.\n    // Node S = N*N, T = N*N+1\n    mcf_graph<int, long long> g(N * N + 2);\n    int S = N * N;\n    int T = N * N + 1;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> grid_h[i][j];\n            current_h[i][j] = grid_h[i][j];\n            int u = i * N + j;\n            \n            // Connect sources and sinks\n            if (grid_h[i][j] > 0) {\n                g.add_edge(S, u, grid_h[i][j], 0);\n            } else if (grid_h[i][j] < 0) {\n                g.add_edge(u, T, -grid_h[i][j], 0);\n            }\n            \n            // Connect grid neighbors\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int v = ni * N + nj;\n                    // Capacity is effectively infinite (bounded by total soil amount)\n                    // Cost is 1 per unit distance\n                    g.add_edge(u, v, 100000000, 1);\n                }\n            }\n        }\n    }\n\n    // 2. Solve Min Cost Flow\n    g.flow(S, T);\n    \n    // 3. Extract static flow plan\n    auto edges = g.edges();\n    for (const auto& e : edges) {\n        if (e.from == S || e.to == T) continue;\n        if (e.flow == 0) continue;\n        \n        int u = e.from;\n        int v = e.to;\n        int r1 = u / N, c1 = u % N;\n        int r2 = v / N, c2 = v % N;\n        \n        for (int k = 0; k < 4; k++) {\n            if (r1 + dr[k] == r2 && c1 + dc[k] == c2) {\n                flow_plan[r1][c1][k] += e.flow;\n                break;\n            }\n        }\n    }\n    \n    // 4. Simulation\n    State truck = {0, 0, 0};\n    vector<string> ops;\n    int turn_limit = 100000;\n    \n    for (int turn = 0; turn < turn_limit; turn++) {\n        // --- Operation: Load / Unload ---\n        long long &h = current_h[truck.r][truck.c];\n        if (h > 0) {\n            // Source: Load everything\n            long long amt = h;\n            truck.load += amt;\n            h = 0;\n            ops.push_back(\"+\" + to_string(amt));\n        } else if (h < 0 && truck.load > 0) {\n            // Sink: Unload needed amount\n            long long need = -h;\n            long long amt = min(truck.load, need);\n            truck.load -= amt;\n            h += amt;\n            ops.push_back(\"-\" + to_string(amt));\n        }\n        \n        // --- Check Completion ---\n        bool done = true;\n        if (truck.load > 0) done = false;\n        else {\n            for(int i=0; i<N; ++i) {\n                for(int j=0; j<N; ++j) {\n                    if (current_h[i][j] != 0) {\n                        done = false;\n                        break;\n                    }\n                }\n                if (!done) break;\n            }\n        }\n        if (done) break;\n        \n        // --- Operation: Move ---\n        int best_k = -1;\n        \n        if (truck.load > 0) {\n            // Strategy: Follow the static flow plan\n            long long max_f = 0;\n            for (int k = 0; k < 4; k++) {\n                int ni = truck.r + dr[k];\n                int nj = truck.c + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    if (flow_plan[truck.r][truck.c][k] > max_f) {\n                        max_f = flow_plan[truck.r][truck.c][k];\n                        best_k = k;\n                    }\n                }\n            }\n            \n            // Fallback: If no flow indication, go to nearest Sink\n            if (best_k == -1) {\n                queue<pair<int, int>> q;\n                q.push({truck.r, truck.c});\n                vector<vector<int>> parent(N, vector<int>(N, -1));\n                vector<vector<bool>> visited(N, vector<bool>(N, false));\n                visited[truck.r][truck.c] = true;\n                \n                int target_r = -1, target_c = -1;\n                \n                while(!q.empty()) {\n                    auto [r, c] = q.front(); q.pop();\n                    if (current_h[r][c] < 0) {\n                        target_r = r; target_c = c;\n                        break;\n                    }\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r + dr[k];\n                        int nc = c + dc[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                            visited[nr][nc] = true;\n                            parent[nr][nc] = k;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                \n                if (target_r != -1) {\n                    // Backtrack to find the first step\n                    int curr = target_r, curc = target_c;\n                    while (true) {\n                        int k = parent[curr][curc];\n                        int pr = curr - dr[k];\n                        int pc = curc - dc[k];\n                        if (pr == truck.r && pc == truck.c) {\n                            best_k = k;\n                            break;\n                        }\n                        curr = pr;\n                        curc = pc;\n                    }\n                }\n            }\n        } else {\n            // truck.load == 0. Strategy: Go to nearest Source\n            queue<pair<int, int>> q;\n            q.push({truck.r, truck.c});\n            vector<vector<int>> parent(N, vector<int>(N, -1));\n            vector<vector<bool>> visited(N, vector<bool>(N, false));\n            visited[truck.r][truck.c] = true;\n            \n            int target_r = -1, target_c = -1;\n            \n            while(!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                if (current_h[r][c] > 0) {\n                    target_r = r; target_c = c;\n                    break;\n                }\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k];\n                    int nc = c + dc[k];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                        visited[nr][nc] = true;\n                        parent[nr][nc] = k;\n                        q.push({nr, nc});\n                    }\n                }\n            }\n            \n            if (target_r != -1) {\n                int curr = target_r, curc = target_c;\n                // If we are already at source (e.g. after unload 0->positive?), handle gracefully\n                if (curr != truck.r || curc != truck.c) {\n                    while (true) {\n                        int k = parent[curr][curc];\n                        int pr = curr - dr[k];\n                        int pc = curc - dc[k];\n                        if (pr == truck.r && pc == truck.c) {\n                            best_k = k;\n                            break;\n                        }\n                        curr = pr;\n                        curc = pc;\n                    }\n                }\n            }\n        }\n        \n        // Execute Move\n        if (best_k != -1) {\n            ops.push_back(string(1, dir_char[best_k]));\n            // Update flow plan: we accomplished 'truck.load' amount of transport in this direction\n            flow_plan[truck.r][truck.c][best_k] -= truck.load;\n            \n            truck.r += dr[best_k];\n            truck.c += dc[best_k];\n        } else {\n            // Should be done\n            break;\n        }\n    }\n    \n    for (const auto& s : ops) cout << s << \"\\n\";\n    \n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Problem constants\nint N, M, T;\nint SEED_COUNT; \nint GRID_SIZE; \n\nstruct Seed {\n    int id;\n    vector<int> x;\n    int total_val;\n};\n\n// Global random engine\nmt19937 rng(12345);\n\n// Timer for managing execution time\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool check() {\n        return elapsed() < limit;\n    }\n};\n\n// Adjacency list for grid\nvector<vector<int>> adj;\n\n// Initialize grid adjacency\nvoid init_grid() {\n    GRID_SIZE = N * N;\n    adj.assign(GRID_SIZE, vector<int>());\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // Down\n            if (r + 1 < N) {\n                int v = (r + 1) * N + c;\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            // Right\n            if (c + 1 < N) {\n                int v = r * N + (c + 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n        }\n    }\n}\n\n// Calculate potential of two seeds: Sum of max(a_i, b_i) across all attributes\ninline int calc_potential(const Seed& a, const Seed& b) {\n    int score = 0;\n    for (int k = 0; k < M; ++k) {\n        if (a.x[k] > b.x[k]) score += a.x[k];\n        else score += b.x[k];\n    }\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> T)) return 0;\n    SEED_COUNT = 2 * N * (N - 1);\n    init_grid();\n\n    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        seeds[i].id = i;\n        seeds[i].x.resize(M);\n        seeds[i].total_val = 0;\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i].x[j];\n            seeds[i].total_val += seeds[i].x[j];\n        }\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // --- Selection Phase ---\n        \n        // 1. Identify global maximums for each attribute to preserve peak genes\n        vector<int> global_max(M, -1);\n        for(const auto& s : seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] > global_max[j]) global_max[j] = s.x[j];\n            }\n        }\n\n        // 2. Sort all seeds by total value descending\n        vector<Seed> sorted_seeds = seeds;\n        sort(sorted_seeds.begin(), sorted_seeds.end(), [](const Seed& a, const Seed& b){\n            return a.total_val > b.total_val;\n        });\n\n        vector<Seed> selected_seeds;\n        selected_seeds.reserve(GRID_SIZE);\n        vector<bool> attr_covered(M, false);\n        vector<bool> is_selected(SEED_COUNT, false);\n        \n        auto select = [&](const Seed& s) {\n            selected_seeds.push_back(s);\n            is_selected[s.id] = true;\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] == global_max[j]) attr_covered[j] = true;\n            }\n        };\n\n        // Priority Selection: Cover global max attributes\n        // We iterate sorted_seeds to prefer high-value seeds for coverage\n        for (const auto& s : sorted_seeds) {\n            if (selected_seeds.size() >= GRID_SIZE) break;\n            bool contributes_new = false;\n            for (int j = 0; j < M; ++j) {\n                if (!attr_covered[j] && s.x[j] == global_max[j]) {\n                    contributes_new = true;\n                    break;\n                }\n            }\n            if (contributes_new) {\n                select(s);\n            }\n        }\n\n        // Fill remaining spots with highest total_val seeds\n        for(const auto& s : sorted_seeds) {\n            if(selected_seeds.size() >= GRID_SIZE) break;\n            if(!is_selected[s.id]) {\n                select(s);\n            }\n        }\n\n        // --- Placement Phase (Simulated Annealing) ---\n        \n        // Current layout maps Grid Cell -> Index in selected_seeds vector\n        vector<int> layout(GRID_SIZE);\n        \n        // Initial placement heuristic: Match high-value seeds to high-degree nodes\n        // 1. Sort nodes by degree (descending)\n        vector<pair<int, int>> node_degrees(GRID_SIZE);\n        for(int i=0; i<GRID_SIZE; ++i) node_degrees[i] = { (int)adj[i].size(), i };\n        sort(node_degrees.rbegin(), node_degrees.rend());\n        \n        // 2. Sort indices of selected_seeds by total_val (descending)\n        vector<int> p(GRID_SIZE);\n        iota(p.begin(), p.end(), 0);\n        sort(p.begin(), p.end(), [&](int a, int b){\n            return selected_seeds[a].total_val > selected_seeds[b].total_val;\n        });\n        \n        // 3. Assign best seeds to nodes with most connections\n        for(int i=0; i<GRID_SIZE; ++i) {\n            layout[node_degrees[i].second] = p[i];\n        }\n\n        // Precompute potentials between all pairs of selected seeds for fast query\n        vector<vector<int>> potentials(GRID_SIZE, vector<int>(GRID_SIZE));\n        for(int i=0; i<GRID_SIZE; ++i) {\n            for(int j=i+1; j<GRID_SIZE; ++j) {\n                potentials[i][j] = potentials[j][i] = calc_potential(selected_seeds[i], selected_seeds[j]);\n            }\n        }\n\n        // Calculate initial score\n        long long current_score = 0;\n        for (int u = 0; u < GRID_SIZE; ++u) {\n            for (int v : adj[u]) {\n                if (u < v) {\n                    current_score += potentials[layout[u]][layout[v]];\n                }\n            }\n        }\n\n        long long best_score = current_score;\n        vector<int> best_layout = layout;\n\n        // Simulated Annealing\n        // Allocate ~0.185s per turn to stay under 2.0s total\n        double time_limit = 0.185; \n        Timer timer(time_limit);\n        double t0 = 200.0;\n        double t1 = 1e-5;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 255) == 0) {\n                if (!timer.check()) break;\n            }\n\n            // Linear cooling schedule\n            double ratio = timer.elapsed() / time_limit;\n            double temp = t0 * (1.0 - ratio);\n            if (temp < t1) temp = t1;\n            \n            // Pick two random distinct cells\n            int c1 = rng() % GRID_SIZE;\n            int c2 = rng() % GRID_SIZE;\n            if (c1 == c2) continue;\n\n            int s1 = layout[c1];\n            int s2 = layout[c2];\n\n            // Calculate score delta efficiently\n            long long delta = 0;\n            \n            // Remove edges connected to c1 (current seed s1)\n            for (int u : adj[c1]) {\n                if (u == c2) continue; // handled later\n                delta -= potentials[s1][layout[u]];\n            }\n            // Remove edges connected to c2 (current seed s2)\n            for (int u : adj[c2]) {\n                if (u == c1) continue;\n                delta -= potentials[s2][layout[u]];\n            }\n            \n            // Add edges connected to c1 if it had s2\n            for (int u : adj[c1]) {\n                if (u == c2) continue;\n                delta += potentials[s2][layout[u]];\n            }\n            // Add edges connected to c2 if it had s1\n            for (int u : adj[c2]) {\n                if (u == c1) continue;\n                delta += potentials[s1][layout[u]];\n            }\n            \n            // Note: Edge (c1, c2) potential changes from P(s1, s2) to P(s2, s1), which is 0 change.\n            // So we don't need to check `u == c2` specially other than to avoid double counting if we iterated all edges.\n            // The logic above skips `u == c2` inside c1's adjacency and vice versa, which is correct.\n\n            // Acceptance criteria\n            if (delta > 0 || bernoulli_distribution(exp(delta / temp))(rng)) {\n                swap(layout[c1], layout[c2]);\n                current_score += delta;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_layout = layout;\n                }\n            }\n        }\n        \n        // --- Output ---\n        // Convert layout back to original seed IDs\n        vector<vector<int>> output_grid(N, vector<int>(N));\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                int cell = r*N + c;\n                int seed_idx = best_layout[cell];\n                output_grid[r][c] = selected_seeds[seed_idx].id;\n            }\n        }\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cout << output_grid[r][c] << (c == N-1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        // --- Input Next Generation ---\n        for(int i=0; i<SEED_COUNT; ++i) {\n            seeds[i].id = i; // Reassign IDs 0..SEED_COUNT-1\n            seeds[i].total_val = 0;\n            for(int j=0; j<M; ++j) {\n                cin >> seeds[i].x[j];\n                seeds[i].total_val += seeds[i].x[j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <map>\n#include <set>\n\nusing namespace std;\n\n// --------------------------------------------------------\n// Constants and Global Variables\n// --------------------------------------------------------\nint N, M, V;\nint grid_t[35][35]; // 1 if it is a target location, 0 otherwise\n\n// Directions: 0:R, 1:D, 2:L, 3:U\nconst int DR[] = {0, 1, 0, -1};\nconst int DC[] = {1, 0, -1, 0};\nconst char MOVE_CHARS[] = {'R', 'D', 'L', 'U'};\nconst char ROT_CHARS[] = {'.', 'R', '.', 'L'}; // Index by diff: 0->., 1->R, 2->X, 3->L\n\nstruct Leaf {\n    int u;          // Vertex ID\n    int dir;        // 0:R, 1:D, 2:L, 3:U relative to Root\n    bool holding;   // Is holding an item?\n};\n\n// State\nint root_r, root_c;\nvector<Leaf> leaves;\nint items_delivered = 0;\nint turns = 0;\n\n// Active Sets\nset<pair<int, int>> s_targets; // Locations of items needing transport\nset<pair<int, int>> t_targets; // Locations of empty target slots\n\n// --------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------\n\n// BFS to find the first step towards the best target\n// Returns pair<move_dir, distance>\n// If target is unreachable or we are there, handles accordingly.\n// We compute BFS from root to all cells to find nearest goal.\npair<int, int> get_best_move_and_cost(bool full, bool empty) {\n    // BFS Distance Map\n    static int dist_map[35][35];\n    static int first_move[35][35];\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) dist_map[i][j] = 1e9;\n    \n    queue<pair<int, int>> q;\n    dist_map[root_r][root_c] = 0;\n    q.push({root_r, root_c});\n    \n    while(!q.empty()){\n        auto [r, c] = q.front(); q.pop();\n        \n        for(int dir=0; dir<4; ++dir){\n            int nr = r + DR[dir];\n            int nc = c + DC[dir];\n            if(nr>=0 && nr<N && nc>=0 && nc<N && dist_map[nr][nc] == 1e9){\n                dist_map[nr][nc] = dist_map[r][c] + 1;\n                // Track first move\n                if (r == root_r && c == root_c) first_move[nr][nc] = dir;\n                else first_move[nr][nc] = first_move[r][c];\n                \n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    // Find closest goal (neighbor of a target)\n    int best_dist = 1e9;\n    int best_move = -1;\n    \n    // Lambda to check a specific cell\n    auto check_goal = [&](const pair<int, int>& p) {\n        int tr = p.first;\n        int tc = p.second;\n        \n        // We need to reach any neighbor of (tr, tc)\n        // If root is at neighbor, dist is 0.\n        int d_to_neighbor = 1e9;\n        int move_to_neighbor = -1;\n        \n        // Check if root is already a neighbor\n        if (abs(root_r - tr) + abs(root_c - tc) == 1) {\n            if (0 < best_dist) {\n                best_dist = 0;\n                best_move = -1; // Stay\n            }\n            return;\n        }\n        \n        // Otherwise check neighbors of target\n        for(int k=0; k<4; ++k) {\n            int nr = tr + DR[k];\n            int nc = tc + DC[k];\n            if (nr>=0 && nr<N && nc>=0 && nc<N) {\n                if (dist_map[nr][nc] < d_to_neighbor) {\n                    d_to_neighbor = dist_map[nr][nc];\n                    move_to_neighbor = first_move[nr][nc];\n                }\n            }\n        }\n        \n        if (d_to_neighbor < best_dist) {\n            best_dist = d_to_neighbor;\n            best_move = move_to_neighbor;\n        }\n    };\n    \n    // Iterate valid goals\n    if (!full) {\n        for(const auto& p : s_targets) check_goal(p);\n    }\n    if (!empty) {\n        for(const auto& p : t_targets) check_goal(p);\n    }\n    \n    return {best_move, best_dist};\n}\n\n// --------------------------------------------------------\n// Main\n// --------------------------------------------------------\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> V)) return 0;\n    \n    vector<string> s_str(N), t_str(N);\n    for(int i=0; i<N; ++i) cin >> s_str[i];\n    for(int i=0; i<N; ++i) cin >> t_str[i];\n    \n    // Init Grid and Sets\n    // Rules:\n    // S=1, T=1: Already correct. Ignore.\n    // S=1, T=0: Needs transport. Add to s_targets.\n    // S=0, T=1: Needs item. Add to t_targets.\n    // S=0, T=0: Empty space.\n    \n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        int is_s = (s_str[i][j] == '1');\n        int is_t = (t_str[i][j] == '1');\n        grid_t[i][j] = is_t;\n        \n        if (is_s && !is_t) s_targets.insert({i, j});\n        if (!is_s && is_t) t_targets.insert({i, j});\n        if (is_s && is_t) items_delivered++; // Pre-satisfied\n    }\n    \n    // Output Arm Design\n    // Star Graph: Root 0, Leaves 1..(V-1), Length 1\n    cout << V << endl;\n    for(int i=1; i<V; ++i) {\n        cout << \"0 1\" << endl;\n    }\n    // Initial Position: Center of grid is a safe heuristic\n    root_r = N/2;\n    root_c = N/2;\n    cout << root_r << \" \" << root_c << endl;\n    \n    // Initialize Leaves\n    leaves.resize(V-1);\n    for(int i=0; i<V-1; ++i) {\n        leaves[i].u = i+1;\n        leaves[i].dir = 0; // Initially Right (0, 1)\n        leaves[i].holding = false;\n    }\n    \n    // Main Loop\n    // Max turns 100,000\n    while ((s_targets.size() > 0 || t_targets.size() > 0) && turns < 100000) {\n        // Check capacity\n        int holding_count = 0;\n        for(const auto& l : leaves) if(l.holding) holding_count++;\n        bool full = (holding_count == V-1);\n        bool empty = (holding_count == 0);\n        \n        // If we are done with all items\n        if (s_targets.empty() && empty) break;\n\n        // 1. Determine Move\n        pair<int, int> move_info = get_best_move_and_cost(full, empty);\n        int move_dir = move_info.first;\n        // int dist_to_goal = move_info.second;\n        \n        // 2. Prepare Command Components\n        char root_move_char = (move_dir == -1) ? '.' : MOVE_CHARS[move_dir];\n        \n        int next_root_r = root_r + (move_dir == -1 ? 0 : DR[move_dir]);\n        int next_root_c = root_c + (move_dir == -1 ? 0 : DC[move_dir]);\n        \n        // 3. Identify Tasks at New Location (Opportunistic Pick/Drop)\n        struct Task {\n            int r, c;\n            int type; // 0: Pick, 1: Drop\n            int dir;  // relative to next_root\n        };\n        vector<Task> tasks;\n        \n        for(int d=0; d<4; ++d) {\n            int nr = next_root_r + DR[d];\n            int nc = next_root_c + DC[d];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            \n            if (t_targets.count({nr, nc}) && !empty) {\n                tasks.push_back({nr, nc, 1, d});\n            } else if (s_targets.count({nr, nc}) && !full) {\n                tasks.push_back({nr, nc, 0, d});\n            }\n        }\n        \n        // Sort tasks: Drops first to free up capacity\n        sort(tasks.begin(), tasks.end(), [](const Task& a, const Task& b){\n            return a.type > b.type;\n        });\n        \n        // 4. Assign Leaves to Tasks\n        vector<char> rot_cmds(V-1, '.');\n        vector<char> act_cmds(V, '.'); // Index 1..V-1 map to leaves 0..V-2\n        vector<Leaf> next_leaves = leaves;\n        vector<bool> leaf_busy(V-1, false);\n        \n        // To ensure we don't pick up more than we can or drop invalidly\n        // We process tasks and update sets conceptually within the turn\n        // Note: s_targets/t_targets are only updated after full turn confirmation\n        // but for assignment, we assume success.\n        \n        for(const auto& task : tasks) {\n            int best_idx = -1;\n            int best_cost = 100;\n            int best_rot = 0; // 0:., 1:R, 3:L\n            \n            for(int i=0; i<V-1; ++i) {\n                if (leaf_busy[i]) continue;\n                \n                // Check Type Compatibility\n                if (task.type == 0 && next_leaves[i].holding) continue; // Pick but full\n                if (task.type == 1 && !next_leaves[i].holding) continue; // Drop but empty\n                \n                // Check Rotation Cost\n                // We can reach neighbor 'd' if leaf is at 'd', 'd-1', 'd+1'\n                // diff: 0 (ok), 1 (R), 3 (L), 2 (impossible in 1 turn)\n                int diff = (task.dir - next_leaves[i].dir + 4) % 4;\n                \n                if (diff == 2) continue; \n                \n                int cost = (diff == 0) ? 0 : 1;\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_idx = i;\n                    best_rot = diff;\n                }\n            }\n            \n            if (best_idx != -1) {\n                // Assign\n                leaf_busy[best_idx] = true;\n                \n                // Rotation Command\n                if (best_rot == 1) rot_cmds[best_idx] = 'R';\n                else if (best_rot == 3) rot_cmds[best_idx] = 'L';\n                \n                // Update Leaf Dir\n                if (best_rot == 1) next_leaves[best_idx].dir = (next_leaves[best_idx].dir + 1) % 4;\n                else if (best_rot == 3) next_leaves[best_idx].dir = (next_leaves[best_idx].dir + 3) % 4;\n                \n                // Action Command\n                act_cmds[best_idx + 1] = 'P';\n                \n                // Update Logic\n                if (task.type == 0) { // Pick\n                     // Double check valid\n                     if (s_targets.count({task.r, task.c})) {\n                         s_targets.erase({task.r, task.c});\n                         // If this spot is also a valid target (was S=1, T=0, now S=0, T=0), \n                         // check if grid_t says it's a target location.\n                         if (grid_t[task.r][task.c]) t_targets.insert({task.r, task.c});\n                         \n                         next_leaves[best_idx].holding = true;\n                     } else {\n                         act_cmds[best_idx + 1] = '.'; // Cancel if race condition\n                     }\n                } else { // Drop\n                     if (t_targets.count({task.r, task.c})) {\n                         t_targets.erase({task.r, task.c});\n                         // Spot becomes S=1? No, it's delivered.\n                         items_delivered++;\n                         \n                         next_leaves[best_idx].holding = false;\n                     } else {\n                         act_cmds[best_idx + 1] = '.';\n                     }\n                }\n            }\n        }\n        \n        // 5. Construct Output String\n        string out_s = \"\";\n        out_s += root_move_char;\n        for(char c : rot_cmds) out_s += c;\n        for(int i=0; i<V; ++i) out_s += act_cmds[i]; // vertex 0..V-1\n        cout << out_s << \"\\n\";\n        \n        // 6. Commit State\n        root_r = next_root_r;\n        root_c = next_root_c;\n        leaves = next_leaves;\n        turns++;\n    }\n    \n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <map>\n#include <set>\n#include <queue>\n#include <cassert>\n#include <chrono>\n\nusing namespace std;\n\n// Constants and Parameters\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\nconst double TIME_LIMIT = 1.95;\n\nstruct Point {\n    int x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Timing utility\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\nlong long start_time;\n\n// Polygon is a list of vertices\ntypedef vector<Point> Polygon;\n\n// Check if point inside polygon (Ray casting)\n// Points on edges are considered inside\nbool is_inside(const Polygon& poly, const Point& p) {\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0; i < n; ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % n];\n        \n        // Check if point is on segment (horizontal or vertical)\n        if (p1.x == p2.x && p1.x == p.x) {\n            if (p.y >= min(p1.y, p2.y) && p.y <= max(p1.y, p2.y)) return true;\n        }\n        if (p1.y == p2.y && p1.y == p.y) {\n            if (p.x >= min(p1.x, p2.x) && p.x <= max(p1.x, p2.x)) return true;\n        }\n        \n        // Standard Ray Casting\n        if ((p1.y > p.y) != (p2.y > p.y)) {\n            double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x;\n            if (p.x < intersect_x) {\n                inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score for a polygon\nint raw_score(const Polygon& poly) {\n    int m = 0, s = 0;\n    int min_x = MAX_COORD, max_x = 0, min_y = MAX_COORD, max_y = 0;\n    for (auto& p : poly) {\n        min_x = min(min_x, p.x);\n        max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y);\n        max_y = max(max_y, p.y);\n    }\n    \n    // Bounding box check for speed\n    for (const auto& p : mackerels) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) m++;\n    }\n    for (const auto& p : sardines) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) s++;\n    }\n    return m - s;\n}\n\nlong long perimeter(const Polygon& poly) {\n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        perim += abs(poly[i].x - poly[(i + 1) % poly.size()].x) + abs(poly[i].y - poly[(i + 1) % poly.size()].y);\n    }\n    return perim;\n}\n\n// Grid-based Solver\nstruct GridSolver {\n    int cell_size;\n    int offset_x, offset_y;\n    int GX, GY;\n    vector<vector<int>> grid_score;\n    \n    GridSolver(int cs, int ox, int oy) : cell_size(cs), offset_x(ox), offset_y(oy) {\n        // Ensure grid covers the range [0, MAX_COORD]\n        // Coordinates map to: (coord + offset) / cell_size\n        GX = (MAX_COORD + offset_x) / cell_size + 2; \n        GY = (MAX_COORD + offset_y) / cell_size + 2;\n        grid_score.assign(GX, vector<int>(GY, 0));\n    }\n    \n    void build() {\n        for (const auto& p : mackerels) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]++;\n        }\n        for (const auto& p : sardines) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]--;\n        }\n    }\n    \n    Polygon solve() {\n        // Find connected components of positive cells\n        vector<vector<bool>> visited(GX, vector<bool>(GY, false));\n        vector<pair<int, vector<pair<int, int>>>> components;\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (grid_score[x][y] > 0 && !visited[x][y]) {\n                    int comp_score = 0;\n                    vector<pair<int, int>> comp_cells;\n                    queue<pair<int, int>> q;\n                    \n                    q.push({x, y});\n                    visited[x][y] = true;\n                    while(!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        comp_score += grid_score[cx][cy];\n                        comp_cells.push_back({cx, cy});\n                        \n                        // 4-neighbor connectivity\n                        int dx[] = {1, -1, 0, 0};\n                        int dy[] = {0, 0, 1, -1};\n                        for(int k=0; k<4; ++k) {\n                            int nx = cx + dx[k];\n                            int ny = cy + dy[k];\n                            if (nx >= 0 && nx < GX && ny >= 0 && ny < GY && !visited[nx][ny] && grid_score[nx][ny] > 0) {\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    components.push_back({comp_score, comp_cells});\n                }\n            }\n        }\n        \n        if (components.empty()) return {};\n        \n        // Pick the component with the highest score\n        sort(components.rbegin(), components.rend());\n        set<pair<int, int>> selected_cells(components[0].second.begin(), components[0].second.end());\n        \n        return trace_boundary(selected_cells);\n    }\n    \n    // Trace the outer boundary of the set of grid cells\n    Polygon trace_boundary(const set<pair<int, int>>& cells) {\n        if (cells.empty()) return {};\n        \n        // Find starting cell (bottom-leftmost)\n        int start_x = GX + 1, start_y = GY + 1;\n        for(auto p : cells) {\n            if (p.second < start_y || (p.second == start_y && p.x < start_x)) {\n                start_x = p.x;\n                start_y = p.second;\n            }\n        }\n        \n        // Start tracing from the bottom-left corner of the start cell\n        // Movement directions: 0=Right, 1=Up, 2=Left, 3=Down\n        // \"Polygon on Left\" rule (CCW traversal)\n        // We start at Bottom-Left corner of cell (start_x, start_y).\n        // The bottom edge of this cell is boundary because (start_x, start_y-1) is not in set (since we picked min y).\n        // We move Right along the bottom edge.\n        \n        int vx = start_x;\n        int vy = start_y; // Using grid indices as corner coordinates implies (vx, vy) is bottom-left of cell (vx, vy)\n        // Wait, let's define grid coordinates: cell (x, y) spans [x, x+1] x [y, y+1].\n        // Bottom-left corner is (x, y).\n        \n        int dir = 0; // Moving Right (x increasing)\n        vector<pair<int, int>> path;\n        path.push_back({vx, vy});\n        \n        int initial_vx = vx, initial_vy = vy, initial_dir = dir;\n        int steps = 0;\n        \n        auto check = [&](int gx, int gy) {\n            return cells.count({gx, gy});\n        };\n        \n        do {\n            // Determine next direction\n            // We are at vertex (vx, vy). Incoming direction was 'dir'.\n            // We check 4 cells around (vx, vy) to decide where to turn.\n            // Standard Wall Following (Left Hand Rule):\n            // Try to turn Left (relative). If wall exists, turn.\n            // Else try Straight.\n            // Else Turn Right.\n            // Else Turn Back.\n            // \"Wall\" here means the boundary between IN and OUT cells.\n            // We want to keep IN cells on our Left.\n            \n            // Relative directions: \n            // Left turn: (dir + 1) % 4\n            // Straight: dir\n            // Right turn: (dir + 3) % 4\n            // Back: (dir + 2) % 4\n            \n            int next_dir = -1;\n            // Priority: Left -> Straight -> Right -> Back\n            int search_order[] = {(dir + 1) % 4, dir, (dir + 3) % 4, (dir + 2) % 4};\n            \n            for (int nd : search_order) {\n                // Check if moving in 'nd' is a valid boundary with IN cell on Left\n                // Identification of Left/Right cells relative to edge 'nd' starting at (vx, vy)\n                // nd=0 (Right): Left Cell (vx, vy), Right Cell (vx, vy-1)\n                // nd=1 (Up): Left Cell (vx, vy), Right Cell (vx-1, vy) ?? No.\n                // Let's map carefully.\n                // Cell coords relative to vertex (vx, vy):\n                // Q1 (Top-Right): (vx, vy)\n                // Q2 (Top-Left): (vx-1, vy)\n                // Q3 (Bottom-Left): (vx-1, vy-1)\n                // Q4 (Bottom-Right): (vx, vy-1)\n                \n                // Edge 0 (Right): Sep Q1 and Q4. Left is Q1 (vx, vy). Right is Q4 (vx, vy-1).\n                // Edge 1 (Up): Sep Q2 and Q1. Left is Q2 (vx-1, vy). Right is Q1 (vx, vy).\n                // Edge 2 (Left): Sep Q3 and Q2. Left is Q3 (vx-1, vy-1). Right is Q2 (vx-1, vy).\n                // Edge 3 (Down): Sep Q4 and Q3. Left is Q4 (vx, vy-1). Right is Q3 (vx-1, vy-1).\n                \n                pair<int,int> l_c, r_c;\n                if (nd == 0) { l_c = {vx, vy}; r_c = {vx, vy-1}; }\n                else if (nd == 1) { l_c = {vx-1, vy}; r_c = {vx, vy}; }\n                else if (nd == 2) { l_c = {vx-1, vy-1}; r_c = {vx-1, vy}; }\n                else { l_c = {vx, vy-1}; r_c = {vx-1, vy-1}; }\n                \n                if (check(l_c.first, l_c.second) && !check(r_c.first, r_c.second)) {\n                    next_dir = nd;\n                    break;\n                }\n            }\n            \n            if (next_dir == -1) break; // Should not happen on valid boundary\n            \n            dir = next_dir;\n            if (dir == 0) vx++;\n            else if (dir == 1) vy++;\n            else if (dir == 2) vx--;\n            else vy--;\n            \n            path.push_back({vx, vy});\n            steps++;\n            if (steps > 20000) break; // Safety break\n            \n        } while (vx != initial_vx || vy != initial_vy);\n        \n        // Map grid coords back to world coords and simplify collinear\n        Polygon poly;\n        if (path.empty()) return {};\n        \n        // Helper to map grid vertex to point\n        auto get_pt = [&](pair<int,int> p) {\n            int X = p.first * cell_size - offset_x;\n            int Y = p.second * cell_size - offset_y;\n            return Point{clamp(X, 0, MAX_COORD), clamp(Y, 0, MAX_COORD)};\n        };\n        \n        // Simplify path (remove collinear vertices)\n        // path contains the loop of grid vertices.\n        // We iterate and keep only corners.\n        if (path.back() == path[0]) path.pop_back();\n        \n        vector<Point> corners;\n        if (!path.empty()) {\n            // Add first point temporarily\n            corners.push_back(get_pt(path[0]));\n            for(size_t i = 1; i < path.size(); ++i) {\n                Point curr = get_pt(path[i]);\n                Point prev = corners.back();\n                // Check if we extended the last segment or started a new one\n                if (corners.size() >= 2) {\n                    Point pprev = corners[corners.size()-2];\n                    bool prev_horz = (prev.y == pprev.y);\n                    bool curr_horz = (curr.y == prev.y);\n                    if (prev_horz == curr_horz) {\n                        corners.back() = curr; // Extend\n                    } else {\n                        corners.push_back(curr); // Turn\n                    }\n                } else {\n                    corners.push_back(curr);\n                }\n            }\n            \n            // Handle wrap-around collinearity\n            if (corners.size() > 2) {\n                Point first = corners[0];\n                Point last = corners.back();\n                Point prev = corners[corners.size()-2];\n                \n                bool last_seg_horz = (last.y == prev.y);\n                bool first_seg_horz = (corners[1].y == first.y); \n                // Actually we need to check the closing edge (last -> first)\n                // Logic: if edge(prev->last) and edge(last->first) are collinear\n                // AND edge(last->first) and edge(first->second) are collinear -> rare\n                // Just check last->first merge with prev->last\n                bool closing_horz = (first.y == last.y);\n                \n                if (last_seg_horz == closing_horz) {\n                    // Merge last into first? \n                    // If last->first is same dir as prev->last, then 'last' is redundant.\n                    corners.pop_back();\n                    last = corners.back(); // new last\n                }\n                \n                // Now check if (new) last -> first matches first -> second\n                bool closing_horz2 = (first.y == last.y);\n                if (closing_horz2 == first_seg_horz) {\n                    corners.erase(corners.begin());\n                }\n            }\n        }\n        \n        return corners;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = get_time_ms();\n    \n    if (!(cin >> N)) return 0;\n    mackerels.resize(N);\n    for(int i=0; i<N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    sardines.resize(N);\n    for(int i=0; i<N; ++i) cin >> sardines[i].x >> sardines[i].y;\n    \n    Polygon best_poly;\n    int best_score = -1;\n    \n    // Random number generator\n    mt19937 rng(1337);\n    \n    // Try different grid sizes to capture clusters of varying density\n    vector<int> grid_sizes = {4000, 2500, 2000, 1500, 1000, 5000, 800};\n    int iter = 0;\n    \n    while (get_time_ms() - start_time < TIME_LIMIT * 1000) {\n        iter++;\n        int cs = grid_sizes[(iter - 1) % grid_sizes.size()];\n        // Randomize selection after first pass\n        if (iter > (int)grid_sizes.size()) {\n            cs = grid_sizes[rng() % grid_sizes.size()];\n        }\n        \n        // Random offset\n        int ox = rng() % cs;\n        int oy = rng() % cs;\n        \n        GridSolver solver(cs, ox, oy);\n        solver.build();\n        Polygon poly = solver.solve();\n        \n        // Validate constraints\n        if (poly.size() < 4) continue;\n        if (poly.size() > MAX_VERTICES) continue; // Too complex, skip\n        if (perimeter(poly) > MAX_PERIMETER) continue;\n        \n        int current_score = raw_score(poly);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_poly = poly;\n        }\n    }\n    \n    // Output\n    if (best_poly.empty()) {\n        // Fallback: just a tiny square somewhere\n        cout << \"4\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n    } else {\n        cout << best_poly.size() << \"\\n\";\n        for (const auto& p : best_poly) {\n            cout << p.x << \" \" << p.y << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Structures ---\nstruct Op {\n    int p; // index of rect (must be i)\n    int r; // rotation 0: no, 1: yes\n    int d; // direction 0:U, 1:L\n    int b; // base rect index (-1 or 0..i-1)\n};\n\nstruct PlacedRect {\n    int x, y, w, h;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    int W, H;\n    long long score;\n};\n\n// --- Global State ---\nint N, T, sigma_val;\nvector<int> w_prime, h_prime;\nvector<double> w_est, h_est;\nSolution best_global_sol;\nmt19937 rng(12345);\n\n// --- Simulation Function ---\n// Simulates the placement of rectangles based on operations and dimensions.\n// Returns {Width, Height} of the bounding box.\npair<int, int> simulate(const vector<Op>& ops, const vector<double>& ws, const vector<double>& hs, vector<PlacedRect>& out_rects) {\n    out_rects.clear();\n    out_rects.resize(N);\n    \n    int W = 0, H = 0;\n    \n    for (const auto& op : ops) {\n        int i = op.p;\n        // Determine dimensions based on rotation\n        int rw = (int)lround(op.r ? hs[i] : ws[i]);\n        int rh = (int)lround(op.r ? ws[i] : hs[i]);\n        if (rw < 1) rw = 1;\n        if (rh < 1) rh = 1;\n        \n        int x = 0, y = 0;\n        \n        if (op.d == 0) { // U: Moves Upward (decreasing y), stops at bottom of others or y=0.\n            // In our coord system (y increases downwards), this stacks in +y direction starting from y=0 or other rects.\n            // x is determined by reference b\n            if (op.b != -1) {\n                const auto& b_rect = out_rects[op.b];\n                x = b_rect.x + b_rect.w;\n            } else {\n                x = 0;\n            }\n            \n            // y is determined by gravity (stacking on existing rects)\n            y = 0;\n            for (int j = 0; j < i; ++j) {\n                // Check x-interval overlap: [x, x+rw) vs [j.x, j.x+j.w)\n                if (max(x, out_rects[j].x) < min(x + rw, out_rects[j].x + out_rects[j].w)) {\n                    y = max(y, out_rects[j].y + out_rects[j].h);\n                }\n            }\n        } else { // L: Moves Leftward (decreasing x), stops at right of others or x=0.\n            // Stacks in +x direction.\n            // y is determined by reference b\n            if (op.b != -1) {\n                const auto& b_rect = out_rects[op.b];\n                y = b_rect.y + b_rect.h;\n            } else {\n                y = 0;\n            }\n            \n            // x is determined by gravity\n            x = 0;\n            for (int j = 0; j < i; ++j) {\n                // Check y-interval overlap\n                if (max(y, out_rects[j].y) < min(y + rh, out_rects[j].y + out_rects[j].h)) {\n                    x = max(x, out_rects[j].x + out_rects[j].w);\n                }\n            }\n        }\n        \n        out_rects[i] = {x, y, rw, rh};\n        W = max(W, x + rw);\n        H = max(H, y + rh);\n    }\n    return {W, H};\n}\n\n// --- Parameter Update ---\n// Updates w_est and h_est based on observed error and critical paths.\nvoid update_estimates(const vector<Op>& last_ops, int W_obs, int H_obs) {\n    vector<PlacedRect> rects;\n    pair<int, int> dim = simulate(last_ops, w_est, h_est, rects);\n    int W_sim = dim.first;\n    int H_sim = dim.second;\n    \n    int diff_W = W_obs - W_sim;\n    int diff_H = H_obs - H_sim;\n    \n    // Build dependency graph to trace critical paths\n    vector<int> parent_x(N, -1);\n    vector<int> parent_y(N, -1);\n    \n    for (int i = 0; i < N; ++i) {\n        const auto& op = last_ops[i];\n        int rw = rects[i].w;\n        int rh = rects[i].h;\n        \n        if (op.d == 0) { // U\n            parent_x[i] = op.b; // X fixed by reference\n            // Y fixed by collision\n            int best_j = -1;\n            int max_y = 0;\n            for(int j=0; j<i; ++j) {\n                if (max(rects[i].x, rects[j].x) < min(rects[i].x + rw, rects[j].x + rects[j].w)) {\n                    if (rects[j].y + rects[j].h > max_y) {\n                        max_y = rects[j].y + rects[j].h;\n                        best_j = j;\n                    }\n                }\n            }\n            parent_y[i] = best_j;\n        } else { // L\n            parent_y[i] = op.b; // Y fixed by reference\n            // X fixed by collision\n            int best_j = -1;\n            int max_x = 0;\n            for(int j=0; j<i; ++j) {\n                if (max(rects[i].y, rects[j].y) < min(rects[i].y + rh, rects[j].y + rects[j].h)) {\n                    if (rects[j].x + rects[j].w > max_x) {\n                        max_x = rects[j].x + rects[j].w;\n                        best_j = j;\n                    }\n                }\n            }\n            parent_x[i] = best_j;\n        }\n    }\n    \n    // Trace Critical Path for W\n    vector<bool> on_path_W(N, false);\n    vector<int> q;\n    for(int i=0; i<N; ++i) if(rects[i].x + rects[i].w == W_sim) {\n        on_path_W[i] = true;\n        q.push_back(i);\n    }\n    int head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        int p = parent_x[u];\n        if(p != -1 && !on_path_W[p]){\n            on_path_W[p] = true;\n            q.push_back(p);\n        }\n    }\n    \n    // Trace Critical Path for H\n    vector<bool> on_path_H(N, false);\n    q.clear();\n    for(int i=0; i<N; ++i) if(rects[i].y + rects[i].h == H_sim) {\n        on_path_H[i] = true;\n        q.push_back(i);\n    }\n    head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        int p = parent_y[u];\n        if(p != -1 && !on_path_H[p]){\n            on_path_H[p] = true;\n            q.push_back(p);\n        }\n    }\n    \n    int cnt_W = 0; for(bool b : on_path_W) if(b) cnt_W++;\n    int cnt_H = 0; for(bool b : on_path_H) if(b) cnt_H++;\n    \n    // Update rule\n    double lr = 0.15; \n    \n    if (cnt_W > 0) {\n        double delta = (double)diff_W / cnt_W * lr;\n        for(int i=0; i<N; ++i) {\n            if(on_path_W[i]) {\n                if (last_ops[i].r == 0) w_est[i] += delta;\n                else h_est[i] += delta;\n            }\n        }\n    }\n    \n    if (cnt_H > 0) {\n        double delta = (double)diff_H / cnt_H * lr;\n        for(int i=0; i<N; ++i) {\n            if(on_path_H[i]) {\n                if (last_ops[i].r == 0) h_est[i] += delta;\n                else w_est[i] += delta;\n            }\n        }\n    }\n    \n    // Clamp\n    for(auto& v : w_est) if(v < 1) v = 1;\n    for(auto& v : h_est) if(v < 1) v = 1;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> T >> sigma_val)) return 0;\n    \n    w_prime.resize(N);\n    h_prime.resize(N);\n    w_est.resize(N);\n    h_est.resize(N);\n    \n    for(int i=0; i<N; ++i) {\n        cin >> w_prime[i] >> h_prime[i];\n        w_est[i] = w_prime[i];\n        h_est[i] = h_prime[i];\n    }\n    \n    // Initialize random solution\n    Solution curr_sol;\n    curr_sol.ops.resize(N);\n    for(int i=0; i<N; ++i) {\n        curr_sol.ops[i] = {i, (int)(rng()%2), (int)(rng()%2), (int)(rng()%(i+1)) - 1};\n    }\n    \n    vector<PlacedRect> dummy_rects;\n    auto dims = simulate(curr_sol.ops, w_est, h_est, dummy_rects);\n    curr_sol.W = dims.first;\n    curr_sol.H = dims.second;\n    curr_sol.score = curr_sol.W + curr_sol.H;\n    \n    best_global_sol = curr_sol;\n    \n    auto start_time = chrono::steady_clock::now();\n    double total_time_limit = 2.9; // sec\n    \n    for (int t = 0; t < T; ++t) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = total_time_limit - elapsed;\n        double time_for_turn = remaining / (T - t);\n        if (time_for_turn < 0.005) time_for_turn = 0.005; // Minimum 5ms\n        if (time_for_turn > 0.100) time_for_turn = 0.100; // Cap to allow distribution\n        \n        auto turn_start = chrono::steady_clock::now();\n        \n        // Re-evaluate best solution with updated estimates\n        {\n             auto d = simulate(best_global_sol.ops, w_est, h_est, dummy_rects);\n             best_global_sol.W = d.first;\n             best_global_sol.H = d.second;\n             best_global_sol.score = d.first + d.second;\n        }\n        curr_sol = best_global_sol; // Start SA from best known\n        \n        // SA Parameters\n        double T0 = 20000.0; \n        double T1 = 10.0;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 127) == 0) {\n                double turn_elapsed = chrono::duration<double>(chrono::steady_clock::now() - turn_start).count();\n                if (turn_elapsed > time_for_turn) break;\n            }\n            \n            // Perturbation\n            int i = rng() % N;\n            int type = rng() % 3;\n            \n            Op saved = curr_sol.ops[i];\n            \n            if (type == 0) { // Change rotation\n                curr_sol.ops[i].r = 1 - curr_sol.ops[i].r;\n            } else if (type == 1) { // Change direction\n                curr_sol.ops[i].d = 1 - curr_sol.ops[i].d;\n            } else { // Change reference\n                int new_b = (int)(rng() % (i + 1)) - 1;\n                if (new_b == curr_sol.ops[i].b && i > 0) {\n                    // try to force a change\n                    new_b = (new_b + 2) % (i + 1) - 1;\n                }\n                curr_sol.ops[i].b = new_b;\n            }\n            \n            // Evaluate\n            auto res = simulate(curr_sol.ops, w_est, h_est, dummy_rects);\n            long long new_score = res.first + res.second;\n            \n            double delta = new_score - curr_sol.score;\n            \n            // Temperature schedule\n            double turn_elapsed = chrono::duration<double>(chrono::steady_clock::now() - turn_start).count();\n            double progress = turn_elapsed / time_for_turn;\n            double temp = T0 * pow(T1/T0, progress);\n            \n            if (delta <= 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                curr_sol.W = res.first;\n                curr_sol.H = res.second;\n                curr_sol.score = new_score;\n                \n                if (curr_sol.score < best_global_sol.score) {\n                    best_global_sol = curr_sol;\n                }\n            } else {\n                // Revert\n                curr_sol.ops[i] = saved;\n            }\n        }\n        \n        // Output best solution\n        cout << N << \"\\n\"; \n        for(int i=0; i<N; ++i) {\n            const auto& op = best_global_sol.ops[i];\n            char d_char = (op.d == 0) ? 'U' : 'L';\n            cout << op.p << \" \" << op.r << \" \" << d_char << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read feedback\n        int W_obs, H_obs;\n        cin >> W_obs >> H_obs;\n        \n        // Update parameter estimates\n        update_estimates(best_global_sol.ops, W_obs, H_obs);\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Problem Constants\nconst int MAXN = 1005;\nconst int H_LIMIT = 10;\n\n// Global Variables\nint N, M, H_in;\nint A[MAXN];\nvector<int> adj[MAXN]; // Adjacency list of the graph\n\n// State Variables\nint p[MAXN];                // Parent of node i\nvector<int> children[MAXN]; // Children of node i\nint S[MAXN];                // Sum of A values in the subtree rooted at i\nint d_max[MAXN];            // Height of subtree at i (max distance to a descendant)\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// Utility: Get depth of v (0-indexed)\nint get_h(int v) {\n    int h = 0;\n    while (p[v] != -1) {\n        v = p[v];\n        h++;\n    }\n    return h;\n}\n\n// Utility: Check if u is a descendant of v (to prevent cycles)\nbool is_descendant(int u, int v) {\n    if (u == -1) return false;\n    if (u == v) return true;\n    while (u != -1) {\n        if (u == v) return true;\n        u = p[u];\n    }\n    return false;\n}\n\n// Update S and d_max for ancestors of start_node up to root\n// S changes by delta_S. d_max is recomputed.\nvoid update_path_optimized(int start_node, int delta_S) {\n    int curr = start_node;\n    while (curr != -1) {\n        S[curr] += delta_S;\n        \n        int max_d = 0;\n        for (int c : children[curr]) {\n            max_d = max(max_d, d_max[c] + 1);\n        }\n        d_max[curr] = max_d;\n        \n        curr = p[curr];\n    }\n}\n\n// Initialize with all roots\nvoid build_initial() {\n    for (int i = 0; i < N; ++i) {\n        p[i] = -1;\n        children[i].clear();\n        S[i] = A[i];\n        d_max[i] = 0;\n    }\n}\n\n// Greedy initialization\nvoid build_greedy() {\n    build_initial();\n    \n    // Process nodes with lower A first to form the base of trees\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        return A[a] < A[b]; \n    });\n    \n    for (int v : order) {\n        // v is currently a root of some component (since we start with all roots, \n        // and we only link roots to others in a specific way, \n        // but here v might have children already attached to it from previous steps).\n        // However, v itself is a root of its component because we only attach v \n        // when we process v.\n        // We try to attach v to a neighbor u to maximize v's depth.\n        \n        int best_u = -1;\n        int best_h = -1; // -1 represents depth of root parent (which implies v depth 0)\n        \n        // Try neighbors\n        vector<int> candidates = adj[v];\n        // Shuffle to break ties randomly\n        shuffle(candidates.begin(), candidates.end(), rng);\n        \n        for (int u : candidates) {\n            // Check cycle\n            if (is_descendant(u, v)) continue;\n            \n            // Check depth constraints\n            int h_u = get_h(u);\n            if (h_u + 1 + d_max[v] > H_LIMIT) continue;\n            \n            if (h_u > best_h) {\n                best_h = h_u;\n                best_u = u;\n            }\n        }\n        \n        // If we found a valid parent u that gives depth >= 0 (relative to root parent -1)\n        // Actually, h_u is at least 0. So best_h >= 0.\n        // If best_u remains -1, v stays root (depth 0).\n        \n        if (best_u != -1) {\n            // Apply move\n            // v is currently a root, so p[v] == -1.\n            // Just link.\n            p[v] = best_u;\n            children[best_u].push_back(v);\n            update_path_optimized(best_u, S[v]);\n        }\n    }\n}\n\nint main() {\n    // Fast IO\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Input\n    if (!(cin >> N >> M >> H_in)) return 0;\n    for(int i=0; i<N; ++i) cin >> A[i];\n    for(int i=0; i<M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for(int i=0; i<N; ++i) {\n        int x, y;\n        cin >> x >> y; // Coordinates not used logic-wise\n    }\n    \n    // Build initial solution\n    build_greedy();\n    \n    // Simulated Annealing Parameters\n    double time_limit = 1.95;\n    double T_start = 200.0;\n    double T_end = 0.01;\n    \n    long long current_score = 0; // Score calculation delta-based usually, or just for debug\n    // We rely on delta updates and output final structure, no need to track absolute score perfectly in variable if not needed.\n    \n    int iter = 0;\n    \n    // SA Loop\n    while(true) {\n        iter++;\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        \n        // Pick random vertex v\n        int v = rng() % N;\n        \n        // Pick random neighbor or -1\n        int u = -1;\n        if (!adj[v].empty()) {\n            // 1/(deg+1) prob for -1, or just uniform over adj + {-1}\n            int idx = rng() % (adj[v].size() + 1);\n            if (idx < (int)adj[v].size()) u = adj[v][idx];\n        }\n        \n        // Same parent check\n        if (p[v] == u) continue;\n        \n        // Validity Checks\n        // 1. Cycle\n        if (is_descendant(u, v)) continue;\n        \n        // 2. Depth\n        // Calculate new depth of v\n        // If u is -1, new depth is 0.\n        // If u is node, new depth is get_h(u) + 1.\n        int new_depth_v = (u == -1) ? 0 : (get_h(u) + 1);\n        if (new_depth_v + d_max[v] > H_LIMIT) continue;\n        \n        // Calculate Score Delta\n        // Gain = (new_depth - old_depth) * S[v]\n        int old_depth_v = (p[v] == -1) ? 0 : (get_h(p[v]) + 1);\n        long long diff = (long long)(new_depth_v - old_depth_v) * S[v];\n        \n        // Metropolis Acceptance\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            double progress = elapsed / time_limit;\n            double T = T_start * pow(T_end / T_start, progress);\n            double prob = exp(diff / T);\n            if (generate_canonical<double, 10>(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            int old_p = p[v];\n            \n            // Remove from old parent\n            if (old_p != -1) {\n                // Find and remove v from children[old_p]\n                auto& ch = children[old_p];\n                for (size_t k = 0; k < ch.size(); ++k) {\n                    if (ch[k] == v) {\n                        ch.erase(ch.begin() + k);\n                        break;\n                    }\n                }\n                // Update ancestors of old_p\n                update_path_optimized(old_p, -S[v]);\n            }\n            \n            // Set new parent\n            p[v] = u;\n            \n            // Add to new parent\n            if (u != -1) {\n                children[u].push_back(v);\n                // Update ancestors of u\n                update_path_optimized(u, S[v]);\n            }\n        }\n    }\n    \n    // Output result\n    for(int i=0; i<N; ++i) {\n        cout << p[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <array>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_OPS = 4 * N * N; // 1600\nconst int INF = 1e9;\n\n// Directions: 0: L, 1: R, 2: U, 3: D\nconst char DIR_CHARS[] = {'L', 'R', 'U', 'D'};\n\nstruct Move {\n    char d;\n    int p; // row or column index\n};\n\nstruct State {\n    array<string, N> board;\n    vector<Move> history;\n    int score; // Heuristic score (lower is better)\n    int cost;  // Number of moves so far\n    int removed_oni; // Number of Oni removed\n\n    // For sorting in priority queue or sort function\n    bool operator>(const State& other) const {\n        return score > other.score;\n    }\n};\n\n// Helper to calculate distance to edge for a specific cell and direction\n// Returns -1 if blocked by 'o'\nint get_dist(const array<string, N>& board, int r, int c, int dir) {\n    if (dir == 0) { // L\n        for (int k = 0; k < c; ++k) if (board[r][k] == 'o') return -1;\n        return c + 1;\n    } else if (dir == 1) { // R\n        for (int k = c + 1; k < N; ++k) if (board[r][k] == 'o') return -1;\n        return N - c;\n    } else if (dir == 2) { // U\n        for (int k = 0; k < r; ++k) if (board[k][c] == 'o') return -1;\n        return r + 1;\n    } else { // D\n        for (int k = r + 1; k < N; ++k) if (board[k][c] == 'o') return -1;\n        return N - r;\n    }\n}\n\n// Calculate heuristic score\n// Heuristic = Sum of min_dist for all remaining Oni + Penalties\nint calculate_heuristic(const array<string, N>& board) {\n    int total_dist = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 'x') {\n                int min_d = INF;\n                int blocked_cnt = 0;\n                for (int d = 0; d < 4; ++d) {\n                    int dist = get_dist(board, r, c, d);\n                    if (dist != -1) {\n                        if (dist < min_d) min_d = dist;\n                    } else {\n                        blocked_cnt++;\n                    }\n                }\n                if (min_d == INF) {\n                    total_dist += 200; // Heavy penalty if blocked in all directions\n                } else {\n                    total_dist += min_d;\n                }\n                total_dist += blocked_cnt * 2; // Penalty for reduced options\n            }\n        }\n    }\n    return total_dist;\n}\n\n// Apply shift to the board\nvoid apply_shift(array<string, N>& board, int type, int idx) {\n    if (type == 0) { // L\n        for (int j = 0; j < N - 1; ++j) board[idx][j] = board[idx][j+1];\n        board[idx][N-1] = '.';\n    } else if (type == 1) { // R\n        for (int j = N - 1; j > 0; --j) board[idx][j] = board[idx][j-1];\n        board[idx][0] = '.';\n    } else if (type == 2) { // U\n        for (int i = 0; i < N - 1; ++i) board[i][idx] = board[i+1][idx];\n        board[N-1][idx] = '.';\n    } else { // D\n        for (int i = N - 1; i > 0; --i) board[i][idx] = board[i-1][idx];\n        board[0][idx] = '.';\n    }\n}\n\n// Count Oni on the board\nint count_oni(const array<string, N>& board) {\n    int c = 0;\n    for (const auto& row : board) \n        for (char ch : row) if (ch == 'x') c++;\n    return c;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    if (cin >> n_dummy) {} \n\n    State initial_state;\n    initial_state.cost = 0;\n    for (int i = 0; i < N; ++i) cin >> initial_state.board[i];\n    \n    int initial_total_oni = count_oni(initial_state.board);\n    initial_state.removed_oni = 0; \n    initial_state.score = calculate_heuristic(initial_state.board);\n\n    // Beam search organized by number of removed Oni\n    // beams[k] holds states with k Oni removed\n    vector<vector<State>> beams(2 * N + 1);\n    beams[0].push_back(initial_state);\n\n    int BEAM_WIDTH = 30; \n\n    // Iterate through progress levels\n    for (int k = 0; k < initial_total_oni; ++k) {\n        if (beams[k].empty()) continue;\n        \n        // Sort by score (lower is better) and keep top BEAM_WIDTH\n        sort(beams[k].begin(), beams[k].end(), [](const State& a, const State& b){\n            return a.score < b.score;\n        });\n        if (beams[k].size() > BEAM_WIDTH) {\n            beams[k].resize(BEAM_WIDTH);\n        }\n        \n        for (const auto& state : beams[k]) {\n            // Try all directions and lines\n            for (int dir = 0; dir < 4; ++dir) {\n                for (int line = 0; line < N; ++line) {\n                    // Calculate safe shift limit\n                    int max_safe = 0;\n                    int first_fuku = -1;\n                    \n                    if (dir == 0) { // L\n                        for(int c=0; c<N; ++c) if(state.board[line][c] == 'o') { first_fuku = c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=0; --c) if(state.board[line][c] == 'o') { first_fuku = (N-1)-c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<N; ++r) if(state.board[r][line] == 'o') { first_fuku = r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else { // D\n                        for(int r=N-1; r>=0; --r) if(state.board[r][line] == 'o') { first_fuku = (N-1)-r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    }\n                    \n                    if (max_safe == 0) continue;\n                    \n                    // Identify Oni positions that can be removed\n                    vector<int> oni_shifts;\n                    if (dir == 0) { // L\n                        for(int c=0; c<max_safe; ++c) if(state.board[line][c] == 'x') oni_shifts.push_back(c + 1);\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=N-max_safe; --c) if(state.board[line][c] == 'x') oni_shifts.push_back((N-1)-c + 1);\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<max_safe; ++r) if(state.board[r][line] == 'x') oni_shifts.push_back(r + 1);\n                    } else { // D\n                        for(int r=N-1; r>=N-max_safe; --r) if(state.board[r][line] == 'x') oni_shifts.push_back((N-1)-r + 1);\n                    }\n                    \n                    if (oni_shifts.empty()) continue;\n\n                    // Only consider:\n                    // 1. Shift to remove the FIRST Oni (minimal progress)\n                    // 2. Shift to remove the LAST safe Oni (maximal progress in this line)\n                    vector<int> candidates;\n                    candidates.push_back(oni_shifts[0]);\n                    if (oni_shifts.back() != oni_shifts[0]) {\n                        candidates.push_back(oni_shifts.back());\n                    }\n\n                    for (int shift_amt : candidates) {\n                        // Option 1: Eject (Permanent Change)\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            next_state.cost += shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                        \n                        // Option 2: Eject & Restore (Safe fallback)\n                        // Costs 2x but preserves board structure\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            int opp_dir = (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? 3 : 2;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, opp_dir, line);\n                                next_state.history.push_back({DIR_CHARS[opp_dir], line});\n                            }\n                            next_state.cost += 2 * shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Select best solution from states that removed all Oni\n    int final_idx = initial_total_oni;\n    // Fallback to best available if full solution not found\n    while (final_idx >= 0 && beams[final_idx].empty()) {\n        final_idx--;\n    }\n    \n    State* best = nullptr;\n    if (final_idx >= 0) {\n        for (auto& s : beams[final_idx]) {\n            if (!best || s.cost < best->cost) {\n                best = &s;\n            }\n        }\n    }\n    \n    if (best) {\n        for (const auto& mv : best->history) {\n            cout << mv.d << \" \" << mv.p << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <queue>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L_TOTAL = 500000;\n\nint T[N];\nint A[N], B[N];\nint best_A[N], best_B[N];\n\n// Simulation variables\nint counts_sim[N];\n\n// Function to run the simulation\n// Returns the sum of absolute errors\nlong long simulate(int steps, const vector<int>& targets, int* counts_out) {\n    // Reset counts\n    for(int i=0; i<N; ++i) counts_out[i] = 0;\n    \n    int curr = 0;\n    counts_out[0]++;\n    \n    // Simulate step by step\n    for (int k = 1; k < steps; ++k) {\n        int prev = curr;\n        // Get the number of times prev had cleaned by the end of last week\n        int t = counts_out[prev];\n        if (t & 1) { // odd\n            curr = A[prev];\n        } else { // even\n            curr = B[prev];\n        }\n        counts_out[curr]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts_out[i] - targets[i]);\n    }\n    return error;\n}\n\nstruct Plug {\n    int u;\n    int type; // 0 for A, 1 for B\n    int size; // Estimated flow\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, l_in;\n    if (cin >> n_in >> l_in) {} // Read N and L\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // --- Initial Construction Phase ---\n    // Use a greedy bin-packing strategy to assign A[i] and B[i]\n    // such that the expected inflow to each node j matches T[j].\n    \n    vector<Plug> plugs;\n    for (int i = 0; i < N; ++i) {\n        // If T[i] > 0, this employee will clean and thus trigger a transition.\n        // The transitions alternate between A[i] (odd visits) and B[i] (even visits).\n        // Number of odd visits is ceil(T[i]/2), even is floor(T[i]/2).\n        if (T[i] > 0) {\n            plugs.push_back({i, 0, (T[i] + 1) / 2});\n            if (T[i] > 1) plugs.push_back({i, 1, T[i] / 2});\n        }\n    }\n    \n    // Sort plugs descending by size to fit largest flow requirements first\n    sort(plugs.begin(), plugs.end(), [](const Plug& a, const Plug& b){\n        return a.size > b.size;\n    });\n    \n    // Priority Queue for sockets (nodes receiving flow)\n    // Stores {remaining_capacity, node_index}\n    // Start node 0 has 1 automatic visit, so its capacity for incoming edges is T[0] - 1.\n    priority_queue<pair<int, int>> pq;\n    for (int i = 0; i < N; ++i) {\n        int cap = T[i];\n        if (i == 0) cap = max(0, cap - 1);\n        // Only consider nodes that are expected to be visited\n        if (cap > 0 || (i == 0 && T[0] > 0)) pq.push({cap, i});\n    }\n    \n    // Initialize A and B to valid values (defaults)\n    for(int i=0; i<N; ++i) { \n        A[i] = (i + 1) % N; \n        B[i] = (i + 1) % N; \n    }\n\n    // Assign plugs to sockets\n    for (const auto& p : plugs) {\n        int target = 0;\n        if (!pq.empty()) {\n            auto top = pq.top();\n            pq.pop();\n            target = top.second;\n            // Decrease capacity\n            int rem = top.first - p.size;\n            // Push back with updated capacity. \n            // We allow negative capacity (overflow) to handle total flow matching.\n            pq.push({rem, target}); \n        } else {\n            target = rand() % N;\n        }\n        \n        if (p.type == 0) A[p.u] = target;\n        else B[p.u] = target;\n    }\n    \n    // Save initial solution\n    copy(begin(A), end(A), begin(best_A));\n    copy(begin(B), end(B), begin(best_B));\n    \n    // --- Optimization Phase ---\n    // Use Simulated Annealing / Hill Climbing to minimize error.\n    // We gradually increase the simulation length from a small value to L_TOTAL.\n    \n    mt19937 rng(12345);\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.90; // Slightly less than 2.0s\n    \n    int current_L = 10000; // Start with shorter simulation\n    vector<int> current_T(N);\n    \n    long long current_score = -1;\n    long long global_best_score_full = -1; \n\n    double temp = 150.0; // Initial temperature\n    bool counts_valid = false; // Tracks if counts_sim matches current A/B\n    \n    while (true) {\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        double progress = elapsed.count() / time_limit;\n        \n        // Adaptive Simulation Length\n        int next_L;\n        if (progress < 0.35) next_L = 20000;\n        else if (progress < 0.65) next_L = 100000;\n        else next_L = L_TOTAL;\n        \n        bool l_changed = (next_L != current_L);\n        if (l_changed || current_score == -1) {\n            current_L = next_L;\n            // Scale target counts T for the current length\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                current_T[i] = (long long)T[i] * current_L / L_TOTAL;\n                sum += current_T[i];\n            }\n            // Adjust rounding errors to ensure sum equals current_L\n            while(sum < current_L) {\n                int idx = rng() % N;\n                if (T[idx] > 0) { current_T[idx]++; sum++; }\n            }\n            while(sum > current_L) {\n                int idx = rng() % N;\n                if (current_T[idx] > 0) { current_T[idx]--; sum--; }\n            }\n            // Re-evaluate current configuration with new length\n            current_score = simulate(current_L, current_T, counts_sim);\n            counts_valid = true;\n        }\n        \n        // Temperature decay\n        double cur_temp = temp * (1.0 - progress) * (1.0 - progress);\n        if (cur_temp < 0.5) cur_temp = 0.5;\n        \n        // Generate Move\n        // We store undo information to revert if rejected\n        vector<tuple<int, int, int>> undo;\n        \n        // Move Types:\n        // 1. Directed Redirect: Move a plug from a surplus node to a deficit node.\n        // 2. Swap: Swap destinations of two plugs.\n        // 3. Random Redirect: Randomly change a plug's destination.\n        \n        int move_type = rng() % 100;\n        bool directed_possible = false;\n\n        if (move_type < 65 && counts_valid) { \n            // Directed Redirect Strategy\n            vector<int> sur, def;\n            for(int i=0; i<N; ++i) {\n                if (counts_sim[i] > current_T[i]) sur.push_back(i);\n                if (counts_sim[i] < current_T[i]) def.push_back(i);\n            }\n            \n            if (!sur.empty() && !def.empty()) {\n                int v = def[rng() % def.size()]; // Target (Deficit)\n                int u = sur[rng() % sur.size()]; // Source (Surplus)\n                \n                // Find plugs pointing to u\n                vector<pair<int,int>> candidates;\n                for(int i=0; i<N; ++i) {\n                    if (A[i] == u) candidates.push_back({i, 0});\n                    if (B[i] == u) candidates.push_back({i, 1});\n                }\n                \n                if (!candidates.empty()) {\n                    auto cand = candidates[rng() % candidates.size()];\n                    int node = cand.first;\n                    int type = cand.second;\n                    int old_val = (type==0 ? A[node] : B[node]);\n                    \n                    // Don't move if already pointing to v\n                    if (old_val != v) {\n                        undo.emplace_back(node, type, old_val);\n                        if (type==0) A[node] = v; else B[node] = v;\n                        directed_possible = true;\n                    }\n                }\n            }\n        } \n        \n        if (!directed_possible) {\n            if (move_type < 85) { // Swap Move\n                int u1 = rng() % N; int t1 = rng() % 2;\n                int u2 = rng() % N; int t2 = rng() % 2;\n                int v1 = (t1==0 ? A[u1] : B[u1]);\n                int v2 = (t2==0 ? A[u2] : B[u2]);\n                if (v1 != v2) {\n                    undo.emplace_back(u1, t1, v1);\n                    undo.emplace_back(u2, t2, v2);\n                    if (t1==0) A[u1] = v2; else B[u1] = v2;\n                    if (t2==0) A[u2] = v1; else B[u2] = v1;\n                }\n            } else { // Random Redirect Move\n                int u = rng() % N;\n                int t = rng() % 2;\n                int v = rng() % N;\n                int old = (t==0 ? A[u] : B[u]);\n                if (old != v) {\n                    undo.emplace_back(u, t, old);\n                    if (t==0) A[u] = v; else B[u] = v;\n                }\n            }\n        }\n        \n        if (undo.empty()) continue;\n        \n        // Evaluate\n        long long new_score = simulate(current_L, current_T, counts_sim);\n        long long delta = new_score - current_score;\n        \n        // Acceptance Criteria\n        bool accept = false;\n        if (delta <= 0) accept = true;\n        else {\n             if (generate_canonical<double, 10>(rng) < exp(-delta/cur_temp)) accept = true;\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            counts_valid = true; // counts_sim is valid for current A/B\n            \n            // Update global best if we are simulating the full problem\n            if (current_L == L_TOTAL) {\n                if (global_best_score_full == -1 || current_score < global_best_score_full) {\n                    global_best_score_full = current_score;\n                    copy(begin(A), end(A), begin(best_A));\n                    copy(begin(B), end(B), begin(best_B));\n                }\n            } else {\n                // Keep track of the best configuration found so far\n                copy(begin(A), end(A), begin(best_A));\n                copy(begin(B), end(B), begin(best_B));\n            }\n        } else {\n            // Revert changes\n            for (auto it = undo.rbegin(); it != undo.rend(); ++it) {\n                auto [u, t, v] = *it;\n                if (t==0) A[u] = v; else B[u] = v;\n            }\n            // counts_sim contains counts from the rejected simulation.\n            // It is invalid for the current (reverted) state.\n            counts_valid = false;\n        }\n    }\n\n    // Output the best solution found\n    for (int i = 0; i < N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <set>\n\n// AC Library DSU implementation\nstruct DSU {\n    std::vector<int> parent_or_size;\n    DSU(int n) : parent_or_size(n, -1) {}\n    int leader(int a) {\n        if (parent_or_size[a] < 0) return a;\n        return parent_or_size[a] = leader(parent_or_size[a]);\n    }\n    bool same(int a, int b) {\n        return leader(a) == leader(b);\n    }\n    bool merge(int a, int b) {\n        int x = leader(a), y = leader(b);\n        if (x == y) return false;\n        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);\n        parent_or_size[x] += parent_or_size[y];\n        parent_or_size[y] = x;\n        return true;\n    }\n    int size(int a) {\n        return -parent_or_size[leader(a)];\n    }\n};\n\n// Global variables\nint N, M, Q, L, W;\nstd::vector<int> G;\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    int x, y; // estimated center\n};\nstd::vector<City> cities;\nstd::vector<std::pair<int, int>> queries_edges;\nstd::vector<std::vector<int>> groups;\n\n// Time management\nauto start_time = std::chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = std::chrono::high_resolution_clock::now();\n    return std::chrono::duration<double>(now - start_time).count();\n}\n\n// Geometry\nlong long dist_sq(int i, int j) {\n    long long dx = cities[i].x - cities[j].x;\n    long long dy = cities[i].y - cities[j].y;\n    return dx * dx + dy * dy;\n}\n\n// Hilbert Curve for spatial sorting\nlong long hilbert(int x, int y, int pow, int rotate) {\n    if (pow == 0) return 0;\n    int hpow = 1 << (pow - 1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rotate) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rotate + rotateDelta[seg]) & 3;\n    long long subSquareSize = 1LL << (2 * pow - 2);\n    long long ans = seg * subSquareSize;\n    long long add = hilbert(nx, ny, pow - 1, nrot);\n    ans += (seg == 1 || seg == 2) ? add : (subSquareSize - 1 - add);\n    return ans;\n}\n\n// MST Cost Calculator (Prim's Algorithm)\nlong long compute_mst_cost(const std::vector<int>& group_cities) {\n    if (group_cities.size() <= 1) return 0;\n    int k = group_cities.size();\n    std::vector<long long> min_dist(k, 2e18); \n    std::vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    long long total_weight = 0;\n    \n    for (int i = 0; i < k; ++i) {\n        int u = -1;\n        long long current_min = 3e18;\n        for (int j = 0; j < k; ++j) {\n            if (!visited[j] && min_dist[j] < current_min) {\n                current_min = min_dist[j];\n                u = j;\n            }\n        }\n        if (u == -1) break;\n        visited[u] = true;\n        total_weight += current_min;\n        \n        int city_u = group_cities[u];\n        for (int v = 0; v < k; ++v) {\n            if (!visited[v]) {\n                long long d = dist_sq(city_u, group_cities[v]);\n                if (d < min_dist[v]) {\n                    min_dist[v] = d;\n                }\n            }\n        }\n    }\n    // Since we want sum of sqrt(dist), but we optimized using squared dist in SA? \n    // Actually for SA, using sum of distances (approx MST) is better.\n    // MST on squared distances is not the same as MST on distances.\n    // However, for local clustering, squared distance penalizes long edges more, which is good.\n    // But to be precise, we should take sqrt. \n    // Re-eval: let's use sqrt for cost to match the objective.\n    // Performance hit: sqrt is slightly slower, but for 800 nodes it's fine.\n    // Wait, the `total_weight` above sums squared distances.\n    // Let's modify to sum sqrt.\n    \n    // Re-implement loop to be safe with sqrt if performance allows.\n    // With 800 nodes, sqrt is cheap enough.\n    return total_weight; \n}\n\n// Correct MST cost with sqrt for SA\nlong long compute_mst_cost_sqrt(const std::vector<int>& group_cities) {\n    if (group_cities.size() <= 1) return 0;\n    int k = group_cities.size();\n    std::vector<long long> min_dist(k, 4e18); // Squared dist\n    std::vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    double total_weight = 0;\n    \n    for (int i = 0; i < k; ++i) {\n        int u = -1;\n        long long current_min = 4e18;\n        for (int j = 0; j < k; ++j) {\n            if (!visited[j] && min_dist[j] < current_min) {\n                current_min = min_dist[j];\n                u = j;\n            }\n        }\n        if (u == -1) break;\n        visited[u] = true;\n        if (i > 0) total_weight += std::sqrt(current_min); // Add sqrt of squared dist\n        \n        int city_u = group_cities[u];\n        for (int v = 0; v < k; ++v) {\n            if (!visited[v]) {\n                long long d = dist_sq(city_u, group_cities[v]);\n                if (d < min_dist[v]) {\n                    min_dist[v] = d;\n                }\n            }\n        }\n    }\n    return (long long)total_weight;\n}\n\n// Get MST edges (on estimated coords)\nstd::vector<std::pair<int, int>> get_mst_edges(const std::vector<int>& group_cities) {\n    if (group_cities.empty()) return {};\n    if (group_cities.size() == 1) return {};\n    \n    int k = group_cities.size();\n    std::vector<long long> min_dist(k, 4e18);\n    std::vector<int> parent(k, -1);\n    std::vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    \n    for (int i = 0; i < k; ++i) {\n        int u = -1;\n        long long current_min = 4e18;\n        for (int j = 0; j < k; ++j) {\n            if (!visited[j] && min_dist[j] < current_min) {\n                current_min = min_dist[j];\n                u = j;\n            }\n        }\n        if (u == -1) break;\n        visited[u] = true;\n        \n        int city_u = group_cities[u];\n        for (int v = 0; v < k; ++v) {\n            if (!visited[v]) {\n                long long d = dist_sq(city_u, group_cities[v]);\n                if (d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    \n    std::vector<std::pair<int, int>> edges;\n    for (int i = 1; i < k; ++i) {\n        if (parent[i] != -1) {\n            edges.push_back({group_cities[i], group_cities[parent[i]]});\n        }\n    }\n    return edges;\n}\n\n// Query generation globals\nstd::vector<int> rem_nodes;\nstd::vector<std::vector<int>> planned_queries;\nstd::vector<std::vector<int>> adj;\n\nvoid dfs_query(int u, int p) {\n    int current_subtree_start = rem_nodes.size();\n    for (int v : adj[u]) {\n        if (v == p) continue;\n        dfs_query(v, u);\n    }\n    rem_nodes.push_back(u);\n    \n    int count = rem_nodes.size() - current_subtree_start;\n    // While we have enough nodes to fill a query of size L (including u)\n    // We take L-1 children + u.\n    while (count >= L) {\n        std::vector<int> query_set;\n        query_set.push_back(u);\n        for (int i = 0; i < L - 1; ++i) {\n            query_set.push_back(rem_nodes[current_subtree_start]);\n            rem_nodes.erase(rem_nodes.begin() + current_subtree_start);\n        }\n        planned_queries.push_back(query_set);\n        count -= (L - 1);\n    }\n}\n\nint main() {\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    if (!(std::cin >> N >> M >> Q >> L >> W)) return 0;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) std::cin >> G[i];\n    \n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        std::cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].x = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].y = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    // Initial Grouping: Hilbert Sort\n    std::vector<int> p(N);\n    std::iota(p.begin(), p.end(), 0);\n    std::sort(p.begin(), p.end(), [&](int i, int j) {\n        return hilbert(cities[i].x, cities[i].y, 14, 0) < hilbert(cities[j].x, cities[j].y, 14, 0);\n    });\n\n    groups.resize(M);\n    std::vector<int> city_to_group(N);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int k = 0; k < G[i]; ++k) {\n            groups[i].push_back(p[current_idx]);\n            city_to_group[p[current_idx]] = i;\n            current_idx++;\n        }\n    }\n\n    // Simulated Annealing\n    std::mt19937 rng(42);\n    double time_limit = 0.8; // 0.8s for grouping\n    \n    // Initial costs\n    std::vector<long long> group_costs(M);\n    long long total_cost = 0;\n    for(int i=0; i<M; ++i) {\n        group_costs[i] = compute_mst_cost_sqrt(groups[i]);\n        total_cost += group_costs[i];\n    }\n\n    int iter = 0;\n    double start_temp = 500.0; \n    double end_temp = 0.1;\n    \n    while (true) {\n        iter++;\n        if ((iter & 127) == 0) {\n            double t = get_time();\n            if (t > time_limit) break;\n        }\n        \n        int g1 = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        int g2 = std::uniform_int_distribution<int>(0, M - 1)(rng);\n        if (g1 == g2) continue;\n        if (groups[g1].empty() || groups[g2].empty()) continue;\n\n        int idx1 = std::uniform_int_distribution<int>(0, groups[g1].size() - 1)(rng);\n        int idx2 = std::uniform_int_distribution<int>(0, groups[g2].size() - 1)(rng);\n        \n        int u = groups[g1][idx1];\n        int v = groups[g2][idx2];\n\n        // Swap\n        std::swap(groups[g1][idx1], groups[g2][idx2]);\n        long long new_cost_g1 = compute_mst_cost_sqrt(groups[g1]);\n        long long new_cost_g2 = compute_mst_cost_sqrt(groups[g2]);\n        \n        long long diff = (new_cost_g1 + new_cost_g2) - (group_costs[g1] + group_costs[g2]);\n        \n        double temp = start_temp + (end_temp - start_temp) * (get_time() / time_limit);\n        bool accept = false;\n        if (diff < 0) accept = true;\n        else if (std::bernoulli_distribution(std::exp(-diff / temp))(rng)) accept = true;\n        \n        if (accept) {\n            total_cost += diff;\n            group_costs[g1] = new_cost_g1;\n            group_costs[g2] = new_cost_g2;\n            city_to_group[u] = g2;\n            city_to_group[v] = g1;\n        } else {\n            std::swap(groups[g1][idx1], groups[g2][idx2]); // Revert\n        }\n    }\n\n    // Phase 2: Query Planning\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if ((int)groups[i].size() <= L) {\n            planned_queries.push_back(groups[i]);\n            continue;\n        }\n\n        std::vector<std::pair<int, int>> mst = get_mst_edges(groups[i]);\n        adj.assign(N, {});\n        for (auto& e : mst) {\n            adj[e.first].push_back(e.second);\n            adj[e.second].push_back(e.first);\n        }\n        \n        rem_nodes.clear();\n        dfs_query(groups[i][0], -1);\n        \n        if (rem_nodes.size() > 1) {\n             if ((int)rem_nodes.size() <= L) {\n                 planned_queries.push_back(rem_nodes);\n             } else {\n                 while((int)rem_nodes.size() > L) {\n                     std::vector<int> q;\n                     for(int k=0; k<L; ++k) q.push_back(rem_nodes[k]);\n                     planned_queries.push_back(q);\n                     rem_nodes.erase(rem_nodes.begin(), rem_nodes.begin() + L - 1);\n                 }\n                 if(rem_nodes.size() > 1) planned_queries.push_back(rem_nodes);\n             }\n        }\n    }\n    \n    // Execute Queries\n    std::shuffle(planned_queries.begin(), planned_queries.end(), rng);\n    int queries_taken = std::min((int)planned_queries.size(), Q);\n    \n    std::vector<std::vector<std::pair<int, int>>> confirmed_edges(M);\n    \n    for (int i = 0; i < queries_taken; ++i) {\n        auto& q_cities = planned_queries[i];\n        std::cout << \"? \" << q_cities.size();\n        for (int c : q_cities) std::cout << \" \" << c;\n        std::cout << std::endl; // flush\n        \n        for (size_t k = 0; k < q_cities.size() - 1; ++k) {\n            int u, v;\n            std::cin >> u >> v;\n            confirmed_edges[city_to_group[u]].push_back({u, v});\n        }\n    }\n    \n    // Final Output\n    std::cout << \"!\" << std::endl;\n    for (int i = 0; i < M; ++i) {\n        for (size_t k = 0; k < groups[i].size(); ++k) {\n            std::cout << groups[i][k] << (k == groups[i].size() - 1 ? \"\" : \" \");\n        }\n        std::cout << \"\\n\";\n        \n        DSU dsu(N); \n        std::vector<std::pair<int, int>> roads;\n        \n        // 1. Use confirmed edges\n        for (auto& e : confirmed_edges[i]) {\n            if (dsu.merge(e.first, e.second)) {\n                roads.push_back(e);\n            }\n        }\n        \n        // 2. If not fully connected, fill with estimated MST edges\n        if ((int)roads.size() < G[i] - 1) {\n            std::vector<std::pair<int, int>> mst = get_mst_edges(groups[i]);\n            for (auto& e : mst) {\n                if (dsu.merge(e.first, e.second)) {\n                    roads.push_back(e);\n                    if ((int)roads.size() == G[i] - 1) break;\n                }\n            }\n        }\n        \n        for (auto& e : roads) {\n            std::cout << e.first << \" \" << e.second << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <map>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const { return tie(r, c) < tie(other.r, other.c); }\n};\n\nstruct State {\n    int dist;\n    int r, c;\n    bool operator>(const State& other) const { return dist > other.dist; }\n};\n\nstruct Action {\n    char type; // 'M', 'S', 'A'\n    char dir;  // 'U', 'D', 'L', 'R'\n};\n\nPoint start_pos;\nbool grid[N][N]; // true if block present\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_chars[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Simulate sliding from (r, c) in direction d\nPoint get_slide_end(int r, int c, int d, const bool current_grid[N][N]) {\n    int cr = r, cc = c;\n    while (true) {\n        int nr = cr + dr[d];\n        int nc = cc + dc[d];\n        if (!is_valid(nr, nc) || current_grid[nr][nc]) {\n            return {cr, cc};\n        }\n        cr = nr;\n        cc = nc;\n    }\n}\n\nstruct Node {\n    int dist = 1e9;\n    Point parent = {-1, -1};\n    Action action = {' ', ' '};\n    bool break_block = false; // If true, action was Move into block (breaking it)\n};\n\n// Run Dijkstra from start_p with current grid\nvoid run_dijkstra(Point start_p, const bool current_grid[N][N], Node nodes[N][N]) {\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) nodes[i][j] = Node();\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    nodes[start_p.r][start_p.c].dist = 0;\n    pq.push({0, start_p.r, start_p.c});\n\n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        int r = top.r;\n        int c = top.c;\n        int d = top.dist;\n\n        if (d > nodes[r][c].dist) continue;\n\n        // Moves & Breaks\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k];\n            int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int cost = 1;\n                bool is_break = false;\n                if (current_grid[nr][nc]) {\n                    cost = 2;\n                    is_break = true;\n                }\n                if (nodes[nr][nc].dist > d + cost) {\n                    nodes[nr][nc].dist = d + cost;\n                    nodes[nr][nc].parent = {r, c};\n                    nodes[nr][nc].action = {'M', dir_chars[k]};\n                    nodes[nr][nc].break_block = is_break;\n                    pq.push({nodes[nr][nc].dist, nr, nc});\n                }\n            }\n        }\n\n        // Slides\n        for (int k = 0; k < 4; ++k) {\n            Point end_p = get_slide_end(r, c, k, current_grid);\n            if (end_p.r != r || end_p.c != c) {\n                if (nodes[end_p.r][end_p.c].dist > d + 1) {\n                    nodes[end_p.r][end_p.c].dist = d + 1;\n                    nodes[end_p.r][end_p.c].parent = {r, c};\n                    nodes[end_p.r][end_p.c].action = {'S', dir_chars[k]};\n                    nodes[end_p.r][end_p.c].break_block = false;\n                    pq.push({nodes[end_p.r][end_p.c].dist, end_p.r, end_p.c});\n                }\n            }\n        }\n    }\n}\n\nvector<Action> reconstruct_path(Point start_p, Point end_p, Node nodes[N][N], vector<Point>& path_points) {\n    vector<Action> path;\n    Point cur = end_p;\n    while (cur != start_p) {\n        Node& n = nodes[cur.r][cur.c];\n        path_points.push_back(cur);\n        if (n.break_block) {\n            path.push_back({'M', n.action.dir});\n            path.push_back({'A', n.action.dir});\n        } else {\n            path.push_back(n.action);\n        }\n        cur = n.parent;\n    }\n    path_points.push_back(start_p);\n    reverse(path.begin(), path.end());\n    reverse(path_points.begin(), path_points.end());\n    return path;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int _n, _m;\n    if (!(cin >> _n >> _m)) return 0;\n    \n    cin >> start_pos.r >> start_pos.c;\n    \n    vector<Point> all_points(M);\n    all_points[0] = start_pos;\n    for(int k=1; k<M; ++k) {\n        cin >> all_points[k].r >> all_points[k].c;\n    }\n\n    for(int i=0; i<N; ++i) fill(grid[i], grid[i]+N, false);\n\n    Point current_pos = start_pos;\n    \n    vector<pair<char, char>> final_actions;\n\n    for (int k = 1; k < M; ++k) {\n        Point target = all_points[k];\n        \n        // 1. Standard Dijkstra\n        static Node nodes_std[N][N];\n        run_dijkstra(current_pos, grid, nodes_std);\n        \n        int best_cost = nodes_std[target.r][target.c].dist;\n        bool use_helper = false;\n        \n        Point best_helper_B = {-1, -1};\n        Point best_helper_NB = {-1, -1};\n        Point best_helper_L = {-1, -1};\n        Node nodes_helper[N][N];\n        \n        // 2. Helper Block Strategy\n        // Try to place a block at neighbor B of Target to enable sliding\n        for (int d = 0; d < 4; ++d) {\n            int br = target.r + dr[d];\n            int bc = target.c + dc[d];\n            \n            if (!is_valid(br, bc)) continue;\n            if (grid[br][bc]) continue; \n            \n            Point B = {br, bc};\n            \n            // Need to reach a neighbor of B to place it\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int nbr = br + dr[d2];\n                int nbc = bc + dc[d2];\n                if (!is_valid(nbr, nbc)) continue;\n                \n                Point NB = {nbr, nbc};\n                int cost_to_NB = nodes_std[nbr][nbc].dist;\n                if (cost_to_NB > 1e8) continue;\n                \n                // Temporarily assume B is blocked for distance calculation from NB\n                static Node nodes_local[N][N];\n                bool saved_val = grid[br][bc];\n                grid[br][bc] = true;\n                run_dijkstra(NB, grid, nodes_local);\n                grid[br][bc] = saved_val;\n                \n                // Find valid Launch position L\n                // To hit B from L via Slide, L must be upstream.\n                // Slide direction must be 'd' (towards B).\n                // L = G - k * vec[d].\n                int opp_d;\n                if (d==0) opp_d=1; else if(d==1) opp_d=0; else if(d==2) opp_d=3; else opp_d=2;\n                \n                int curr = target.r + dr[opp_d];\n                int curc = target.c + dc[opp_d];\n                \n                while (is_valid(curr, curc)) {\n                    if (grid[curr][curc]) break; \n                    \n                    int cost_NB_L = nodes_local[curr][curc].dist;\n                    if (cost_NB_L < 1e8) {\n                        int total_helper = cost_to_NB + 1 + cost_NB_L + 1; // 1 Alter, 1 Slide\n                        if (total_helper < best_cost) {\n                            best_cost = total_helper;\n                            use_helper = true;\n                            best_helper_B = B;\n                            best_helper_NB = NB;\n                            best_helper_L = {curr, curc};\n                            for(int ii=0; ii<N; ++ii) for(int jj=0; jj<N; ++jj) nodes_helper[ii][jj] = nodes_local[ii][jj];\n                        }\n                    }\n                    curr += dr[opp_d];\n                    curc += dc[opp_d];\n                }\n            }\n        }\n\n        // 3. Execute Plan\n        auto execute_move = [&](char type, char dir, Point& pos) {\n            if (type == 'A') {\n                 int nr = pos.r, nc = pos.c;\n                 if (dir == 'U') nr--; else if (dir == 'D') nr++; else if (dir == 'L') nc--; else if (dir == 'R') nc++;\n                 if (is_valid(nr, nc)) grid[nr][nc] = !grid[nr][nc];\n            } else if (type == 'M') {\n                 if (dir == 'U') pos.r--; else if (dir == 'D') pos.r++; else if (dir == 'L') pos.c--; else if (dir == 'R') pos.c++;\n            } else if (type == 'S') {\n                 pos = get_slide_end(pos.r, pos.c, (dir=='U'?0:(dir=='D'?1:(dir=='L'?2:3))), grid);\n            }\n            final_actions.push_back({type, dir});\n        };\n\n        if (use_helper) {\n            vector<Point> pts;\n            vector<Action> p1 = reconstruct_path(current_pos, best_helper_NB, nodes_std, pts);\n            for (auto a : p1) execute_move(a.type, a.dir, current_pos);\n            \n            // Alter B\n            int d_alter = -1;\n            for(int dd=0; dd<4; ++dd) if (best_helper_NB.r + dr[dd] == best_helper_B.r && best_helper_NB.c + dc[dd] == best_helper_B.c) d_alter = dd;\n            execute_move('A', dir_chars[d_alter], current_pos);\n            \n            vector<Point> pts2;\n            vector<Action> p2 = reconstruct_path(best_helper_NB, best_helper_L, nodes_helper, pts2);\n            for (auto a : p2) execute_move(a.type, a.dir, current_pos);\n            \n            // Slide to Target\n            int d_slide = -1;\n            if (target.r > best_helper_L.r) d_slide = 1;\n            else if (target.r < best_helper_L.r) d_slide = 0;\n            else if (target.c > best_helper_L.c) d_slide = 3;\n            else d_slide = 2;\n            execute_move('S', dir_chars[d_slide], current_pos);\n\n        } else {\n            vector<Point> pts;\n            vector<Action> p = reconstruct_path(current_pos, target, nodes_std, pts);\n            for (auto a : p) execute_move(a.type, a.dir, current_pos);\n        }\n    }\n    \n    for(auto p : final_actions) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}"},"2":{"ahc001":"/**\n * Solution for AtCoder Heuristic Contest 001\n * Algorithm: Randomized Recursive Space Partitioning (k-d tree style) with Area Optimization\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\n// Time limit configuration\nconst double TIME_LIMIT = 4.85; \nauto start_time = chrono::high_resolution_clock::now();\n\n// Function to get elapsed time in seconds\ndouble get_elapsed_time() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nstruct Point {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nint N;\nvector<Point> points;\nvector<Rect> best_rects;\ndouble best_score = -1.0;\n\nvector<Rect> current_rects;\nmt19937 rng(12345);\n\n// Compute the raw score based on problem statement\ndouble compute_score(const vector<Rect>& rects) {\n    double score_sum = 0;\n    for(int i=0; i<N; ++i) {\n        long long w = rects[i].x2 - rects[i].x1;\n        long long h = rects[i].y2 - rects[i].y1;\n        double s = (double)w * h;\n        double r = points[i].r;\n        \n        if (s == 0) continue; \n        \n        // Verify point inclusion (sanity check)\n        if (rects[i].x1 > points[i].x || rects[i].x2 <= points[i].x ||\n            rects[i].y1 > points[i].y || rects[i].y2 <= points[i].y) {\n            return 0;\n        }\n        \n        double val = min(r, s) / max(r, s);\n        score_sum += 1.0 - (1.0 - val) * (1.0 - val);\n    }\n    return 1e9 * score_sum / N;\n}\n\n// Structure to hold split candidate information\nstruct Candidate {\n    int axis; // 0: x-axis (vertical cut), 1: y-axis (horizontal cut)\n    int cut_pos;\n    double cost;\n};\n\n// Recursive function to build the partition tree\nvoid build(const vector<int>& p_idxs, Rect r) {\n    // Base case: single point\n    if (p_idxs.size() == 1) {\n        current_rects[points[p_idxs[0]].id] = r;\n        return;\n    }\n\n    long long total_r = 0;\n    for(int idx : p_idxs) total_r += points[idx].r;\n\n    vector<Candidate> candidates;\n    candidates.reserve(p_idxs.size() * 2);\n\n    // We copy indices to sort them for splitting analysis\n    vector<int> sorted = p_idxs;\n    \n    // --- Try X splits (Vertical cuts) ---\n    sort(sorted.begin(), sorted.end(), [](int a, int b){\n        return points[a].x < points[b].x;\n    });\n    \n    long long current_r = 0;\n    for(size_t i=0; i<sorted.size()-1; ++i) {\n        current_r += points[sorted[i]].r;\n        // The split line must be > max x of left set and <= min x of right set\n        int max_l = points[sorted[i]].x;\n        int min_r = points[sorted[i+1]].x;\n        \n        if (max_l < min_r) {\n            // Ideal position based on area ratio\n            double target_ratio = (double)current_r / total_r;\n            double ideal_x = r.x1 + (r.x2 - r.x1) * target_ratio;\n            \n            // Clamp to valid integer range\n            int pos = round(ideal_x);\n            int valid_min = max_l + 1;\n            int valid_max = min_r;\n            pos = max(valid_min, min(valid_max, pos));\n            \n            double cost = abs(pos - ideal_x);\n            candidates.push_back({0, pos, cost});\n        }\n    }\n\n    // --- Try Y splits (Horizontal cuts) ---\n    sort(sorted.begin(), sorted.end(), [](int a, int b){\n        return points[a].y < points[b].y;\n    });\n    \n    current_r = 0;\n    for(size_t i=0; i<sorted.size()-1; ++i) {\n        current_r += points[sorted[i]].r;\n        int max_l = points[sorted[i]].y;\n        int min_r = points[sorted[i+1]].y;\n        \n        if (max_l < min_r) {\n            double target_ratio = (double)current_r / total_r;\n            double ideal_y = r.y1 + (r.y2 - r.y1) * target_ratio;\n            \n            int pos = round(ideal_y);\n            int valid_min = max_l + 1;\n            int valid_max = min_r;\n            pos = max(valid_min, min(valid_max, pos));\n            \n            double cost = abs(pos - ideal_y);\n            candidates.push_back({1, pos, cost});\n        }\n    }\n    \n    // Fallback for extremely degenerate cases (should not be reached with distinct points)\n    if (candidates.empty()) {\n        return;\n    }\n\n    // --- Selection Strategy ---\n    // Sort candidates by cost (lower is better)\n    sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n        return a.cost < b.cost;\n    });\n    \n    // Pick from top K best candidates to introduce randomness\n    int K = 4; \n    int n_cand = candidates.size();\n    int limit = min(n_cand, K);\n    \n    uniform_int_distribution<int> dist(0, limit - 1);\n    int choice = dist(rng);\n    \n    // Occasionally pick completely random valid cut to escape local optima\n    if (uniform_real_distribution<double>(0,1)(rng) < 0.01) {\n        uniform_int_distribution<int> dist_all(0, n_cand - 1);\n        choice = dist_all(rng);\n    }\n    \n    Candidate best = candidates[choice];\n    \n    // Split points and recurse\n    vector<int> set_l, set_r;\n    set_l.reserve(p_idxs.size()); \n    set_r.reserve(p_idxs.size());\n\n    if (best.axis == 0) { // Vertical cut\n        for(int idx : p_idxs) {\n            if (points[idx].x < best.cut_pos) set_l.push_back(idx);\n            else set_r.push_back(idx);\n        }\n        build(set_l, {r.x1, r.y1, best.cut_pos, r.y2});\n        build(set_r, {best.cut_pos, r.y1, r.x2, r.y2});\n    } else { // Horizontal cut\n        for(int idx : p_idxs) {\n            if (points[idx].y < best.cut_pos) set_l.push_back(idx);\n            else set_r.push_back(idx);\n        }\n        build(set_l, {r.x1, r.y1, r.x2, best.cut_pos});\n        build(set_r, {r.x1, best.cut_pos, r.x2, r.y2});\n    }\n}\n\n// Post-processing: Shrink rectangles that are larger than desired area\nvoid optimize_rects(vector<Rect>& rects) {\n    for(int i=0; i<N; ++i) {\n        long long w = rects[i].x2 - rects[i].x1;\n        long long h = rects[i].y2 - rects[i].y1;\n        long long s = w * h;\n        long long r = points[i].r;\n        \n        // Only shrink if actual area is larger than desired\n        if (s <= r) continue;\n        \n        // Iteratively reduce dimensions while keeping the point inside\n        while (s > r) {\n            bool moved = false;\n            // Heuristic: try to reduce the larger dimension first to maintain aspect ratio\n            bool reduce_w = (rects[i].x2 - rects[i].x1) > (rects[i].y2 - rects[i].y1);\n            \n            // Try preferred dimension first\n            if (reduce_w) {\n                 int dist_l = points[i].x - rects[i].x1;\n                 int dist_r = rects[i].x2 - 1 - points[i].x;\n                 // Trim from the side further from the point\n                 if (dist_l > dist_r) {\n                     if (rects[i].x1 < points[i].x) { rects[i].x1++; moved=true; }\n                     else if (dist_r > 0) { rects[i].x2--; moved=true; }\n                 } else {\n                     if (rects[i].x2 - 1 > points[i].x) { rects[i].x2--; moved=true; }\n                     else if (dist_l > 0) { rects[i].x1++; moved=true; }\n                 }\n            } else {\n                 int dist_t = points[i].y - rects[i].y1;\n                 int dist_b = rects[i].y2 - 1 - points[i].y;\n                 if (dist_t > dist_b) {\n                     if (rects[i].y1 < points[i].y) { rects[i].y1++; moved=true; }\n                     else if (dist_b > 0) { rects[i].y2--; moved=true; }\n                 } else {\n                     if (rects[i].y2 - 1 > points[i].y) { rects[i].y2--; moved=true; }\n                     else if (dist_t > 0) { rects[i].y1++; moved=true; }\n                 }\n            }\n            \n            // If preferred failed, try the other dimension\n            if (!moved) {\n                reduce_w = !reduce_w;\n                if (reduce_w) {\n                     int dist_l = points[i].x - rects[i].x1;\n                     int dist_r = rects[i].x2 - 1 - points[i].x;\n                     if (dist_l > dist_r) {\n                         if (rects[i].x1 < points[i].x) { rects[i].x1++; moved=true; }\n                         else if (dist_r > 0) { rects[i].x2--; moved=true; }\n                     } else {\n                         if (rects[i].x2 - 1 > points[i].x) { rects[i].x2--; moved=true; }\n                         else if (dist_l > 0) { rects[i].x1++; moved=true; }\n                     }\n                } else {\n                     int dist_t = points[i].y - rects[i].y1;\n                     int dist_b = rects[i].y2 - 1 - points[i].y;\n                     if (dist_t > dist_b) {\n                         if (rects[i].y1 < points[i].y) { rects[i].y1++; moved=true; }\n                         else if (dist_b > 0) { rects[i].y2--; moved=true; }\n                     } else {\n                         if (rects[i].y2 - 1 > points[i].y) { rects[i].y2--; moved=true; }\n                         else if (dist_t > 0) { rects[i].y1++; moved=true; }\n                     }\n                }\n            }\n            \n            if (!moved) break; // Cannot shrink further due to point constraints\n            \n            w = rects[i].x2 - rects[i].x1;\n            h = rects[i].y2 - rects[i].y1;\n            s = w * h;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if (!(cin >> N)) return 0;\n    \n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y >> points[i].r;\n    }\n    \n    best_rects.resize(N);\n    current_rects.resize(N);\n    \n    // Initial list of point indices\n    vector<int> p_indices(N);\n    iota(p_indices.begin(), p_indices.end(), 0);\n    \n    int iterations = 0;\n    \n    // Monte Carlo loop\n    while(get_elapsed_time() < TIME_LIMIT) {\n        iterations++;\n        \n        // Build a random valid partition\n        build(p_indices, {0, 0, 10000, 10000});\n        \n        // Shrink rectangles that are too big\n        optimize_rects(current_rects);\n        \n        // Evaluate\n        double score = compute_score(current_rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = current_rects;\n        }\n    }\n    \n    // Output results\n    for(int i=0; i<N; ++i) {\n        cout << best_rects[i].x1 << \" \" << best_rects[i].y1 << \" \" \n             << best_rects[i].x2 << \" \" << best_rects[i].y2 << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Problem Constants\nconst int H = 50;\nconst int W_GRID = 50;\nconst int MAX_TILES = 2500;\n\n// Algorithm Parameters\n// Beam Width: Number of states kept per step. \n// 2500 is a balance between depth of search and speed, allowing multiple iterations.\nconst int BEAM_WIDTH = 2500; \n// Diversity: Max states to keep that end at the same cell.\n// Keeps the beam from converging too early on one area.\nconst int MAX_PER_CELL = 3;  \n// Time limit in seconds (slightly less than 2.0 to be safe)\nconst double TIME_LIMIT = 1.96;\n\n// Grid Data\nint si, sj;\nint tiles[H][W_GRID];\nint points[H][W_GRID];\nint iter_points[H][W_GRID]; // Points with added noise for the current iteration\n\n// Directions: U, D, L, R\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dchar[4] = {'U', 'D', 'L', 'R'};\n\n// Tree node for efficient path reconstruction\n// We store the search tree in a flat vector to avoid pointer overhead.\nstruct TreeNode {\n    int parent_idx;\n    char move_char;\n};\n// Global tree buffer\nvector<TreeNode> tree;\n\n// State definition\nstruct State {\n    int coord;      // Current position (r * 50 + c)\n    int eval_score; // Score + Noise (used for beam selection)\n    int real_score; // Actual Score (used for tracking the best answer)\n    int tree_idx;   // Index in the tree vector\n    bitset<MAX_TILES> visited; // Set of visited tiles\n};\n\n// Helper for bucketing candidates\nstruct Candidate {\n    int score;     // eval_score\n    int state_idx; // Index in 'next_states'\n};\n\n// Global buffers to avoid repeated allocations\nvector<State> current_beam;\nvector<State> next_states;\nvector<Candidate> cell_buckets[2500]; // One bucket per grid cell to manage spatial diversity\nvector<int> touched_buckets;          // To clear buckets efficiently\n\n// Global best result\nint global_best_score = -1;\nstring global_best_path = \"\";\n\nint main() {\n    // Optimization for fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_clock = chrono::system_clock::now();\n\n    // Read Input\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> tiles[i][j];\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> points[i][j];\n        }\n    }\n\n    // Memory Reservation\n    // Tree needs to hold nodes for one full iteration.\n    // With pruning, 10M nodes is sufficient and fits within 1024MiB.\n    tree.reserve(10000000);\n    current_beam.reserve(BEAM_WIDTH);\n    next_states.reserve(BEAM_WIDTH * 4);\n    touched_buckets.reserve(2500);\n    for (int i = 0; i < 2500; ++i) {\n        cell_buckets[i].reserve(MAX_PER_CELL + 1);\n    }\n\n    // Random Number Generation\n    mt19937 rng(12345);\n    // Noise distribution: enough to reorder candidates but correlated with real score\n    // Points are 0-99, so 0-25 is a reasonable perturbation.\n    uniform_int_distribution<int> noise_dist(0, 25);\n\n    int iteration = 0;\n\n    // Iterative Loop\n    while (true) {\n        // Check time limit at the start of iteration\n        auto now = chrono::system_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_clock).count() / 1000.0;\n        if (elapsed > TIME_LIMIT) break;\n\n        iteration++;\n\n        // 1. Set up weights for this iteration\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W_GRID; ++j) {\n                if (iteration == 1) {\n                    // First run: pure greedy (baseline)\n                    iter_points[i][j] = points[i][j];\n                } else {\n                    // Subsequent runs: add noise to encourage exploration\n                    iter_points[i][j] = points[i][j] + noise_dist(rng);\n                }\n            }\n        }\n\n        // 2. Reset Search State\n        tree.clear();\n        current_beam.clear();\n\n        State start_node;\n        start_node.coord = si * W_GRID + sj;\n        start_node.real_score = points[si][sj];\n        start_node.eval_score = iter_points[si][sj];\n        start_node.tree_idx = -1; // Root\n        start_node.visited.reset();\n        start_node.visited.set(tiles[si][sj]);\n\n        current_beam.push_back(start_node);\n\n        // Track best immediately\n        if (start_node.real_score > global_best_score) {\n            global_best_score = start_node.real_score;\n            global_best_path = \"\";\n        }\n\n        // 3. Run Beam Search\n        for (int step = 0; step < MAX_TILES; ++step) {\n            if (current_beam.empty()) break;\n\n            // Periodic time check inside the loop (every 128 steps) to prevent TLE\n            if ((step & 127) == 0) {\n                auto n = chrono::system_clock::now();\n                double el = chrono::duration_cast<chrono::milliseconds>(n - start_clock).count() / 1000.0;\n                if (el > TIME_LIMIT) goto end_search;\n            }\n\n            next_states.clear();\n            touched_buckets.clear();\n\n            // Expansion Phase\n            for (const auto& s : current_beam) {\n                int r = s.coord / W_GRID;\n                int c = s.coord % W_GRID;\n                int cur_tile = tiles[r][c];\n\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n\n                    // Boundary Check\n                    if (nr < 0 || nr >= H || nc < 0 || nc >= W_GRID) continue;\n\n                    int next_tile = tiles[nr][nc];\n                    \n                    // Constraint Check: Must move to different tile & tile not visited\n                    if (next_tile != cur_tile && !s.visited.test(next_tile)) {\n                        \n                        // Record move in tree\n                        tree.push_back({s.tree_idx, dchar[d]});\n                        int new_tree_idx = (int)tree.size() - 1;\n\n                        State ns;\n                        ns.coord = nr * W_GRID + nc;\n                        // Use noisy score for evaluation\n                        ns.eval_score = s.eval_score + iter_points[nr][nc];\n                        // Use real score for tracking result\n                        ns.real_score = s.real_score + points[nr][nc];\n                        ns.tree_idx = new_tree_idx;\n                        ns.visited = s.visited;\n                        ns.visited.set(next_tile);\n\n                        next_states.push_back(ns);\n                    }\n                }\n            }\n\n            if (next_states.empty()) break;\n\n            // Pruning Phase: Bucket by cell coordinate\n            // This is crucial for performance and diversity.\n            for (int i = 0; i < (int)next_states.size(); ++i) {\n                int c = next_states[i].coord;\n                int sc = next_states[i].eval_score;\n                \n                auto& bucket = cell_buckets[c];\n                if (bucket.empty()) {\n                    touched_buckets.push_back(c);\n                    bucket.push_back({sc, i});\n                } else {\n                    // Keep top MAX_PER_CELL candidates per cell\n                    // Use simple insertion logic since list is tiny (<= 3)\n                    bool inserted = false;\n                    for (auto it = bucket.begin(); it != bucket.end(); ++it) {\n                        if (sc > it->score) {\n                            bucket.insert(it, {sc, i});\n                            inserted = true;\n                            break;\n                        }\n                    }\n                    if (!inserted && bucket.size() < MAX_PER_CELL) {\n                        bucket.push_back({sc, i});\n                    }\n                    if (bucket.size() > MAX_PER_CELL) {\n                        bucket.pop_back();\n                    }\n                }\n            }\n\n            // Selection Phase: Gather survivors and check global best\n            vector<int> survivors;\n            survivors.reserve(BEAM_WIDTH + 200);\n\n            for (int c : touched_buckets) {\n                for (const auto& cand : cell_buckets[c]) {\n                    survivors.push_back(cand.state_idx);\n\n                    // Update Global Best\n                    // We check every candidate because a sub-optimal local path (in eval_score)\n                    // might currently have the highest real_score seen so far.\n                    const auto& st = next_states[cand.state_idx];\n                    if (st.real_score > global_best_score) {\n                        global_best_score = st.real_score;\n                        // Reconstruct path\n                        string p;\n                        p.reserve(step + 1);\n                        int curr = st.tree_idx;\n                        while (curr != -1) {\n                            p += tree[curr].move_char;\n                            curr = tree[curr].parent_idx;\n                        }\n                        reverse(p.begin(), p.end());\n                        global_best_path = p;\n                    }\n                }\n                cell_buckets[c].clear();\n            }\n\n            // Global Truncation if too many states across all cells\n            if ((int)survivors.size() > BEAM_WIDTH) {\n                nth_element(survivors.begin(), survivors.begin() + BEAM_WIDTH, survivors.end(),\n                    [&](int a, int b) {\n                        return next_states[a].eval_score > next_states[b].eval_score;\n                    });\n                survivors.resize(BEAM_WIDTH);\n            }\n\n            // Form new beam\n            current_beam.clear();\n            for (int idx : survivors) {\n                current_beam.push_back(next_states[idx]);\n            }\n        }\n    }\n\n    end_search:;\n    cout << global_best_path << endl;\n\n    return 0;\n}","ahc003":"/**\n * AtCoder Heuristic Contest Solution\n * Problem: Shortest Path with Unknown Edge Lengths\n * Approach:\n * 1. Model the problem as finding shortest paths in a grid graph with weighted edges.\n * 2. Initially, edge weights are unknown (assume uniform prior).\n * 3. As we traverse paths and receive total length measurements, we update edge estimates.\n * 4. Use Dijkstra's algorithm for pathfinding.\n * 5. Use Stochastic Gradient Descent (Adam) to update edge weights.\n *    - Loss function: Squared Relative Error of predicted vs measured path length.\n *    - Regularization: L2 smoothness on adjacent horizontal edges (row-wise) and vertical edges (column-wise)\n *      to exploit the problem structure where edges are generated with row/column correlations.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst int NUM_H = N * (N - 1); // 30 * 29 = 870\nconst int NUM_V = (N - 1) * N; // 29 * 30 = 870\nconst int NUM_EDGES = NUM_H + NUM_V; // 1740\n\n// Helper to get edge indices\n// Horizontal edges: (r, c) -> (r, c+1)\nint get_h_idx(int r, int c) {\n    return r * (N - 1) + c;\n}\n\n// Vertical edges: (r, c) -> (r+1, c)\nint get_v_idx(int r, int c) {\n    return NUM_H + r * N + c;\n}\n\n// Structure to store query history\nstruct Query {\n    vector<int> path_edges;\n    int measured_dist;\n};\n\nclass Solver {\nprivate:\n    // Estimated weights of edges\n    vector<double> weights;\n    \n    // Adam Optimizer parameters\n    vector<double> m, v; // First and second moment vectors\n    double beta1 = 0.9;\n    double beta2 = 0.999;\n    double epsilon = 1e-8;\n    \n    // Hyperparameters\n    double learning_rate = 150.0;\n    double lambda = 10.0; // Regularization strength for smoothness\n    \n    long long updates_count = 0;\n    vector<Query> history;\n    mt19937 rng;\n\npublic:\n    Solver() {\n        // Initialize weights with expected mean value (approx 5000)\n        weights.assign(NUM_EDGES, 5000.0);\n        m.assign(NUM_EDGES, 0.0);\n        v.assign(NUM_EDGES, 0.0);\n        rng.seed(42);\n    }\n\n    // Dijkstra's algorithm to find the shortest path based on current weight estimates\n    pair<string, vector<int>> find_path(int si, int sj, int ti, int tj) {\n        vector<double> dist(N * N, 1e18);\n        vector<int> parent_edge(N * N, -1);\n        vector<int> parent_node(N * N, -1);\n        \n        auto get_node = [&](int r, int c) { return r * N + c; };\n        \n        int start_node = get_node(si, sj);\n        int target_node = get_node(ti, tj);\n        \n        dist[start_node] = 0;\n        using State = pair<double, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, start_node});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == target_node) break;\n            \n            int r = u / N;\n            int c = u % N;\n            \n            // Explore neighbors\n            // Up\n            if (r > 0) {\n                int nr = r - 1, nc = c;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_v_idx(r - 1, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Down\n            if (r < N - 1) {\n                int nr = r + 1, nc = c;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_v_idx(r, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Left\n            if (c > 0) {\n                int nr = r, nc = c - 1;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_h_idx(r, c - 1);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Right\n            if (c < N - 1) {\n                int nr = r, nc = c + 1;\n                int v_node = get_node(nr, nc);\n                int e_idx = get_h_idx(r, c);\n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path = \"\";\n        vector<int> edges;\n        int curr = target_node;\n        while (curr != start_node) {\n            int prev = parent_node[curr];\n            int e_idx = parent_edge[curr];\n            edges.push_back(e_idx);\n            \n            int pr = prev / N, pc = prev % N;\n            int cr = curr / N, cc = curr % N;\n            \n            if (pr == cr + 1) path += 'U';\n            else if (pr == cr - 1) path += 'D';\n            else if (pc == cc + 1) path += 'L';\n            else if (pc == cc - 1) path += 'R';\n            \n            curr = prev;\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges.begin(), edges.end());\n        return {path, edges};\n    }\n\n    // Update estimates using SGD\n    void train(const vector<int>& path_edges, int measured, int k) {\n        history.push_back({path_edges, measured});\n        \n        int batch_size = 32;\n        int iterations = 80; // Number of SGD steps per query\n        \n        vector<double> grad(NUM_EDGES);\n        // Normalizing coefficient for regularization to match magnitude of prediction error\n        double reg_coeff = lambda * 2.0 / (5000.0 * 5000.0);\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            fill(grad.begin(), grad.end(), 0.0);\n            updates_count++;\n            \n            // Select mini-batch (always include the latest query)\n            vector<int> indices;\n            indices.reserve(batch_size + 1);\n            indices.push_back(history.size() - 1);\n            if (history.size() > 1) {\n                for (int b = 0; b < batch_size; ++b) {\n                    indices.push_back(rng() % (history.size() - 1));\n                }\n            }\n\n            // Compute gradients for Prediction Error: ((Pred - Measured)/Measured)^2\n            for (int idx : indices) {\n                const auto& q = history[idx];\n                double pred = 0;\n                for (int e : q.path_edges) pred += weights[e];\n                \n                double y = q.measured_dist;\n                double diff = pred - y;\n                // Derivative w.r.t w_e is 2 * (diff) / y^2\n                double g_factor = 2.0 * diff / (y * y);\n                \n                for (int e : q.path_edges) {\n                    grad[e] += g_factor;\n                }\n            }\n            \n            // Compute gradients for Smoothness Regularization\n            // Horizontal edges: smooth along rows\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N - 2; ++c) {\n                    int e1 = get_h_idx(r, c);\n                    int e2 = get_h_idx(r, c + 1);\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    double g = (w1 - w2) * reg_coeff;\n                    grad[e1] += g;\n                    grad[e2] -= g;\n                }\n            }\n            // Vertical edges: smooth along columns\n            for (int c = 0; c < N; ++c) {\n                for (int r = 0; r < N - 2; ++r) {\n                    int e1 = get_v_idx(r, c);\n                    int e2 = get_v_idx(r + 1, c);\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    double g = (w1 - w2) * reg_coeff;\n                    grad[e1] += g;\n                    grad[e2] -= g;\n                }\n            }\n            \n            // Adam Update Step\n            double bias_corr1 = 1.0 - pow(beta1, updates_count);\n            double bias_corr2 = 1.0 - pow(beta2, updates_count);\n            \n            for (int i = 0; i < NUM_EDGES; ++i) {\n                m[i] = beta1 * m[i] + (1 - beta1) * grad[i];\n                v[i] = beta2 * v[i] + (1 - beta2) * grad[i] * grad[i];\n                \n                double m_hat = m[i] / bias_corr1;\n                double v_hat = v[i] / bias_corr2;\n                \n                weights[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);\n                \n                // Clamp weights to reasonable bounds\n                if (weights[i] < 100.0) weights[i] = 100.0;\n                if (weights[i] > 20000.0) weights[i] = 20000.0;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    Solver solver;\n    \n    // Process 1000 queries\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        \n        // 1. Find and output path\n        auto [path_str, path_edges] = solver.find_path(si, sj, ti, tj);\n        cout << path_str << endl;\n        \n        // 2. Read feedback\n        int measured;\n        cin >> measured;\n        \n        // 3. Update model\n        solver.train(path_edges, measured, k);\n    }\n    \n    return 0;\n}","ahc004":"/**\n * Problem: AHC004 - Genetic Information\n * Approach: Multi-start Simulated Annealing with Optimized Move Evaluation\n * \n * Optimization Highlights:\n * 1. FastHashMap: Uses a custom open-addressing hash table instead of std::map for O(1) lookups.\n * 2. Buffer Optimization: Uses line buffers to minimize expensive modulo operations during rolling hash updates.\n * 3. Multi-Start Strategy: Runs multiple independent SA sessions to escape local optima, which is crucial for this problem.\n * 4. Dot Optimization: Applies a greedy pass to insert dots only when a perfect string match is found.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <cmath>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconstexpr int N = 20;\nconstexpr int TIMEOUT_MS = 2950;\n\n// Xorshift for fast random number generation\nstruct Xorshift {\n    uint64_t state = 0x123456789ABCDEF;\n    inline uint64_t next() {\n        uint64_t x = state;\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return state = x;\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline int next_char() {\n        return next() & 7; // Returns 0-7\n    }\n    inline double next_double() {\n        return (next() & 0xFFFFFFFF) / 4294967296.0;\n    }\n};\n\nXorshift rng;\n\n// Target representation\nstruct Target {\n    int id;\n    int weight;\n};\n\n// Simple Open-Addressing Hash Map\n// Size 4096 is sufficient for M <= 800 with low collision rate\nconstexpr int HASH_MAP_SIZE = 4096;\nconstexpr int HASH_MAP_MASK = HASH_MAP_SIZE - 1;\n\nstruct FastHashMap {\n    uint64_t keys[HASH_MAP_SIZE];\n    int ids[HASH_MAP_SIZE]; // Stores id + 1 (0 means empty)\n    \n    FastHashMap() {\n        memset(ids, 0, sizeof(ids));\n    }\n    \n    void clear() {\n        memset(ids, 0, sizeof(ids));\n    }\n    \n    void insert(uint64_t key, int id) {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return; // Duplicate handling\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        keys[idx] = key;\n        ids[idx] = id + 1; // Store as 1-based index\n    }\n    \n    inline int get(uint64_t key) const {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return ids[idx] - 1;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        return -1;\n    }\n};\n\nstruct Solver {\n    int M;\n    int max_possible_weight;\n    \n    // Targets grouped by length, using FastHashMap\n    FastHashMap maps[13];\n    vector<Target> targets_info; // id -> weight\n    vector<int> active_lengths;\n    \n    // Current State\n    int grid[N][N];\n    vector<int> occ; // occurrences of each target id\n    int current_score;\n    \n    // Best State\n    int best_grid[N][N];\n    int best_score;\n    \n    // Buffer for row/col extraction to avoid modulo in inner loops\n    // Size = N + Max Length wrap = 20 + 12 = 32\n    int line_buf[32]; \n\n    Solver() {\n        best_score = -1;\n    }\n\n    void read_input() {\n        int n_dummy;\n        if (!(cin >> n_dummy >> M)) return;\n        \n        map<string, int> counts;\n        for (int i = 0; i < M; ++i) {\n            string s;\n            cin >> s;\n            counts[s]++;\n        }\n        \n        max_possible_weight = M;\n        int id_counter = 0;\n        targets_info.reserve(counts.size());\n        \n        vector<bool> len_active(13, false);\n        \n        for (auto const& [s, count] : counts) {\n            int len = s.length();\n            uint64_t h = 0;\n            for (char c : s) h = (h << 3) | (c - 'A');\n            \n            maps[len].insert(h, id_counter);\n            targets_info.push_back({id_counter, count});\n            len_active[len] = true;\n            id_counter++;\n        }\n        \n        for(int l=2; l<=12; ++l) {\n            if (len_active[l]) active_lengths.push_back(l);\n        }\n        \n        occ.resize(id_counter, 0);\n    }\n    \n    // Helper to update occurrences and calculate score difference\n    // Modifies `occ` directly. Returns score diff.\n    // If `sign` is positive, we are adding a character (incrementing occ).\n    // If `sign` is negative, we are removing (decrementing occ).\n    inline void update_state(int r, int c, int val, int sign, int& score_diff) {\n        // Horizontal Check\n        // Copy row `r` to buffer, override `c` with `val`\n        for(int j=0; j<N; ++j) line_buf[j] = grid[r][j];\n        line_buf[c] = val;\n        // Handle wrap-around\n        for(int j=0; j<12; ++j) line_buf[N+j] = line_buf[j];\n        \n        for (int l : active_lengths) {\n            // We check all windows of length `l` that include index `c`.\n            // A window starting at `s` includes `c` if `s <= c` and `s + l - 1 >= c`.\n            // This translates to `c - l + 1 <= s <= c` (modulo logic applies).\n            // We iterate `k` from 0 to `l-1`, representing the shift.\n            \n            for (int k = 0; k < l; ++k) {\n                // Calculate start column for the window\n                // (c - l + 1 + k) gives the start index relative to unwrapped space\n                // We normalize to [0, N)\n                int start_col = (c - l + 1 + k + N) % N;\n                \n                // Compute hash using buffer. \n                // Since buffer has wrap-around copy, we can just access linearly.\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) {\n                    h = (h << 3) | line_buf[start_col + i];\n                }\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    if (sign > 0) {\n                        if (occ[id] == 0) score_diff += targets_info[id].weight;\n                        occ[id]++;\n                    } else {\n                        if (occ[id] == 1) score_diff -= targets_info[id].weight;\n                        occ[id]--;\n                    }\n                }\n            }\n        }\n        \n        // Vertical Check\n        // Copy col `c` to buffer\n        for(int i=0; i<N; ++i) line_buf[i] = grid[i][c];\n        line_buf[r] = val;\n        for(int i=0; i<12; ++i) line_buf[N+i] = line_buf[i];\n        \n        for (int l : active_lengths) {\n            for (int k = 0; k < l; ++k) {\n                int start_row = (r - l + 1 + k + N) % N;\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) {\n                    h = (h << 3) | line_buf[start_row + i];\n                }\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    if (sign > 0) {\n                        if (occ[id] == 0) score_diff += targets_info[id].weight;\n                        occ[id]++;\n                    } else {\n                        if (occ[id] == 1) score_diff -= targets_info[id].weight;\n                        occ[id]--;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Full score recalculation (used at initialization and verification)\n    int calc_full_score() {\n        fill(occ.begin(), occ.end(), 0);\n        int score = 0;\n        \n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // Horizontal\n                for (int l : active_lengths) {\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[r][(c+k)%N];\n                    int id = maps[l].get(h);\n                    if (id != -1) {\n                        if (occ[id] == 0) score += targets_info[id].weight;\n                        occ[id]++;\n                    }\n                }\n                // Vertical\n                for (int l : active_lengths) {\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[(r+k)%N][c];\n                    int id = maps[l].get(h);\n                    if (id != -1) {\n                        if (occ[id] == 0) score += targets_info[id].weight;\n                        occ[id]++;\n                    }\n                }\n            }\n        }\n        return score;\n    }\n\n    void run_sa(double duration_ms, bool refinement = false) {\n        auto start_time = chrono::steady_clock::now();\n        \n        // Temperature schedule\n        double t0 = refinement ? 0.5 : 2.0;\n        double t1 = 0.0;\n        \n        int64_t steps = 0;\n        \n        while (true) {\n            steps++;\n            // Check time periodically\n            if ((steps & 1023) == 0) {\n                auto curr = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n                if (elapsed > duration_ms) break;\n            }\n            \n            int r = rng.next_int(N);\n            int c = rng.next_int(N);\n            int old_val = grid[r][c];\n            int new_val = rng.next_char();\n            \n            if (old_val == new_val) continue;\n            \n            int diff = 0;\n            // Tentatively apply update. Note: This modifies `occ`.\n            update_state(r, c, old_val, -1, diff); // Remove old contribution\n            update_state(r, c, new_val, 1, diff);  // Add new contribution\n            \n            bool accept = false;\n            if (diff >= 0) {\n                accept = true;\n            } else {\n                // Calculate temp based on approx time or steps\n                // To be faster, we can estimate time or check less frequently\n                // Here we use a simplified check or the cached elapsed time from block\n                auto curr = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n                if (elapsed > duration_ms) {\n                    // Revert and exit\n                    update_state(r, c, new_val, -1, diff);\n                    update_state(r, c, old_val, 1, diff);\n                    break;\n                }\n                \n                double temp = t0 + (t1 - t0) * (elapsed / duration_ms);\n                if (exp(diff / temp) > rng.next_double()) {\n                    accept = true;\n                }\n            }\n            \n            if (accept) {\n                grid[r][c] = new_val;\n                current_score += diff;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else {\n                // Revert changes to `occ`\n                int dummy = 0;\n                update_state(r, c, new_val, -1, dummy);\n                update_state(r, c, old_val, 1, dummy);\n            }\n        }\n    }\n    \n    // Try to replace characters with dots if we have perfect score\n    void optimize_dots() {\n        if (best_score < max_possible_weight) return;\n        \n        // Load best grid\n        memcpy(grid, best_grid, sizeof(grid));\n        current_score = calc_full_score(); // Ensure occ is consistent\n        \n        vector<pair<int,int>> cells;\n        cells.reserve(N*N);\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) cells.push_back({i,j});\n        \n        // Shuffle check order\n        for(int i=cells.size()-1; i>0; --i) {\n            swap(cells[i], cells[rng.next_int(i+1)]);\n        }\n        \n        for(auto p : cells) {\n            int r = p.first;\n            int c = p.second;\n            int old_val = grid[r][c];\n            if (old_val == -1) continue;\n            \n            int diff = 0;\n            update_state(r, c, old_val, -1, diff);\n            \n            // If score is maintained (meaning diff cancels out any loss to 0 total loss for unique strings)\n            // Actually, update_state decrements occ. \n            // If occ goes 1->0, diff decreases.\n            // We want current_score + diff == max_possible_weight.\n            \n            if (current_score + diff == max_possible_weight) {\n                current_score += diff;\n                grid[r][c] = -1; // Dot\n                memcpy(best_grid, grid, sizeof(grid)); \n            } else {\n                // Revert\n                int dummy = 0;\n                update_state(r, c, old_val, 1, dummy);\n            }\n        }\n    }\n\n    void solve() {\n        auto global_start = chrono::steady_clock::now();\n        \n        best_score = -1;\n        int restart_count = 0;\n        \n        // Multi-start Strategy\n        while(true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - global_start).count();\n            if (elapsed > TIMEOUT_MS - 500 && restart_count > 0) break; \n            \n            // Initialize random grid\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = rng.next_char();\n            current_score = calc_full_score();\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                memcpy(best_grid, grid, sizeof(grid));\n            }\n            \n            // Allocate time for this run\n            double run_duration = 500.0;\n            if (elapsed + run_duration > TIMEOUT_MS - 100) {\n                run_duration = TIMEOUT_MS - elapsed - 100;\n            }\n            \n            if (run_duration < 50) break;\n            \n            run_sa(run_duration, false);\n            restart_count++;\n        }\n        \n        // Refinement Phase: Run SA on the best solution found so far\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double, milli>(now - global_start).count();\n        if (elapsed < TIMEOUT_MS - 50) {\n            memcpy(grid, best_grid, sizeof(grid));\n            current_score = calc_full_score();\n            run_sa(TIMEOUT_MS - elapsed - 20, true);\n        }\n\n        // Optimization Phase: Try to insert dots\n        optimize_dots();\n        \n        // Output\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                int val = best_grid[i][j];\n                if (val >= 0) cout << (char)('A' + val);\n                else cout << '.';\n            }\n            cout << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver s;\n    s.read_input();\n    s.solve();\n    return 0;\n}","ahc005":"/**\n * Problem Analysis:\n * The problem asks for a minimum cost tour that \"sees\" every road cell on an N x N grid.\n * Visibility is defined by line-of-sight in cardinal directions.\n *\n * Key Insights:\n * 1. Geometric Set Cover:\n *    - We can decompose the road cells into maximal contiguous horizontal (H) and vertical (V) segments.\n *    - Standing on any cell of a segment allows seeing the entire segment.\n *    - Every road cell (r, c) belongs to exactly one H-segment and one V-segment.\n *    - To see cell (r, c), we must visit either its H-segment or its V-segment.\n *    - This structure forms a Bipartite Matching / Vertex Cover problem constraints.\n *      Specifically, we need to select a subset of segments to visit such that every cell (edge in bipartite graph)\n *      is covered by a selected segment (vertex). This is the Vertex Cover problem.\n *\n * 2. Minimum Weight Vertex Cover (MWVC):\n *    - Since we want to minimize travel time, we should prefer visiting segments that are \"close\" to our path.\n *    - We can assign a weight to each segment equal to the cost to reach it from the current position.\n *    - MWVC on a bipartite graph can be solved efficiently using Max-Flow Min-Cut (Konig's theorem extension).\n *\n * 3. Iterative Greedy Strategy:\n *    - The optimal set of segments depends on our current position (dynamic costs).\n *    - We employ an iterative approach:\n *      a. From current position, calculate distances to all segments.\n *      b. Construct the bipartite graph of *unseen* cells.\n *      c. Assign weights to segments based on distance (+ random noise for diversity).\n *      d. Solve MWVC to identify the most efficient set of segments to visit next.\n *      e. Move to the best candidate from the MWVC set.\n *      f. Repeat until all cells are seen, then return to start.\n *\n * 4. Optimization:\n *    - Since the grid is small (N <= 69), we can run many simulations with different random seeds/weights within the time limit.\n *    - We track the best solution found.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <map>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>\n\n// Use AtCoder Library for MaxFlow\n#include <atcoder/maxflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconst int INF = 1e9;\nconst int DX[] = {-1, 1, 0, 0};\nconst int DY[] = {0, 0, -1, 1};\nconst char DIR_CHAR[] = {'U', 'D', 'L', 'R'};\n\n// Global variables\nint N;\nint SI, SJ;\nvector<string> GRID;\nvector<vector<int>> COSTS;\nbool IS_ROAD[70][70];\n\n// Structs\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\nstruct Segment {\n    int id;\n    int type; // 0: Horizontal, 1: Vertical\n    vector<Point> cells;\n};\n\nvector<Segment> H_SEGS, V_SEGS;\nint H_ID[70][70]; // Map cell to H segment ID\nint V_ID[70][70]; // Map cell to V segment ID\n\n// Parsing and Setup\nvoid parse_input() {\n    if (!(cin >> N >> SI >> SJ)) return;\n    GRID.resize(N);\n    COSTS.assign(N, vector<int>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        cin >> GRID[i];\n        for (int j = 0; j < N; ++j) {\n            if (GRID[i][j] != '#') {\n                COSTS[i][j] = GRID[i][j] - '0';\n                IS_ROAD[i][j] = true;\n            } else {\n                IS_ROAD[i][j] = false;\n            }\n        }\n    }\n\n    // Identify Horizontal Segments\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) H_ID[i][j] = -1;\n    }\n    int h_count = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (!IS_ROAD[i][j]) {\n                j++;\n                continue;\n            }\n            int k = j;\n            while (k < N && IS_ROAD[i][k]) k++;\n            Segment seg;\n            seg.id = h_count;\n            seg.type = 0;\n            for (int c = j; c < k; ++c) {\n                seg.cells.push_back({i, c});\n                H_ID[i][c] = h_count;\n            }\n            H_SEGS.push_back(seg);\n            h_count++;\n            j = k;\n        }\n    }\n\n    // Identify Vertical Segments\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) V_ID[i][j] = -1;\n    }\n    int v_count = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (!IS_ROAD[i][j]) {\n                i++;\n                continue;\n            }\n            int k = i;\n            while (k < N && IS_ROAD[k][j]) k++;\n            Segment seg;\n            seg.id = v_count;\n            seg.type = 1;\n            for (int r = i; r < k; ++r) {\n                seg.cells.push_back({r, j});\n                V_ID[r][j] = v_count;\n            }\n            V_SEGS.push_back(seg);\n            v_count++;\n            i = k;\n        }\n    }\n}\n\n// Dijkstra's Algorithm for shortest paths on the grid\nvoid get_dist_matrix(Point start, vector<vector<int>>& dist, vector<vector<int>>& parent_dir) {\n    dist.assign(N, vector<int>(N, INF));\n    parent_dir.assign(N, vector<int>(N, -1));\n    \n    priority_queue<pair<int, pair<int,int>>, vector<pair<int, pair<int,int>>>, greater<pair<int, pair<int,int>>>> pq;\n    \n    dist[start.r][start.c] = 0;\n    pq.push({0, {start.r, start.c}});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        int r = u.first;\n        int c = u.second;\n        \n        if (d > dist[r][c]) continue;\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + DX[k];\n            int nc = c + DY[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && IS_ROAD[nr][nc]) {\n                int weight = COSTS[nr][nc];\n                if (dist[r][c] + weight < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + weight;\n                    parent_dir[nr][nc] = k;\n                    pq.push({dist[nr][nc], {nr, nc}});\n                }\n            }\n        }\n    }\n}\n\n// Reconstruct path string\nstring get_path_str(Point start, Point end, const vector<vector<int>>& parent_dir) {\n    string path = \"\";\n    int r = end.r;\n    int c = end.c;\n    while (r != start.r || c != start.c) {\n        int dir = parent_dir[r][c];\n        if (dir == -1) break; \n        path += DIR_CHAR[dir];\n        r -= DX[dir];\n        c -= DY[dir];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Result {\n    string path;\n    long long score;\n    int time_cost;\n};\n\nmt19937 rng(12345);\n\nResult solve_iterative_mwvc() {\n    // State tracking\n    vector<vector<bool>> is_covered(N, vector<bool>(N, false));\n    int covered_count = 0;\n    int total_road_cells = 0;\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(IS_ROAD[i][j]) total_road_cells++;\n\n    auto see_cell = [&](int r, int c) {\n        if (!is_covered[r][c]) {\n            is_covered[r][c] = true;\n            covered_count++;\n        }\n    };\n\n    auto visit_pos = [&](Point p) {\n        int hid = H_ID[p.r][p.c];\n        if (hid != -1) {\n            for (auto& cell : H_SEGS[hid].cells) see_cell(cell.r, cell.c);\n        }\n        int vid = V_ID[p.r][p.c];\n        if (vid != -1) {\n            for (auto& cell : V_SEGS[vid].cells) see_cell(cell.r, cell.c);\n        }\n    };\n\n    Point current = {SI, SJ};\n    visit_pos(current);\n\n    string full_path = \"\";\n    int total_cost = 0;\n\n    // Random weight perturbation for diversity\n    uniform_real_distribution<double> d_rand(0.85, 1.15);\n\n    while (covered_count < total_road_cells) {\n        // 1. Calculate distances from current\n        vector<vector<int>> dist;\n        vector<vector<int>> parent;\n        get_dist_matrix(current, dist, parent);\n\n        // 2. Precompute min distance to each segment\n        vector<int> dist_h(H_SEGS.size(), INF);\n        vector<Point> closest_h(H_SEGS.size());\n        for (auto& seg : H_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < dist_h[seg.id]) {\n                    dist_h[seg.id] = dist[p.r][p.c];\n                    closest_h[seg.id] = p;\n                }\n            }\n        }\n        vector<int> dist_v(V_SEGS.size(), INF);\n        vector<Point> closest_v(V_SEGS.size());\n        for (auto& seg : V_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < dist_v[seg.id]) {\n                    dist_v[seg.id] = dist[p.r][p.c];\n                    closest_v[seg.id] = p;\n                }\n            }\n        }\n\n        // 3. Build Flow Network for MWVC\n        mf_graph<long long> g(H_SEGS.size() + V_SEGS.size() + 2);\n        int S = H_SEGS.size() + V_SEGS.size();\n        int T_sink = S + 1;\n\n        // Edges S -> H (Capacity = Weight of H segment)\n        for (auto& seg : H_SEGS) {\n            long long w = (long long)(dist_h[seg.id] * d_rand(rng)) + 50; \n            g.add_edge(S, seg.id, w);\n        }\n        // Edges V -> T (Capacity = Weight of V segment)\n        for (auto& seg : V_SEGS) {\n            long long w = (long long)(dist_v[seg.id] * d_rand(rng)) + 50;\n            g.add_edge(H_SEGS.size() + seg.id, T_sink, w);\n        }\n        // Edges H -> V for uncovered cells (Infinite Capacity)\n        bool has_uncovered = false;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (IS_ROAD[r][c] && !is_covered[r][c]) {\n                    int h = H_ID[r][c];\n                    int v = V_ID[r][c];\n                    g.add_edge(h, H_SEGS.size() + v, 1e18);\n                    has_uncovered = true;\n                }\n            }\n        }\n\n        if (!has_uncovered) break;\n\n        // 4. Solve Min Cut\n        g.flow(S, T_sink);\n        auto cut = g.min_cut(S);\n\n        // 5. Extract Vertex Cover\n        // S-side in cut means reachable from S.\n        // VC = (L \\ S_side) U (R \\cap S_side)\n        // cut[i] == true means i is in S_side.\n        vector<int> target_h, target_v;\n        for (int i = 0; i < (int)H_SEGS.size(); ++i) {\n            if (!cut[i]) target_h.push_back(i);\n        }\n        for (int i = 0; i < (int)V_SEGS.size(); ++i) {\n            if (cut[H_SEGS.size() + i]) target_v.push_back(i);\n        }\n\n        // 6. Select Best Target from Cover\n        Point best_p = {-1, -1};\n        double best_score = 1e18;\n\n        // Check H candidates\n        for (int hid : target_h) {\n            Point p = closest_h[hid];\n            double d = (double)dist_h[hid];\n            // Heuristic: if this point also satisfies a V-target, it's better\n            int vid = V_ID[p.r][p.c];\n            bool covers_v = false;\n            for(int t_vid : target_v) if(t_vid == vid) covers_v = true;\n            \n            double score = d;\n            if (covers_v) score *= 0.6; // Discount if double cover\n            \n            if (score < best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        // Check V candidates\n        for (int vid : target_v) {\n            Point p = closest_v[vid];\n            double d = (double)dist_v[vid];\n            int hid = H_ID[p.r][p.c];\n            bool covers_h = false;\n            for(int t_hid : target_h) if(t_hid == hid) covers_h = true;\n            \n            double score = d;\n            if (covers_h) score *= 0.6;\n            \n            if (score < best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n\n        // 7. Move\n        string subpath = get_path_str(current, best_p, parent);\n        full_path += subpath;\n        total_cost += dist[best_p.r][best_p.c];\n\n        // Update coverage along path\n        Point temp = current;\n        for (char c : subpath) {\n            int dir = -1;\n            if (c == 'U') dir = 0;\n            else if (c == 'D') dir = 1;\n            else if (c == 'L') dir = 2;\n            else if (c == 'R') dir = 3;\n            temp.r += DX[dir];\n            temp.c += DY[dir];\n            visit_pos(temp);\n        }\n        current = best_p;\n        visit_pos(current); // Ensure endpoint processed\n    }\n\n    // Return to start\n    if (current.r != SI || current.c != SJ) {\n        vector<vector<int>> dist;\n        vector<vector<int>> parent;\n        get_dist_matrix(current, dist, parent);\n        string subpath = get_path_str(current, {SI, SJ}, parent);\n        full_path += subpath;\n        total_cost += dist[SI][SJ];\n    }\n\n    Result res;\n    res.path = full_path;\n    res.time_cost = (total_cost == 0 ? 1 : total_cost);\n    // Calculate approximate score (assuming full coverage)\n    res.score = 10000 + (long long)(1e7 * N / res.time_cost);\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    parse_input();\n\n    auto start_clock = chrono::high_resolution_clock::now();\n    // Use slightly less than 3.0s to ensure output\n    double time_limit = 2.85;\n\n    Result best_res;\n    best_res.score = -1;\n    best_res.path = \"\";\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_clock;\n        if (elapsed.count() > time_limit) break;\n\n        Result res = solve_iterative_mwvc();\n        if (res.score > best_res.score) {\n            best_res = res;\n        }\n    }\n\n    cout << best_res.path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"/*\n * Solution for F Corporation Project Leader\n * Approach: Greedy scheduling on Critical Path + Online Learning of Skills via Coordinate Descent\n */\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n\nusing namespace std;\n\n// Random number generator\nmt19937 rng(12345);\n\nstruct Task {\n    int id;\n    vector<int> d; // Required skill levels\n    vector<int> dependency_to; // Adjacency list (children)\n    int unresolved_dependencies; // In-degree counter\n    int height; // Critical path length (distance to sink)\n};\n\nstruct Member {\n    int id;\n    vector<int> s; // Estimated skill levels\n    // History of tasks completed: pair<task_id, duration>\n    vector<pair<int, int>> history; \n    int current_task_id; // -1 if free\n    int task_start_day;\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<int> task_status; // 0: not started, 1: started, 2: completed\nvector<int> memo_height;\n\n// Calculate w_{i,j} based on current skill estimate\nint calc_w(int task_idx, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += max(0, tasks[task_idx].d[k] - s[k]);\n    }\n    return w;\n}\n\n// Predict duration days based on current skill estimate\nint predict_days(int task_idx, const vector<int>& s) {\n    int w = calc_w(task_idx, s);\n    if (w == 0) return 1;\n    return max(1, w); // Expected value approx w\n}\n\n// Update skill estimates for a member using local search to fit observations\nvoid update_skills(int member_idx) {\n    Member& m = members[member_idx];\n    int iterations = 1000; // Number of local search steps\n    \n    // Precompute w for all history items to allow incremental updates\n    vector<int> current_w(m.history.size());\n    long long current_sum_s = 0;\n    for (int x : m.s) current_sum_s += x;\n\n    for (size_t i = 0; i < m.history.size(); ++i) {\n        current_w[i] = calc_w(m.history[i].first, m.s);\n    }\n\n    // Helper to calculate error term for a single observation\n    // Actual duration t implies constraints on w\n    auto calc_error_term = [&](int w, int actual) -> long long {\n        int lb, ub;\n        if (actual == 1) {\n            // If t=1, w could be 0, or w+r <= 1. Since r >= -3, w <= 4.\n            lb = 0; ub = 4;\n        } else {\n            // If t > 1, t = w + r => w = t - r. r in [-3, 3].\n            lb = actual - 3;\n            ub = actual + 3;\n        }\n        int diff = 0;\n        if (w < lb) diff = lb - w;\n        else if (w > ub) diff = w - ub;\n        return (long long)diff * diff;\n    };\n\n    // Initial total error\n    long long current_total_err = 0;\n    for (size_t i = 0; i < m.history.size(); ++i) {\n        current_total_err += calc_error_term(current_w[i], m.history[i].second);\n    }\n    \n    // Cost function: minimize prediction error (primary) and skill magnitude (secondary, regularization)\n    // Weight 100000LL ensures error reduction takes precedence over regularization\n    long long current_cost = current_total_err * 100000LL + current_sum_s;\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int k = rng() % K;\n        int original_val = m.s[k];\n        \n        // Helper to evaluate and apply a change in s[k]\n        auto try_change = [&](int new_val) -> bool {\n            long long new_total_err = 0;\n            // Incrementally compute new error\n            for (size_t i = 0; i < m.history.size(); ++i) {\n                int t_idx = m.history[i].first;\n                int d_k = tasks[t_idx].d[k];\n                int w_old = current_w[i];\n                // Removing old contribution of k, adding new contribution\n                int term_old = max(0, d_k - original_val);\n                int term_new = max(0, d_k - new_val);\n                int w_new = w_old - term_old + term_new;\n                new_total_err += calc_error_term(w_new, m.history[i].second);\n            }\n            \n            long long new_sum_s = current_sum_s - original_val + new_val;\n            long long new_cost = new_total_err * 100000LL + new_sum_s;\n            \n            if (new_cost < current_cost) {\n                // Accept change\n                m.s[k] = new_val;\n                current_sum_s = new_sum_s;\n                current_total_err = new_total_err;\n                current_cost = new_cost;\n                // Update cached w values\n                for (size_t i = 0; i < m.history.size(); ++i) {\n                    int t_idx = m.history[i].first;\n                    int d_k = tasks[t_idx].d[k];\n                    current_w[i] = current_w[i] - max(0, d_k - original_val) + max(0, d_k - new_val);\n                }\n                return true;\n            }\n            return false;\n        };\n\n        // Try increasing skill\n        if (try_change(original_val + 1)) continue;\n        \n        // Try decreasing skill\n        if (original_val > 0) {\n            try_change(original_val - 1);\n        }\n    }\n}\n\n// Compute critical path height using memoization\nint get_height(int u) {\n    if (memo_height[u] != -1) return memo_height[u];\n    int h = 0;\n    for (int v : tasks[u].dependency_to) {\n        h = max(h, get_height(v));\n    }\n    return memo_height[u] = 1 + h;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) cin >> tasks[i].d[k];\n        tasks[i].unresolved_dependencies = 0;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-based indexing\n        tasks[u].dependency_to.push_back(v);\n        tasks[v].unresolved_dependencies++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].s.assign(K, 0); // Initialize skills to 0\n        members[i].current_task_id = -1;\n        members[i].task_start_day = -1;\n    }\n\n    task_status.assign(N, 0);\n    memo_height.assign(N, -1);\n\n    // Precompute heights for prioritization\n    for (int i = 0; i < N; ++i) get_height(i);\n\n    int day = 0;\n    int tasks_finished_count = 0;\n\n    // Simulation loop\n    while (true) {\n        day++;\n        \n        // 1. Identify available tasks and free members\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 0 && tasks[i].unresolved_dependencies == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        vector<int> free_members;\n        for (int i = 0; i < M; ++i) {\n            if (members[i].current_task_id == -1) {\n                free_members.push_back(i);\n            }\n        }\n\n        // 2. Sort tasks by Importance (Critical Path Height > OutDegree)\n        sort(available_tasks.begin(), available_tasks.end(), [&](int a, int b) {\n            if (tasks[a].height != tasks[b].height) return tasks[a].height > tasks[b].height;\n            return tasks[a].dependency_to.size() > tasks[b].dependency_to.size();\n        });\n\n        // 3. Greedy Assignment\n        vector<pair<int, int>> assignments;\n        vector<bool> member_taken(M, false);\n\n        for (int tid : available_tasks) {\n            int best_m = -1;\n            int min_days = 1e9;\n            long long best_waste = 1e18; \n\n            for (int mid : free_members) {\n                if (member_taken[mid]) continue;\n                \n                int pred = predict_days(tid, members[mid].s);\n                long long current_sum_s = 0;\n                for(int v : members[mid].s) current_sum_s += v;\n\n                // Prioritize minimizing duration. \n                // Tie-break: choose member with lower total skill (saving \"experts\" for harder tasks).\n                if (pred < min_days) {\n                    min_days = pred;\n                    best_m = mid;\n                    best_waste = current_sum_s;\n                } else if (pred == min_days) {\n                    if (current_sum_s < best_waste) {\n                        best_m = mid;\n                        best_waste = current_sum_s;\n                    }\n                }\n            }\n\n            if (best_m != -1) {\n                assignments.push_back({best_m, tid});\n                member_taken[best_m] = true;\n            }\n        }\n\n        // 4. Output Assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n            // Update state\n            members[p.first].current_task_id = p.second;\n            members[p.first].task_start_day = day;\n            task_status[p.second] = 1; \n        }\n        cout << endl; // Flush output\n\n        // 5. Read Completed Tasks\n        int n_completed;\n        cin >> n_completed;\n        if (n_completed == -1) {\n            // End of simulation\n            break;\n        }\n\n        for (int i = 0; i < n_completed; ++i) {\n            int member_id_1based;\n            cin >> member_id_1based;\n            int mid = member_id_1based - 1;\n            \n            int tid = members[mid].current_task_id;\n            int start_day = members[mid].task_start_day;\n            int duration = day - start_day + 1; \n            \n            // Record history\n            members[mid].history.push_back({tid, duration});\n            members[mid].current_task_id = -1;\n            members[mid].task_start_day = -1;\n            \n            // Learn skills\n            update_skills(mid);\n            \n            // Update dependency graph\n            task_status[tid] = 2;\n            tasks_finished_count++;\n            \n            for (int next_task : tasks[tid].dependency_to) {\n                tasks[next_task].unresolved_dependencies--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconst int NUM_ORDERS = 1000;\nconst int TARGET_ORDERS = 50;\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// Data structures\nstruct Order {\n    int id;\n    int a, b, c, d; // (a,b) pickup, (c,d) delivery\n};\n\nstruct Node {\n    int id; // Internal ID: 0..999 for Pickup, 1000..1999 for Delivery\n    int x, y;\n    bool is_pickup;\n    int order_idx;\n};\n\nstruct Solution {\n    vector<int> route; // Stores node IDs. Does not include Office.\n    bool selected[NUM_ORDERS];\n    int total_dist;\n};\n\n// Globals\nOrder orders[NUM_ORDERS];\n\n// Utils\ninline int dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline Node get_node(int val) {\n    if (val < 1000) {\n        return {val, orders[val].a, orders[val].b, true, val};\n    } else {\n        return {val, orders[val - 1000].c, orders[val - 1000].d, false, val - 1000};\n    }\n}\n\n// Calculate total distance of a route\nint calc_route_dist(const vector<int>& route) {\n    int d = 0;\n    int cx = OFFICE_X;\n    int cy = OFFICE_Y;\n    for (int val : route) {\n        Node n = get_node(val);\n        d += dist(cx, cy, n.x, n.y);\n        cx = n.x;\n        cy = n.y;\n    }\n    d += dist(cx, cy, OFFICE_X, OFFICE_Y);\n    return d;\n}\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        return next() % n;\n    }\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n} rng;\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read Input\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n\n    // Initial Solution Construction\n    Solution curr_sol;\n    fill(curr_sol.selected, curr_sol.selected + NUM_ORDERS, false);\n    \n    // Heuristic: Find order closest to office to start a cluster\n    int start_order = -1;\n    int min_d = 1e9;\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        int d = dist(OFFICE_X, OFFICE_Y, orders[i].a, orders[i].b);\n        if(d < min_d) {\n            min_d = d;\n            start_order = i;\n        }\n    }\n    \n    // Select 50 orders based on proximity to the start_order\n    vector<pair<int,int>> dists;\n    dists.reserve(NUM_ORDERS);\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        // Distance metric: dist(start_P, i_P)\n        int d = dist(orders[start_order].a, orders[start_order].b, orders[i].a, orders[i].b); \n        dists.push_back({d, i});\n    }\n    sort(dists.begin(), dists.end());\n    \n    for(int k=0; k<TARGET_ORDERS; ++k) {\n        int idx = dists[k].second;\n        curr_sol.selected[idx] = true;\n        curr_sol.route.push_back(idx);        // Pickup\n        curr_sol.route.push_back(idx + 1000); // Delivery\n    }\n    \n    curr_sol.total_dist = calc_route_dist(curr_sol.route);\n    Solution best_sol = curr_sol;\n\n    // Simulated Annealing\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95;\n    double temp_start = 200.0;\n    double temp_end = 1.0;\n    \n    int iter = 0;\n    \n    // Pos array for quick lookups in validity checks\n    vector<int> pos_cache(2000); \n\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            chrono::duration<double> diff = now - start_time;\n            if (diff.count() > time_limit) break;\n        }\n        \n        // Temperature Schedule\n        // Simple linear interpolation based on time isn't strictly exponential but works well\n        auto now = chrono::high_resolution_clock::now();\n        double progress = (now - start_time).count() / 1e9 / time_limit; \n        // Actually proper annealing uses exponential decay\n        double cur_time = (double)(iter) / 500000.0; // approximate scaling\n        if (progress > 1.0) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int type = rng.next_int(100);\n        \n        if (type < 15) { \n            // ==========================================\n            // Move Type 1: Swap Order (Remove one, Add one)\n            // ==========================================\n            \n            // 1. Pick random order to remove from route\n            int r_idx = rng.next_int(curr_sol.route.size());\n            int val = curr_sol.route[r_idx];\n            int rem_order = (val < 1000) ? val : val - 1000;\n            \n            // 2. Remove P and D from temporary route\n            vector<int> next_route = curr_sol.route;\n            // Remove larger index first to keep smaller index valid\n            int p_pos = -1, d_pos = -1;\n            for(size_t i=0; i<next_route.size(); ++i) {\n                int ov = next_route[i];\n                if (ov == rem_order) p_pos = i;\n                else if (ov == rem_order + 1000) d_pos = i;\n            }\n            \n            if (d_pos > p_pos) {\n                next_route.erase(next_route.begin() + d_pos);\n                next_route.erase(next_route.begin() + p_pos);\n            } else {\n                next_route.erase(next_route.begin() + p_pos);\n                next_route.erase(next_route.begin() + d_pos);\n            }\n            \n            // 3. Pick random new order\n            int new_order = -1;\n            while(true) {\n                int cand = rng.next_int(NUM_ORDERS);\n                if (!curr_sol.selected[cand]) {\n                    new_order = cand;\n                    break;\n                }\n            }\n            \n            // 4. Greedy Insertion: Find best valid positions for P and D of new_order\n            // We need to insert P at i, D at j (j >= i).\n            \n            // Calculate base distance of the route without the new order\n            int base_dist = calc_route_dist(next_route);\n            \n            Node P = get_node(new_order);\n            Node D = get_node(new_order + 1000);\n            \n            int best_cost = 2e9;\n            int best_i = -1, best_j = -1;\n            \n            int n_size = next_route.size();\n            \n            // Optimization: Pre-calculate node coordinates for fast access\n            // Adding Office at start and end virtually\n            \n            for(int i=0; i<=n_size; ++i) {\n                // Context for P insertion: between (i-1) and (i)\n                int prev_x = (i==0) ? OFFICE_X : get_node(next_route[i-1]).x;\n                int prev_y = (i==0) ? OFFICE_Y : get_node(next_route[i-1]).y;\n                int next_x = (i==n_size) ? OFFICE_X : get_node(next_route[i]).x;\n                int next_y = (i==n_size) ? OFFICE_Y : get_node(next_route[i]).y;\n                \n                // Delta for inserting P\n                int delta_P = dist(prev_x, prev_y, P.x, P.y) + dist(P.x, P.y, next_x, next_y) \n                              - dist(prev_x, prev_y, next_x, next_y);\n                \n                // Pruning: if delta_P alone makes it worse than best known, maybe skip? \n                // No, because D insertion adds cost, so cost always increases.\n                \n                // Try inserting D at j >= i\n                // If j == i, D is inserted immediately after P.\n                // If j > i, D is inserted at position j in the *original* next_route indices\n                // which corresponds to between next_route[j-1] and next_route[j].\n                \n                for(int j=i; j<=n_size; ++j) {\n                    int current_val = base_dist + delta_P;\n                    int delta_D = 0;\n                    \n                    if (j == i) {\n                        // Sequence: prev -> P -> D -> next\n                        // Currently delta_P accounts for prev->P->next.\n                        // We need to change P->next to P->D->next.\n                        delta_D = dist(P.x, P.y, D.x, D.y) + dist(D.x, D.y, next_x, next_y)\n                                  - dist(P.x, P.y, next_x, next_y);\n                    } else {\n                        // Sequence around j (j > i): node[j-1] -> D -> node[j]\n                        int d_prev_x = get_node(next_route[j-1]).x;\n                        int d_prev_y = get_node(next_route[j-1]).y;\n                        int d_next_x = (j==n_size) ? OFFICE_X : get_node(next_route[j]).x;\n                        int d_next_y = (j==n_size) ? OFFICE_Y : get_node(next_route[j]).y;\n                        \n                        delta_D = dist(d_prev_x, d_prev_y, D.x, D.y) + dist(D.x, D.y, d_next_x, d_next_y)\n                                  - dist(d_prev_x, d_prev_y, d_next_x, d_next_y);\n                    }\n                    \n                    if (current_val + delta_D < best_cost) {\n                        best_cost = current_val + delta_D;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            int delta = best_cost - curr_sol.total_dist;\n            if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                curr_sol.selected[rem_order] = false;\n                curr_sol.selected[new_order] = true;\n                curr_sol.route = next_route;\n                curr_sol.route.insert(curr_sol.route.begin() + best_i, new_order);\n                // Since P inserted at i, indices >= i shift by 1. \n                // If j was index in next_route, now it's j+1 relative to new array start\n                // Exception: if j=i, we insert D after P, so at i+1.\n                // If j > i, we insert after original j-1 (now j), so at j+1.\n                curr_sol.route.insert(curr_sol.route.begin() + best_j + 1, new_order + 1000);\n                curr_sol.total_dist = best_cost;\n                \n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 65) {\n            // ==========================================\n            // Move Type 2: 2-opt (Reverse segment)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int l = rng.next_int(sz - 1);\n            int r = rng.next_int(sz - l - 1) + l + 1; // l < r < sz\n            \n            // Validity Check: Reversed segment [l, r] must not contain P_k and D_k for any k.\n            // Efficient check:\n            bool valid = true;\n            \n            // Fill cache for current route positions\n            for(int k=0; k<sz; ++k) pos_cache[curr_sol.route[k]] = k;\n            \n            for(int k=l; k<=r; ++k) {\n                int val = curr_sol.route[k];\n                int partner = (val < 1000) ? val + 1000 : val - 1000;\n                // If partner is also in [l, r], invalid\n                int p_idx = pos_cache[partner];\n                if (p_idx >= l && p_idx <= r) {\n                    valid = false;\n                    break;\n                }\n            }\n            \n            if (valid) {\n                Node n_prev = (l==0) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[l-1]);\n                Node n_l = get_node(curr_sol.route[l]);\n                Node n_r = get_node(curr_sol.route[r]);\n                Node n_next = (r==sz-1) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[r+1]);\n                \n                int cur_seg = dist(n_prev.x, n_prev.y, n_l.x, n_l.y) + dist(n_r.x, n_r.y, n_next.x, n_next.y);\n                int new_seg = dist(n_prev.x, n_prev.y, n_r.x, n_r.y) + dist(n_l.x, n_l.y, n_next.x, n_next.y);\n                \n                int delta = new_seg - cur_seg;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    reverse(curr_sol.route.begin() + l, curr_sol.route.begin() + r + 1);\n                    curr_sol.total_dist += delta;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n\n        } else {\n            // ==========================================\n            // Move Type 3: Relocate (Move single node)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int u = rng.next_int(sz); // Node to move\n            int v = rng.next_int(sz); // Target: insert after v (if v=-1, start)\n            // To simplify, let's say we pick index `ins_idx` in the route *after removal*.\n            // Range 0 to sz-1.\n            \n            if (u == v) continue;\n            \n            // Logic: remove u, insert at v (relative to original indices is tricky).\n            // Let's form candidate vector to check validity/cost simply,\n            // relying on vector speed for small N=100.\n            \n            vector<int> next_route = curr_sol.route;\n            int val = next_route[u];\n            next_route.erase(next_route.begin() + u);\n            \n            // Insert position logic: \n            // We picked random v in range [0, sz-1].\n            // We interpret v as the index to insert *at* in the reduced vector.\n            int ins_idx = v; \n            if (ins_idx > (int)next_route.size()) ins_idx = next_route.size();\n            \n            // Precedence check\n            int partner = (val < 1000) ? val + 1000 : val - 1000;\n            int p_idx = -1;\n            for(int k=0; k<(int)next_route.size(); ++k) {\n                if (next_route[k] == partner) { p_idx = k; break; }\n            }\n            \n            bool ok = true;\n            if (val < 1000) { // Moving Pickup\n                // Must be before Delivery (p_idx)\n                if (ins_idx > p_idx) ok = false;\n            } else { // Moving Delivery\n                // Must be after Pickup (p_idx)\n                if (ins_idx <= p_idx) ok = false;\n            }\n            \n            if (ok) {\n                next_route.insert(next_route.begin() + ins_idx, val);\n                int new_dist = calc_route_dist(next_route);\n                int delta = new_dist - curr_sol.total_dist;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    curr_sol.route = next_route;\n                    curr_sol.total_dist = new_dist;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n        }\n    }\n\n    // Output Formatting\n    // 1. Output m and selected orders\n    vector<int> selected_ids;\n    set<int> seen;\n    for(int val : best_sol.route) {\n        int ord = (val < 1000) ? val : val - 1000;\n        if(seen.find(ord) == seen.end()) {\n            selected_ids.push_back(ord + 1); // 1-based index for output\n            seen.insert(ord);\n        }\n    }\n    \n    cout << selected_ids.size();\n    for(int id : selected_ids) cout << \" \" << id;\n    cout << \"\\n\";\n    \n    // 2. Output route coordinates\n    cout << best_sol.route.size() + 2 << \" \" << OFFICE_X << \" \" << OFFICE_Y;\n    for(int val : best_sol.route) {\n        Node n = get_node(val);\n        cout << \" \" << n.x << \" \" << n.y;\n    }\n    cout << \" \" << OFFICE_X << \" \" << OFFICE_Y << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Global constants and data structures\nconst int N_FIXED = 400;\n\nstruct Point {\n    int x, y;\n};\n\nstruct EdgeInfo {\n    int u, v;\n    int d;\n    int id;\n};\n\nstruct ContractedEdge {\n    int u_c, v_c; // component leaders\n    int d_val;\n    int original_idx;\n};\n\nint N, M;\nvector<Point> points;\nvector<EdgeInfo> all_edges;\nvector<int> min_d_vals; // Helper for filtering\n\n// Random number generator\nmt19937 rng(12345);\n\n// Custom lightweight DSU for simulation speed\nstruct FastDSU {\n    vector<int> parent;\n    FastDSU(int n) : parent(n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    void reset() {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        // Path compression\n        int root = i;\n        while (root != parent[root]) root = parent[root];\n        int curr = i;\n        while (curr != root) {\n            int next = parent[curr];\n            parent[curr] = root;\n            curr = next;\n        }\n        return root;\n    }\n    bool unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n            return true;\n        }\n        return false;\n    }\n};\n\nint calc_dist(int i, int j) {\n    long long dx = points[i].x - points[j].x;\n    long long dy = points[i].y - points[j].y;\n    return (int)round(sqrt(dx*dx + dy*dy));\n}\n\n// Time management\nconst double TIME_LIMIT = 1.85; \nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_elapsed_time() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nint main() {\n    // Setup IO\n    ios_base::sync_with_stdio(false);\n    // cin.tie(NULL); // Interactive problem, but we flush with endl\n\n    if (!(cin >> N >> M)) return 0;\n    \n    points.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> points[i].x >> points[i].y;\n    }\n    \n    all_edges.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> all_edges[i].u >> all_edges[i].v;\n        all_edges[i].d = calc_dist(all_edges[i].u, all_edges[i].v);\n        all_edges[i].id = i;\n    }\n\n    // Buffer for filtering edges\n    min_d_vals.assign(N * N, 1000000);\n    \n    // Main DSU for tracking actual connected components\n    dsu main_dsu(N);\n    int components = N;\n    \n    // Reusable DSU for simulations\n    FastDSU sim_dsu(N);\n    \n    // Pre-allocate vectors for simulation\n    vector<pair<int, int>> weighted_edges;\n    weighted_edges.reserve(M);\n    vector<int> spans;\n    spans.reserve(M);\n    \n    // BFS structures for bridge check\n    vector<vector<int>> adj(N);\n    vector<int> q_bfs; q_bfs.reserve(N);\n    vector<bool> visited(N);\n\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n        \n        int u = all_edges[i].u;\n        int v = all_edges[i].v;\n        \n        // 1. If u and v are already connected, reject immediately (cycle).\n        if (main_dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n        \n        // 2. Filter and prepare future edges\n        // We only care about edges that connect different components.\n        // We also prune edges that are strictly worse than others (d > 3*min_d).\n        \n        vector<ContractedEdge> future_edges;\n        future_edges.reserve(M - 1 - i);\n        vector<int> active_pairs;\n        active_pairs.reserve(M - 1 - i);\n        \n        // Pass 1: Find min d for each pair of components\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.leader(all_edges[j].u);\n            int rv = main_dsu.leader(all_edges[j].v);\n            if (ru == rv) continue;\n            if (ru > rv) swap(ru, rv);\n            int idx = ru * N + rv;\n            \n            if (min_d_vals[idx] == 1000000) {\n                active_pairs.push_back(idx);\n            }\n            if (all_edges[j].d < min_d_vals[idx]) {\n                min_d_vals[idx] = all_edges[j].d;\n            }\n        }\n        \n        // Pass 2: Collect valid future edges\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.leader(all_edges[j].u);\n            int rv = main_dsu.leader(all_edges[j].v);\n            if (ru == rv) continue;\n            if (ru > rv) swap(ru, rv);\n            int idx = ru * N + rv;\n            \n            // Pruning heuristic\n            if (all_edges[j].d > 3 * min_d_vals[idx]) continue;\n            \n            future_edges.push_back({ru, rv, all_edges[j].d, j});\n        }\n        \n        // Reset min_d_vals\n        for (int idx : active_pairs) min_d_vals[idx] = 1000000;\n        \n        int ru_curr = main_dsu.leader(u);\n        int rv_curr = main_dsu.leader(v);\n\n        // 3. Bridge Check\n        // Check if connectivity is possible without the current edge using only future edges\n        for(int k=0; k<N; ++k) adj[k].clear();\n        for(const auto& e : future_edges) {\n            adj[e.u_c].push_back(e.v_c);\n            adj[e.v_c].push_back(e.u_c);\n        }\n        \n        fill(visited.begin(), visited.end(), false);\n        q_bfs.clear();\n        q_bfs.push_back(ru_curr);\n        visited[ru_curr] = true;\n        \n        bool connected = false;\n        int head = 0;\n        while(head < (int)q_bfs.size()){\n            int curr = q_bfs[head++];\n            if (curr == rv_curr) {\n                connected = true;\n                break;\n            }\n            for(int nxt : adj[curr]){\n                if(!visited[nxt]){\n                    visited[nxt] = true;\n                    q_bfs.push_back(nxt);\n                }\n            }\n        }\n        \n        if (!connected) {\n            // Must accept to maintain connectivity\n            cout << 1 << endl;\n            main_dsu.merge(u, v);\n            components--;\n            continue;\n        }\n        \n        // 4. Monte Carlo Simulation\n        double elapsed = get_elapsed_time();\n        double rem_time = TIME_LIMIT - elapsed;\n        int steps_left = M - 1 - i;\n        // Allocate time budget for this step\n        double budget = rem_time / (steps_left + 20); \n        \n        long long sum_accept = 0;\n        long long sum_reject = 0;\n        int sims = 0;\n        \n        auto sim_start_t = chrono::high_resolution_clock::now();\n        \n        weighted_edges.resize(future_edges.size());\n        spans.resize(future_edges.size());\n        for(size_t k=0; k<future_edges.size(); ++k) {\n            spans[k] = 2 * future_edges[k].d_val + 1;\n        }\n\n        do {\n            sims++;\n            // Generate random weights for future edges\n            for (size_t k = 0; k < future_edges.size(); ++k) {\n                unsigned int r = rng();\n                int w = future_edges[k].d_val + (r % spans[k]);\n                weighted_edges[k] = {w, (int)k};\n            }\n            \n            // Kruskal's requires sorted edges\n            sort(weighted_edges.begin(), weighted_edges.end());\n            \n            // Calculate MST cost given a starting state (merge_uv or not)\n            auto get_mst_cost = [&](bool merge_uv) {\n                sim_dsu.reset();\n                int edges_needed = components - 1;\n                if (merge_uv) {\n                    sim_dsu.unite(ru_curr, rv_curr);\n                    edges_needed--;\n                }\n                \n                long long cost = 0;\n                int cnt = 0;\n                // If already connected (edges_needed <= 0), cost is 0\n                if (cnt >= edges_needed) return cost;\n\n                for (const auto& p : weighted_edges) {\n                    const auto& e = future_edges[p.second];\n                    if (sim_dsu.unite(e.u_c, e.v_c)) {\n                        cost += p.first;\n                        cnt++;\n                        if (cnt >= edges_needed) break;\n                    }\n                }\n                return cost;\n            };\n            \n            sum_accept += (l_i + get_mst_cost(true));\n            sum_reject += get_mst_cost(false);\n            \n            // Check time every 16 iterations to minimize overhead\n            if ((sims & 15) == 0) {\n                auto now = chrono::high_resolution_clock::now();\n                chrono::duration<double> d_sim = now - sim_start_t;\n                if (d_sim.count() > budget) break;\n            }\n            \n        } while (sims < 500); // Safety cap\n        \n        // Decision\n        if (sum_accept < sum_reject) {\n            cout << 1 << endl;\n            main_dsu.merge(u, v);\n            components--;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"/**\n * AtCoder Heuristic Contest 008\n * Solution: Robust Honeycomb Trap with Strict Conflict Resolution\n * \n * Strategy:\n * 1. Layout: We overlay a skeleton of \"rooms\" (approx 5x5 size) on the 30x30 grid.\n *    - Walls are planned at specific rows/cols.\n *    - Gates are planned at the centers of these wall segments.\n * 2. Dynamic Logic:\n *    - We detect \"Dirty\" components (containing pets) and \"Clean\" components.\n *    - We assign priorities: \n *      a. ESCAPE: Humans in dirty rooms must leave.\n *      b. TRAP: Close gates connecting dirty rooms to clean rooms.\n *      c. BUILD: Construct the skeleton.\n * 3. Safety & Conflict Resolution:\n *    - Strict checks to ensure no two humans move to the same square.\n *    - Strict checks to ensure no human moves into a wall being built in the same turn.\n *    - A conservative reservation system ensures that high-priority movers do not displace \n *      low-priority waiters (preventing the \"moving to occupied square\" error).\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --- Constants & Utils ---\nconst int N_ROWS = 30;\nconst int N_COLS = 30;\nconst int MAX_TURNS = 300;\n\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'}; \n\nstruct Pet {\n    int id;\n    int r, c; \n    int type;\n};\n\nstruct Human {\n    int id;\n    int r, c;\n};\n\nstruct State {\n    vector<Pet> pets;\n    vector<Human> humans;\n    bool walls[N_ROWS][N_COLS];\n};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_ROWS && c >= 0 && c < N_COLS;\n}\n\n// --- Strategic Plan ---\nbool plan_skeleton[N_ROWS][N_COLS];\nbool plan_gate[N_ROWS][N_COLS]; // True if this wall part is a gate (initially open)\n\nvoid init_plan() {\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c) {\n            plan_skeleton[r][c] = false;\n            plan_gate[r][c] = false;\n        }\n\n    // Create a grid of walls. \n    // Lines at indices: 5, 11, 17, 23. \n    // This creates 5x5 and 4x5 sized regions.\n    vector<int> lines = {5, 11, 17, 23};\n    \n    for (int r : lines) {\n        for (int c = 0; c < N_COLS; ++c) plan_skeleton[r][c] = true;\n    }\n    for (int c : lines) {\n        for (int r = 0; r < N_ROWS; ++r) plan_skeleton[r][c] = true;\n    }\n    \n    // Define Gates at midpoints of wall segments\n    // Segments: 0-4, 6-10, 12-16, 18-22, 24-29\n    // Mids: 2, 8, 14, 20, 27\n    vector<int> mids = {2, 8, 14, 20, 27};\n    \n    for(int r : lines) {\n        for(int m : mids) plan_gate[r][m] = true;\n    }\n    for(int c : lines) {\n        for(int m : mids) plan_gate[m][c] = true;\n    }\n    \n    // Intersections are always solid walls\n    for(int r : lines) {\n        for(int c : lines) plan_gate[r][c] = false;\n    }\n}\n\n// --- Analysis Helpers ---\n\nstruct Component {\n    int id;\n    bool has_pet = false;\n    vector<pair<int,int>> cells;\n};\n\nvoid get_components(const State& st, vector<vector<int>>& id_map, vector<Component>& comps) {\n    id_map.assign(N_ROWS, vector<int>(N_COLS, -1));\n    comps.clear();\n    \n    for(int r=0; r<N_ROWS; ++r){\n        for(int c=0; c<N_COLS; ++c){\n            if(!st.walls[r][c] && id_map[r][c] == -1){\n                int cid = comps.size();\n                Component comp;\n                comp.id = cid;\n                \n                queue<pair<int,int>> q;\n                q.push({r,c});\n                id_map[r][c] = cid;\n                \n                while(!q.empty()){\n                    auto [cr, cc] = q.front();\n                    q.pop();\n                    comp.cells.push_back({cr, cc});\n                    \n                    for(int i=0; i<4; ++i){\n                        int nr = cr + DR[i];\n                        int nc = cc + DC[i];\n                        if(is_valid(nr, nc) && !st.walls[nr][nc] && id_map[nr][nc] == -1){\n                            id_map[nr][nc] = cid;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                comps.push_back(comp);\n            }\n        }\n    }\n    \n    for(const auto& p : st.pets) {\n        if(id_map[p.r][p.c] != -1) comps[id_map[p.r][p.c]].has_pet = true;\n    }\n}\n\n// BFS pathfinding with strict reservation checks\n// Returns direction index (0-3) or -1\nint bfs_move(int sr, int sc, const vector<pair<int,int>>& targets, \n             const State& st, \n             const vector<vector<bool>>& reserved_next_pos, \n             const vector<vector<bool>>& reserved_new_wall,\n             const vector<bool>& processed_agents) {\n    \n    if(targets.empty()) return -1;\n\n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    \n    vector<vector<int>> dist(N_ROWS, vector<int>(N_COLS, 1e9));\n    vector<vector<pair<int,int>>> parent(N_ROWS, vector<pair<int,int>>(N_COLS, {-1,-1}));\n    \n    dist[sr][sc] = 0;\n    bool found = false;\n    int er = -1, ec = -1;\n    \n    // Optimization: Check targets quickly\n    static int target_mark[N_ROWS][N_COLS];\n    static int mark_counter = 0;\n    mark_counter++;\n    for(auto& t : targets) target_mark[t.first][t.second] = mark_counter;\n    \n    while(!q.empty()){\n        auto [cr, cc] = q.front();\n        q.pop();\n        \n        if(target_mark[cr][cc] == mark_counter){\n            found = true;\n            er = cr; ec = cc;\n            break;\n        }\n        \n        for(int i=0; i<4; ++i){\n            int nr = cr + DR[i];\n            int nc = cc + DC[i];\n            \n            if(!is_valid(nr, nc)) continue;\n            if(st.walls[nr][nc]) continue;\n            \n            // Check dynamic obstacles only for the immediate next step (t+1)\n            if(dist[cr][cc] == 0) {\n                // Cannot move into a new wall\n                if(reserved_new_wall[nr][nc]) continue;\n                // Cannot move into a spot reserved by a processed agent\n                if(reserved_next_pos[nr][nc]) continue;\n                \n                // Conservative Check: Cannot move into a spot occupied by an unprocessed agent\n                // (Because that agent might stay)\n                bool collision = false;\n                for(const auto& h : st.humans){\n                    if(!processed_agents[h.id] && h.r == nr && h.c == nc) collision = true;\n                }\n                if(collision) continue;\n            }\n            \n            if(dist[nr][nc] > dist[cr][cc] + 1){\n                dist[nr][nc] = dist[cr][cc] + 1;\n                parent[nr][nc] = {cr, cc};\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if(!found) return -1;\n    if(er == sr && ec == sc) return -1;\n    \n    // Backtrack\n    int cur_r = er, cur_c = ec;\n    while(parent[cur_r][cur_c].first != sr || parent[cur_r][cur_c].second != sc){\n        auto p = parent[cur_r][cur_c];\n        cur_r = p.first;\n        cur_c = p.second;\n    }\n    \n    for(int i=0; i<4; ++i){\n        if(sr + DR[i] == cur_r && sc + DC[i] == cur_c) return i;\n    }\n    return -1;\n}\n\n// --- Main Logic ---\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_plan();\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    \n    State state;\n    state.pets.resize(N);\n    for(int i=0; i<N; ++i){\n        state.pets[i].id = i;\n        cin >> state.pets[i].r >> state.pets[i].c >> state.pets[i].type;\n        state.pets[i].r--; state.pets[i].c--; \n    }\n    \n    int M;\n    cin >> M;\n    state.humans.resize(M);\n    for(int i=0; i<M; ++i){\n        state.humans[i].id = i;\n        cin >> state.humans[i].r >> state.humans[i].c;\n        state.humans[i].r--; state.humans[i].c--;\n    }\n    \n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c)\n            state.walls[r][c] = false;\n            \n    for(int turn=0; turn<MAX_TURNS; ++turn){\n        // 1. Component Analysis\n        vector<vector<int>> comp_map;\n        vector<Component> comps;\n        get_components(state, comp_map, comps);\n        \n        // Identify humans in danger\n        vector<bool> in_danger(M, false);\n        for(int i=0; i<M; ++i){\n            int cid = comp_map[state.humans[i].r][state.humans[i].c];\n            if(cid != -1 && comps[cid].has_pet) in_danger[i] = true;\n        }\n        \n        // 2. Generate Build Tasks\n        struct Task {\n            int r, c; // Wall location\n            int priority;\n        };\n        vector<Task> tasks;\n        \n        for(int r=0; r<N_ROWS; ++r){\n            for(int c=0; c<N_COLS; ++c){\n                if(state.walls[r][c]) continue;\n                if(!plan_skeleton[r][c]) continue;\n                \n                int prio = 0;\n                bool is_gate = plan_gate[r][c];\n                \n                // Check connectivity of this potential wall\n                set<int> adj_comps;\n                for(int k=0; k<4; ++k){\n                    int nr = r + DR[k];\n                    int nc = c + DC[k];\n                    if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                        if(comp_map[nr][nc] != -1) adj_comps.insert(comp_map[nr][nc]);\n                    }\n                }\n                \n                bool connects_dirty = false;\n                bool connects_clean = false;\n                for(int cid : adj_comps){\n                    if(comps[cid].has_pet) connects_dirty = true;\n                    else connects_clean = true;\n                }\n                \n                if(!is_gate) {\n                    prio = 50; \n                    if(connects_dirty) prio += 200; \n                } else {\n                    // Gate logic\n                    if(connects_dirty && connects_clean) prio = 1000; // MUST CLOSE\n                    else if(connects_dirty) prio = 500; // Contain dirty\n                    else prio = 10; // Clean area, keep low priority\n                }\n                \n                if(prio > 0) tasks.push_back({r, c, prio});\n            }\n        }\n        \n        // 3. Assign Agents to Plans\n        struct AgentPlan {\n            int h_idx;\n            int type; // 0: Wait, 1: Build, 2: Escape/Move\n            int target_r, target_c; \n            double score;\n        };\n        vector<AgentPlan> agents;\n        \n        auto get_dist = [&](int r1, int c1, int r2, int c2) {\n            return abs(r1 - r2) + abs(c1 - c2);\n        };\n        \n        for(int i=0; i<M; ++i){\n            AgentPlan p;\n            p.h_idx = i;\n            p.type = 0; \n            p.score = -1e9;\n            \n            if(in_danger[i]){\n                p.type = 2; \n                p.score = 100000; \n                p.target_r = -1; // Generic \"Safe Place\"\n            } else {\n                // Find best build task\n                for(const auto& t : tasks){\n                    // Verify safety (adjacent to pet rule)\n                    bool pet_adj = false;\n                    for(const auto& pt : state.pets) if(get_dist(t.r, t.c, pt.r, pt.c) <= 1) pet_adj = true;\n                    if(pet_adj) continue;\n                    \n                    // Verify no human stands on the wall site (current pos)\n                    bool human_on_site = false;\n                    for(const auto& h : state.humans) if(h.r == t.r && h.c == t.c) human_on_site = true;\n                    if(human_on_site) continue;\n                    \n                    int d = 1e9;\n                    for(int k=0; k<4; ++k){\n                        int nr = t.r + DR[k];\n                        int nc = t.c + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                            d = min(d, get_dist(state.humans[i].r, state.humans[i].c, nr, nc));\n                        }\n                    }\n                    \n                    if(d < 1e9){\n                        double s = t.priority * 100.0 - d;\n                        if(s > p.score){\n                            p.score = s;\n                            p.target_r = t.r;\n                            p.target_c = t.c;\n                            p.type = 1; // Build\n                        }\n                    }\n                }\n            }\n            agents.push_back(p);\n        }\n        \n        // Sort by score descending\n        sort(agents.begin(), agents.end(), [](const AgentPlan& a, const AgentPlan& b){\n            return a.score > b.score;\n        });\n        \n        // 4. Execute Plans with strict conflict checks\n        vector<string> res_actions(M, \".\");\n        vector<vector<bool>> reserved_next(N_ROWS, vector<bool>(N_COLS, false));\n        vector<vector<bool>> reserved_wall(N_ROWS, vector<bool>(N_COLS, false));\n        vector<bool> processed(M, false);\n        \n        // Note: reserved_next tracks FINALIZED positions.\n        // processed[id] tracks if human `id` has moved.\n        // Unprocessed humans are treated as obstacles at their current pos.\n        \n        for(const auto& ag : agents){\n            int i = ag.h_idx;\n            processed[i] = true; // Mark as processed\n            \n            int r = state.humans[i].r;\n            int c = state.humans[i].c;\n            bool done = false;\n            \n            // -- Type 2: Escape --\n            if(ag.type == 2){\n                vector<pair<int,int>> clean_targets;\n                for(const auto& comp : comps){\n                    if(!comp.has_pet) {\n                        for(auto cell : comp.cells) clean_targets.push_back(cell);\n                    }\n                }\n                \n                int dir = bfs_move(r, c, clean_targets, state, reserved_next, reserved_wall, processed);\n                if(dir != -1){\n                    int nr = r + DR[dir];\n                    int nc = c + DC[dir];\n                    res_actions[i] = string(1, MOVE_CHARS[dir]);\n                    reserved_next[nr][nc] = true;\n                    done = true;\n                }\n            }\n            // -- Type 1: Build --\n            else if(ag.type == 1){\n                int tr = ag.target_r;\n                int tc = ag.target_c;\n                \n                // Can build?\n                if(get_dist(r, c, tr, tc) == 1){\n                    bool ok = true;\n                    if(state.walls[tr][tc] || reserved_wall[tr][tc]) ok = false;\n                    // Pet adjacency check\n                    for(const auto& pt : state.pets) if(get_dist(tr, tc, pt.r, pt.c) <= 1) ok = false;\n                    // Human occupancy (processed)\n                    if(reserved_next[tr][tc]) ok = false;\n                    // Human occupancy (unprocessed)\n                    for(const auto& h : state.humans) if(!processed[h.id] && h.r == tr && h.c == tc) ok = false;\n                    \n                    if(ok){\n                        int b_dir = -1;\n                        for(int k=0; k<4; ++k) if(r+DR[k]==tr && c+DC[k]==tc) b_dir = k;\n                        \n                        res_actions[i] = string(1, BLOCK_CHARS[b_dir]);\n                        reserved_wall[tr][tc] = true;\n                        reserved_next[r][c] = true; // Stay\n                        done = true;\n                    }\n                }\n                \n                // Move to build spot\n                if(!done){\n                    vector<pair<int,int>> spots;\n                    for(int k=0; k<4; ++k){\n                        int nr = tr + DR[k];\n                        int nc = tc + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc]){\n                            spots.push_back({nr, nc});\n                        }\n                    }\n                    int dir = bfs_move(r, c, spots, state, reserved_next, reserved_wall, processed);\n                    if(dir != -1){\n                        int nr = r + DR[dir];\n                        int nc = c + DC[dir];\n                        res_actions[i] = string(1, MOVE_CHARS[dir]);\n                        reserved_next[nr][nc] = true;\n                        done = true;\n                    }\n                }\n            }\n            \n            // -- Default: Stay --\n            if(!done){\n                // Try to stay\n                if(!reserved_next[r][c]){\n                    // Double check nobody claimed it (should be covered by reserved_next)\n                    // Check new wall\n                    if(!reserved_wall[r][c]) {\n                        res_actions[i] = \".\";\n                        reserved_next[r][c] = true;\n                    } else {\n                        // Emergency: Someone built a wall on us (should be prevented by build checks, but just in case)\n                        // Try to move any adjacent free\n                        for(int k=0; k<4; ++k){\n                            int nr = r+DR[k];\n                            int nc = c+DC[k];\n                            if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc] && !reserved_next[nr][nc]){\n                                // And check unprocessed\n                                bool coll = false;\n                                for(const auto& h : state.humans) if(!processed[h.id] && h.r==nr && h.c==nc) coll = true;\n                                if(!coll){\n                                    res_actions[i] = string(1, MOVE_CHARS[k]);\n                                    reserved_next[nr][nc] = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output\n        string out_s = \"\";\n        for(const auto& s : res_actions) out_s += s;\n        cout << out_s << endl;\n        \n        // Update State\n        for(int i=0; i<M; ++i){\n            char c = res_actions[i][0];\n            if(c >= 'A' && c <= 'Z'){ \n                for(int k=0; k<4; ++k){\n                    if(MOVE_CHARS[k] == c){\n                        state.humans[i].r += DR[k];\n                        state.humans[i].c += DC[k];\n                    }\n                }\n            } else if(c >= 'a' && c <= 'z'){\n                 for(int k=0; k<4; ++k){\n                    if(BLOCK_CHARS[k] == c){\n                        state.walls[state.humans[i].r + DR[k]][state.humans[i].c + DC[k]] = true;\n                    }\n                }\n            }\n        }\n        \n        if(turn < MAX_TURNS){\n            string p_s;\n            for(int i=0; i<N; ++i){\n                cin >> p_s;\n                for(char c : p_s){\n                     for(int k=0; k<4; ++k){\n                        if(MOVE_CHARS[k] == c){\n                            state.pets[i].r += DR[k];\n                            state.pets[i].c += DC[k];\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_STEPS = 200;\nconst int BEAM_WIDTH = 800; \nconst double EPS = 1e-12;\n\n// Globals\nint Si, Sj, Ti, Tj;\ndouble P;\nint H[N][N-1]; // Horizontal walls\nint V[N-1][N]; // Vertical walls\nint dist_mat[N][N];\nint flat_dist[N*N];\n\n// Directions: U, D, L, R\n// dr, dc\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dchar[4] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    string s;\n    vector<double> probs; // flattened 20x20 probability distribution\n    double score; \n    double heuristic; \n\n    // For descending sort/selection\n    bool operator>(const State& other) const {\n        return heuristic > other.heuristic;\n    }\n};\n\n// Compute shortest path distances from all cells to target using BFS\nvoid bfs_distances() {\n    for(int i=0; i<N; ++i) fill(dist_mat[i], dist_mat[i]+N, 100000);\n    queue<pair<int,int>> q;\n    dist_mat[Ti][Tj] = 0;\n    q.push({Ti, Tj});\n    \n    while(!q.empty()){\n        auto [r, c] = q.front();\n        q.pop();\n        \n        // Check all 4 directions for valid moves (reverse of normal moves)\n        // U: neighbor is (r-1, c), connected via V[r-1][c]\n        if (r > 0 && V[r-1][c] == 0) {\n            if (dist_mat[r-1][c] > dist_mat[r][c] + 1) {\n                dist_mat[r-1][c] = dist_mat[r][c] + 1;\n                q.push({r-1, c});\n            }\n        }\n        // D: neighbor is (r+1, c), connected via V[r][c]\n        if (r < N-1 && V[r][c] == 0) {\n            if (dist_mat[r+1][c] > dist_mat[r][c] + 1) {\n                dist_mat[r+1][c] = dist_mat[r][c] + 1;\n                q.push({r+1, c});\n            }\n        }\n        // L: neighbor is (r, c-1), connected via H[r][c-1]\n        if (c > 0 && H[r][c-1] == 0) {\n            if (dist_mat[r][c-1] > dist_mat[r][c] + 1) {\n                dist_mat[r][c-1] = dist_mat[r][c] + 1;\n                q.push({r, c-1});\n            }\n        }\n        // R: neighbor is (r, c+1), connected via H[r][c]\n        if (c < N-1 && H[r][c] == 0) {\n            if (dist_mat[r][c+1] > dist_mat[r][c] + 1) {\n                dist_mat[r][c+1] = dist_mat[r][c] + 1;\n                q.push({r, c+1});\n            }\n        }\n    }\n    // Flatten for faster access\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            flat_dist[i*N+j] = dist_mat[i][j];\n}\n\nint main(){\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> Si >> Sj >> Ti >> Tj >> P)) return 0;\n\n    // Read Horizontal walls\n    for(int i=0; i<N; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N-1; ++j) H[i][j] = s[j] - '0';\n    }\n    // Read Vertical walls\n    for(int i=0; i<N-1; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) V[i][j] = s[j] - '0';\n    }\n    \n    bfs_distances();\n    \n    double inv_prob = 1.0 / (1.0 - P);\n    int target_idx = Ti*N + Tj;\n\n    State initial;\n    initial.s = \"\";\n    initial.probs.resize(N*N, 0.0);\n    initial.probs[Si*N + Sj] = 1.0;\n    initial.score = 0.0;\n    \n    if(Si == Ti && Sj == Tj) {\n        initial.heuristic = 0; \n    } else {\n        double dist = flat_dist[Si*N + Sj];\n        initial.heuristic = initial.score + 1.0 * (401.0 - (0.0 + dist * inv_prob)); \n    }\n\n    vector<State> beam;\n    beam.reserve(BEAM_WIDTH * 4);\n    beam.push_back(initial);\n    \n    for(int t=0; t<MAX_STEPS; ++t){\n        vector<State> next_beam;\n        next_beam.reserve(beam.size() * 4);\n        \n        for(const auto& st : beam){\n            // Try all 4 directions\n            for(int k=0; k<4; ++k){\n                State nst;\n                nst.s = st.s + dchar[k];\n                nst.probs.assign(N*N, 0.0); \n                nst.score = st.score;\n                \n                // Update distribution based on move\n                for(int idx=0; idx<N*N; ++idx){\n                    if(st.probs[idx] < EPS) continue;\n                    \n                    double p_val = st.probs[idx];\n                    int r = idx / N;\n                    int c = idx % N;\n                    \n                    // 1. Stay with probability P\n                    nst.probs[idx] += p_val * P;\n                    \n                    // 2. Move with probability 1-P\n                    bool blocked = false;\n                    if(k == 0){ // U\n                        if(r == 0 || V[r-1][c] == 1) blocked = true;\n                    } else if(k == 1){ // D\n                        if(r == N-1 || V[r][c] == 1) blocked = true;\n                    } else if(k == 2){ // L\n                        if(c == 0 || H[r][c-1] == 1) blocked = true;\n                    } else if(k == 3){ // R\n                        if(c == N-1 || H[r][c] == 1) blocked = true;\n                    }\n                    \n                    if(blocked){\n                        // Hit wall, stay\n                        nst.probs[idx] += p_val * (1.0 - P);\n                    } else {\n                        // Move success\n                        int nr = r + dr[k];\n                        int nc = c + dc[k];\n                        nst.probs[nr*N + nc] += p_val * (1.0 - P);\n                    }\n                }\n                \n                // Handle probability mass arriving at target\n                if(nst.probs[target_idx] > EPS){\n                    double arrived = nst.probs[target_idx];\n                    // Score for arriving at step t+1 is 401 - (t+1)\n                    nst.score += arrived * (401.0 - (t + 1));\n                    // Remove mass from grid so it's not simulated further\n                    nst.probs[target_idx] = 0.0;\n                }\n                \n                // Compute heuristic efficiently in one pass\n                double M = 0.0; // Remaining mass\n                double Wu = 0.0; // Weighted expected steps\n                for(int idx=0; idx<N*N; ++idx){\n                    if(nst.probs[idx] > EPS){\n                        M += nst.probs[idx];\n                        Wu += nst.probs[idx] * flat_dist[idx];\n                    }\n                }\n                \n                // Heuristic: Score so far + Expected score of remaining mass\n                // Expected arrival time ~ current_time + dist / (1-P)\n                nst.heuristic = nst.score + M * (401.0 - (t + 1)) - Wu * inv_prob;\n                \n                next_beam.push_back(std::move(nst));\n            }\n        }\n        \n        // Select top BEAM_WIDTH candidates\n        if(next_beam.size() > BEAM_WIDTH){\n            nth_element(next_beam.begin(), next_beam.begin() + BEAM_WIDTH, next_beam.end(), \n                [](const State& a, const State& b){\n                    return a.heuristic > b.heuristic;\n                });\n            next_beam.resize(BEAM_WIDTH);\n        }\n        beam = std::move(next_beam);\n    }\n    \n    // Find best solution in the final beam\n    double best_h = -1e18;\n    string best_s = \"\";\n    for(const auto& st : beam){\n        if(st.heuristic > best_h){\n            best_h = st.heuristic;\n            best_s = st.s;\n        }\n    }\n    \n    cout << best_s << endl;\n    \n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// Map (type, entry_dir) -> exit_dir\n// -1 if no connection\nint to[8][4];\n\nvoid init_tables() {\n    // Initialize with -1\n    for(int t=0; t<8; ++t) for(int d=0; d<4; ++d) to[t][d] = -1;\n\n    // 0: Left(0)-Up(1)\n    to[0][0] = 1; to[0][1] = 0;\n    // 1: Left(0)-Down(3)\n    to[1][0] = 3; to[1][3] = 0;\n    // 2: Right(2)-Down(3)\n    to[2][2] = 3; to[2][3] = 2;\n    // 3: Right(2)-Up(1)\n    to[3][2] = 1; to[3][1] = 2;\n    \n    // 4: Left(0)-Up(1) & Right(2)-Down(3)\n    to[4][0] = 1; to[4][1] = 0;\n    to[4][2] = 3; to[4][3] = 2;\n    \n    // 5: Left(0)-Down(3) & Right(2)-Up(1)\n    to[5][0] = 3; to[5][3] = 0;\n    to[5][2] = 1; to[5][1] = 2;\n    \n    // 6: Up(1)-Down(3) (Vertical)\n    to[6][1] = 3; to[6][3] = 1;\n    \n    // 7: Left(0)-Right(2) (Horizontal)\n    to[7][0] = 2; to[7][2] = 0;\n}\n\n// Calculate the effective tile type after r counter-clockwise rotations\nint get_rotated_type(int t, int r) {\n    for (int k = 0; k < r; ++k) {\n        if (t >= 0 && t <= 3) {\n            t = (t + 1) % 4;\n        } else if (t == 4) {\n            t = 5;\n        } else if (t == 5) {\n            t = 4;\n        } else if (t == 6) {\n            t = 7;\n        } else if (t == 7) {\n            t = 6;\n        }\n    }\n    return t;\n}\n\nstruct State {\n    int rots[30][30];\n    int types[30][30]; // Cached actual types for performance\n};\n\nint initial_types[30][30];\nState current_state;\nState best_state;\nlong long best_score_real = -1;\n\n// Random number generator\nmt19937 rng(12345);\n\n// Visited array for loop detection\n// Dimensions: [row][col][entry_direction]\n// We use a generation counter to avoid memset\nint visited[30][30][4];\nint gen = 0;\n\nlong long evaluate(const State& st, vector<int>& loop_lengths) {\n    gen++;\n    // In case of overflow (extremely unlikely), reset\n    if (gen <= 0) {\n        memset(visited, 0, sizeof(visited));\n        gen = 1;\n    }\n\n    loop_lengths.clear();\n    vector<int> path_lengths; \n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int t = st.types[i][j];\n            for (int d = 0; d < 4; ++d) {\n                // Only process if valid entry and not visited\n                if (visited[i][j][d] == gen) continue;\n                if (to[t][d] == -1) continue;\n\n                // Start tracing\n                int curr_i = i;\n                int curr_j = j;\n                int curr_d = d; // Entry direction\n                int len = 0;\n                bool is_loop = false;\n                \n                int start_i = i;\n                int start_j = j;\n                int start_d = d;\n\n                while (true) {\n                    visited[curr_i][curr_j][curr_d] = gen;\n                    \n                    // Determine exit direction from current tile\n                    int out_d = to[st.types[curr_i][curr_j]][curr_d];\n                    \n                    // Mark the reverse direction on this tile as visited too\n                    // effectively marking the track segment\n                    visited[curr_i][curr_j][out_d] = gen; \n\n                    len++;\n                    \n                    // Move to neighbor\n                    int ni = curr_i + di[out_d];\n                    int nj = curr_j + dj[out_d];\n                    \n                    // Check bounds\n                    if (ni < 0 || ni >= 30 || nj < 0 || nj >= 30) {\n                        is_loop = false;\n                        break;\n                    }\n                    \n                    // Determine entry direction into neighbor\n                    // Entering neighbor (ni, nj) from direction opposite to out_d\n                    int next_entry_d = (out_d + 2) % 4;\n                    \n                    // Check if neighbor connects back\n                    if (to[st.types[ni][nj]][next_entry_d] == -1) {\n                        is_loop = false;\n                        break;\n                    }\n\n                    // Check if we hit a visited state\n                    if (visited[ni][nj][next_entry_d] == gen) {\n                        // If we returned to start, it's a loop\n                        if (ni == start_i && nj == start_j && next_entry_d == start_d) {\n                            is_loop = true;\n                        } else {\n                            // We hit the current path somewhere else, or a previously visited component.\n                            // Due to graph degree <= 2, hitting !start means we merged into a previous component.\n                            // Previous components are fully explored, so this is a path ending in a merge.\n                            is_loop = false;\n                        }\n                        break;\n                    }\n                    \n                    curr_i = ni;\n                    curr_j = nj;\n                    curr_d = next_entry_d;\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(len);\n                } else {\n                    path_lengths.push_back(len);\n                }\n            }\n        }\n    }\n    \n    sort(loop_lengths.rbegin(), loop_lengths.rend());\n    \n    long long score = 0;\n    \n    // Primary objective: Maximize product of two longest loops\n    // We use a large multiplier to ensure any valid solution (2 loops) \n    // is strictly better than any invalid solution.\n    if (loop_lengths.size() >= 2) {\n        long long prod = (long long)loop_lengths[0] * loop_lengths[1];\n        score = prod * 1000000LL;\n    }\n    \n    // Secondary objective: Maximize loop lengths (sum of squares)\n    for (int l : loop_lengths) {\n        score += l * l;\n    }\n    \n    // Tertiary objective: Maximize path lengths (encourage connectivity)\n    for (int p : path_lengths) {\n        score += (p * p) / 10; \n    }\n\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_tables();\n    \n    // Input\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            initial_types[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Random initialization\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            current_state.rots[i][j] = rng() % 4;\n            current_state.types[i][j] = get_rotated_type(initial_types[i][j], current_state.rots[i][j]);\n        }\n    }\n    \n    vector<int> loops;\n    best_score_real = -1;\n    \n    auto start_time = chrono::steady_clock::now();\n    // Reserve a small buffer from 2.0s\n    double time_limit = 1.95;\n    \n    long long current_score_aug = evaluate(current_state, loops);\n    best_state = current_state;\n    if (loops.size() >= 2) best_score_real = (long long)loops[0] * loops[1];\n    else best_score_real = 0;\n    \n    // Simulated Annealing parameters\n    double t0 = 50000.0;\n    double t1 = 1.0;\n    double temp = t0;\n    int iter = 0;\n    \n    while (true) {\n        iter++;\n        \n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Exponential cooling\n            double progress = elapsed / time_limit;\n            temp = t0 * pow(t1 / t0, progress);\n        }\n        \n        // Mutation: Rotate one tile\n        int r = rng() % 30;\n        int c = rng() % 30;\n        int old_rot = current_state.rots[r][c];\n        int old_type = current_state.types[r][c];\n        \n        // Pick a random different rotation\n        int new_rot = (old_rot + 1 + (rng() % 3)) % 4;\n        current_state.rots[r][c] = new_rot;\n        current_state.types[r][c] = get_rotated_type(initial_types[r][c], new_rot);\n        \n        long long new_score_aug = evaluate(current_state, loops);\n        \n        double delta = new_score_aug - current_score_aug;\n        \n        // Metropolis criterion\n        if (delta >= 0 || (temp > 1e-9 && exp(delta / temp) > std::uniform_real_distribution<>(0.0, 1.0)(rng))) {\n            current_score_aug = new_score_aug;\n            \n            // Track best valid solution found\n            long long real_score = 0;\n            if (loops.size() >= 2) {\n                real_score = (long long)loops[0] * loops[1];\n            }\n            \n            if (real_score > best_score_real) {\n                best_score_real = real_score;\n                best_state = current_state;\n            }\n        } else {\n            // Revert change\n            current_state.rots[r][c] = old_rot;\n            current_state.types[r][c] = old_type;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            cout << best_state.rots[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <map>\n#include <iomanip>\n#include <cstring>\n\nusing namespace std;\n\n// Constants for directions and bitmasks\nconst int UP = 2;\nconst int DOWN = 8;\nconst int LEFT = 1;\nconst int RIGHT = 4;\nconst int DIR[4] = {UP, DOWN, LEFT, RIGHT};\nconst int DR[4] = {-1, 1, 0, 0}; \nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nint N, T;\nvector<vector<int>> initial_board;\nvector<vector<int>> target_board;\n\n// Time Management\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Helper functions to check connections\nbool has_dir(int tile, int dir) {\n    return (tile & dir) != 0;\n}\n\nint reverse_dir(int dir) {\n    if (dir == UP) return DOWN;\n    if (dir == DOWN) return UP;\n    if (dir == LEFT) return RIGHT;\n    if (dir == RIGHT) return LEFT;\n    return 0;\n}\n\nmt19937 rng(42);\n\n// Fast BFS for evaluation using a generation token to avoid reallocation\nint vis_token[10][10];\nint current_token = 0;\n\n// Structure to hold evaluation results\nstruct BoardScore {\n    int mismatches;\n    int max_component;\n    int total_score;\n};\n\nBoardScore evaluate(const vector<vector<int>>& board) {\n    int mismatches = 0;\n    int connections = 0;\n    int boundary_penalty = 0;\n    int max_comp = 0;\n\n    current_token++;\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) continue; \n            if (vis_token[r][c] == current_token) continue;\n\n            int comp_size = 0;\n            queue<pair<int,int>> q;\n            q.push({r, c});\n            vis_token[r][c] = current_token;\n            comp_size++;\n\n            while(!q.empty()) {\n                auto [cr, cc] = q.front();\n                q.pop();\n\n                int tile = board[cr][cc];\n                for (int d = 0; d < 4; ++d) {\n                    if (has_dir(tile, DIR[d])) {\n                        int nr = cr + DR[d];\n                        int nc = cc + DC[d];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                            int neighbor = board[nr][nc];\n                            if (neighbor != 0 && has_dir(neighbor, reverse_dir(DIR[d]))) {\n                                if (vis_token[nr][nc] != current_token) {\n                                    vis_token[nr][nc] = current_token;\n                                    q.push({nr, nc});\n                                    comp_size++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if (comp_size > max_comp) max_comp = comp_size;\n        }\n    }\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int tile = board[r][c];\n            if (tile == 0) continue;\n            \n            if (has_dir(tile, UP)) {\n                if (r == 0) boundary_penalty++;\n                else {\n                    int n = board[r-1][c];\n                    if (n == 0) boundary_penalty++; \n                    else if (!has_dir(n, DOWN)) mismatches++;\n                    else connections++; \n                }\n            }\n            if (has_dir(tile, DOWN)) {\n                if (r == N-1) boundary_penalty++;\n                else {\n                    int n = board[r+1][c];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, UP)) mismatches++;\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, LEFT)) {\n                if (c == 0) boundary_penalty++;\n                else {\n                    int n = board[r][c-1];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, RIGHT)) mismatches++;\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, RIGHT)) {\n                if (c == N-1) boundary_penalty++;\n                else {\n                    int n = board[r][c+1];\n                    if (n == 0) boundary_penalty++;\n                    else if (!has_dir(n, LEFT)) mismatches++;\n                    else connections++;\n                }\n            }\n        }\n    }\n\n    int score = max_comp * 1000 - mismatches * 50 - boundary_penalty * 20;\n    return {mismatches + boundary_penalty, max_comp, score};\n}\n\nvoid find_target_configuration() {\n    vector<int> tiles;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tiles.push_back(initial_board[r][c]);\n    \n    // Bias: put 0 at N-1, N-1\n    auto it = find(tiles.begin(), tiles.end(), 0);\n    if(it != tiles.end()) iter_swap(it, tiles.end() - 1);\n\n    target_board.assign(N, vector<int>(N));\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) target_board[r][c] = tiles[r*N + c];\n    \n    BoardScore current_eval = evaluate(target_board);\n    int current_score = current_eval.total_score;\n    \n    vector<vector<int>> best_board = target_board;\n    int best_score = current_score;\n\n    double start_temp = 500.0;\n    double end_temp = 0.1;\n    double time_limit = 1.2; // Safe time limit\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 127) == 0) {\n            if (get_time() > time_limit) break;\n        }\n\n        double t = get_time();\n        double progress = t / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, progress);\n\n        int r1 = rng() % N;\n        int c1 = rng() % N;\n        int r2 = rng() % N;\n        int c2 = rng() % N;\n        \n        if (r1 == r2 && c1 == c2) continue;\n        \n        swap(target_board[r1][c1], target_board[r2][c2]);\n        \n        BoardScore next_eval = evaluate(target_board);\n        int next_score = next_eval.total_score;\n        \n        if (next_score >= current_score) {\n            current_score = next_score;\n            if (next_score > best_score) {\n                best_score = next_score;\n                best_board = target_board;\n            }\n        } else {\n            double prob = exp((next_score - current_score) / temp);\n            if (uniform_real_distribution<>(0,1)(rng) < prob) {\n                current_score = next_score;\n            } else {\n                swap(target_board[r1][c1], target_board[r2][c2]);\n            }\n        }\n    }\n    target_board = best_board;\n}\n\nstring moves_str = \"\";\npair<int, int> empty_pos;\n\nvoid apply_move(char c) {\n    int dr = 0, dc = 0;\n    if (c == 'U') dr = -1;\n    if (c == 'D') dr = 1;\n    if (c == 'L') dc = -1;\n    if (c == 'R') dc = 1;\n    \n    int nr = empty_pos.first + dr;\n    int nc = empty_pos.second + dc;\n    \n    // Safety check\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n\n    moves_str += c;\n    swap(initial_board[empty_pos.first][empty_pos.second], initial_board[nr][nc]);\n    empty_pos = {nr, nc};\n}\n\nint bfs_dist[10][10];\nint bfs_gen[10][10];\nint cur_bfs_gen = 0;\npair<int,int> bfs_parent[10][10];\nchar bfs_move[10][10];\n\nbool bfs_empty(int tr, int tc, const vector<vector<bool>>& locked) {\n    if (empty_pos.first == tr && empty_pos.second == tc) return true;\n    \n    cur_bfs_gen++;\n    queue<pair<int,int>> q;\n    q.push(empty_pos);\n    bfs_gen[empty_pos.first][empty_pos.second] = cur_bfs_gen;\n    \n    bool found = false;\n    while(!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == tr && c == tc) {\n            found = true;\n            break;\n        }\n        \n        for (int i=0; i<4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n            \n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !locked[nr][nc]) {\n                if (bfs_gen[nr][nc] != cur_bfs_gen) {\n                    bfs_gen[nr][nc] = cur_bfs_gen;\n                    bfs_parent[nr][nc] = {r, c};\n                    bfs_move[nr][nc] = DIR_CHAR[i];\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    \n    if (!found) return false;\n    \n    string path = \"\";\n    pair<int,int> curr = {tr, tc};\n    while (curr != empty_pos) {\n        path += bfs_move[curr.first][curr.second];\n        curr = bfs_parent[curr.first][curr.second];\n    }\n    reverse(path.begin(), path.end());\n    for(char c : path) apply_move(c);\n    return true;\n}\n\n// Parity utilities\nint get_inv_count(const vector<int>& arr) {\n    int inv_count = 0;\n    for (int i = 0; i < arr.size(); i++) {\n        if (arr[i] == -1) continue;\n        for (int j = i + 1; j < arr.size(); j++) {\n            if (arr[j] == -1) continue;\n            if (arr[i] > arr[j]) inv_count++;\n        }\n    }\n    return inv_count;\n}\n\nvoid solve_puzzle() {\n    // ID mapping to distinguish identical tiles\n    vector<vector<int>> tile_ids(N, vector<int>(N));\n    int id_counter = 0;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tile_ids[r][c] = id_counter++;\n\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c] == 0) empty_pos = {r,c};\n\n    vector<int> target_assignment(N*N, -1);\n    vector<bool> id_used(N*N, false);\n\n    // Initial Greedy Assignment\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int type = target_board[r][c];\n            int best_id = -1;\n            int min_dist = 10000;\n            \n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                int id = tile_ids[i][j];\n                if (!id_used[id] && initial_board[i][j] == type) {\n                    int dist = abs(r - i) + abs(c - j);\n                    if (dist < min_dist) { min_dist = dist; best_id = id; }\n                }\n            }\n            target_assignment[r*N + c] = best_id;\n            id_used[best_id] = true;\n        }\n    }\n\n    // Parity Fix\n    vector<int> s1; \n    int empty_id = -1;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n        s1.push_back(tile_ids[r][c]);\n        if(initial_board[r][c] == 0) empty_id = tile_ids[r][c];\n    }\n    \n    int target_empty_pos = -1;\n    for(int i=0; i<N*N; ++i) if(target_assignment[i] == empty_id) target_empty_pos = i;\n    int target_empty_row = target_empty_pos / N;\n    int target_empty_col = target_empty_pos % N;\n\n    vector<int> s1_clean = s1;\n    for(int &x : s1_clean) if(x == empty_id) x = -1;\n    int inv1 = get_inv_count(s1_clean);\n    int p1 = (inv1 + empty_pos.first + empty_pos.second) % 2;\n    \n    vector<int> s2 = target_assignment;\n    for(int &x : s2) if(x == empty_id) x = -1;\n    int inv2 = get_inv_count(s2);\n    int p2 = (inv2 + target_empty_row + target_empty_col) % 2;\n    \n    if (p1 != p2) {\n        bool swapped = false;\n        for(int i=0; i<N*N && !swapped; ++i) {\n            for(int j=i+1; j<N*N && !swapped; ++j) {\n                int id1 = target_assignment[i];\n                int id2 = target_assignment[j];\n                if (id1 == empty_id || id2 == empty_id) continue;\n                \n                int type1 = -1, type2 = -2;\n                for(int r=0;r<N;++r) for(int c=0;c<N;++c) if(tile_ids[r][c]==id1) type1 = initial_board[r][c];\n                for(int r=0;r<N;++r) for(int c=0;c<N;++c) if(tile_ids[r][c]==id2) type2 = initial_board[r][c];\n                \n                if (type1 == type2) {\n                    swap(target_assignment[i], target_assignment[j]);\n                    swapped = true;\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> target_ids_map(N, vector<int>(N));\n    for(int i=0; i<N*N; ++i) target_ids_map[i/N][i%N] = target_assignment[i];\n    \n    vector<vector<bool>> locked(N, vector<bool>(N, false));\n    auto get_pos = [&](int id) {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n        return make_pair(-1,-1);\n    };\n\n    // Phase 1: Rows\n    for (int r = 0; r <= N - 3; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (c < N - 2) {\n                int id = target_ids_map[r][c];\n                pair<int,int> curr = get_pos(id);\n                if (curr == make_pair(r,c)) { locked[r][c] = true; continue; }\n                \n                while (curr.first != r || curr.second != c) {\n                    int dr = 0, dc = 0;\n                    if (curr.first < r) dr = 1; else if (curr.first > r) dr = -1;\n                    else if (curr.second < c) dc = 1; else if (curr.second > c) dc = -1;\n                    int nr = curr.first + dr; int nc = curr.second + dc;\n                    \n                    locked[curr.first][curr.second] = true;\n                    if (!bfs_empty(nr, nc, locked)) {\n                        locked[curr.first][curr.second] = false;\n                        break;\n                    }\n                    locked[curr.first][curr.second] = false;\n                    \n                    char m = ' ';\n                    if (curr.first == nr + 1) m = 'D'; else if (curr.first == nr - 1) m = 'U';\n                    else if (curr.second == nc + 1) m = 'R'; else if (curr.second == nc - 1) m = 'L';\n                    \n                    apply_move(m);\n                    swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                    curr = {nr, nc};\n                }\n                locked[r][c] = true;\n            } else {\n                int t1_id = target_ids_map[r][N-2];\n                int t2_id = target_ids_map[r][N-1];\n                \n                auto move_p = [&](int id, int tr, int tc, int avoid_id = -1) {\n                    pair<int,int> curr = get_pos(id);\n                    while(curr.first != tr || curr.second != tc) {\n                         int dr = 0, dc = 0;\n                         if (curr.first < tr) dr = 1; else if (curr.first > tr) dr = -1;\n                         else if (curr.second < tc) dc = 1; else if (curr.second > tc) dc = -1;\n                         int nr = curr.first + dr; int nc = curr.second + dc;\n                         \n                         pair<int,int> avoid_pos = {-1,-1};\n                         if(avoid_id != -1) { avoid_pos = get_pos(avoid_id); locked[avoid_pos.first][avoid_pos.second] = true; }\n                         \n                         locked[curr.first][curr.second] = true;\n                         bool ok = bfs_empty(nr, nc, locked);\n                         locked[curr.first][curr.second] = false;\n                         if(avoid_id != -1) locked[avoid_pos.first][avoid_pos.second] = false;\n                         \n                         if(!ok) break;\n\n                         char m = ' ';\n                         if (curr.first == nr + 1) m = 'D'; else if (curr.first == nr - 1) m = 'U';\n                         else if (curr.second == nc + 1) m = 'R'; else if (curr.second == nc - 1) m = 'L';\n                         apply_move(m);\n                         swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                         curr = {nr, nc};\n                    }\n                };\n                \n                move_p(t2_id, r+1, N-1, t1_id);\n                pair<int,int> p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n                move_p(t1_id, r, N-1);\n                locked[p2.first][p2.second] = false;\n                \n                pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n                p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n                bfs_empty(r, N-2, locked);\n                \n                apply_move('R'); swap(tile_ids[r][N-2], tile_ids[r][N-1]);\n                apply_move('D'); swap(tile_ids[r][N-1], tile_ids[r+1][N-1]);\n                \n                locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n                locked[r][N-2] = true; locked[r][N-1] = true;\n                break;\n            }\n        }\n    }\n\n    // Phase 2: Cols\n    for(int c=0; c <= N-3; ++c) {\n        int t1_id = target_ids_map[N-2][c];\n        int t2_id = target_ids_map[N-1][c];\n        \n        auto move_p = [&](int id, int tr, int tc, int avoid_id = -1) {\n            pair<int,int> curr = get_pos(id);\n            while(curr.first != tr || curr.second != tc) {\n                int dr = 0, dc = 0;\n                if (curr.first < tr) dr = 1; else if (curr.first > tr) dr = -1;\n                else if (curr.second < tc) dc = 1; else if (curr.second > tc) dc = -1;\n                int nr = curr.first + dr; int nc = curr.second + dc;\n                \n                pair<int,int> avoid_pos = {-1,-1};\n                if(avoid_id != -1) { avoid_pos = get_pos(avoid_id); locked[avoid_pos.first][avoid_pos.second] = true; }\n                locked[curr.first][curr.second] = true;\n                bool ok = bfs_empty(nr, nc, locked);\n                locked[curr.first][curr.second] = false;\n                if(avoid_id != -1) locked[avoid_pos.first][avoid_pos.second] = false;\n                \n                if(!ok) break;\n                \n                char m = ' ';\n                if (curr.first == nr + 1) m = 'D'; else if (curr.first == nr - 1) m = 'U';\n                else if (curr.second == nc + 1) m = 'R'; else if (curr.second == nc - 1) m = 'L';\n                apply_move(m);\n                swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n                curr = {nr, nc};\n            }\n        };\n        \n        move_p(t2_id, N-1, c+1, t1_id);\n        pair<int,int> p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n        move_p(t1_id, N-1, c);\n        locked[p2.first][p2.second] = false;\n        \n        pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n        p2 = get_pos(t2_id); locked[p2.first][p2.second] = true;\n        bfs_empty(N-2, c, locked);\n        \n        apply_move('D'); swap(tile_ids[N-2][c], tile_ids[N-1][c]);\n        apply_move('R'); swap(tile_ids[N-1][c], tile_ids[N-1][c+1]);\n        \n        locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n        locked[N-2][c] = true; locked[N-1][c] = true;\n    }\n\n    // Phase 3: 2x3 BFS\n    locked[N-2][N-3] = false; locked[N-1][N-3] = false; \n    \n    vector<pair<int,int>> pos_map = {{N-2, N-3}, {N-2, N-2}, {N-2, N-1}, {N-1, N-3}, {N-1, N-2}, {N-1, N-1}};\n    \n    auto get_state = [&]() {\n        vector<int> s(6);\n        for(int i=0; i<6; ++i) s[i] = tile_ids[pos_map[i].first][pos_map[i].second];\n        return s;\n    };\n    \n    vector<int> target_state(6);\n    for(int i=0; i<6; ++i) target_state[i] = target_ids_map[pos_map[i].first][pos_map[i].second];\n    \n    map<vector<int>, char> move_map;\n    map<vector<int>, vector<int>> parent_map;\n    queue<vector<int>> q;\n    \n    vector<int> start_s = get_state();\n    q.push(start_s);\n    move_map[start_s] = 0;\n    \n    bool solved = false;\n    vector<int> final_s;\n    int steps = 0;\n    \n    while(!q.empty()) {\n        vector<int> curr = q.front();\n        q.pop();\n        \n        if (curr == target_state) {\n            solved = true;\n            final_s = curr;\n            break;\n        }\n        \n        if(++steps > 50000) break; \n        \n        int z = -1;\n        for(int i=0; i<6; ++i) if(curr[i] == empty_id) z = i;\n        if(z == -1) continue; \n        \n        int r = pos_map[z].first;\n        int c = pos_map[z].second;\n        \n        for(int d=0; d<4; ++d) {\n            int nr = r + DR[d];\n            int nc = c + DC[d];\n            \n            int nz = -1;\n            for(int k=0; k<6; ++k) if(pos_map[k].first == nr && pos_map[k].second == nc) nz = k;\n            \n            if (nz != -1) {\n                vector<int> next_s = curr;\n                swap(next_s[z], next_s[nz]);\n                if (move_map.find(next_s) == move_map.end()) {\n                    move_map[next_s] = DIR_CHAR[d];\n                    parent_map[next_s] = curr;\n                    q.push(next_s);\n                }\n            }\n        }\n    }\n    \n    if (solved) {\n        string path = \"\";\n        vector<int> curr = final_s;\n        while (curr != start_s) {\n            path += move_map[curr];\n            curr = parent_map[curr];\n        }\n        reverse(path.begin(), path.end());\n        for(char c : path) apply_move(c);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if(!(cin >> N >> T)) return 0;\n    initial_board.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') initial_board[i][j] = c - '0';\n            else initial_board[i][j] = c - 'a' + 10;\n        }\n    }\n\n    find_target_configuration();\n    solve_puzzle();\n    \n    cout << moves_str << endl;\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst double PI = std::acos(-1.0);\nconst int MAX_K = 105; // Limit is 100, + safety\nconst int MAX_N = 6000; // N can be up to 5500\n\nstruct Point {\n    int id;\n    long long x, y;\n    double px, py; // projected coordinates\n    int rank_x, rank_y; // rank in unique coords\n};\n\n// Global variables\nint N;\nint K_limit;\nint A[11];\nvector<Point> points;\nmt19937 rng(42);\n\n// Buffers for fast evaluation\nint counts_grid[MAX_K][MAX_K];\nint Lx[MAX_N];\nint Ly[MAX_N];\n\n// Timer\nclass Timer {\n    chrono::high_resolution_clock::time_point start;\npublic:\n    Timer() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(now - start).count();\n    }\n};\n\n// Helper to get unique coordinates with epsilon tolerance\nvector<double> get_unique_coords(const vector<double>& coords) {\n    vector<double> uniq;\n    if (coords.empty()) return uniq;\n    vector<double> sorted = coords;\n    sort(sorted.begin(), sorted.end());\n    uniq.push_back(sorted[0]);\n    for (size_t i = 1; i < sorted.size(); ++i) {\n        // Use tolerance to prevent cutting between extremely close points\n        // which might be risky with integer arithmetic later\n        if (sorted[i] - uniq.back() > 1e-3) { \n            uniq.push_back(sorted[i]);\n        }\n    }\n    return uniq;\n}\n\nstruct Solver {\n    vector<Point> current_points;\n    vector<double> uniq_x, uniq_y;\n    double angle;\n    \n    vector<int> best_cx, best_cy; // best cuts indices\n    long long best_score_raw = -1;\n\n    // Initialize solver for a specific rotation angle\n    void init(double ang) {\n        angle = ang;\n        current_points = points;\n        double rad = angle * PI / 180.0;\n        double c = cos(rad), s = sin(rad);\n        \n        vector<double> raw_x(N), raw_y(N);\n        for(int i=0; i<N; ++i) {\n            current_points[i].px = current_points[i].x * c + current_points[i].y * s;\n            current_points[i].py = -current_points[i].x * s + current_points[i].y * c;\n            raw_x[i] = current_points[i].px;\n            raw_y[i] = current_points[i].py;\n        }\n        \n        uniq_x = get_unique_coords(raw_x);\n        uniq_y = get_unique_coords(raw_y);\n        \n        // Assign ranks to points based on unique coordinates\n        for(int i=0; i<N; ++i) {\n            auto it = lower_bound(uniq_x.begin(), uniq_x.end(), current_points[i].px - 1e-4);\n            current_points[i].rank_x = (int)distance(uniq_x.begin(), it);\n            \n            it = lower_bound(uniq_y.begin(), uniq_y.end(), current_points[i].py - 1e-4);\n            current_points[i].rank_y = (int)distance(uniq_y.begin(), it);\n        }\n    }\n    \n    // Fast evaluation of a configuration using lookup tables\n    // Complexity: O(N + unique_coords)\n    long long eval(const vector<int>& cx, const vector<int>& cy) {\n        int nx = (int)cx.size() + 1;\n        int ny = (int)cy.size() + 1;\n        \n        int uxs = (int)uniq_x.size();\n        int uys = (int)uniq_y.size();\n        \n        // Fill Lx lookup table: map rank_x -> bin index\n        int current_cut_idx = 0;\n        int current_bin = 0;\n        for(int i=0; i<uxs; ++i) {\n            if(current_cut_idx < (int)cx.size() && i == cx[current_cut_idx]) {\n                current_bin++;\n                current_cut_idx++;\n            }\n            Lx[i] = current_bin;\n        }\n        \n        // Fill Ly lookup table\n        current_cut_idx = 0;\n        current_bin = 0;\n        for(int i=0; i<uys; ++i) {\n            if(current_cut_idx < (int)cy.size() && i == cy[current_cut_idx]) {\n                current_bin++;\n                current_cut_idx++;\n            }\n            Ly[i] = current_bin;\n        }\n        \n        // Reset relevant parts of the grid\n        for(int i=0; i<nx; ++i) {\n             memset(counts_grid[i], 0, sizeof(int) * ny);\n        }\n        \n        // Assign points to bins\n        for(const auto& p : current_points) {\n            counts_grid[Lx[p.rank_x]][Ly[p.rank_y]]++;\n        }\n        \n        // Calculate score based on matched pieces\n        int piece_b[11] = {0};\n        for(int i=0; i<nx; ++i) {\n            for(int j=0; j<ny; ++j) {\n                int c = counts_grid[i][j];\n                if(c <= 10 && c >= 1) piece_b[c]++;\n            }\n        }\n        \n        long long num = 0;\n        for(int d=1; d<=10; ++d) {\n            num += min(A[d], piece_b[d]);\n        }\n        return num;\n    }\n    \n    // Simulated Annealing\n    void run_sa(double duration, bool warm_start) {\n        Timer t;\n        vector<int> cx, cy;\n        int uxs = (int)uniq_x.size();\n        int uys = (int)uniq_y.size();\n        \n        // Initialize cuts based on quantiles (uniform distribution of points)\n        auto gen_quantile_cuts = [&](int n, int max_v) {\n             vector<int> res;\n             if (max_v <= 1) return res;\n             if (n > max_v - 1) n = max_v - 1;\n             for (int i = 1; i <= n; ++i) {\n                 int idx = (int)(1.0 * i * max_v / (n + 1));\n                 if (idx < 1) idx = 1;\n                 if (idx >= max_v) idx = max_v - 1;\n                 res.push_back(idx);\n             }\n             sort(res.begin(), res.end());\n             res.erase(unique(res.begin(), res.end()), res.end());\n             return res;\n        };\n        \n        if (warm_start && !best_cx.empty()) {\n            cx = best_cx;\n            cy = best_cy;\n        } else {\n            int kx = K_limit / 2;\n            int ky = K_limit - kx;\n            cx = gen_quantile_cuts(kx, uxs);\n            cy = gen_quantile_cuts(ky, uys);\n        }\n        \n        long long current_score = eval(cx, cy);\n        if (current_score > best_score_raw) {\n            best_score_raw = current_score;\n            best_cx = cx;\n            best_cy = cy;\n        }\n        \n        double start_temp = 2.0;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 255) == 0) {\n                if (t.elapsed() > duration) break;\n            }\n            \n            double progress = t.elapsed() / duration;\n            double temp = start_temp * (1.0 - progress);\n            \n            vector<int> ncx = cx;\n            vector<int> ncy = cy;\n            int op = rng() % 2; // Choose X or Y\n            \n            vector<int>* cuts = (op == 0) ? &ncx : &ncy;\n            int max_val = (op == 0) ? uxs : uys;\n            int other_size = (op == 0) ? ncy.size() : ncx.size();\n            \n            if (max_val <= 1) continue;\n            \n            int type = rng() % 3; // 0: Shift, 1: Add, 2: Delete\n            \n            if (type == 0 && !cuts->empty()) {\n                // Shift a cut locally\n                int idx = rng() % cuts->size();\n                int old_v = (*cuts)[idx];\n                int shift = (rng() % 11) - 5;\n                int val = old_v + shift;\n                if (val < 1) val = 1;\n                if (val >= max_val) val = max_val - 1;\n                \n                bool exists = false;\n                // Small loop check ok\n                for(int v : *cuts) if(v == val && v != old_v) exists = true;\n                \n                if (!exists) {\n                    (*cuts)[idx] = val;\n                    sort(cuts->begin(), cuts->end());\n                } else {\n                    continue;\n                }\n            } \n            else if (type == 1) {\n                // Add a new cut\n                if (cuts->size() + other_size < K_limit) {\n                    int val = (rng() % (max_val - 1)) + 1;\n                    bool exists = false;\n                    for(int v : *cuts) if(v == val) exists = true;\n                    if (!exists) {\n                        cuts->push_back(val);\n                        sort(cuts->begin(), cuts->end());\n                    } else {\n                        continue;\n                    }\n                } else {\n                    continue;\n                }\n            }\n            else if (type == 2 && !cuts->empty()) {\n                // Delete a cut\n                int idx = rng() % cuts->size();\n                cuts->erase(cuts->begin() + idx);\n            } else {\n                continue;\n            }\n            \n            long long new_score = eval(ncx, ncy);\n            long long diff = new_score - current_score;\n            \n            if (diff >= 0 || (temp > 1e-9 && exp(diff / temp) > (double(rng()) / mt19937::max()))) {\n                cx = ncx;\n                cy = ncy;\n                current_score = new_score;\n                if (current_score > best_score_raw) {\n                    best_score_raw = current_score;\n                    best_cx = cx;\n                    best_cy = cy;\n                }\n            }\n        }\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 >> K_limit)) return 0;\n    for(int i=1; i<=10; ++i) {\n        cin >> A[i];\n    }\n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y;\n    }\n    \n    // Create a list of candidate angles\n    vector<double> angles;\n    // Try every integer degree and half-degrees\n    for(int i=0; i<90; ++i) {\n        angles.push_back(i); \n        angles.push_back(i + 0.5);\n    }\n    // Add some random angles to avoid systematic bias\n    for(int i=0; i<20; ++i) {\n        angles.push_back(std::uniform_real_distribution<double>(0.0, 90.0)(rng));\n    }\n    \n    shuffle(angles.begin(), angles.end(), rng);\n    \n    // Limit total angles if too many to ensure reasonable time per angle\n    if (angles.size() > 200) angles.resize(200);\n    \n    int n_angles = angles.size();\n    vector<Solver> solvers(n_angles);\n    \n    Timer total_timer;\n    double time_limit = 2.85;\n    \n    // Phase 1: Exploration\n    // Quickly try many angles to find the most promising orientation\n    double exploration_time = 1.5; \n    double time_per_angle = exploration_time / n_angles;\n    \n    int best_idx = -1;\n    \n    for(int i=0; i<n_angles; ++i) {\n        solvers[i].init(angles[i]);\n        solvers[i].run_sa(time_per_angle, false);\n        if (best_idx == -1 || solvers[i].best_score_raw > solvers[best_idx].best_score_raw) {\n            best_idx = i;\n        }\n    }\n    \n    // Phase 2: Exploitation\n    // Focus remaining time on the best angle found\n    double remaining = time_limit - total_timer.elapsed();\n    if (remaining > 0 && best_idx != -1) {\n        solvers[best_idx].run_sa(remaining, true);\n    }\n    \n    // Output the best solution\n    const Solver& S = solvers[best_idx];\n    cout << S.best_cx.size() + S.best_cy.size() << endl;\n    \n    double rad = S.angle * PI / 180.0;\n    double c = cos(rad), s = sin(rad);\n    \n    auto print_line = [&](double A, double B, double C) {\n        // Line Ax + By = C\n        // Find two points very far apart\n        double Mx = C * A;\n        double My = C * B;\n        double Dx = -B;\n        double Dy = A;\n        \n        long long scale = 400000000LL; \n        \n        long long x1 = round(Mx - scale * Dx);\n        long long y1 = round(My - scale * Dy);\n        long long x2 = round(Mx + scale * Dx);\n        long long y2 = round(My + scale * Dy);\n        \n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    };\n    \n    for(int idx : S.best_cx) {\n        // Cut at index `idx` separates rank `idx-1` and `idx`\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_x.size())\n            val = (S.uniq_x[idx-1] + S.uniq_x[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_x[0] - 10.0; \n        else val = S.uniq_x.back() + 10.0;\n            \n        print_line(c, s, val);\n    }\n    for(int idx : S.best_cy) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_y.size())\n             val = (S.uniq_y[idx-1] + S.uniq_y[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_y[0] - 10.0;\n        else val = S.uniq_y.back() + 10.0;\n\n        print_line(-s, c, val);\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double TIME_LIMIT = 4.8;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n};\n\nint N, M;\nint C; \nlong long weights[65][65];\n\nusing Mask = unsigned long long;\n\ninline void set_bit(Mask& m, int i) {\n    m |= (1ULL << i);\n}\n\n// Check if bits in range [l, r) are all 0\n// Range is inclusive of l, exclusive of r.\ninline bool check_range_empty(Mask m, int l, int r) {\n    if (l >= r) return true;\n    if (l >= 64) return true; \n    unsigned long long mask_r = (r >= 64) ? (~0ULL) : ((1ULL << r) - 1);\n    unsigned long long mask_l = (1ULL << l) - 1;\n    Mask mask = mask_r ^ mask_l;\n    return (m & mask) == 0;\n}\n\nstruct Move {\n    Point p1, p2, p3, p4;\n};\n\nstruct State {\n    Mask row_dots[62];\n    Mask col_dots[62];\n    Mask d1_dots[130]; \n    Mask d2_dots[130]; \n\n    Mask h_edges[62]; \n    Mask v_edges[62];\n    Mask d1_edges[130];\n    Mask d2_edges[130];\n\n    long long current_score_w;\n    vector<Move> history;\n\n    State() {\n        for(int i=0; i<62; ++i) row_dots[i] = col_dots[i] = h_edges[i] = v_edges[i] = 0;\n        for(int i=0; i<130; ++i) d1_dots[i] = d2_dots[i] = d1_edges[i] = d2_edges[i] = 0;\n        current_score_w = 0;\n    }\n\n    bool has_dot(int x, int y) const {\n        return (row_dots[y] >> x) & 1;\n    }\n\n    void add_dot(int x, int y) {\n        set_bit(row_dots[y], x);\n        set_bit(col_dots[x], y);\n        set_bit(d1_dots[x + y], x);\n        set_bit(d2_dots[x - y + N], x);\n        current_score_w += weights[x][y];\n    }\n    \n    void add_edges(Point p1, Point p2, Point p3, Point p4) {\n        auto mark = [&](Point a, Point b) {\n            if (a.y == b.y) { \n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                for (int x = l; x < r; ++x) set_bit(h_edges[y], x);\n            } else if (a.x == b.x) { \n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                for (int y = l; y < r; ++y) set_bit(v_edges[x], y);\n            } else {\n                if ((a.x + a.y) == (b.x + b.y)) { \n                    int k = a.x + a.y;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d1_edges[k], x);\n                } else { \n                    int k = a.x - a.y + N;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d2_edges[k], x);\n                }\n            }\n        };\n        mark(p1, p2);\n        mark(p2, p3);\n        mark(p3, p4);\n        mark(p4, p1);\n    }\n};\n\nconst int pairs90[8][2] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0}, \n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\nstruct Solver {\n    vector<State> beam;\n    vector<Point> initial_dots;\n\n    Point find_neighbor(const State& s, Point p, int dir) {\n        int x = p.x, y = p.y;\n        if (dir == 0) { // R\n            Mask m = s.row_dots[y];\n            m &= (~0ULL << (x + 1)); \n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, y};\n        } else if (dir == 2) { // L\n            Mask m = s.row_dots[y];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, y};\n        } else if (dir == 1) { // U\n            Mask m = s.col_dots[x];\n            m &= (~0ULL << (y + 1));\n            if (m == 0) return {-1, -1};\n            int ny = __builtin_ctzll(m);\n            return {x, ny};\n        } else if (dir == 3) { // D\n            Mask m = s.col_dots[x];\n            m &= ((1ULL << y) - 1);\n            if (m == 0) return {-1, -1};\n            int ny = 63 - __builtin_clzll(m);\n            return {x, ny};\n        } else if (dir == 4) { // NE (d2 const, x inc)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 6) { // SW (d2 const, x dec)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 5) { // NW (d1 const, x dec)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, k - nx};\n        } else if (dir == 7) { // SE (d1 const, x inc)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, k - nx};\n        }\n        return {-1, -1};\n    }\n\n    bool check_edges_free(const State& s, Point p1, Point p2, Point p3, Point p4) {\n        auto check = [&](Point a, Point b) {\n            if (a.y == b.y) {\n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.h_edges[y], l, r);\n            } else if (a.x == b.x) {\n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                return check_range_empty(s.v_edges[x], l, r);\n            } else if ((a.x + a.y) == (b.x + b.y)) {\n                int k = a.x + a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d1_edges[k], l, r);\n            } else {\n                int k = a.x - a.y + N;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d2_edges[k], l, r);\n            }\n        };\n        return check(p1, p2) && check(p2, p3) && check(p3, p4) && check(p4, p1);\n    }\n    \n    bool check_perimeter_dots(const State& s, Point p1, Point p2) {\n         if (p1.y == p2.y) {\n             int y = p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.row_dots[y], l, r);\n         } else if (p1.x == p2.x) {\n             int x = p1.x;\n             int l = min(p1.y, p2.y) + 1;\n             int r = max(p1.y, p2.y);\n             return check_range_empty(s.col_dots[x], l, r);\n         } else if ((p1.x + p1.y) == (p2.x + p2.y)) {\n             int k = p1.x + p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d1_dots[k], l, r);\n         } else {\n             int k = p1.x - p1.y + N;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d2_dots[k], l, r);\n         }\n    }\n\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        State s0;\n        for (auto p : initial_dots) {\n            s0.add_dot(p.x, p.y);\n        }\n        beam.push_back(s0);\n        \n        // Beam width adjustment based on N\n        int BEAM_WIDTH = 80;\n        if (N > 45) BEAM_WIDTH = 50;\n        if (N > 55) BEAM_WIDTH = 30; \n\n        struct NextStateInfo {\n            int parent_idx;\n            Move move;\n            long long new_score;\n            double heuristic; \n        };\n        vector<NextStateInfo> candidates;\n        candidates.reserve(BEAM_WIDTH * 50);\n\n        int turn = 0;\n        static vector<Point> dots;\n\n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            candidates.clear();\n            bool any_move = false;\n\n            for (int i = 0; i < beam.size(); ++i) {\n                const State& s = beam[i];\n                \n                dots.clear();\n                for(int y=0; y<N; ++y) {\n                    Mask m = s.row_dots[y];\n                    while(m) {\n                        int x = __builtin_ctzll(m);\n                        dots.push_back({x, y});\n                        m &= (m - 1);\n                    }\n                }\n\n                for (const auto& p3 : dots) {\n                    for (int pair_idx = 0; pair_idx < 8; ++pair_idx) {\n                        int d_idx1 = pairs90[pair_idx][0];\n                        int d_idx2 = pairs90[pair_idx][1];\n\n                        Point p2 = find_neighbor(s, p3, d_idx1);\n                        if (p2.x == -1) continue;\n                        Point p4 = find_neighbor(s, p3, d_idx2);\n                        if (p4.x == -1) continue;\n\n                        Point p1 = {p2.x + p4.x - p3.x, p2.y + p4.y - p3.y};\n                        \n                        if (p1.x < 0 || p1.x >= N || p1.y < 0 || p1.y >= N) continue;\n                        if (s.has_dot(p1.x, p1.y)) continue;\n\n                        if (!check_perimeter_dots(s, p1, p2)) continue;\n                        if (!check_perimeter_dots(s, p1, p4)) continue;\n                        if (!check_edges_free(s, p1, p2, p3, p4)) continue;\n\n                        long long gain = weights[p1.x][p1.y];\n                        long long new_total = s.current_score_w + gain;\n                        \n                        // Heuristic is simple greedy gain\n                        candidates.push_back({i, {p1, p2, p3, p4}, new_total, (double)gain});\n                        any_move = true;\n                    }\n                }\n            }\n\n            if (!any_move) break;\n\n            if (candidates.size() > BEAM_WIDTH) {\n                 nth_element(candidates.begin(), candidates.begin() + BEAM_WIDTH, candidates.end(),\n                    [](const NextStateInfo& a, const NextStateInfo& b) {\n                        return a.heuristic > b.heuristic;\n                    });\n                 candidates.resize(BEAM_WIDTH);\n            }\n            \n            sort(candidates.begin(), candidates.end(), \n                 [](const NextStateInfo& a, const NextStateInfo& b) {\n                     return a.heuristic > b.heuristic;\n                 });\n\n            vector<State> next_beam;\n            next_beam.reserve(candidates.size());\n            \n            for (const auto& cand : candidates) {\n                State ns = beam[cand.parent_idx];\n                ns.add_dot(cand.move.p1.x, cand.move.p1.y);\n                ns.add_edges(cand.move.p1, cand.move.p2, cand.move.p3, cand.move.p4);\n                ns.history.push_back(cand.move);\n                next_beam.push_back(ns);\n            }\n\n            beam = move(next_beam);\n            turn++;\n        }\n\n        if (beam.empty()) return;\n        auto best_it = max_element(beam.begin(), beam.end(), [](const State& a, const State& b){\n            return a.current_score_w < b.current_score_w;\n        });\n        \n        const auto& history = best_it->history;\n        cout << history.size() << \"\\n\";\n        for (const auto& m : history) {\n            cout << m.p1.x << \" \" << m.p1.y << \" \" \n                 << m.p2.x << \" \" << m.p2.y << \" \" \n                 << m.p3.x << \" \" << m.p3.y << \" \" \n                 << m.p4.x << \" \" << m.p4.y << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if (!(cin >> N >> M)) return 0;\n\n    C = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            weights[x][y] = 1LL * (x - C) * (x - C) + 1LL * (y - C) * (y - C) + 1;\n        }\n    }\n\n    Solver solver;\n    solver.initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> solver.initial_dots[i].x >> solver.initial_dots[i].y;\n    }\n\n    solver.solve();\n\n    return 0;\n}","ahc015":"/**\n * Improved Solution for AtCoder Heuristic Contest (AHC015) - Halloween Candy\n * \n * Strategy & Improvements:\n * 1. State Representation & LUT Optimization:\n *    - The 10x10 grid is small enough to be represented using bit-packed integers.\n *    - Each row (10 cells, 2 bits per cell) fits into a 32-bit integer.\n *    - Movement (Tilting) and Scoring (Adjacency) logic is precomputed into Look-Up Tables (LUTs).\n *    - This reduces the complexity of 'tilt' and 'eval' operations from O(N) loops to O(1) table lookups (plus a fast transpose for vertical ops).\n * \n * 2. Monte Carlo Tree Search (MCTS) / Simulation:\n *    - Due to the faster state operations, we can perform significantly more simulations (playouts) within the 2s time limit.\n *    - The playout strategy is \"Greedy with Lookahead\": at each step of the simulation, we choose the move that maximizes immediate same-flavor adjacency.\n *    - We simulate until the end of the game (t=100) and evaluate using the exact scoring function (Sum of Squares of Component Sizes) using DSU.\n * \n * 3. Time Management:\n *    - Time is allocated dynamically per step based on remaining time and remaining steps.\n *    - As the game progresses and the simulation depth decreases, the number of iterations naturally increases, improving precision for critical late-game moves.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// --- Constants ---\nconstexpr int N = 10;\nconstexpr int MAX_T = 100;\nconstexpr int NUM_DIRS = 4;\nconstexpr char DIR_CHARS[] = {'F', 'B', 'L', 'R'}; // 0:F(Up), 1:B(Down), 2:L, 3:R\n\n// 2 bits per cell * 10 cells = 20 bits. Size = 2^20 approx 1MB.\nconstexpr int LUT_SIZE = 1 << (2 * N);\n\n// --- Global Look-Up Tables ---\nuint32_t lut_move_L[LUT_SIZE];\nuint32_t lut_move_R[LUT_SIZE];\nuint8_t lut_adj_score[LUT_SIZE]; // Max score for a row is 9, fits in uint8\n\n// --- Global Data ---\nint flavors[MAX_T]; // Pre-read flavors\n\n// --- Random Number Generator ---\nstruct XorShift128 {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    \n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    \n    inline int next_int(int n) {\n        if (n <= 0) return 0;\n        return next() % n;\n    }\n} rng;\n\n// --- Initialization ---\nvoid init_lut() {\n    // Iterate all possible row configurations (20 bits)\n    for (int i = 0; i < LUT_SIZE; ++i) {\n        int cells[N];\n        int temp = i;\n        // Decode bits to cells\n        for (int k = 0; k < N; ++k) {\n            cells[k] = temp & 3;\n            temp >>= 2;\n        }\n        \n        // 1. Precompute Move Left\n        // Pack non-zero cells to the beginning (index 0)\n        int p = 0;\n        int new_cells_L[N] = {0};\n        for (int k = 0; k < N; ++k) {\n            if (cells[k] != 0) {\n                new_cells_L[p++] = cells[k];\n            }\n        }\n        uint32_t res_L = 0;\n        for (int k = 0; k < N; ++k) {\n            res_L |= (uint32_t(new_cells_L[k]) << (2 * k));\n        }\n        lut_move_L[i] = res_L;\n        \n        // 2. Precompute Move Right\n        // Pack non-zero cells to the end (index N-1)\n        p = N - 1;\n        int new_cells_R[N] = {0};\n        for (int k = N - 1; k >= 0; --k) {\n            if (cells[k] != 0) {\n                new_cells_R[p--] = cells[k];\n            }\n        }\n        uint32_t res_R = 0;\n        for (int k = 0; k < N; ++k) {\n            res_R |= (uint32_t(new_cells_R[k]) << (2 * k));\n        }\n        lut_move_R[i] = res_R;\n        \n        // 3. Precompute Adjacency Score\n        // Count adjacent pairs of same flavor\n        int score = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            if (cells[k] != 0 && cells[k] == cells[k+1]) {\n                score++;\n            }\n        }\n        lut_adj_score[i] = score;\n    }\n}\n\n// --- State Structure ---\nstruct State {\n    // rows[r] stores the configuration of row r.\n    // Bits 0-1 correspond to column 0, bits 2-3 to column 1, etc.\n    uint32_t rows[N]; \n\n    void init() {\n        memset(rows, 0, sizeof(rows));\n    }\n    \n    // Place a candy of flavor f at (r, c)\n    // Assumes cell is empty (0)\n    inline void place(int r, int c, int f) {\n        rows[r] |= (uint32_t(f) << (2 * c));\n    }\n    \n    // Transpose the grid: rows -> cols\n    // Used to apply row-based operations (L/R/Score) to columns (U/D)\n    inline void transpose(uint32_t* dst) const {\n        memset(dst, 0, sizeof(uint32_t) * N);\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            if (val == 0) continue; // Optimization for empty rows\n            for (int c = 0; c < N; ++c) {\n                uint32_t f = (val >> (2 * c)) & 3;\n                if (f) {\n                    // Element at (r, c) moves to dest col c at position r\n                    dst[c] |= (f << (2 * r));\n                }\n            }\n        }\n    }\n    \n    // Reconstruct rows from columns (inverse transpose)\n    inline void from_cols(const uint32_t* cols) {\n        memset(rows, 0, sizeof(rows));\n        for (int c = 0; c < N; ++c) {\n            uint32_t val = cols[c];\n            if (val == 0) continue;\n            for (int r = 0; r < N; ++r) {\n                uint32_t f = (val >> (2 * r)) & 3;\n                if (f) {\n                    rows[r] |= (f << (2 * c));\n                }\n            }\n        }\n    }\n\n    // Tilt the board in direction dir\n    // 0:F(Up), 1:B(Down), 2:L, 3:R\n    void tilt(int dir) {\n        if (dir == 2) { // Left\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_L[rows[i]];\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_R[rows[i]];\n        } else {\n            // Vertical moves require transpose\n            uint32_t cols[N];\n            transpose(cols);\n            if (dir == 0) { // Forward/Up -> Like Left on columns\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_L[cols[i]];\n            } else { // Backward/Down -> Like Right on columns\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_R[cols[i]];\n            }\n            from_cols(cols);\n        }\n    }\n    \n    // Fast evaluation: count adjacent same-flavor pairs\n    int eval_adj() const {\n        int score = 0;\n        // Horizontal score from rows\n        for (int i = 0; i < N; ++i) score += lut_adj_score[rows[i]];\n        \n        // Vertical score needs transpose\n        uint32_t cols[N];\n        transpose(cols);\n        for (int i = 0; i < N; ++i) score += lut_adj_score[cols[i]];\n        \n        return score;\n    }\n    \n    // Find the k-th empty cell (1-based index)\n    // Priority: Top-to-Bottom, Left-to-Right\n    pair<int,int> get_kth_empty(int k) const {\n        int cnt = 0;\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            // Optimization: if row is full (no zeros), skip? \n            // Checking if full is complex due to 2-bit packing, simple loop is fine for N=10.\n            for (int c = 0; c < N; ++c) {\n                if (((val >> (2 * c)) & 3) == 0) {\n                    cnt++;\n                    if (cnt == k) return {r, c};\n                }\n            }\n        }\n        return {-1, -1};\n    }\n    \n    // Full Score Calculation: Sum of squares of connected component sizes.\n    // Uses Disjoint Set Union (DSU).\n    long long eval_full() const {\n        static int parent[N*N];\n        static int sz[N*N];\n        static int board_flat[N*N];\n        \n        // Flatten board for easier indexing\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            for (int c = 0; c < N; ++c) {\n                board_flat[r*N + c] = (val >> (2*c)) & 3;\n            }\n        }\n        \n        // Init DSU\n        for (int i = 0; i < N*N; ++i) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n        \n        auto find_set = [&](int i) {\n            int root = i;\n            while (root != parent[root]) root = parent[root];\n            // Path compression\n            int curr = i;\n            while (curr != root) {\n                int next = parent[curr];\n                parent[curr] = root;\n                curr = next;\n            }\n            return root;\n        };\n        \n        auto unite_sets = [&](int i, int j) {\n            int root_i = find_set(i);\n            int root_j = find_set(j);\n            if (root_i != root_j) {\n                parent[root_j] = root_i;\n                sz[root_i] += sz[root_j];\n            }\n        };\n        \n        // Horizontal connections\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N - 1; ++c) {\n                int idx = r*N + c;\n                int f = board_flat[idx];\n                if (f != 0 && f == board_flat[idx+1]) {\n                    unite_sets(idx, idx+1);\n                }\n            }\n        }\n        \n        // Vertical connections\n        for (int r = 0; r < N - 1; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int idx = r*N + c;\n                int f = board_flat[idx];\n                if (f != 0 && f == board_flat[idx+N]) {\n                    unite_sets(idx, idx+N);\n                }\n            }\n        }\n        \n        long long total_sq = 0;\n        // Use a simple array to track visited roots to avoid recounting\n        // (re-using parent array logic is complex, just use a bool flag array)\n        bool counted[N*N] = {false};\n        \n        for (int i = 0; i < N*N; ++i) {\n            if (board_flat[i] != 0) {\n                int root = find_set(i);\n                if (!counted[root]) {\n                    total_sq += (long long)sz[root] * sz[root];\n                    counted[root] = true;\n                }\n            }\n        }\n        return total_sq;\n    }\n};\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_lut();\n    \n    // Read flavors\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n    \n    State current_state;\n    current_state.init();\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Total time limit set slightly below 2.0s to be safe\n    double total_time_limit = 1.95;\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // 1. Place the candy\n        pair<int,int> pos = current_state.get_kth_empty(p);\n        current_state.place(pos.first, pos.second, flavors[t]);\n        \n        int best_dir = 0;\n        \n        // Time management\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        double remaining_time = total_time_limit - elapsed.count();\n        double time_per_move = remaining_time / (100 - t);\n        \n        // Ensure a minimum budget to avoid skipping\n        if (time_per_move < 0.001) time_per_move = 0.001;\n        \n        // Last move: just maximize final score (no randomness left)\n        if (t == 99) {\n            long long max_score = -1;\n            for (int d = 0; d < 4; ++d) {\n                State next = current_state;\n                next.tilt(d);\n                long long s = next.eval_full();\n                if (s > max_score) {\n                    max_score = s;\n                    best_dir = d;\n                }\n            }\n        } else {\n            // Monte Carlo Simulation\n            long long sum_scores[4] = {0};\n            int counts[4] = {0};\n            \n            auto move_start_time = chrono::high_resolution_clock::now();\n            int iter = 0;\n            \n            // Loop until time budget for this move is exhausted\n            while (true) {\n                // Check time every 64 iterations to minimize overhead\n                if ((iter & 63) == 0) {\n                    auto curr = chrono::high_resolution_clock::now();\n                    if ((curr - move_start_time).count() * 1e-9 > time_per_move) break;\n                }\n                iter++;\n                \n                int first_move = (iter - 1) % 4;\n                \n                // Playout\n                State sim_state = current_state;\n                sim_state.tilt(first_move);\n                \n                // Simulate rest of the game\n                for (int k = t + 1; k < 100; ++k) {\n                    int empty_cnt = 100 - k;\n                    if (empty_cnt <= 0) break;\n                    \n                    // Random placement\n                    int rnd_p = rng.next_int(empty_cnt) + 1;\n                    pair<int,int> rnd_pos = sim_state.get_kth_empty(rnd_p);\n                    sim_state.place(rnd_pos.first, rnd_pos.second, flavors[k]);\n                    \n                    // Greedy Policy: Choose move that maximizes immediate adjacency\n                    int best_adj = -1;\n                    int cands[4];\n                    int cand_cnt = 0;\n                    \n                    for (int d = 0; d < 4; ++d) {\n                        State temp = sim_state;\n                        temp.tilt(d);\n                        int adj = temp.eval_adj();\n                        if (adj > best_adj) {\n                            best_adj = adj;\n                            cand_cnt = 0;\n                            cands[cand_cnt++] = d;\n                        } else if (adj == best_adj) {\n                            cands[cand_cnt++] = d;\n                        }\n                    }\n                    \n                    // Pick random among best candidates\n                    int chosen = cands[rng.next_int(cand_cnt)];\n                    sim_state.tilt(chosen);\n                }\n                \n                sum_scores[first_move] += sim_state.eval_full();\n                counts[first_move]++;\n            }\n            \n            // Select best average score\n            double best_avg = -1.0;\n            for (int d = 0; d < 4; ++d) {\n                if (counts[d] > 0) {\n                    double avg = (double)sum_scores[d] / counts[d];\n                    if (avg > best_avg) {\n                        best_avg = avg;\n                        best_dir = d;\n                    }\n                }\n            }\n        }\n        \n        // Output and update\n        cout << DIR_CHARS[best_dir] << endl;\n        current_state.tilt(best_dir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\nmt19937 rng(12345);\n\nint rand_int(int l, int r) {\n    return uniform_int_distribution<int>(l, r)(rng);\n}\n\nstruct Code {\n    int x, y, z; // edges in block 1-1, 1-2, 2-2\n    // Convention: Group 1 (size n1) has higher degree than Group 2 (size n2)\n};\n\nstruct Config {\n    int N;\n    int n1, n2;\n    bool mode_2group;\n    vector<Code> codebook;\n    double min_dist;\n};\n\nstruct Solver {\n    int M;\n    double eps;\n    \n    void init(int m_in, double e_in) {\n        M = m_in;\n        eps = e_in;\n    }\n\n    // Calculate squared distance between two codes in \"sigma units\"\n    double calc_dist_sq(const Code& a, const Code& b, double varA, double varB, double varC) {\n        // The signal is attenuated by (1-2eps)\n        double scale = (1.0 - 2.0 * eps);\n        if (scale < 0) scale = 0; // Should not happen for eps <= 0.4\n\n        double dx = (a.x - b.x) * scale;\n        double dy = (a.y - b.y) * scale;\n        double dz = (a.z - b.z) * scale;\n        \n        double d2 = 0;\n        // Add distances for each valid block\n        if (varA > 1e-9) d2 += dx*dx / varA;\n        if (varB > 1e-9) d2 += dy*dy / varB;\n        if (varC > 1e-9) d2 += dz*dz / varC;\n        return d2;\n    }\n\n    // Try to find a good codebook for a specific N and mode\n    bool try_config(int n, bool use_2group, Config& out_cfg) {\n        int c_n1 = n / 2;\n        int c_n2 = n - c_n1;\n        if (!use_2group) {\n            c_n1 = n; c_n2 = 0;\n        }\n\n        double var_edge = eps * (1.0 - eps);\n        if (var_edge < 1e-9) var_edge = 1e-9; \n\n        int max_A = c_n1 * (c_n1 - 1) / 2;\n        int max_B = c_n1 * c_n2;\n        int max_C = c_n2 * (c_n2 - 1) / 2;\n\n        // Variance of the observed edge count in a block of size S is S * eps(1-eps)\n        double varA = max(0.1, (double)max_A * var_edge);\n        double varB = max(0.1, (double)max_B * var_edge);\n        double varC = max(0.1, (double)max_C * var_edge);\n        \n        double sigma_v = sqrt((n - 1) * var_edge);\n\n        vector<Code> pool;\n        int attempts = (use_2group ? 5000 : 2000); \n        \n        // Generate random candidates\n        if (!use_2group) {\n            // For 1 group, we just need total edges. Uniform sampling is fine.\n            // Actually, deterministic spacing is better for 1D.\n            for(int i=0; i<attempts; ++i) {\n                Code c; \n                c.x = rand_int(0, max_A);\n                c.y = 0; c.z = 0;\n                pool.push_back(c);\n            }\n        } else {\n            for(int i=0; i<attempts; ++i) {\n                Code c;\n                c.x = rand_int(0, max_A);\n                c.y = rand_int(0, max_B);\n                c.z = rand_int(0, max_C);\n\n                // Calculate expected average degrees\n                double deg1 = (2.0 * c.x + c.y) / c_n1;\n                double deg2 = (c.y + 2.0 * c.z) / c_n2;\n                \n                // Attenuated difference observed at receiver\n                double diff = (deg1 - deg2) * (1.0 - 2.0 * eps);\n                \n                // Constraint: Means must be separated by at least 3.8 sigma to allow sorting\n                // With 3.8, overlap is < 1e-4.\n                if (diff > 3.8 * sigma_v) {\n                    pool.push_back(c);\n                }\n            }\n        }\n\n        if ((int)pool.size() < M) return false;\n\n        // Greedy MaxMin Selection\n        vector<Code> selected;\n        selected.push_back(pool[0]);\n        \n        // Distance cache\n        vector<double> min_dists(pool.size(), 1e18);\n        auto dist_func = [&](const Code& a, const Code& b) {\n             return calc_dist_sq(a, b, varA, varB, varC);\n        };\n\n        // Initialize distances to first selected\n        for(size_t i=0; i<pool.size(); ++i) min_dists[i] = dist_func(pool[i], selected[0]);\n\n        while(selected.size() < M) {\n            int best_idx = -1;\n            double max_val = -1.0;\n            for(size_t i=0; i<pool.size(); ++i) {\n                if (min_dists[i] > max_val) {\n                    max_val = min_dists[i];\n                    best_idx = i;\n                }\n            }\n            \n            if (best_idx == -1) break; \n            \n            selected.push_back(pool[best_idx]);\n            min_dists[best_idx] = -1.0; // mark used\n            \n            // Update distances\n            for(size_t i=0; i<pool.size(); ++i) {\n                if (min_dists[i] > -0.5) { // if not used\n                    min_dists[i] = min(min_dists[i], dist_func(pool[i], pool[best_idx]));\n                }\n            }\n        }\n\n        if (selected.size() < M) return false;\n\n        // Compute final min distance of the codebook\n        double min_d_sq = 1e18;\n        for(int i=0; i<M; ++i) {\n            for(int j=i+1; j<M; ++j) {\n                min_d_sq = min(min_d_sq, dist_func(selected[i], selected[j]));\n            }\n        }\n\n        out_cfg.N = n;\n        out_cfg.n1 = c_n1;\n        out_cfg.n2 = c_n2;\n        out_cfg.mode_2group = use_2group;\n        out_cfg.codebook = selected;\n        out_cfg.min_dist = sqrt(min_d_sq);\n        return true;\n    }\n\n    void run() {\n        // Low epsilon optimization\n        if (eps < 1e-4) {\n            // Minimal valid N\n            for(int n=4; n<=100; ++n) {\n                if (n*(n-1)/2 + 1 >= M) {\n                    cout << n << endl;\n                    for(int i=0; i<M; ++i) {\n                        string s(n*(n-1)/2, '0');\n                        for(int k=0; k<i; ++k) s[k] = '1';\n                        cout << s << endl;\n                    }\n                    for(int q=0; q<100; ++q) {\n                        string s; cin >> s;\n                        int cnt = 0; for(char c:s) if(c=='1') cnt++;\n                        cout << min(cnt, M-1) << endl;\n                    }\n                    return;\n                }\n            }\n        }\n\n        // General Case: Search for optimal N\n        // We want smallest N such that min_dist > target_threshold.\n        // Target threshold ensures error rate ~ 0.\n        // For M=100, roughly need dist > 7.0 sigma.\n        double target = 7.0;\n        \n        Config best_global;\n        best_global.min_dist = -1.0;\n        best_global.N = 100; // Default safe\n\n        // Try N from 4 to 100\n        for(int n=4; n<=100; ++n) {\n            Config cfg1, cfg2;\n            double d1 = -1, d2 = -1;\n            \n            bool ok1 = try_config(n, false, cfg1);\n            if(ok1) d1 = cfg1.min_dist;\n            \n            bool ok2 = try_config(n, true, cfg2);\n            if(ok2) d2 = cfg2.min_dist;\n\n            // Pick best for this N\n            Config* best_local = nullptr;\n            if (ok2 && d2 > d1) best_local = &cfg2;\n            else if (ok1) best_local = &cfg1;\n            \n            if (best_local) {\n                // Update global best if this is the best distance seen so far\n                // Or if we reached target with a smaller N than previous solution (implicit since loop is increasing N)\n                if (best_local->min_dist > best_global.min_dist) {\n                    best_global = *best_local;\n                }\n                \n                // If we satisfy safety margin, stop immediately (since smaller N is better score)\n                if (best_local->min_dist > target) {\n                    best_global = *best_local;\n                    break;\n                }\n            }\n        }\n        \n        output(best_global);\n    }\n\n    void output(const Config& cfg) {\n        cout << cfg.N << endl;\n        \n        // Output Codes\n        for(int i=0; i<M; ++i) {\n            string s_out = \"\";\n            int req_x = cfg.codebook[i].x;\n            int req_y = cfg.codebook[i].y;\n            int req_z = cfg.codebook[i].z;\n            \n            // Adjacency matrix construction\n            vector<string> adj(cfg.N, string(cfg.N, '0'));\n            int cur_x=0, cur_y=0, cur_z=0;\n            \n            for(int u=0; u<cfg.N; ++u) {\n                for(int v=u+1; v<cfg.N; ++v) {\n                    // Determine block type\n                    // Group 1 is [0, n1), Group 2 is [n1, N)\n                    bool u1 = (u < cfg.n1);\n                    bool v1 = (v < cfg.n1);\n                    int type = 1; // 1-2\n                    if (u1 && v1) type = 0; // 1-1\n                    else if (!u1 && !v1) type = 2; // 2-2\n                    \n                    bool add = false;\n                    if (type==0 && cur_x < req_x) { add=true; cur_x++; }\n                    else if (type==1 && cur_y < req_y) { add=true; cur_y++; }\n                    else if (type==2 && cur_z < req_z) { add=true; cur_z++; }\n                    \n                    if(add) adj[u][v] = adj[v][u] = '1';\n                }\n            }\n            \n            // Flatten\n            for(int u=0; u<cfg.N; ++u) {\n                for(int v=u+1; v<cfg.N; ++v) {\n                    s_out += adj[u][v];\n                }\n            }\n            cout << s_out << endl;\n        }\n        \n        // Decode\n        for(int q=0; q<100; ++q) {\n            string s; cin >> s;\n            cout << decode(s, cfg) << endl;\n        }\n    }\n    \n    int decode(const string& s, const Config& cfg) {\n        int N = cfg.N;\n        \n        // 1. Calculate degrees\n        vector<int> deg(N, 0);\n        int k=0;\n        int total_edges = 0;\n        vector<vector<int>> adj(N, vector<int>(N));\n        \n        for(int u=0; u<N; ++u) {\n            for(int v=u+1; v<N; ++v) {\n                if(s[k]=='1') {\n                    deg[u]++; deg[v]++;\n                    total_edges++;\n                    adj[u][v] = adj[v][u] = 1;\n                }\n                k++;\n            }\n        }\n        \n        double obs_x = 0, obs_y = 0, obs_z = 0;\n        \n        if (!cfg.mode_2group) {\n            obs_x = total_edges;\n        } else {\n            // Sort vertices by degree descending\n            vector<pair<int, int>> p(N);\n            for(int i=0; i<N; ++i) p[i] = {deg[i], i};\n            sort(p.rbegin(), p.rend());\n            \n            // Assign groups\n            vector<int> g(N);\n            for(int i=0; i<cfg.n1; ++i) g[p[i].second] = 0;\n            for(int i=cfg.n1; i<N; ++i) g[p[i].second] = 1;\n            \n            // Count block edges\n            for(int u=0; u<N; ++u) {\n                for(int v=u+1; v<N; ++v) {\n                    if(adj[u][v]) {\n                        if (g[u]==0 && g[v]==0) obs_x++;\n                        else if (g[u]==1 && g[v]==1) obs_z++;\n                        else obs_y++;\n                    }\n                }\n            }\n        }\n        \n        // Max Likelihood (Minimum Distance)\n        int max_A = cfg.n1*(cfg.n1-1)/2;\n        int max_B = cfg.n1*cfg.n2;\n        int max_C = cfg.n2*(cfg.n2-1)/2;\n        if (!cfg.mode_2group) { max_A = N*(N-1)/2; max_B=0; max_C=0; }\n        \n        double varA = max(0.1, (double)max_A * eps * (1.0 - eps));\n        double varB = max(0.1, (double)max_B * eps * (1.0 - eps));\n        double varC = max(0.1, (double)max_C * eps * (1.0 - eps));\n        \n        int best_id = -1;\n        double min_dist = 1e18;\n        \n        for(int i=0; i<M; ++i) {\n            // Expected observed count = Original * (1-eps) + (Total-Original) * eps\n            //                         = Original * (1-2eps) + Total * eps\n            double ex_x = cfg.codebook[i].x * (1.0 - 2.0 * eps) + max_A * eps;\n            double ex_y = cfg.codebook[i].y * (1.0 - 2.0 * eps) + max_B * eps;\n            double ex_z = cfg.codebook[i].z * (1.0 - 2.0 * eps) + max_C * eps;\n            \n            double d = 0;\n            d += (obs_x - ex_x)*(obs_x - ex_x) / varA;\n            if (cfg.mode_2group) {\n                d += (obs_y - ex_y)*(obs_y - ex_y) / varB;\n                d += (obs_z - ex_z)*(obs_z - ex_z) / varC;\n            }\n            \n            if (d < min_dist) {\n                min_dist = d;\n                best_id = i;\n            }\n        }\n        return best_id;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int M;\n    double eps;\n    if (cin >> M >> eps) {\n        Solver s;\n        s.init(M, eps);\n        s.run();\n    }\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants\nconst long long INF_DIST = 1e18;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Point {\n    int x, y;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<Point> coords;\nvector<vector<pair<int, int>>> adj; // u -> {v, edge_index}\n\n// Precomputed data\nvector<vector<int16_t>> edge_hop_dist; // MxM matrix storing hop distances between edges\nvector<double> edge_importance; // size M, stores approximate betweenness centrality\n\n// Solution state\nvector<int> assignment; // edge_id -> day (1-based)\nvector<vector<int>> day_edges; // day (1-based) -> list of edge_ids\n\n// Random number generator\nmt19937 rng(12345);\n\n// Time management\nauto start_time = chrono::steady_clock::now();\ndouble get_time() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Union Find for connectivity checks\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n + 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) parent[rootX] = rootY;\n    }\n};\n\n// Preprocessing: Hop distances between all pairs of nodes and then edges\nvoid compute_hop_distances() {\n    // node_hop_dist[u][v]: min hops between node u and node v\n    vector<vector<int16_t>> node_dist(N + 1, vector<int16_t>(N + 1, 0));\n\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        vector<int> d(N + 1, -1);\n        queue<int> q;\n        \n        d[start_node] = 0;\n        q.push(start_node);\n        \n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            for (auto& edge : adj[u]) {\n                int v = edge.first;\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        for(int i=1; i<=N; ++i) node_dist[start_node][i] = (int16_t)d[i];\n    }\n\n    // Compute edge_hop_dist[i][j]: min hops between any endpoint of edge i and any endpoint of edge j\n    edge_hop_dist.assign(M, vector<int16_t>(M));\n    for (int i = 0; i < M; ++i) {\n        for (int j = i; j < M; ++j) {\n            if (i == j) {\n                edge_hop_dist[i][j] = 0;\n            } else {\n                int u1 = edges[i].u;\n                int v1 = edges[i].v;\n                int u2 = edges[j].u;\n                int v2 = edges[j].v;\n                \n                int d1 = node_dist[u1][u2];\n                int d2 = node_dist[u1][v2];\n                int d3 = node_dist[v1][u2];\n                int d4 = node_dist[v1][v2];\n                \n                int min_d = min({d1, d2, d3, d4});\n                edge_hop_dist[i][j] = min_d;\n                edge_hop_dist[j][i] = min_d;\n            }\n        }\n    }\n}\n\n// Preprocessing: Importance (Betweenness Centrality approximation)\nvoid compute_importance() {\n    edge_importance.assign(M, 0.0);\n    \n    // Run Dijkstra from each node to count how often an edge is part of a Shortest Path Tree\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, INF_DIST);\n        vector<int> parent_edge(N + 1, -1);\n        \n        dist[start_node] = 0;\n        pq.push({0, start_node});\n        \n        while (!pq.empty()) {\n            long long d = pq.top().first;\n            int u = pq.top().second;\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            \n            for (auto& e : adj[u]) {\n                int v = e.first;\n                int idx = e.second;\n                int w = edges[idx].w;\n                \n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        // Backtrack to increment counts\n        for (int i = 1; i <= N; ++i) {\n            if (i == start_node) continue;\n            int curr = i;\n            while (curr != start_node && parent_edge[curr] != -1) {\n                int e_idx = parent_edge[curr];\n                edge_importance[e_idx] += 1.0;\n                \n                int u = edges[e_idx].u;\n                int v = edges[e_idx].v;\n                // Determine which node is closer to start_node\n                if (dist[u] < dist[v]) curr = u;\n                else curr = v;\n            }\n        }\n    }\n    \n    // Normalize\n    double max_imp = 0;\n    for (double v : edge_importance) max_imp = max(max_imp, v);\n    if (max_imp > 0) {\n        for (auto& v : edge_importance) v /= max_imp;\n    }\n}\n\n// Initial Solution Generation\nvoid initial_solution() {\n    assignment.assign(M, 0);\n    day_edges.assign(D + 1, vector<int>());\n    \n    // Use BFS on the dual-like structure or just BFS on edges starting from center\n    // to ensure nearby edges get consecutive indices.\n    vector<bool> visited(M, false);\n    queue<int> q;\n    \n    // Find node closest to center (500, 500)\n    int center_node = 1;\n    int min_dist = 1e9;\n    if (!coords.empty()) {\n        for(int i=1; i<=N; ++i) {\n            int d = (coords[i-1].x - 500)*(coords[i-1].x - 500) + (coords[i-1].y - 500)*(coords[i-1].y - 500);\n            if (d < min_dist) {\n                min_dist = d;\n                center_node = i;\n            }\n        }\n    }\n    \n    // Push edges of center node\n    for(auto& p : adj[center_node]) {\n        q.push(p.second);\n        visited[p.second] = true;\n    }\n    if(q.empty()) { q.push(0); visited[0] = true; }\n\n    vector<int> ordered_edges;\n    ordered_edges.reserve(M);\n    \n    while(ordered_edges.size() < M) {\n        if (q.empty()) {\n            for(int i=0; i<M; ++i) if(!visited[i]) { q.push(i); visited[i]=true; break; }\n        }\n        \n        while(!q.empty()){\n            int e_idx = q.front();\n            q.pop();\n            ordered_edges.push_back(e_idx);\n            \n            int u = edges[e_idx].u;\n            int v = edges[e_idx].v;\n            \n            for(auto& p : adj[u]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n            for(auto& p : adj[v]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n        }\n    }\n    \n    // Assign days in a round-robin fashion to spatially separate edges on the same day\n    vector<int> counts(D + 1, 0);\n    int current_day = 1;\n    for(int e_idx : ordered_edges) {\n        // Ensure we don't exceed K\n        while(counts[current_day] >= K) {\n            current_day = (current_day % D) + 1;\n        }\n        assignment[e_idx] = current_day;\n        day_edges[current_day].push_back(e_idx);\n        counts[current_day]++;\n        current_day = (current_day % D) + 1;\n    }\n}\n\n// Cost Function for SA\n// Calculate contribution of a pair of removed edges (i, j)\ninline double pair_cost(int i, int j) {\n    double dist = edge_hop_dist[i][j];\n    // Penalty is high if distance is small.\n    // Penalty is scaled by importance: removing two important edges nearby is very bad.\n    double imp_factor = 1.0 + 10.0 * edge_importance[i] * edge_importance[j]; \n    return imp_factor / ((dist + 1.0) * (dist + 1.0));\n}\n\n// Calculate total dispersion cost for a day\ndouble calculate_day_cost(int d) {\n    double cost = 0;\n    const auto& es = day_edges[d];\n    for (size_t i = 0; i < es.size(); ++i) {\n        for (size_t j = i + 1; j < es.size(); ++j) {\n            cost += pair_cost(es[i], es[j]);\n        }\n    }\n    return cost;\n}\n\n// Check if graph remains connected when edges of day 'd' are removed\nbool check_connectivity(int d) {\n    DSU dsu(N);\n    int components = N;\n    for(int i=0; i<M; ++i) {\n        if (assignment[i] != d) {\n            if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                dsu.unite(edges[i].u, edges[i].v);\n                components--;\n            }\n        }\n    }\n    return components == 1;\n}\n\n// Try to fix connectivity issues greedily\nbool fix_connectivity() {\n    bool changed = false;\n    for (int d = 1; d <= D; ++d) {\n        if (!check_connectivity(d)) {\n            // Identify components\n            DSU dsu(N);\n            for(int i=0; i<M; ++i) {\n                if (assignment[i] != d) {\n                    dsu.unite(edges[i].u, edges[i].v);\n                }\n            }\n            \n            // Find an edge currently scheduled for day 'd' that connects two different components\n            // If we move this edge to another day, it will be present on day 'd', fixing connectivity.\n            int best_edge = -1;\n            \n            for (int e_idx : day_edges[d]) {\n                if (dsu.find(edges[e_idx].u) != dsu.find(edges[e_idx].v)) {\n                    best_edge = e_idx;\n                    break; // Found a bridging edge\n                }\n            }\n            \n            if (best_edge != -1) {\n                // Move best_edge to a day with capacity < K\n                for (int target = 1; target <= D; ++target) {\n                    if (target != d && day_edges[target].size() < K) {\n                        // Perform move\n                        vector<int>& vec_d = day_edges[d];\n                        vec_d.erase(remove(vec_d.begin(), vec_d.end(), best_edge), vec_d.end());\n                        \n                        day_edges[target].push_back(best_edge);\n                        assignment[best_edge] = target;\n                        changed = true;\n                        break; \n                    }\n                }\n            }\n        }\n    }\n    return changed;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> D >> K)) return 0;\n    \n    adj.resize(N + 1);\n    edges.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        edges.push_back({u, v, w, i});\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n    \n    coords.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n\n    // 1. Preprocessing\n    compute_hop_distances();\n    compute_importance();\n    \n    // 2. Initial Assignment\n    initial_solution();\n\n    // Calculate initial costs\n    vector<double> day_costs(D + 1);\n    double total_cost = 0;\n    for (int d = 1; d <= D; ++d) {\n        day_costs[d] = calculate_day_cost(d);\n        total_cost += day_costs[d];\n    }\n\n    // 3. Simulated Annealing\n    double time_limit = 5.6; \n    double t0 = 5.0;\n    double t1 = 0.0001;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) { \n            if (get_time() > time_limit) break;\n        }\n        \n        double temp = t0 + (t1 - t0) * (get_time() / time_limit);\n        \n        // Swap Move: Pick two different days and swap an edge\n        int d1 = uniform_int_distribution<int>(1, D)(rng);\n        int d2 = uniform_int_distribution<int>(1, D)(rng);\n        if (d1 == d2) continue;\n        \n        if (day_edges[d1].empty() || day_edges[d2].empty()) continue;\n\n        int idx1 = uniform_int_distribution<int>(0, day_edges[d1].size() - 1)(rng);\n        int idx2 = uniform_int_distribution<int>(0, day_edges[d2].size() - 1)(rng);\n        \n        int e1 = day_edges[d1][idx1];\n        int e2 = day_edges[d2][idx2];\n        \n        // Calculate cost delta incrementally\n        double d1_old = day_costs[d1];\n        double d2_old = day_costs[d2];\n        \n        // Remove e1 from d1, add e2 to d1\n        double cost_e1_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e1_in_d1 += pair_cost(e1, other);\n        }\n        double cost_e2_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e2_in_d1 += pair_cost(e2, other);\n        }\n        \n        // Remove e2 from d2, add e1 to d2\n        double cost_e2_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e2_in_d2 += pair_cost(e2, other);\n        }\n        double cost_e1_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e1_in_d2 += pair_cost(e1, other);\n        }\n        \n        double d1_new = d1_old - cost_e1_in_d1 + cost_e2_in_d1;\n        double d2_new = d2_old - cost_e2_in_d2 + cost_e1_in_d2;\n        \n        double delta = (d1_new + d2_new) - (d1_old + d2_old);\n        \n        if (delta < 0 || bernoulli_distribution(exp(-delta / temp))(rng)) {\n            // Accept swap\n            day_edges[d1][idx1] = e2;\n            day_edges[d2][idx2] = e1;\n            assignment[e1] = d2;\n            assignment[e2] = d1;\n            day_costs[d1] = d1_new;\n            day_costs[d2] = d2_new;\n            total_cost += delta;\n        }\n    }\n    \n    // 4. Ensure Connectivity\n    // Keep trying to fix until valid or time is up (allow slight over time if needed, but keep safe)\n    while (get_time() < 5.9) {\n        if (!fix_connectivity()) break; \n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        cout << assignment[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cstring>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Timing\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\nconst int MAX_D = 14;\nint D;\n\n// Inputs\nvector<string> f1_in, r1_in, f2_in, r2_in;\n\nstruct Point {\n    int x, y, z;\n    bool operator<(const Point& other) const {\n        if (x != other.x) return x < other.x;\n        if (y != other.y) return y < other.y;\n        return z < other.z;\n    }\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y && z == other.z;\n    }\n    Point operator+(const Point& other) const {\n        return {x + other.x, y + other.y, z + other.z};\n    }\n    Point operator-(const Point& other) const {\n        return {x - other.x, y - other.y, z - other.z};\n    }\n};\n\nstruct Rotation {\n    int p[3];\n    int s[3];\n};\nvector<Rotation> rotations;\n\nvoid init_rotations() {\n    int perms[6][3] = {{0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}};\n    for (int i = 0; i < 6; ++i) {\n        for (int mask = 0; mask < 8; ++mask) {\n            Rotation r;\n            for (int j = 0; j < 3; ++j) {\n                r.p[j] = perms[i][j];\n                r.s[j] = (mask & (1 << j)) ? -1 : 1;\n            }\n            int mat[3][3] = {0};\n            for(int j=0; j<3; ++j) mat[j][r.p[j]] = r.s[j];\n            int det = mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1])\n                    - mat[0][1]*(mat[1][0]*mat[2][2] - mat[1][2]*mat[2][0])\n                    + mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]);\n            if (det == 1) rotations.push_back(r);\n        }\n    }\n}\n\nPoint apply(const Point& pt, int rot_idx) {\n    const Rotation& r = rotations[rot_idx];\n    int coords[3] = {pt.x, pt.y, pt.z};\n    return {\n        coords[r.p[0]] * r.s[0],\n        coords[r.p[1]] * r.s[1],\n        coords[r.p[2]] * r.s[2]\n    };\n}\n\nbool get_bit(const vector<string>& bits, int r, int c) {\n    return bits[r][c] == '1';\n}\n\nusing VoxelSet = vector<Point>;\n\nVoxelSet get_maximal(const vector<string>& f, const vector<string>& r_sil) {\n    VoxelSet voxels;\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = 0; z < D; ++z) {\n                if (get_bit(f, z, x) && get_bit(r_sil, z, y)) {\n                    voxels.push_back({x, y, z});\n                }\n            }\n        }\n    }\n    return voxels;\n}\n\n// Compute importance weights for voxels based on current silhouette coverage\n// Higher weight = more essential\nvector<double> compute_weights(const VoxelSet& voxels, const vector<string>& f, const vector<string>& r_sil) {\n    vector<double> weights(voxels.size());\n    vector<vector<int>> czx(D, vector<int>(D, 0));\n    vector<vector<int>> czy(D, vector<int>(D, 0));\n\n    for(const auto& p : voxels) {\n        czx[p.z][p.x]++;\n        czy[p.z][p.y]++;\n    }\n\n    for(size_t i=0; i<voxels.size(); ++i) {\n        Point p = voxels[i];\n        double w = 0.1; // Base weight for volume\n        // Add weight if it supports a pixel with few supporters\n        if (czx[p.z][p.x] > 0) w += 1.0 / czx[p.z][p.x];\n        if (czy[p.z][p.y] > 0) w += 1.0 / czy[p.z][p.y];\n        weights[i] = w;\n    }\n    return weights;\n}\n\n// Find best alignment and extract shared block\n// Returns: indices in v1, indices in v2 (that form the block)\npair<vector<int>, vector<int>> find_best_shared_block(\n    const VoxelSet& v1, const VoxelSet& v2, \n    const vector<double>& w1, const vector<double>& w2,\n    mt19937& rng\n) {\n    if(v1.empty() || v2.empty()) return {{}, {}};\n\n    double best_val = -1.0;\n    int best_rot = -1;\n    Point best_shift = {0,0,0};\n\n    int offset_base = D;\n    int dim = 2 * D + 1;\n    int dim_sq = dim * dim;\n    static vector<double> votes;\n    if(votes.size() != dim*dim*dim) votes.resize(dim*dim*dim);\n\n    for (int rot = 0; rot < 24; ++rot) {\n        fill(votes.begin(), votes.end(), 0.0);\n\n        // Transform v2\n        vector<Point> v2_rot(v2.size());\n        for(size_t i=0; i<v2.size(); ++i) v2_rot[i] = apply(v2[i], rot);\n\n        // Convolution-like voting with weights\n        for (size_t i = 0; i < v1.size(); ++i) {\n            for (size_t j = 0; j < v2.size(); ++j) {\n                Point d = v1[i] - v2_rot[j];\n                if (abs(d.x) < D && abs(d.y) < D && abs(d.z) < D) {\n                    int idx = (d.x + offset_base) * dim_sq + (d.y + offset_base) * dim + (d.z + offset_base);\n                    votes[idx] += (w1[i] + w2[j]);\n                }\n            }\n        }\n\n        // Find max\n        for(int i=0; i<dim*dim*dim; ++i) {\n            if(votes[i] > best_val) {\n                best_val = votes[i];\n                best_rot = rot;\n                int dz = i % dim;\n                int dy = (i / dim) % dim;\n                int dx = (i / dim_sq);\n                best_shift = {dx - offset_base, dy - offset_base, dz - offset_base};\n            }\n        }\n    }\n\n    if (best_val < 0.001) return {{}, {}};\n\n    // Reconstruct Intersection\n    map<Point, int> v2_map;\n    for(size_t i=0; i<v2.size(); ++i) {\n        Point p = apply(v2[i], best_rot) + best_shift;\n        v2_map[p] = i;\n    }\n\n    VoxelSet intersection;\n    map<Point, int> p_to_v1;\n    for(size_t i=0; i<v1.size(); ++i) {\n        if (v2_map.count(v1[i])) {\n            intersection.push_back(v1[i]);\n            p_to_v1[v1[i]] = i;\n        }\n    }\n\n    // Find component with max weight\n    set<Point> int_set(intersection.begin(), intersection.end());\n    set<Point> visited;\n    vector<Point> best_comp;\n    double max_comp_weight = -1.0;\n\n    for(const auto& p : intersection) {\n        if (visited.count(p)) continue;\n        \n        vector<Point> comp;\n        double current_weight = 0;\n        queue<Point> q;\n        q.push(p);\n        visited.insert(p);\n        comp.push_back(p);\n        current_weight += w1[p_to_v1[p]] + w2[v2_map[p]];\n        \n        while(!q.empty()){\n            Point u = q.front(); q.pop();\n            int dx[] = {1, -1, 0, 0, 0, 0};\n            int dy[] = {0, 0, 1, -1, 0, 0};\n            int dz[] = {0, 0, 0, 0, 1, -1};\n            \n            for(int k=0; k<6; ++k){\n                Point v = {u.x + dx[k], u.y + dy[k], u.z + dz[k]};\n                if(int_set.count(v) && visited.find(v) == visited.end()){\n                    visited.insert(v);\n                    q.push(v);\n                    comp.push_back(v);\n                    current_weight += w1[p_to_v1[v]] + w2[v2_map[v]];\n                }\n            }\n        }\n        \n        if (current_weight > max_comp_weight) {\n            max_comp_weight = current_weight;\n            best_comp = comp;\n        }\n    }\n    \n    vector<int> r1, r2;\n    for(auto& p : best_comp) {\n        r1.push_back(p_to_v1[p]);\n        r2.push_back(v2_map[p]);\n    }\n    return {r1, r2};\n}\n\n// Minimal set cover for residuals\nvector<Point> solve_residual(const VoxelSet& candidates, const vector<string>& f, const vector<string>& r_sil, const set<pair<int,int>>& covered_xz, const set<pair<int,int>>& covered_yz) {\n    vector<pair<int,int>> targets_xz;\n    vector<pair<int,int>> targets_yz;\n    for(int z=0; z<D; ++z) {\n        for(int x=0; x<D; ++x) if(get_bit(f,z,x) && covered_xz.find({x,z}) == covered_xz.end()) targets_xz.push_back({x,z});\n        for(int y=0; y<D; ++y) if(get_bit(r_sil,z,y) && covered_yz.find({y,z}) == covered_yz.end()) targets_yz.push_back({y,z});\n    }\n\n    vector<Point> chosen;\n    if(targets_xz.empty() && targets_yz.empty()) return chosen;\n\n    vector<int> status(candidates.size(), 1); \n    vector<bool> tx_cov(targets_xz.size(), false);\n    vector<bool> ty_cov(targets_yz.size(), false);\n    int rem_tx = targets_xz.size();\n    int rem_ty = targets_yz.size();\n\n    while(rem_tx > 0 || rem_ty > 0) {\n        int best_idx = -1;\n        int best_cnt = -1;\n        \n        int step = 1;\n        if (candidates.size() > 1000) step = 2;\n\n        for(size_t i=0; i<candidates.size(); i+=step) {\n            if(!status[i]) continue;\n            int cnt = 0;\n            const Point& p = candidates[i];\n            for(size_t k=0; k<targets_xz.size(); ++k) {\n                if(!tx_cov[k] && targets_xz[k].first == p.x && targets_xz[k].second == p.z) cnt++;\n            }\n            for(size_t k=0; k<targets_yz.size(); ++k) {\n                if(!ty_cov[k] && targets_yz[k].first == p.y && targets_yz[k].second == p.z) cnt++;\n            }\n            if(cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = i;\n            }\n        }\n        \n        if(best_idx == -1 || best_cnt == 0) break;\n\n        chosen.push_back(candidates[best_idx]);\n        status[best_idx] = 0;\n        const Point& p = candidates[best_idx];\n        for(size_t k=0; k<targets_xz.size(); ++k) {\n            if(!tx_cov[k] && targets_xz[k].first == p.x && targets_xz[k].second == p.z) {\n                tx_cov[k] = true; rem_tx--;\n            }\n        }\n        for(size_t k=0; k<targets_yz.size(); ++k) {\n            if(!ty_cov[k] && targets_yz[k].first == p.y && targets_yz[k].second == p.z) {\n                ty_cov[k] = true; rem_ty--;\n            }\n        }\n    }\n    return chosen;\n}\n\nstruct BlockRes {\n    int id;\n    int vol;\n};\nstruct FullSol {\n    vector<int> g1, g2;\n    int n_blocks;\n    double score;\n};\n\nvoid solve() {\n    cin >> D;\n    f1_in.resize(D); r1_in.resize(D);\n    f2_in.resize(D); r2_in.resize(D);\n    for(int i=0; i<D; ++i) cin >> f1_in[i];\n    for(int i=0; i<D; ++i) cin >> r1_in[i];\n    for(int i=0; i<D; ++i) cin >> f2_in[i];\n    for(int i=0; i<D; ++i) cin >> r2_in[i];\n\n    init_rotations();\n    VoxelSet M1_orig = get_maximal(f1_in, r1_in);\n    VoxelSet M2_orig = get_maximal(f2_in, r2_in);\n\n    FullSol best_sol;\n    best_sol.score = 1e18;\n\n    mt19937 rng(123);\n\n    while (get_time() < 5.7) {\n        VoxelSet M1 = M1_orig;\n        VoxelSet M2 = M2_orig;\n        vector<bool> used1(M1.size(), false);\n        vector<bool> used2(M2.size(), false);\n        int rem1_cnt = M1.size();\n        int rem2_cnt = M2.size();\n\n        vector<int> grid1(D*D*D, 0);\n        vector<int> grid2(D*D*D, 0);\n        int block_id = 1;\n        vector<BlockRes> shared_blocks;\n\n        // Iterative matching with dynamic weights\n        while(rem1_cnt > 0 && rem2_cnt > 0) {\n            VoxelSet s1, s2;\n            vector<int> m1, m2;\n            for(size_t i=0; i<M1.size(); ++i) if(!used1[i]) { s1.push_back(M1[i]); m1.push_back(i); }\n            for(size_t i=0; i<M2.size(); ++i) if(!used2[i]) { s2.push_back(M2[i]); m2.push_back(i); }\n\n            if (s1.empty() || s2.empty()) break;\n\n            vector<double> w1 = compute_weights(s1, f1_in, r1_in);\n            vector<double> w2 = compute_weights(s2, f2_in, r2_in);\n            \n            // Noise for randomization\n            for(auto& w : w1) w *= uniform_real_distribution<>(0.9, 1.1)(rng);\n            for(auto& w : w2) w *= uniform_real_distribution<>(0.9, 1.1)(rng);\n\n            auto res = find_best_shared_block(s1, s2, w1, w2, rng);\n            if(res.first.empty()) break;\n\n            BlockRes b; b.id = block_id++; b.vol = res.first.size();\n            shared_blocks.push_back(b);\n\n            for(int idx : res.first) {\n                int orig = m1[idx];\n                used1[orig] = true;\n                Point p = M1[orig];\n                grid1[p.x*D*D + p.y*D + p.z] = b.id;\n                rem1_cnt--;\n            }\n            for(int idx : res.second) {\n                int orig = m2[idx];\n                used2[orig] = true;\n                Point p = M2[orig];\n                grid2[p.x*D*D + p.y*D + p.z] = b.id;\n                rem2_cnt--;\n            }\n        }\n\n        // Fill Residuals\n        set<pair<int,int>> cov1_xz, cov1_yz, cov2_xz, cov2_yz;\n        for(int x=0; x<D; ++x) for(int y=0; y<D; ++y) for(int z=0; z<D; ++z) {\n            if(grid1[x*D*D + y*D + z] != 0) {\n                cov1_xz.insert({x,z}); cov1_yz.insert({y,z});\n            }\n            if(grid2[x*D*D + y*D + z] != 0) {\n                cov2_xz.insert({x,z}); cov2_yz.insert({y,z});\n            }\n        }\n\n        VoxelSet rem_cand1, rem_cand2;\n        for(size_t i=0; i<M1.size(); ++i) if(!used1[i]) rem_cand1.push_back(M1[i]);\n        for(size_t i=0; i<M2.size(); ++i) if(!used2[i]) rem_cand2.push_back(M2[i]);\n\n        vector<Point> unique1 = solve_residual(rem_cand1, f1_in, r1_in, cov1_xz, cov1_yz);\n        vector<Point> unique2 = solve_residual(rem_cand2, f2_in, r2_in, cov2_xz, cov2_yz);\n\n        double cur_score = 0;\n        for(const auto& b : shared_blocks) cur_score += 1.0/b.vol;\n        cur_score += unique1.size();\n        cur_score += unique2.size();\n\n        if (cur_score < best_sol.score) {\n            best_sol.score = cur_score;\n            best_sol.g1 = grid1;\n            best_sol.g2 = grid2;\n            int cur_id = block_id;\n            for(auto p : unique1) best_sol.g1[p.x*D*D + p.y*D + p.z] = cur_id++;\n            for(auto p : unique2) best_sol.g2[p.x*D*D + p.y*D + p.z] = cur_id++;\n            best_sol.n_blocks = cur_id - 1;\n        }\n    }\n\n    cout << best_sol.n_blocks << endl;\n    for(int i=0; i<(int)best_sol.g1.size(); ++i) cout << best_sol.g1[i] << (i==best_sol.g1.size()-1?\"\":\" \");\n    cout << endl;\n    for(int i=0; i<(int)best_sol.g2.size(); ++i) cout << best_sol.g2[i] << (i==best_sol.g2.size()-1?\"\":\" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc020":"/**\n * Problem: AHC020 - Broadcasting\n * Approach: Simulated Annealing to optimize resident-to-station assignment.\n * 1. Precompute all-pairs shortest paths on the graph G to support Steiner Tree heuristics.\n * 2. Represent the state by the assignment of each resident to a station.\n *    - The power P_i of station i is determined by the farthest resident assigned to it.\n *    - The active stations (terminals) are those with at least one resident assigned, plus station 1.\n * 3. The cost function is sum(P_i^2) + ApproximateSteinerTreeCost(active_stations).\n * 4. Use Simulated Annealing to move residents between nearby stations.\n *    - A move updates P_i and P_j incrementally.\n *    - If a station becomes empty or non-empty, the Steiner Tree cost is re-evaluated.\n * 5. Post-process to generate the exact edge set:\n *    - Construct the tree using the union of shortest paths between terminals (MST on metric closure).\n *    - Prune unnecessary leaves to minimize edge cost.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 105;\nconst int MAX_K = 5005;\nconst int MAX_M = 305;\nconst long long INF = 1e18;\n\n// Structures\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Station {\n    int x, y;\n    int id;\n};\n\n// Global Inputs\nint N, M, K;\nStation stations[MAX_N];\nEdge edges[MAX_M];\nPoint residents[MAX_K];\n\n// Precomputed Data\nlong long adj_dist[MAX_N][MAX_N];      // Shortest path distance in G\nint next_node[MAX_N][MAX_N];           // Next node in shortest path\nint edge_index[MAX_N][MAX_N];          // Edge ID connecting two nodes\nint resident_ceil_dist[MAX_K][MAX_N];  // Required P for resident k at station i\nvector<int> nearby_stations[MAX_K];    // List of stations sorted by distance for each resident\n\n// Random number generator\nmt19937 rng(12345);\n\n// Helper Functions\nlong long distSq(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint get_P(long long sq_dist) {\n    if (sq_dist == 0) return 0;\n    return (int)ceil(sqrt((double)sq_dist));\n}\n\n// State Management\nstruct State {\n    vector<int> assignment;                 // resident k -> station index\n    vector<multiset<int>> station_radii;    // station i -> set of required radii (P values)\n    vector<int> active_residents_count;     // station i -> number of assigned residents\n    \n    long long power_cost;\n    long long network_cost;\n    long long total_cost;\n\n    State() {\n        assignment.resize(K);\n        station_radii.resize(N);\n        active_residents_count.assign(N, 0);\n        power_cost = 0;\n        network_cost = 0;\n        total_cost = 0;\n    }\n};\n\nvoid precompute_paths() {\n    // Initialize\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            adj_dist[i][j] = (i == j ? 0 : INF);\n            next_node[i][j] = -1;\n            edge_index[i][j] = -1;\n        }\n    }\n\n    // Load edges\n    for(int i=0; i<M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int w = edges[i].w;\n        // Graph is simple, but standard check\n        if(w < adj_dist[u][v] || adj_dist[u][v] == INF) {\n            adj_dist[u][v] = adj_dist[v][u] = w;\n            next_node[u][v] = v;\n            next_node[v][u] = u;\n            edge_index[u][v] = edge_index[v][u] = i;\n        }\n    }\n\n    // Floyd-Warshall with path reconstruction\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(adj_dist[i][k] != INF && adj_dist[k][j] != INF) {\n                    if(adj_dist[i][k] + adj_dist[k][j] < adj_dist[i][j]) {\n                        adj_dist[i][j] = adj_dist[i][k] + adj_dist[k][j];\n                        next_node[i][j] = next_node[i][k];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate Approximate Steiner Tree Cost\n// This constructs a tree covering the active terminals (stations with residents + station 0).\n// It uses the union of shortest paths from the MST on the metric closure.\nlong long calc_steiner_cost(const vector<bool>& is_terminal) {\n    vector<int> terminals;\n    for(int i=0; i<N; ++i) {\n        if(is_terminal[i] || i == 0) terminals.push_back(i);\n    }\n    \n    if(terminals.size() <= 1) return 0;\n\n    // 1. MST on metric closure (complete graph of terminals)\n    int T = terminals.size();\n    vector<long long> min_dist(T, INF);\n    vector<int> parent(T, -1);\n    vector<bool> visited(T, false);\n    \n    min_dist[0] = 0;\n    \n    // Prim's Algorithm\n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_dist[j] < best) {\n                best = min_dist[j];\n                u = j;\n            }\n        }\n        if (u == -1) break;\n        visited[u] = true;\n        \n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[terminals[u]][terminals[v]];\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    \n    // 2. Map MST edges back to original graph paths and sum unique edge weights\n    bitset<MAX_M> used_edges;\n    long long total_w = 0;\n    \n    for(int i=1; i<T; ++i) {\n        if (parent[i] == -1) continue; \n        int u = terminals[i];\n        int v = terminals[parent[i]];\n        \n        int curr = u;\n        while(curr != v) {\n            int nxt = next_node[curr][v];\n            int idx = edge_index[curr][nxt];\n            if(idx != -1 && !used_edges[idx]) {\n                used_edges[idx] = 1;\n                total_w += edges[idx].w;\n            }\n            curr = nxt;\n        }\n    }\n    \n    return total_w;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    if (!(cin >> N >> M >> K)) return 0;\n    for(int i=0; i<N; ++i) {\n        cin >> stations[i].x >> stations[i].y;\n        stations[i].id = i;\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--; // 0-indexed\n        edges[i].id = i;\n    }\n    for(int i=0; i<K; ++i) {\n        cin >> residents[i].x >> residents[i].y;\n    }\n\n    // Initialization\n    precompute_paths();\n\n    // Precompute distances and sort nearby stations for each resident\n    for(int k=0; k<K; ++k) {\n        vector<pair<int, int>> dists;\n        for(int i=0; i<N; ++i) {\n            long long sq = distSq(residents[k].x, residents[k].y, stations[i].x, stations[i].y);\n            int P = get_P(sq);\n            resident_ceil_dist[k][i] = P;\n            dists.push_back({P, i});\n        }\n        // Sort by distance\n        sort(dists.begin(), dists.end());\n        for(auto& p : dists) nearby_stations[k].push_back(p.second);\n    }\n\n    // Initial State: Assign each resident to the closest station\n    State current_state;\n    vector<bool> is_terminal(N, false);\n    \n    for(int k=0; k<K; ++k) {\n        int st_idx = nearby_stations[k][0]; \n        current_state.assignment[k] = st_idx;\n        current_state.station_radii[st_idx].insert(resident_ceil_dist[k][st_idx]);\n        current_state.active_residents_count[st_idx]++;\n    }\n\n    for(int i=0; i<N; ++i) {\n        if(current_state.active_residents_count[i] > 0) {\n            int P = *current_state.station_radii[i].rbegin();\n            current_state.power_cost += (long long)P * P;\n            is_terminal[i] = true;\n        }\n    }\n    \n    current_state.network_cost = calc_steiner_cost(is_terminal);\n    current_state.total_cost = current_state.power_cost + current_state.network_cost;\n\n    State best_state = current_state;\n\n    // Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95; \n    double start_temp = 2000000.0; // Tuned based on cost magnitude\n    double end_temp = 100.0;\n\n    int iter = 0;\n    while(true) {\n        iter++;\n        if((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if(elapsed > time_limit) break;\n        }\n\n        // 1. Pick a random resident\n        int k = rng() % K;\n        int old_u = current_state.assignment[k];\n        \n        // 2. Pick a new station (biased towards nearby ones)\n        // Consider top 15 closest stations\n        int rank = rng() % min(N, 15);\n        int new_v = nearby_stations[k][rank];\n        \n        if(old_u == new_v) continue;\n\n        // 3. Calculate Delta Power Cost\n        long long old_P_u_sq = 0;\n        if(!current_state.station_radii[old_u].empty()) {\n            int r = *current_state.station_radii[old_u].rbegin();\n            old_P_u_sq = (long long)r * r;\n        }\n        \n        long long old_P_v_sq = 0;\n        if(!current_state.station_radii[new_v].empty()) {\n            int r = *current_state.station_radii[new_v].rbegin();\n            old_P_v_sq = (long long)r * r;\n        }\n\n        // New P_u if k is removed\n        long long new_P_u_sq = old_P_u_sq;\n        int r_k_u = resident_ceil_dist[k][old_u];\n        bool u_becomes_empty = (current_state.active_residents_count[old_u] == 1);\n        \n        if (u_becomes_empty) {\n            new_P_u_sq = 0;\n        } else {\n            int current_max = *current_state.station_radii[old_u].rbegin();\n            if (r_k_u == current_max) {\n                // Check if there are other residents with the same max radius\n                if (current_state.station_radii[old_u].count(r_k_u) == 1) {\n                     // Find the second largest\n                     auto it = current_state.station_radii[old_u].find(r_k_u);\n                     if (it != current_state.station_radii[old_u].begin()) {\n                         auto prev_it = prev(it);\n                         new_P_u_sq = (long long)(*prev_it) * (*prev_it);\n                     } else {\n                         // Should not happen if count > 1, but technically possible if data inconsistent\n                         new_P_u_sq = 0; \n                     }\n                }\n                // If count > 1, removing one doesn't change the max\n            }\n        }\n\n        // New P_v if k is added\n        int r_k_v = resident_ceil_dist[k][new_v];\n        long long new_P_v_sq = old_P_v_sq;\n        bool v_becomes_active = (current_state.active_residents_count[new_v] == 0);\n\n        if (v_becomes_active) {\n            new_P_v_sq = (long long)r_k_v * r_k_v;\n        } else {\n            int current_max = *current_state.station_radii[new_v].rbegin();\n            if (r_k_v > current_max) {\n                new_P_v_sq = (long long)r_k_v * r_k_v;\n            }\n        }\n\n        long long power_delta = (new_P_u_sq - old_P_u_sq) + (new_P_v_sq - old_P_v_sq);\n        long long network_delta = 0;\n        long long new_network_cost = current_state.network_cost;\n\n        // 4. Calculate Delta Network Cost (only if active set changes)\n        if (u_becomes_empty || v_becomes_active) {\n            if (u_becomes_empty) is_terminal[old_u] = false;\n            if (v_becomes_active) is_terminal[new_v] = true;\n            \n            new_network_cost = calc_steiner_cost(is_terminal);\n            network_delta = new_network_cost - current_state.network_cost;\n            \n            // Revert for now\n            if (u_becomes_empty) is_terminal[old_u] = true;\n            if (v_becomes_active) is_terminal[new_v] = false;\n        }\n\n        long long total_delta = power_delta + network_delta;\n\n        // 5. Accept or Reject\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        double temp = start_temp + (end_temp - start_temp) * (elapsed / time_limit);\n        \n        bool accept = (total_delta <= 0);\n        if (!accept) {\n            double prob = exp(-total_delta / temp);\n            if (generate_canonical<double, 10>(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            // Apply changes\n            current_state.assignment[k] = new_v;\n            \n            auto it = current_state.station_radii[old_u].find(r_k_u);\n            current_state.station_radii[old_u].erase(it);\n            current_state.active_residents_count[old_u]--;\n            \n            current_state.station_radii[new_v].insert(r_k_v);\n            current_state.active_residents_count[new_v]++;\n            \n            current_state.power_cost += power_delta;\n            current_state.network_cost = new_network_cost;\n            current_state.total_cost += total_delta;\n            \n            if (u_becomes_empty) is_terminal[old_u] = false;\n            if (v_becomes_active) is_terminal[new_v] = true;\n            \n            if (current_state.total_cost < best_state.total_cost) {\n                best_state = current_state;\n            }\n        }\n    }\n\n    // Final Output Generation\n    \n    // 1. Identify final terminals\n    fill(is_terminal.begin(), is_terminal.end(), false);\n    vector<int> P_vals(N, 0);\n    vector<int> terminals;\n    \n    for(int i=0; i<N; ++i) {\n        if(best_state.active_residents_count[i] > 0) {\n            is_terminal[i] = true;\n            P_vals[i] = *best_state.station_radii[i].rbegin();\n        }\n    }\n    // Add root and all active stations to terminals list\n    for(int i=0; i<N; ++i) if(is_terminal[i] || i==0) terminals.push_back(i);\n    \n    // 2. Construct the network (Union of shortest paths)\n    bitset<MAX_M> used_edges_bs;\n    int T = terminals.size();\n    if (T > 1) {\n         vector<long long> min_dist(T, INF);\n         vector<int> parent(T, -1);\n         vector<bool> visited(T, false);\n         min_dist[0] = 0;\n         \n         for(int i=0; i<T; ++i) {\n            int u = -1;\n            long long best = INF;\n            for(int j=0; j<T; ++j) {\n                if(!visited[j] && min_dist[j] < best) {\n                    best = min_dist[j];\n                    u = j;\n                }\n            }\n            visited[u] = true;\n            for(int v=0; v<T; ++v) {\n                if(!visited[v]) {\n                    long long d = adj_dist[terminals[u]][terminals[v]];\n                    if(d < min_dist[v]) {\n                        min_dist[v] = d;\n                        parent[v] = u;\n                    }\n                }\n            }\n         }\n         \n         for(int i=1; i<T; ++i) {\n             int u = terminals[i];\n             int v = terminals[parent[i]];\n             int curr = u;\n             while(curr != v) {\n                 int nxt = next_node[curr][v];\n                 int idx = edge_index[curr][nxt];\n                 if(idx != -1) used_edges_bs[idx] = 1;\n                 curr = nxt;\n             }\n         }\n    }\n    \n    // 3. Pruning: Use Kruskal's on the induced subgraph and remove non-terminal leaves\n    vector<int> subgraph_edges;\n    for(int i=0; i<M; ++i) if(used_edges_bs[i]) subgraph_edges.push_back(i);\n    \n    // Sort edges by weight for Kruskal's\n    sort(subgraph_edges.begin(), subgraph_edges.end(), [](int a, int b){\n        return edges[a].w < edges[b].w;\n    });\n    \n    struct DSU {\n        vector<int> p;\n        DSU(int n) : p(n) { iota(p.begin(), p.end(), 0); }\n        int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n        bool unite(int x, int y) {\n            x = find(x); y = find(y);\n            if(x == y) return false;\n            p[x] = y; return true;\n        }\n    };\n    \n    DSU dsu(N);\n    vector<int> tree_edges;\n    vector<vector<pair<int,int>>> tree_adj(N);\n    vector<int> degree(N, 0);\n    \n    for(int id : subgraph_edges) {\n        if(dsu.unite(edges[id].u, edges[id].v)) {\n            tree_edges.push_back(id);\n            tree_adj[edges[id].u].push_back({edges[id].v, id});\n            tree_adj[edges[id].v].push_back({edges[id].u, id});\n            degree[edges[id].u]++;\n            degree[edges[id].v]++;\n        }\n    }\n    \n    // Leaf Pruning\n    queue<int> q;\n    for(int i=0; i<N; ++i) {\n        if(degree[i] == 1 && !is_terminal[i] && i != 0) {\n            q.push(i);\n        }\n    }\n    \n    vector<bool> final_edges(M, false);\n    for(int id : tree_edges) final_edges[id] = true;\n    \n    while(!q.empty()) {\n        int u = q.front(); q.pop();\n        for(auto& edge : tree_adj[u]) {\n            int v = edge.first;\n            int id = edge.second;\n            if(final_edges[id]) {\n                final_edges[id] = false;\n                degree[u]--;\n                degree[v]--;\n                if(degree[v] == 1 && !is_terminal[v] && v != 0) {\n                    q.push(v);\n                }\n                break; \n            }\n        }\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) cout << P_vals[i] << (i == N-1 ? \"\" : \" \");\n    cout << \"\\n\";\n    for(int i=0; i<M; ++i) cout << (final_edges[i] ? 1 : 0) << (i == M-1 ? \"\" : \" \");\n    cout << \"\\n\";\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 30;\nconst int MAX_OPS = 10000;\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\n// Check if a node violates the condition: must be smaller than both children\nbool is_violation(const vector<vector<int>>& b, int x, int y) {\n    if (x >= N - 1) return false;\n    int val = b[x][y];\n    int l = b[x+1][y];\n    int r = b[x+1][y+1];\n    // Violation if value is greater than either child\n    return (val > l || val > r);\n}\n\n// Global RNG\nmt19937 rng(0);\n\n// Solver function\n// strategy:\n// 0: LIFO (Stack)\n// 1: FIFO (Queue) - Not explicitly prioritized in loop but acts as baseline\n// 2: Min X (Top-Down Priority)\n// 3: Max X (Bottom-Up Priority)\n// 4: Random\n// 5: Max Value (Prioritize swapping large values)\n// 6: Min Value (Prioritize swapping small values)\nvector<Move> solve(const vector<vector<int>>& initial_board, int strategy, size_t limit_k) {\n    vector<vector<int>> b = initial_board;\n    vector<Move> ops;\n    ops.reserve(3000);\n\n    // Manage active violations\n    vector<pair<int,int>> violations;\n    violations.reserve(500);\n    // Lookup to prevent duplicates in the queue\n    vector<vector<bool>> in_violation(N, vector<bool>(N, false));\n    \n    auto add_violation = [&](int x, int y) {\n        if (x < 0 || x >= N - 1 || y < 0 || y > x) return;\n        if (!in_violation[x][y] && is_violation(b, x, y)) {\n            in_violation[x][y] = true;\n            violations.push_back({x, y});\n        }\n    };\n    \n    // Helper to remove a violation from the vector at index idx\n    auto remove_violation_at = [&](int idx) {\n        pair<int,int> p = violations[idx];\n        in_violation[p.first][p.second] = false;\n        // Swap with back and pop to keep vector compact (O(1))\n        violations[idx] = violations.back();\n        violations.pop_back();\n        return p;\n    };\n\n    // Initial scan\n    for(int x = 0; x < N - 1; ++x) {\n        for(int y = 0; y <= x; ++y) {\n            add_violation(x, y);\n        }\n    }\n\n    while (!violations.empty()) {\n        // Pruning: if we already exceeded the best solution found so far\n        if (ops.size() >= limit_k) {\n            return vector<Move>(MAX_OPS + 5); // Return invalid large vector\n        }\n\n        int idx = 0;\n        \n        if (strategy == 4) { // Random\n            uniform_int_distribution<int> dist(0, violations.size() - 1);\n            idx = dist(rng);\n        } else if (strategy == 0) { // LIFO (Stack)\n            idx = violations.size() - 1;\n        } else if (strategy == 1) { // FIFO\n            idx = 0;\n        } else {\n            // For prioritized strategies, scan the violations list.\n            // The list size is generally small (< 400), so linear scan is acceptable.\n            idx = 0;\n            // We use best_idx to track the optimal choice\n            int best_idx = 0;\n            \n            // Optimization: If list is large, sampling or partial scan could be faster,\n            // but complete scan is robust for quality.\n            for (int i = 1; i < (int)violations.size(); ++i) {\n                const auto& p1 = violations[i];\n                const auto& p_best = violations[best_idx];\n                \n                bool better = false;\n                if (strategy == 2) { // Min X (Top first)\n                    if (p1.first < p_best.first) better = true;\n                    else if (p1.first == p_best.first && p1.second < p_best.second) better = true;\n                } else if (strategy == 3) { // Max X (Bottom first)\n                    if (p1.first > p_best.first) better = true;\n                } else if (strategy == 5) { // Max Value\n                    if (b[p1.first][p1.second] > b[p_best.first][p_best.second]) better = true;\n                } else if (strategy == 6) { // Min Value\n                    if (b[p1.first][p1.second] < b[p_best.first][p_best.second]) better = true;\n                }\n                \n                if (better) best_idx = i;\n            }\n            idx = best_idx;\n        }\n\n        pair<int, int> u = remove_violation_at(idx);\n        int x = u.first;\n        int y = u.second;\n\n        // Check if it's still a violation (neighbors might have changed since addition)\n        if (!is_violation(b, x, y)) continue;\n\n        // Determine swap\n        // We must swap with the smaller of the two children to fix the local heap property optimally\n        int l = b[x+1][y];\n        int r = b[x+1][y+1];\n        \n        int swap_x = x + 1;\n        int swap_y = (l < r) ? y : y + 1;\n        \n        // Execute swap\n        swap(b[x][y], b[swap_x][swap_y]);\n        ops.push_back({x, y, swap_x, swap_y});\n\n        // Re-evaluate violations in neighborhood\n        // 1. The node itself might still be a violation (if it's very large)\n        add_violation(x, y);\n        \n        // 2. Parents of the original position\n        if (x > 0) {\n            if (y < x) add_violation(x-1, y);   // Parent at top-right\n            if (y > 0) add_violation(x-1, y-1); // Parent at top-left\n        }\n        \n        // 3. The position we swapped into\n        add_violation(swap_x, swap_y);\n        \n        // 4. Parents of the new position (other than (x,y))\n        // The child (swap_x, swap_y) has two parents: (x,y) and one other.\n        if (swap_y == y) { \n            // Left child: other parent is (x, y-1)\n            if (y > 0) add_violation(x, y-1);\n        } else { \n            // Right child: other parent is (x, y+1)\n            add_violation(x, y+1);\n        }\n    }\n\n    return ops;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    // Timing\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95; // Safety buffer\n\n    // State tracking\n    vector<Move> best_ops;\n    size_t min_k = MAX_OPS + 1;\n\n    auto update = [&](const vector<Move>& ops) {\n        if (ops.size() < min_k && ops.size() <= MAX_OPS) {\n            // If ops is empty, it means input was already sorted or handled correctly\n            // We accept it (size 0 is better than min_k)\n            // We need to ensure the solver actually finished (returned vector size <= MAX_OPS)\n            min_k = ops.size();\n            best_ops = ops;\n        }\n    };\n\n    // 1. Deterministic Strategies\n    update(solve(a, 2, min_k)); // Top-Down\n    update(solve(a, 3, min_k)); // Bottom-Up\n    update(solve(a, 5, min_k)); // Max Value\n    update(solve(a, 6, min_k)); // Min Value\n    \n    // 2. Randomized Strategies with Iteration\n    int seed = 12345;\n    while (true) {\n        auto curr_time = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = curr_time - start_time;\n        if (elapsed.count() > time_limit) break;\n\n        rng.seed(seed++);\n        // Strategy 4 is Random order\n        update(solve(a, 4, min_k));\n        \n        // Also try randomizing Top-Down / Bottom-Up slightly? \n        // Pure random (4) covers the space well.\n    }\n\n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\nconst int D = 9;\nint N;\nint grid_data[D][D]; // 0: empty, 1: obstacle, 2: container\n// Entrance is at (0, 4)\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\n// BFS optimization variables\nint visited_token[D][D];\nint dist_map[D][D];\nint bfs_token = 0;\nint q_r[D * D], q_c[D * D];\n\n// Directions\nint dr[] = {0, 0, 1, -1};\nint dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// Optimized BFS to get distances and count reachable empty cells\n// Returns count of reachable empty cells (excluding entrance if empty)\nint fast_bfs() {\n    bfs_token++;\n    int head = 0, tail = 0;\n    \n    // Start at entrance\n    q_r[tail] = 0; q_c[tail] = 4; tail++;\n    visited_token[0][4] = bfs_token;\n    dist_map[0][4] = 0;\n    \n    int count = 0;\n    while(head < tail){\n        int r = q_r[head];\n        int c = q_c[head];\n        head++;\n        \n        int d_next = dist_map[r][c] + 1;\n        \n        for(int i=0; i<4; ++i){\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if(is_valid(nr, nc) && grid_data[nr][nc] == 0 && visited_token[nr][nc] != bfs_token){\n                visited_token[nr][nc] = bfs_token;\n                dist_map[nr][nc] = d_next;\n                q_r[tail] = nr; q_c[tail] = nc; tail++;\n                \n                // Count valid storage cells (entrance is not storage)\n                if(nr != 0 || nc != 4) {\n                    count++;\n                }\n            }\n        }\n    }\n    return count;\n}\n\n// Helper to get distance of a cell after running fast_bfs\n// Returns -1 if not reachable or blocked\nint get_dist(int r, int c) {\n    if (visited_token[r][c] == bfs_token) return dist_map[r][c];\n    return -1;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int d_in;\n    if (!(cin >> d_in)) return 0;\n    cin >> N;\n    \n    // Init grid\n    for(int r=0; r<D; ++r)\n        for(int c=0; c<D; ++c)\n            grid_data[r][c] = 0;\n            \n    for(int i=0; i<N; ++i){\n        int r, c;\n        cin >> r >> c;\n        grid_data[r][c] = 1;\n    }\n    \n    // Reset BFS token\n    for(int r=0; r<D; ++r)\n        for(int c=0; c<D; ++c)\n            visited_token[r][c] = 0;\n\n    int K = D*D - 1 - N;\n    vector<bool> id_seen(D*D, false);\n    vector<Point> final_pos(D*D);\n    \n    for(int step=0; step<K; ++step){\n        int t;\n        cin >> t;\n        \n        // Calculate percentile of the current ID t among remaining IDs\n        // Count how many available IDs are smaller than t\n        int rem_count = 0;\n        int rank_t = 0;\n        // The ID t is \"available\" until we place it, but id_seen tracks past placements.\n        // We iterate all possible IDs\n        for(int i=0; i<K; ++i){\n            if(!id_seen[i] || i == t) { // if not seen yet (including t)\n                rem_count++;\n                if(i < t) rank_t++;\n            }\n        }\n        \n        double P = 0.5;\n        if(rem_count > 1) P = (double)rank_t / (rem_count - 1);\n        \n        id_seen[t] = true; // Mark as seen for next steps\n        \n        // Run BFS to analyze current empty space\n        int reachable_cnt = fast_bfs();\n        \n        vector<int> all_dists;\n        vector<Point> empty_cells;\n        all_dists.reserve(rem_count);\n        empty_cells.reserve(rem_count);\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_data[r][c] == 0 && (r!=0 || c!=4)){\n                    int d = get_dist(r, c);\n                    if(d != -1){\n                        all_dists.push_back(d);\n                        empty_cells.push_back({r, c});\n                    }\n                }\n            }\n        }\n        \n        sort(all_dists.begin(), all_dists.end());\n        double target_dist = 0;\n        if(!all_dists.empty()){\n            int idx = (int)round(P * (all_dists.size() - 1));\n            target_dist = all_dists[idx];\n        }\n        \n        // Identify Candidates\n        // A cell is a candidate if it's empty, reachable, and placing a container there\n        // does not disconnect other empty cells from the entrance.\n        // Connectivity check: reachable count decreases by exactly 1.\n        vector<Point> candidates;\n        candidates.reserve(empty_cells.size());\n        \n        for(auto p : empty_cells){\n            grid_data[p.r][p.c] = 2; // Temporarily place\n            int cnt = fast_bfs();\n            grid_data[p.r][p.c] = 0; // Restore\n            \n            if(cnt == reachable_cnt - 1){\n                candidates.push_back(p);\n            }\n        }\n        \n        // Score Candidates\n        // Heuristic: Minimize squared distance error + maximize future candidates count\n        double best_score = -1e18;\n        Point best_p = candidates[0];\n        \n        for(auto p : candidates){\n            // Need dist from the ORIGINAL BFS state (before temp placement)\n            // We can't use get_dist() because fast_bfs was run inside loop.\n            // Need to re-run or cache?\n            // Actually we can just re-run or use cached values if we stored them.\n            // Since fast_bfs overwrites dist_map, we must re-calculate or look up carefully.\n            // Better: Store dists in empty_cells loop.\n            // Let's find dist of p from all_dists logic? No, lookup by coord.\n            // We need to run BFS on the *original* grid again to get dist(p)?\n            // Or just store dist in a separate map before candidate loop.\n            \n            // Optimization: We ran BFS at start of step. We can copy dist_map or store dists.\n            // But fast_bfs overwrites global dist_map.\n            // Let's just run BFS for connectivity check anyway.\n            // We can grab distance from a saved structure.\n            \n            // To avoid complexity, let's just re-run BFS on clean grid to get dist\n            // But that's slow inside loop.\n            // Correct approach: Save dists of all empty cells in a vector/map before candidate loop.\n            // But since we iterate `empty_cells`, we can store dist in Point or parallel vector.\n        }\n        \n        // Let's redo data gathering properly\n        // Restore distances of current state\n        fast_bfs(); \n        vector<vector<int>> current_dists(D, vector<int>(D));\n        for(int r=0; r<D; ++r) for(int c=0; c<D; ++c) current_dists[r][c] = get_dist(r, c);\n        \n        for(auto p : candidates){\n            double dist = current_dists[p.r][p.c];\n            double match_err = (dist - target_dist) * (dist - target_dist);\n            \n            // Calculate Future Freedom (c_prime)\n            grid_data[p.r][p.c] = 2;\n            int cnt2 = fast_bfs();\n            \n            // Count how many candidates exist in this new state\n            // This requires another nested check.\n            // To be fast, we only check cells that are reachable in new state.\n            int c_prime = 0;\n            \n            // Collect empty cells in new state\n            vector<Point> next_empty; \n            next_empty.reserve(cnt2);\n            for(int r=0; r<D; ++r){\n                for(int c=0; c<D; ++c){\n                    if(grid_data[r][c] == 0 && (r!=0 || c!=4) && get_dist(r, c) != -1){\n                        next_empty.push_back({r, c});\n                    }\n                }\n            }\n            \n            // Check candidacy for each\n            for(auto np : next_empty){\n                grid_data[np.r][np.c] = 2;\n                int cnt3 = fast_bfs();\n                if(cnt3 == cnt2 - 1) c_prime++;\n                grid_data[np.r][np.c] = 0;\n            }\n            \n            grid_data[p.r][p.c] = 0; // Restore\n            \n            // Weighted score\n            // Weight A=100 for distance match, B=1 for freedom.\n            double score = -100.0 * match_err + (double)c_prime;\n            \n            if(score > best_score){\n                best_score = score;\n                best_p = p;\n            }\n        }\n        \n        // Output and Commit\n        cout << best_p.r << \" \" << best_p.c << endl;\n        grid_data[best_p.r][best_p.c] = 2;\n        final_pos[t] = best_p;\n    }\n    \n    // Retrieval Phase\n    // Map coordinates to IDs\n    vector<vector<int>> grid_ids(D, vector<int>(D, -1));\n    for(int i=0; i<K; ++i){\n        grid_ids[final_pos[i].r][final_pos[i].c] = i;\n    }\n    \n    // Greedily retrieve smallest available ID\n    for(int step=0; step<K; ++step){\n        fast_bfs(); // Updates dist_map to show what is reachable from entrance\n        \n        int best_id = 1000000;\n        Point best_loc = {-1, -1};\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_data[r][c] == 2){\n                    // Check if reachable: adjacent to visited empty cell (or entrance)\n                    bool reachable = false;\n                    for(int i=0; i<4; ++i){\n                        int nr = r + dr[i];\n                        int nc = c + dc[i];\n                        if(is_valid(nr, nc)){\n                            // Entrance is (0,4), always visited/available source\n                            if((nr == 0 && nc == 4) || get_dist(nr, nc) != -1){\n                                reachable = true;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if(reachable){\n                        int id = grid_ids[r][c];\n                        if(id < best_id){\n                            best_id = id;\n                            best_loc = {r, c};\n                        }\n                    }\n                }\n            }\n        }\n        \n        cout << best_loc.r << \" \" << best_loc.c << endl;\n        grid_data[best_loc.r][best_loc.c] = 0; // Remove container\n    }\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n#include <map>\n\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\nconst int TIME_LIMIT_MS = 1950;\n\nint grid[N][N];\nint best_grid[N][N];\nint current_score = 0;\nint best_score = 0;\n\n// Adjacency\n// adj_count[u][v] stores the number of boundary segments between color u and v.\nint adj_count[M + 1][M + 1];\nbool is_required[M + 1][M + 1];\n\n// BFS State\nint visited[N][N];\nint visited_token = 0;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n} rng;\n\n// Global Connectivity Check (BFS)\n// Returns true if removing (rem_r, rem_c) of 'color' leaves the 'color' component connected.\nbool check_global_connectivity(int rem_r, int rem_c, int color) {\n    visited_token++;\n    int neighbors_r[4], neighbors_c[4];\n    int k = 0;\n    bool touches_boundary = false;\n\n    for (int i = 0; i < 4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) {\n                neighbors_r[k] = nr;\n                neighbors_c[k] = nc;\n                k++;\n            }\n        } else if (color == 0) {\n            touches_boundary = true;\n        }\n    }\n    \n    if (k == 0) return true; \n\n    // If color != 0, all neighbors must be in one component.\n    // If color == 0, all neighbors must be able to reach the boundary (or be connected to it via outside).\n    \n    if (color != 0) {\n        int q_r[N * N], q_c[N * N];\n        int head = 0, tail = 0;\n        \n        q_r[tail] = neighbors_r[0];\n        q_c[tail] = neighbors_c[0];\n        tail++;\n        visited[neighbors_r[0]][neighbors_c[0]] = visited_token;\n        \n        int found_neighbors = 1;\n\n        while(head < tail) {\n            int r = q_r[head++];\n            int c = q_c[head-1]; // Bug fix: was referencing head\n            \n            for(int i=0; i<4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                \n                if (!is_valid(nr, nc)) continue;\n                if (nr == rem_r && nc == rem_c) continue;\n                \n                if (grid[nr][nc] == color && visited[nr][nc] != visited_token) {\n                    visited[nr][nc] = visited_token;\n                    q_r[tail] = nr;\n                    q_c[tail] = nc;\n                    tail++;\n                    \n                    // Check if we found a neighbor\n                    // Optimization: Manhattan dist to rem_r, rem_c is 1\n                    if (abs(nr - rem_r) + abs(nc - rem_c) == 1) {\n                        found_neighbors++;\n                    }\n                }\n            }\n        }\n        return found_neighbors == k;\n    } else {\n        // For color 0, check if each neighbor component touches boundary\n        // We use visited array to track processed neighbors\n        for(int j=0; j<k; ++j) {\n            if (visited[neighbors_r[j]][neighbors_c[j]] == visited_token) continue;\n            \n            // Start BFS for this component\n            int q_r[N * N], q_c[N * N];\n            int head = 0, tail = 0;\n            q_r[tail] = neighbors_r[j];\n            q_c[tail] = neighbors_c[j];\n            tail++;\n            visited[neighbors_r[j]][neighbors_c[j]] = visited_token;\n            \n            bool reached_boundary = false;\n            if (neighbors_r[j] == 0 || neighbors_r[j] == N-1 || neighbors_c[j] == 0 || neighbors_c[j] == N-1)\n                reached_boundary = true;\n                \n            while(head < tail) {\n                int r = q_r[head++];\n                int c = q_c[head-1];\n                \n                for(int i=0; i<4; ++i) {\n                    int nr = r + dr[i];\n                    int nc = c + dc[i];\n                    \n                    if (!is_valid(nr, nc)) {\n                        reached_boundary = true;\n                        continue;\n                    }\n                    if (nr == rem_r && nc == rem_c) continue;\n                    \n                    if (grid[nr][nc] == 0 && visited[nr][nc] != visited_token) {\n                        visited[nr][nc] = visited_token;\n                        q_r[tail] = nr;\n                        q_c[tail] = nc;\n                        tail++;\n                        if (!reached_boundary) {\n                            if (nr == 0 || nr == N-1 || nc == 0 || nc == N-1) reached_boundary = true;\n                        }\n                    }\n                }\n            }\n            \n            if (!reached_boundary && !touches_boundary) return false;\n        }\n        return true;\n    }\n}\n\n// Local Connectivity Check (3x3 window)\n// Returns true if neighbors are connected within the 3x3 area excluding center\nbool check_local(int r, int c, int color) {\n    int n_idx[4], k = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) n_idx[k++] = i;\n        } else if (color == 0) {\n            n_idx[k++] = i;\n        }\n    }\n    if (k <= 1) return true;\n    \n    // Union-Find\n    int parent[4];\n    for(int i=0; i<k; ++i) parent[i] = i;\n    auto find = [&](int i) { while(i != parent[i]) i = parent[i]; return i; };\n    \n    int dir_map[4]; \n    // -1 init\n    dir_map[0]=dir_map[1]=dir_map[2]=dir_map[3]=-1;\n    for(int i=0; i<k; ++i) dir_map[n_idx[i]] = i;\n    \n    // Diagonals check\n    int pairs[4][2] = {{0,2}, {0,3}, {1,2}, {1,3}}; // (Up,Left), (Up,Right), (Down,Left), (Down,Right)\n    int d_off[4][2] = {{-1,-1}, {-1,1}, {1,-1}, {1,1}};\n    \n    for(int i=0; i<4; ++i) {\n        int idx1 = dir_map[pairs[i][0]];\n        int idx2 = dir_map[pairs[i][1]];\n        if(idx1 != -1 && idx2 != -1) {\n            int nr = r + d_off[i][0];\n            int nc = c + d_off[i][1];\n            bool conn = false;\n            if(is_valid(nr, nc)) {\n                if(grid[nr][nc] == color) conn = true;\n            } else if(color == 0) conn = true;\n            \n            if(conn) {\n                int r1 = find(idx1), r2 = find(idx2);\n                if(r1 != r2) parent[r1] = r2;\n            }\n        }\n    }\n    int root = find(0);\n    for(int i=1; i<k; ++i) if(find(i) != root) return false;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int n_in, m_in;\n    if (!(cin >> n_in >> m_in)) return 0;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> grid[i][j];\n            best_grid[i][j] = grid[i][j];\n            // Initial grid has no 0s inside as per constraints, so score 0\n        }\n    }\n    // Calculate initial adjacencies\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = grid[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int nr = i + dr[k];\n                int nc = j + dc[k];\n                int v = 0; \n                if (is_valid(nr, nc)) v = grid[nr][nc];\n                \n                if (u != v) {\n                    adj_count[u][v]++; // Increments for both u->v and v->u during full scan\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i <= M; ++i) {\n        for (int j = 0; j <= M; ++j) {\n            if (adj_count[i][j] > 0) is_required[i][j] = true;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    double start_temp = 2.5;\n    double end_temp = 0.1;\n\n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0xFFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        int r = rng.next_int(N);\n        int c = rng.next_int(N);\n        int current_color = grid[r][c];\n        \n        // Pick a target color from neighbors (eroding or shifting)\n        int k = rng.next_int(4);\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n        int target_color = 0;\n        if (is_valid(nr, nc)) target_color = grid[nr][nc];\n        \n        if (current_color == target_color) continue;\n\n        int score_diff = 0;\n        if (current_color == 0) score_diff--;\n        if (target_color == 0) score_diff++;\n\n        // SA Logic\n        if (score_diff < 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            double temp = start_temp + (end_temp - start_temp) * (elapsed / TIME_LIMIT_MS);\n            if (rng.next_double() > exp(score_diff / temp)) continue;\n        }\n\n        // 1. Adjacency Constraints\n        // Calculate aggregate changes to adjacency counts\n        map<pair<int,int>, int> changes; \n        \n        for(int i=0; i<4; ++i) {\n            int nnr = r + dr[i];\n            int nnc = c + dc[i];\n            int n_col = 0;\n            if (is_valid(nnr, nnc)) n_col = grid[nnr][nnc];\n            \n            // Removing current_color\n            if (n_col != current_color) {\n                int u = current_color, v = n_col;\n                if (u > v) swap(u, v);\n                changes[{u, v}]--;\n            }\n            // Adding target_color\n            if (n_col != target_color) {\n                int u = target_color, v = n_col;\n                if (u > v) swap(u, v);\n                changes[{u, v}]++;\n            }\n        }\n        \n        bool adj_ok = true;\n        for (auto const& [key, val] : changes) {\n            if (val == 0) continue;\n            int u = key.first;\n            int v = key.second;\n            int new_count = adj_count[u][v] + val;\n            \n            if (is_required[u][v]) {\n                // Must maintain at least one edge\n                if (new_count <= 0) { adj_ok = false; break; }\n            } else {\n                // Must not create new edge\n                if (new_count > 0) { adj_ok = false; break; }\n            }\n        }\n        if (!adj_ok) continue;\n\n        // 2. Connectivity of Old Color\n        if (!check_local(r, c, current_color)) {\n            if (!check_global_connectivity(r, c, current_color)) continue;\n        }\n        \n        // 3. Connectivity of New Color\n        // Safe by construction (extending from neighbor), unless specific split cases for color 0.\n        // But adding a 0 adjacent to existing 0 is always safe for 0's connectivity.\n        // Adding non-0 adjacent to existing non-0 is safe.\n        \n        // Apply Move\n        for (auto const& [key, val] : changes) {\n            int u = key.first;\n            int v = key.second;\n            adj_count[u][v] += val;\n            adj_count[v][u] += val;\n        }\n        \n        grid[r][c] = target_color;\n        current_score += score_diff;\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) copy(begin(grid[i]), end(grid[i]), begin(best_grid[i]));\n        }\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    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\nvector<vector<int>> memo; // Memoization for item comparisons\n\n// Perform a query: Output L size, R size, then elements of L and R\nvoid ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    query_count++;\n}\n\n// Read the judge's response\nint get_response() {\n    string res;\n    cin >> res;\n    if (res == \"<\") return 1;\n    if (res == \">\") return -1;\n    if (res == \"=\") return 2;\n    return 0; \n}\n\n// Pad remaining queries with dummy operations to meet the exact Q requirement\nvoid pad_queries() {\n    while (query_count < Q) {\n        // Compare item 0 and item 1. They are always valid indices (N >= 30).\n        // This consumes a query without changing state.\n        ask({0}, {1});\n        get_response(); \n    }\n}\n\n// Compare items a and b using the balance scale.\n// Returns 1 if a < b, -1 if a > b, 0 if a == b.\n// Uses memoization to avoid redundant queries.\nint compare_items(int a, int b) {\n    if (a == b) return 0;\n    if (memo[a][b] != 0) return (memo[a][b] == 2 ? 0 : memo[a][b]);\n\n    ask({a}, {b});\n    int res = get_response();\n    \n    if (res == 1) {\n        memo[a][b] = 1;\n        memo[b][a] = -1;\n        return 1;\n    } else if (res == -1) {\n        memo[a][b] = -1;\n        memo[b][a] = 1;\n        return -1;\n    } else {\n        memo[a][b] = 2;\n        memo[b][a] = 2;\n        return 0;\n    }\n}\n\n// Compute expected values of order statistics for the Exponential Distribution\nvector<double> compute_expected_weights(int n) {\n    vector<double> w(n);\n    double current = 0;\n    for (int i = 0; i < n; ++i) {\n        current += 1.0 / (n - i);\n        w[i] = current;\n    }\n    return w;\n}\n\n// Isotonic Regression (Pool Adjacent Violators Algorithm)\n// Fits data to be monotonically non-decreasing minimizing MSE.\nvector<double> isotonic_regression(const vector<double>& y) {\n    vector<pair<double, double>> stack; \n    for (double val : y) {\n        double current_val = val;\n        double current_w = 1.0;\n        while (!stack.empty() && stack.back().first >= current_val) {\n            double prev_val = stack.back().first;\n            double prev_w = stack.back().second;\n            stack.pop_back();\n            current_val = (prev_val * prev_w + current_val * current_w) / (prev_w + current_w);\n            current_w += prev_w;\n        }\n        stack.push_back({current_val, current_w});\n    }\n    vector<double> res;\n    for (auto p : stack) {\n        for (int i = 0; i < (int)p.second; ++i) res.push_back(p.first);\n    }\n    return res;\n}\n\nint main() {\n    // IO setup\n    ios_base::sync_with_stdio(false);\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    memo.assign(N, vector<int>(N, 0));\n    srand(123); \n\n    // Determine budget for initial sorting.\n    // We reserve queries for the refinement phase (sorting sets + adjusting).\n    // Sorting D sets takes approx D * log2(D) queries. We want a few rounds.\n    // Maximize sort budget but ensure we can do at least some refinement.\n    int refinement_budget = max(Q / 4, min(Q / 2, D * D * 2));\n    int sort_budget = Q - refinement_budget;\n    if (sort_budget < 0) sort_budget = 0;\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // 1. Sort items (partially if budget is tight)\n    // We use stable_sort. If we hit the query limit, we stop comparing, \n    // effectively leaving the remaining items in their original relative order.\n    try {\n        stable_sort(p.begin(), p.end(), [&](int a, int b) {\n            if (query_count >= sort_budget) return false; \n            int res = compare_items(a, b);\n            return res == 1; // a < b\n        });\n    } catch(...) {}\n\n    // 2. Assign Expected Weights based on rank\n    vector<double> exp_w_sorted = compute_expected_weights(N);\n    vector<double> item_w(N);\n    // The item at p[i] is the i-th smallest found.\n    for (int i = 0; i < N; ++i) {\n        item_w[p[i]] = exp_w_sorted[i];\n    }\n\n    // 3. Greedy Partitioning (Largest Items First)\n    // This heuristic generally works well for minimizing variance.\n    vector<int> p_desc = p;\n    reverse(p_desc.begin(), p_desc.end());\n\n    vector<vector<int>> sets(D);\n    vector<double> set_sums(D, 0.0);\n\n    for (int idx : p_desc) {\n        int best_s = -1;\n        double min_sum = 1e18;\n        for (int s = 0; s < D; ++s) {\n            if (set_sums[s] < min_sum) {\n                min_sum = set_sums[s];\n                best_s = s;\n            }\n        }\n        sets[best_s].push_back(idx);\n        set_sums[best_s] += item_w[idx];\n    }\n\n    // 4. Local Search (In Silico)\n    // Optimize the partition using the estimated weights before spending more queries.\n    int ls_iter = 0;\n    while (ls_iter < 20000) {\n        ls_iter++;\n        int s1 = rand() % D;\n        int s2 = rand() % D;\n        if (s1 == s2) continue;\n        if (sets[s1].empty()) continue;\n\n        int type = (sets[s2].empty() ? 0 : rand() % 2);\n        int idx1 = rand() % sets[s1].size();\n        int u = sets[s1][idx1];\n\n        if (type == 0) { // Move u from s1 to s2\n            double new_s1 = set_sums[s1] - item_w[u];\n            double new_s2 = set_sums[s2] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n            \n            if (new_sq < old_sq) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        } else { // Swap u (from s1) with v (from s2)\n            int idx2 = rand() % sets[s2].size();\n            int v = sets[s2][idx2];\n            \n            double new_s1 = set_sums[s1] - item_w[u] + item_w[v];\n            double new_s2 = set_sums[s2] - item_w[v] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n\n            if (new_sq < old_sq) {\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        }\n    }\n\n    // 5. Refinement Phase with Physical Queries\n    // We sort the sets by weight using the scale, then update our belief (estimates)\n    // using Isotonic Regression, and finally try to balance the extremes.\n    while (true) {\n        // Check if we have enough queries to perform a set sort.\n        int needed = D * log2(D) + 2;\n        if (query_count + needed > Q) break;\n\n        // 5.1 Sort sets physically\n        vector<int> set_indices(D);\n        iota(set_indices.begin(), set_indices.end(), 0);\n        \n        bool possible = true;\n        stable_sort(set_indices.begin(), set_indices.end(), [&](int a, int b){\n            if (query_count >= Q) { possible = false; return false; }\n            ask(sets[a], sets[b]);\n            int res = get_response();\n            return res == 1; // a < b\n        });\n        if (!possible) break;\n\n        // 5.2 Correct estimates\n        // We extract the current estimates in the physical sorted order\n        vector<double> sorted_estimates;\n        for (int idx : set_indices) sorted_estimates.push_back(set_sums[idx]);\n        \n        // Apply PAVA to enforce monotonicity\n        vector<double> pav_res = isotonic_regression(sorted_estimates);\n        \n        // Slightly perturb to enforce strict inequality where PAVA flattens,\n        // to encourage movement.\n        for (int i = 1; i < D; ++i) {\n            if (pav_res[i] <= pav_res[i-1] + 1e-9) {\n                pav_res[i] = pav_res[i-1] + 1e-5;\n            }\n        }\n        // Update set_sums\n        for (int i = 0; i < D; ++i) set_sums[set_indices[i]] = pav_res[i];\n\n        // 5.3 Balance Heaviest and Lightest\n        int light_idx = set_indices[0];\n        int heavy_idx = set_indices.back();\n\n        double diff = set_sums[heavy_idx] - set_sums[light_idx];\n        if (diff < 1e-5) break; // Already balanced within estimate precision\n\n        double target = diff / 2.0; // Amount to transfer from Heavy to Light\n        int best_type = -1;\n        int best_u_idx = -1, best_v_idx = -1;\n        double min_err = 1e18;\n\n        // Try Move\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            int u = sets[heavy_idx][i];\n            double err = abs(item_w[u] - target);\n            if (err < min_err) {\n                min_err = err;\n                best_type = 0;\n                best_u_idx = i;\n            }\n        }\n        // Try Swap\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            for (int j = 0; j < (int)sets[light_idx].size(); ++j) {\n                int u = sets[heavy_idx][i];\n                int v = sets[light_idx][j];\n                double delta = item_w[u] - item_w[v];\n                if (delta <= 0) continue; // Must move mass from heavy to light\n                double err = abs(delta - target);\n                if (err < min_err) {\n                    min_err = err;\n                    best_type = 1;\n                    best_u_idx = i;\n                    best_v_idx = j;\n                }\n            }\n        }\n\n        // Apply best operation\n        if (best_type == 0) {\n            int u = sets[heavy_idx][best_u_idx];\n            sets[heavy_idx].erase(sets[heavy_idx].begin() + best_u_idx);\n            sets[light_idx].push_back(u);\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[light_idx] += item_w[u];\n        } else if (best_type == 1) {\n            int u = sets[heavy_idx][best_u_idx];\n            int v = sets[light_idx][best_v_idx];\n            swap(sets[heavy_idx][best_u_idx], sets[light_idx][best_v_idx]);\n            set_sums[heavy_idx] -= item_w[u] - item_w[v];\n            set_sums[light_idx] += item_w[u] - item_w[v];\n        } else {\n            break; // Cannot find a move/swap that matches target\n        }\n    }\n\n    // Ensure exactly Q queries are performed\n    pad_queries();\n\n    // Output final assignment\n    vector<int> ans(N);\n    for (int i = 0; i < D; ++i) {\n        for (int x : sets[i]) ans[x] = i;\n    }\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"/**\n * Heuristic solution for \"Stack of Boxes\" problem.\n * \n * Strategy:\n * The problem asks us to retrieve boxes 1 to N in order. This implies a strong constraint on\n * the order of access.\n * We adopt a greedy simulation strategy. We iterate through the targets 1 to N.\n * If the current target is buried, we must move the boxes covering it to other stacks.\n * \n * Key decision point: When moving covering boxes, where should we put them?\n * And how many should we move at once?\n * \n * Algorithm Steps:\n * 1. Identify the current target 'v'.\n * 2. If 'v' is not at the top of its stack 'src', we need to clear boxes above it.\n * 3. Identify the longest \"sorted suffix\" at the top of 'src'. \n *    A sorted suffix is a sequence of boxes at the top that are in decreasing order (e.g., 10, 8, 5).\n *    Moving unsorted chunks (e.g., 5, 10) is generally inefficient because it maintains disorder.\n *    By only moving sorted chunks (or parts of them), we naturally decompose unsorted stacks into sorted ones.\n * 4. Evaluate all valid moves:\n *    - A \"move\" is defined by a split point in the sorted suffix (defining a chunk) \n *      and a destination stack.\n *    - We calculate a Cost for each move:\n *      Cost = Energy + Penalties\n * \n * Cost Function Components:\n * - Energy: (Chunk Size + 1). Direct cost minimization.\n * - Bad Link Penalty: Placing a box 'B' on top of 'T' where B > T.\n *   This is bad because 'T' is smaller and will be needed before 'B'. 'B' blocks 'T'.\n *   The penalty is proportional to \"Urgency\": how close 'T' is to the current global target.\n *   If 'T' is needed very soon, the penalty is massive.\n * - Gap Penalty: Placing 'B' on 'T' where B < T (Good link).\n *   We prefer T - B to be small (tight packing) to save \"number space\" for other boxes.\n * - Empty Stack Penalty: Using an empty stack is penalized, especially for small values.\n *   We want to reserve empty stacks for base of new piles or emergency maneuvering.\n * \n * The parameters are tuned to balance immediate energy costs against the future cost of fixing bad states.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Tuned heuristic constants\nconst double WEIGHT_ENERGY = 1.0;\nconst double PENALTY_BAD_LINK_BASE = 100.0;       // Base penalty for inverting order\nconst double PENALTY_BAD_LINK_URGENCY_FACTOR = 2000.0; // High penalty if blocked box is needed soon\nconst double PENALTY_GAP_FACTOR = 0.5;            // Penalty for gaps in sorted stacks\nconst double PENALTY_EMPTY_BASE = 50.0;           // High cost to consume an empty stack\nconst double PENALTY_EMPTY_VAL_FACTOR = 0.2;      // Prefer high values on empty stacks\n\nstruct Move {\n    int v;\n    int i;\n};\n\nint N, M;\nvector<vector<int>> stacks;\nvector<Move> result;\nint op_count = 0;\nconst int MAX_OPS = 5000;\n\n// Find the stack index and position of a box v\npair<int, int> find_box(int v) {\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<(int)stacks[i].size(); ++j) {\n            if(stacks[i][j] == v) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Execute the chosen move\nvoid execute_move(int src, int k, int dst) {\n    // The box at stacks[src][k] is the bottom of the chunk being moved.\n    int v = stacks[src][k];\n    \n    vector<int> chunk;\n    for(int i = k; i < (int)stacks[src].size(); ++i) {\n        chunk.push_back(stacks[src][i]);\n    }\n    \n    stacks[src].resize(k);\n    \n    for(int x : chunk) {\n        stacks[dst].push_back(x);\n    }\n    \n    result.push_back({v, dst + 1});\n    op_count++;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<N/M; ++j) {\n            int val;\n            cin >> val;\n            stacks[i].push_back(val);\n        }\n    }\n\n    // Process boxes 1 to N in order\n    for (int target = 1; target <= N; ++target) {\n        if (op_count >= MAX_OPS) break;\n\n        while (true) {\n            pair<int, int> loc = find_box(target);\n            if (loc.first == -1) break; // Should not happen\n            \n            int src = loc.first;\n            int idx = loc.second;\n            \n            // If target is at the top, we can carry it out (Operation 2)\n            if (idx == (int)stacks[src].size() - 1) {\n                result.push_back({target, 0});\n                stacks[src].pop_back();\n                op_count++;\n                break; \n            }\n            \n            // Target is buried. We need to move boxes above it.\n            // We identify the longest sequence at the top that is already sorted (decreasing upwards).\n            // We only consider moving sub-chunks of this sorted sequence.\n            int top_idx = (int)stacks[src].size() - 1;\n            int start_sorted = top_idx;\n            \n            // Extend sorted range downwards as long as order is valid (bottom > top)\n            while(start_sorted > idx + 1) {\n                if (stacks[src][start_sorted - 1] > stacks[src][start_sorted]) {\n                    start_sorted--;\n                } else {\n                    break;\n                }\n            }\n            \n            double best_cost = 1e18;\n            int best_k = -1;\n            int best_dst = -1;\n            \n            // Evaluate all possible chunks [k...top] from the sorted suffix\n            for (int k = start_sorted; k <= top_idx; ++k) {\n                int chunk_bottom_val = stacks[src][k];\n                int chunk_sz = top_idx - k + 1;\n                double energy = (double)(chunk_sz + 1);\n                \n                // Try all possible destination stacks\n                for (int dst = 0; dst < M; ++dst) {\n                    if (dst == src) continue;\n                    \n                    double cost = energy * WEIGHT_ENERGY;\n                    bool dst_empty = stacks[dst].empty();\n                    int dst_top_val = dst_empty ? -1 : stacks[dst].back();\n                    \n                    if (dst_empty) {\n                        // Penalty for using an empty stack\n                        // Reduces if we place a large value (good base)\n                        cost += PENALTY_EMPTY_BASE + PENALTY_EMPTY_VAL_FACTOR * (double)(N - chunk_bottom_val);\n                    } else {\n                        if (chunk_bottom_val < dst_top_val) {\n                            // Good Link: Placing smaller on larger (e.g., 10 on 20)\n                            // We penalize large gaps to keep stacks compact\n                            int gap = dst_top_val - chunk_bottom_val;\n                            cost += (double)gap * PENALTY_GAP_FACTOR;\n                        } else {\n                            // Bad Link: Placing larger on smaller (e.g., 20 on 10)\n                            // The smaller box (dst_top_val) is now blocked.\n                            // Penalize based on how soon we need dst_top_val.\n                            int dist = dst_top_val - target;\n                            if (dist < 1) dist = 1; // Safety check\n                            \n                            double urgency = 1.0 / (double)dist;\n                            double penalty = PENALTY_BAD_LINK_BASE + PENALTY_BAD_LINK_URGENCY_FACTOR * urgency;\n                            \n                            // Additional penalty for heavy chunks (harder to undo)\n                            penalty *= (1.0 + 0.2 * chunk_sz);\n                            \n                            cost += penalty;\n                        }\n                    }\n                    \n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_k = k;\n                        best_dst = dst;\n                    }\n                }\n            }\n            \n            // Fallback logic (rarely needed)\n            if (best_k == -1) {\n                best_k = top_idx;\n                best_dst = (src + 1) % M;\n                if (best_dst == src) best_dst = (src + 2) % M;\n            }\n            \n            execute_move(src, best_k, best_dst);\n            if (op_count >= MAX_OPS) break;\n        }\n    }\n    \n    // Output the sequence of operations\n    for(const auto &m : result) {\n        cout << m.v << \" \" << m.i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Timer class to manage execution time\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    Timer() { reset(); }\n    void reset() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto end = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end - start).count() / 1000.0;\n    }\n};\n\nint N;\nvector<string> h_walls, v_walls;\nvector<int> D_vals; // Flattened dirtiness values\nvector<int> dist_mat_flat; // Flattened All-Pairs Shortest Paths matrix\n\n// Directions: Up, Down, Left, Right\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dc_char[] = {'U', 'D', 'L', 'R'};\nconst int INF = 1e9;\n\n// Check if a move is blocked by a wall\nbool can_move(int r, int c, int dir) {\n    if (dir == 0) return r > 0 && h_walls[r-1][c] == '0';\n    if (dir == 1) return r < N-1 && h_walls[r][c] == '0';\n    if (dir == 2) return c > 0 && v_walls[r][c-1] == '0';\n    if (dir == 3) return c < N-1 && v_walls[r][c] == '0';\n    return false;\n}\n\n// Compute APSP using BFS since edge weights are 1\nvoid compute_apsp() {\n    int num_nodes = N * N;\n    dist_mat_flat.assign(num_nodes * num_nodes, INF);\n    \n    // Static vectors to reuse memory\n    static vector<int> q_vec;\n    static vector<int> d_local; \n    if (q_vec.capacity() < num_nodes) { \n        q_vec.resize(num_nodes); \n        d_local.resize(num_nodes); \n    }\n    \n    for (int u = 0; u < num_nodes; ++u) {\n        // BFS from u\n        fill(d_local.begin(), d_local.end(), INF);\n        int head = 0, tail = 0;\n        q_vec[tail++] = u;\n        d_local[u] = 0;\n        dist_mat_flat[u * num_nodes + u] = 0;\n        \n        while(head < tail){\n            int curr = q_vec[head++];\n            int d_c = d_local[curr];\n            dist_mat_flat[u * num_nodes + curr] = d_c;\n            \n            int cr = curr / N;\n            int cc = curr % N;\n            \n            for(int k=0; k<4; ++k){\n                if(can_move(cr, cc, k)){\n                    int nr = cr + dr[k];\n                    int nc = cc + dc[k];\n                    int v = nr * N + nc;\n                    if(d_local[v] == INF){\n                        d_local[v] = d_c + 1;\n                        q_vec[tail++] = v;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate the average dirtiness score for the given cycle\nlong long calculate_score_cycle(const string& path) {\n    if (path.empty()) return 2e18;\n    long long L = path.length();\n    \n    int num_nodes = N * N;\n    vector<vector<int>> visits(num_nodes);\n    \n    // Simulation starts at (0,0). We assume (0,0) is cleaned at t=0.\n    int r = 0, c = 0;\n    visits[0].push_back(0);\n    \n    for(int t=1; t<=L; ++t){\n        char m = path[t-1];\n        if(m=='U') r--;\n        else if(m=='D') r++;\n        else if(m=='L') c--;\n        else if(m=='R') c++;\n        visits[r*N + c].push_back(t);\n    }\n    \n    double total_sum = 0;\n    for(int u=0; u<num_nodes; ++u){\n        // If a node is not visited, the cost is infinite (conceptually)\n        // But our construction guarantees visitation.\n        if(visits[u].empty()) return 2e18; \n        \n        long long s_sq = 0;\n        // Sum of (interval * (interval - 1))\n        for(size_t i=0; i<visits[u].size()-1; ++i){\n            long long diff = visits[u][i+1] - visits[u][i];\n            s_sq += diff * (diff - 1);\n        }\n        // Wrap-around interval: distance from last visit back to first visit (+L)\n        long long diff = (visits[u][0] + L) - visits[u].back();\n        s_sq += diff * (diff - 1);\n        \n        total_sum += (double)D_vals[u] * s_sq;\n    }\n    \n    // The formula for average dirtiness simplifies to: sum(d * sum(intervals^2)) / 2L\n    return (long long)round(total_sum / (2.0 * L));\n}\n\nint main() {\n    // Initialize IO and timer\n    Timer timer;\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input reading\n    if(!(cin >> N)) return 0;\n    h_walls.resize(N-1);\n    for(int i=0; i<N-1; ++i) cin >> h_walls[i];\n    v_walls.resize(N);\n    for(int i=0; i<N; ++i) cin >> v_walls[i];\n    \n    int num_nodes = N*N;\n    D_vals.resize(num_nodes);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> D_vals[i*N + j];\n        }\n    }\n\n    // Preprocessing\n    compute_apsp();\n\n    // Parameter exploration strategy\n    // params represent the exponent 'k' in the gravity formula 1 / dist^k\n    // Small k: global attraction (visit far away dirty nodes)\n    // Large k: local attraction (clean nearby dirty nodes first)\n    vector<double> params = {2.5, 1.5, 3.5, 1.0, 4.0, 0.5, 5.0, 2.0};\n    \n    long long best_score = -1;\n    string best_path = \"\";\n    \n    mt19937 rng(123);\n    \n    // Limit path length to save time. 25,000 is sufficient for N<=40.\n    const int MAX_PATH_LEN = 25000; \n    \n    int p_idx = 0;\n    \n    // Loop until time is close to limit\n    while(timer.elapsed() < 1.85) {\n        // Select parameter\n        double k_pow;\n        if (p_idx < params.size()) k_pow = params[p_idx++];\n        else {\n            uniform_real_distribution<double> dist_p(0.5, 5.0);\n            k_pow = dist_p(rng);\n        }\n\n        // Precompute lookup table for power function to avoid calls in loop\n        vector<double> pow_lookup(2 * num_nodes + 5);\n        for(int d=0; d<pow_lookup.size(); ++d) pow_lookup[d] = 1.0 / pow(d + 1, k_pow);\n\n        // Precompute Weight matrix W based on APSP\n        // W[u][v] = weight of node u viewed from v (symmetric)\n        // Stored flat, effectively row-major\n        vector<double> W(num_nodes * num_nodes);\n        for(int i=0; i<num_nodes * num_nodes; ++i) {\n            if(dist_mat_flat[i] == INF) W[i] = 0;\n            else W[i] = pow_lookup[dist_mat_flat[i]];\n        }\n        \n        // Incremental score tracking\n        // static_score[v]: potential dirtiness gain rate from v's perspective\n        // dynamic_score[v]: penalty reduction based on recent visits\n        vector<double> static_score(num_nodes, 0.0);\n        vector<double> dynamic_score(num_nodes, 0.0);\n        vector<int> last_visit(num_nodes, -MAX_PATH_LEN); \n        \n        // Initialize static scores\n        for(int v=0; v<num_nodes; ++v) {\n            double s = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                s += D_vals[u] * w_row[u];\n            }\n            static_score[v] = s;\n        }\n        \n        // Initialize state\n        int curr = 0;\n        last_visit[0] = 0; // (0,0) visited at t=0\n        \n        // Initialize dynamic scores (urgency)\n        for(int v=0; v<num_nodes; ++v) {\n            double d = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                d += (double)D_vals[u] * last_visit[u] * w_row[u];\n            }\n            dynamic_score[v] = d;\n        }\n        \n        string path;\n        path.reserve(MAX_PATH_LEN + 5);\n        \n        // Greedy Construction Step\n        for(int t=1; t<=MAX_PATH_LEN; ++t) {\n            // Frequent time check to prevent TLE\n            if((t & 1023) == 0) {\n                if(timer.elapsed() > 1.95) break;\n            }\n\n            int best_next = -1;\n            \n            // Check return condition: if we can't extend much further without violating return ability\n            int dist_to_home = dist_mat_flat[curr * num_nodes + 0];\n            bool must_return = (t + dist_to_home >= MAX_PATH_LEN);\n            \n            if(must_return) {\n                // Move towards (0,0) via shortest path\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        // Distance strictly decreases in BFS tree towards root\n                        if(dist_mat_flat[next_node * num_nodes + 0] < dist_to_home) {\n                            best_next = next_node;\n                            break; \n                        }\n                    }\n                }\n                if(best_next == -1) break; // Should not happen\n            } else {\n                // Greedy choice: Maximize (t * static - dynamic)\n                double max_s = -1e18;\n                \n                // Inspect valid neighbors\n                // dr/dc arrays are small, loop unrolling is implicit\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        \n                        // Heuristic score\n                        double s = (double)t * static_score[next_node] - dynamic_score[next_node];\n                        \n                        if(s > max_s) {\n                            max_s = s;\n                            best_next = next_node;\n                        }\n                    }\n                }\n            }\n            \n            if(best_next == -1) break;\n            \n            // Record Move\n            if(best_next == curr - N) path += 'U';\n            else if(best_next == curr + N) path += 'D';\n            else if(best_next == curr - 1) path += 'L';\n            else path += 'R';\n            \n            // Update State\n            // Only update dynamic scores based on the change in `last_visit` of `best_next`\n            long long old_last = last_visit[best_next];\n            double update_factor = (double)D_vals[best_next] * (t - old_last);\n            \n            // Optimized Update: Access W memory sequentially\n            const double* w_vec = &W[best_next * num_nodes];\n            for(int v=0; v<num_nodes; ++v) {\n                dynamic_score[v] += update_factor * w_vec[v];\n            }\n            \n            last_visit[best_next] = t;\n            curr = best_next;\n            \n            // Check if we successfully closed the cycle\n            if(curr == 0 && must_return) {\n                break;\n            }\n        }\n        \n        // Evaluate result\n        if(curr == 0 && !path.empty()) {\n            long long sc = calculate_score_cycle(path);\n            if(best_score == -1 || sc < best_score) {\n                best_score = sc;\n                best_path = path;\n            }\n        }\n    }\n\n    cout << best_path << endl;\n\n    return 0;\n}","ahc028":"/**\n * Solution for AtCoder Heuristic Contest 028\n * \n * Improvements:\n * 1. Decoupled string ordering from physical pathfinding.\n * 2. Modeled ordering as Asymmetric TSP with precomputed costs.\n * 3. Cost heuristic: Minimized transition cost over all possible physical key instances.\n * 4. High-speed Simulated Annealing on the TSP (Millions of iterations).\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <iomanip>\n\nusing namespace std;\n\n// -------------------- Constants & Globals --------------------\nint N, M;\nint start_r, start_c;\nvector<string> A;\nvector<string> T;\n// positions of each character 'A'-'Z'\nvector<pair<int, int>> char_positions[26];\n\n// overlaps[i][j] = length of longest suffix of T[i] matching prefix of T[j]\nint overlaps[205][205];\n\n// ATSP Distance Matrix\n// dist_matrix[i][j] = estimated minimal cost to type extension of T[j] after T[i]\n// This minimizes over all possible ending positions of T[i].\nint dist_matrix[205][205];\n\n// start_dist[i] = estimated minimal cost to type T[i] from the initial finger position\nint start_dist[205];\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// -------------------- Helper Functions --------------------\n\ninline int c2i(char c) {\n    return c - 'A';\n}\n\ninline int dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Calculate overlap length between suffix of s1 and prefix of s2\nint calc_overlap(const string& s1, const string& s2) {\n    // Max overlap is 4 since strings are distinct length 5\n    for (int len = 4; len >= 1; --len) {\n        bool match = true;\n        for (int k = 0; k < len; ++k) {\n            if (s1[5 - len + k] != s2[k]) {\n                match = false;\n                break;\n            }\n        }\n        if (match) return len;\n    }\n    return 0;\n}\n\n// Calculate min cost to type string s starting from any of the start_coords\n// start_coords are the possible positions of the finger BEFORE typing s[0]\n// Returns the minimum cost to type the whole string 's'.\nint calc_segment_cost(const vector<pair<int,int>>& start_coords, const string& s) {\n    if (s.empty()) return 0;\n    \n    int L = s.size();\n    // DP state: current costs at each position of the current character\n    // We use static vectors to reduce allocation overhead\n    static vector<int> dp_prev;\n    static vector<int> dp_curr;\n    \n    // Initialize for first char of s\n    int c0 = c2i(s[0]);\n    const auto& pos0 = char_positions[c0];\n    dp_prev.assign(pos0.size(), INT_MAX);\n    \n    // Transition from start_coords to first char instances\n    for (size_t j = 0; j < pos0.size(); ++j) {\n        int r = pos0[j].first;\n        int c = pos0[j].second;\n        for (const auto& start_pos : start_coords) {\n            int d = dist(start_pos.first, start_pos.second, r, c) + 1; // +1 for typing\n            if (d < dp_prev[j]) dp_prev[j] = d;\n        }\n    }\n    \n    // Iterate through the rest of the string\n    for (int i = 1; i < L; ++i) {\n        int curr_char = c2i(s[i]);\n        const auto& curr_pos = char_positions[curr_char];\n        const auto& prev_pos = char_positions[c2i(s[i-1])];\n        \n        dp_curr.assign(curr_pos.size(), INT_MAX);\n        \n        for (size_t j = 0; j < curr_pos.size(); ++j) {\n            int r = curr_pos[j].first;\n            int c = curr_pos[j].second;\n            \n            // Find best previous position\n            for (size_t k = 0; k < prev_pos.size(); ++k) {\n                if (dp_prev[k] == INT_MAX) continue;\n                int d = dist(prev_pos[k].first, prev_pos[k].second, r, c) + 1;\n                if (dp_prev[k] + d < dp_curr[j]) {\n                    dp_curr[j] = dp_prev[k] + d;\n                }\n            }\n        }\n        dp_prev = dp_curr;\n    }\n    \n    int ans = INT_MAX;\n    for (int v : dp_prev) if (v < ans) ans = v;\n    return ans;\n}\n\n// Reconstruct and output the full path coordinates from the optimal permutation\nvoid solve_final(const vector<int>& p) {\n    // 1. Build the full character sequence index vector\n    vector<int> S;\n    S.reserve(1200);\n    \n    // First string full\n    for (char c : T[p[0]]) S.push_back(c2i(c));\n    // Subsequent strings (extensions only)\n    for (size_t i = 1; i < p.size(); ++i) {\n        int u = p[i-1];\n        int v = p[i];\n        int ov = overlaps[u][v];\n        for (size_t k = ov; k < 5; ++k) {\n            S.push_back(c2i(T[v][k]));\n        }\n    }\n    \n    // 2. Standard DP to find the optimal physical path for sequence S\n    int L = S.size();\n    vector<vector<int>> parent(L);\n    vector<vector<int>> dp(L);\n    \n    // Initialization (Start -> First char)\n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp[0].resize(pos0.size());\n    parent[0].resize(pos0.size(), -1);\n    \n    for (size_t j = 0; j < pos0.size(); ++j) {\n        dp[0][j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    // DP Transitions\n    for (int i = 1; i < L; ++i) {\n        int curr_c = S[i];\n        int prev_c = S[i-1];\n        const auto& curr_pos = char_positions[curr_c];\n        const auto& prev_pos = char_positions[prev_c];\n        \n        dp[i].resize(curr_pos.size());\n        parent[i].resize(curr_pos.size());\n        \n        for (size_t j = 0; j < curr_pos.size(); ++j) {\n            int r = curr_pos[j].first;\n            int c = curr_pos[j].second;\n            int min_val = INT_MAX;\n            int best_p = -1;\n            \n            for (size_t k = 0; k < prev_pos.size(); ++k) {\n                int d = dist(prev_pos[k].first, prev_pos[k].second, r, c);\n                int total = dp[i-1][k] + d + 1;\n                if (total < min_val) {\n                    min_val = total;\n                    best_p = k;\n                }\n            }\n            dp[i][j] = min_val;\n            parent[i][j] = best_p;\n        }\n    }\n    \n    // Find best end state\n    int min_total = INT_MAX;\n    int curr_idx = -1;\n    for (size_t j = 0; j < dp[L-1].size(); ++j) {\n        if (dp[L-1][j] < min_total) {\n            min_total = dp[L-1][j];\n            curr_idx = j;\n        }\n    }\n    \n    // Backtrack\n    vector<pair<int,int>> path;\n    for (int i = L - 1; i >= 0; --i) {\n        path.push_back(char_positions[S[i]][curr_idx]);\n        curr_idx = parent[i][curr_idx];\n    }\n    reverse(path.begin(), path.end());\n    \n    // Output\n    for (auto& pt : path) {\n        cout << pt.first << \" \" << pt.second << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    cin >> N >> M;\n    cin >> start_r >> start_c;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    T.resize(M);\n    for (int i = 0; i < M; ++i) cin >> T[i];\n    \n    // Map positions\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char_positions[c2i(A[i][j])].push_back({i, j});\n        }\n    }\n    \n    // Precompute Overlaps\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) overlaps[i][j] = 0;\n            else overlaps[i][j] = calc_overlap(T[i], T[j]);\n        }\n    }\n    \n    // --- Precompute Distance Matrix (ATSP weights) ---\n    // 1. Costs from START to each string\n    vector<pair<int,int>> s_pos;\n    s_pos.push_back({start_r, start_c});\n    for (int i = 0; i < M; ++i) {\n        start_dist[i] = calc_segment_cost(s_pos, T[i]);\n    }\n    \n    // 2. Transition Costs between strings\n    for (int i = 0; i < M; ++i) {\n        int last_char_idx = c2i(T[i].back());\n        // Possible ending positions of string i\n        const auto& end_positions = char_positions[last_char_idx];\n        \n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                dist_matrix[i][j] = 999999; // Infinity\n                continue;\n            }\n            int ov = overlaps[i][j];\n            // String segment to type\n            string ext = T[j].substr(ov);\n            // Calculate min cost to type 'ext' given we start from one of 'end_positions'\n            dist_matrix[i][j] = calc_segment_cost(end_positions, ext);\n        }\n    }\n    \n    // --- Simulated Annealing for TSP ---\n    // State: Permutation p\n    vector<int> p(M);\n    for(int i=0; i<M; ++i) p[i] = i;\n    \n    // Greedy Initialization (Nearest Neighbor)\n    // Pick best start node\n    vector<bool> used(M, false);\n    int current_node = -1;\n    int best_start_val = INT_MAX;\n    for(int i=0; i<M; ++i) {\n        if(start_dist[i] < best_start_val) {\n            best_start_val = start_dist[i];\n            current_node = i;\n        }\n    }\n    \n    p[0] = current_node;\n    used[current_node] = true;\n    int current_tsp_cost = best_start_val;\n    \n    for(int i=1; i<M; ++i) {\n        int best_next = -1;\n        int min_d = INT_MAX;\n        for(int j=0; j<M; ++j) {\n            if(!used[j]) {\n                if(dist_matrix[current_node][j] < min_d) {\n                    min_d = dist_matrix[current_node][j];\n                    best_next = j;\n                }\n            }\n        }\n        p[i] = best_next;\n        used[best_next] = true;\n        current_tsp_cost += min_d;\n        current_node = best_next;\n    }\n    \n    // SA Parameters\n    vector<int> best_p = p;\n    int current_cost = current_tsp_cost;\n    int best_cost = current_cost;\n    \n    double T0 = 20.0;\n    double T1 = 0.1;\n    double TL = 1.95; // Time Limit\n    \n    int iters = 0;\n    \n    while(true) {\n        iters++;\n        if ((iters & 511) == 0) {\n            double el = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (el > TL) break;\n        }\n        \n        // Simple cooling schedule\n        // Recomputing temp every iter is slow, do it periodically or approx? \n        // Doing it every iter is fine given M=200 is small enough.\n        // But let's just use a decreasing counter proxy or check time rarely?\n        // Checking time is expensive. Let's approximate.\n        // Actually, with 2 seconds, we can check time every 512 iters.\n        \n        // To avoid high frequency clock calls, use linear approximation inside the block\n        // For now, just standard clock check is fine with mask.\n        \n        // Since we are inside the loop, we need temp.\n        // Let's just assume linear cooling based on iteration count estimation?\n        // Hard to estimate max iters. Let's stick to time.\n        // Optimization: Only update temp every 512 iters.\n        static double temp = T0;\n        if ((iters & 511) == 0) {\n             double el = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n             temp = T0 + (T1 - T0) * (el / TL);\n        }\n\n        // Neighbor: Swap or Insert\n        int type = rng() % 2; \n        \n        if (type == 0) { // Swap p[i] and p[j]\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            \n            int prev_i = (i == 0) ? -1 : p[i-1];\n            int curr_i = p[i];\n            int next_i = (i == M-1) ? -1 : p[i+1];\n            \n            int prev_j = p[j-1]; \n            int curr_j = p[j];\n            int next_j = (j == M-1) ? -1 : p[j+1];\n            \n            int delta = 0;\n            \n            if (j == i + 1) {\n                // Adjacent Swap\n                if (prev_i == -1) delta -= start_dist[curr_i];\n                else delta -= dist_matrix[prev_i][curr_i];\n                delta -= dist_matrix[curr_i][curr_j];\n                if (next_j != -1) delta -= dist_matrix[curr_j][next_j];\n                \n                if (prev_i == -1) delta += start_dist[curr_j];\n                else delta += dist_matrix[prev_i][curr_j];\n                delta += dist_matrix[curr_j][curr_i];\n                if (next_j != -1) delta += dist_matrix[curr_i][next_j];\n            } else {\n                // Disjoint Swap\n                if (prev_i == -1) delta -= start_dist[curr_i];\n                else delta -= dist_matrix[prev_i][curr_i];\n                delta -= dist_matrix[curr_i][next_i];\n                \n                delta -= dist_matrix[prev_j][curr_j];\n                if (next_j != -1) delta -= dist_matrix[curr_j][next_j];\n                \n                if (prev_i == -1) delta += start_dist[curr_j];\n                else delta += dist_matrix[prev_i][curr_j];\n                delta += dist_matrix[curr_j][next_i];\n                \n                delta += dist_matrix[prev_j][curr_i];\n                if (next_j != -1) delta += dist_matrix[curr_i][next_j];\n            }\n            \n            if (delta < 0 || bernoulli_distribution(exp(-delta / temp))(rng)) {\n                swap(p[i], p[j]);\n                current_cost += delta;\n                if (current_cost < best_cost) {\n                    best_cost = current_cost;\n                    best_p = p;\n                }\n            }\n            \n        } else { // Insert (Move p[i] to index k)\n            // For simplicity and speed, we can recalculate full cost or use careful delta.\n            // Recalculating full cost is O(M) = 200, which is acceptable given simplicity.\n            // Let's use full recalc to be safe and support general moves.\n            \n            int i = rng() % M;\n            int k = rng() % M; // new position\n            if (i == k) continue;\n            \n            // Create candidate\n            vector<int> next_p = p;\n            int val = next_p[i];\n            next_p.erase(next_p.begin() + i);\n            next_p.insert(next_p.begin() + k, val);\n            \n            // Compute cost\n            int new_c = start_dist[next_p[0]];\n            for(int x=0; x<M-1; ++x) {\n                new_c += dist_matrix[next_p[x]][next_p[x+1]];\n            }\n            \n            int diff = new_c - current_cost;\n            if (diff < 0 || bernoulli_distribution(exp(-diff / temp))(rng)) {\n                p = next_p;\n                current_cost = new_c;\n                if (current_cost < best_cost) {\n                    best_cost = current_cost;\n                    best_p = p;\n                }\n            }\n        }\n    }\n    \n    // Output result\n    solve_final(best_p);\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------------------- Utils ----------------------\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool is_time_over() {\n        return elapsed() > limit;\n    }\n};\n\nmt19937 rng(12345);\n\n// ---------------------- Globals ----------------------\n\nint N, M;\ndouble EPS;\n\nstruct Point { int r, c; };\n\nstruct Polyomino {\n    vector<Point> shape;\n};\nvector<Polyomino> fields;\n\nstruct Operation {\n    int type; // 0: drill, 1: divine\n    int r, c; // for drill\n    vector<Point> set_points; // for divine\n    int result_drill;\n    int result_divine;\n    \n    // Precomputed parameters for energy calc\n    double divine_mean_base; // k*eps\n    double divine_mean_coeff; // 1 - 2*eps\n    double divine_var_inv; // 1 / (2*sigma^2)\n};\nvector<Operation> history;\n// Map from cell (r,c) to list of operation indices that include this cell\nvector<vector<vector<int>>> cell_to_ops;\n\nstruct ValidPos {\n    int r, c; // top-left\n    vector<Point> cells;\n};\nvector<vector<ValidPos>> possible_positions; // [field_id][pos_id]\nvector<vector<int>> active_indices; // [field_id] -> list of valid pos_ids\n\nvector<vector<int>> grid_known; // -1: unknown, >=0: exact value\n\n// ---------------------- Functions ----------------------\n\nvoid precompute_positions() {\n    possible_positions.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = 0, max_c = 0;\n        for (auto& p : fields[k].shape) {\n            max_r = max(max_r, p.r);\n            max_c = max(max_c, p.c);\n        }\n        for (int r = 0; r < N - max_r; ++r) {\n            for (int c = 0; c < N - max_c; ++c) {\n                ValidPos vp;\n                vp.r = r;\n                vp.c = c;\n                for (auto& p : fields[k].shape) {\n                    vp.cells.push_back({p.r + r, p.c + c});\n                }\n                possible_positions[k].push_back(vp);\n            }\n        }\n    }\n}\n\nvoid add_history(Operation op) {\n    int idx = history.size();\n    \n    if (op.type == 1) {\n        int k_sz = op.set_points.size();\n        double var = k_sz * EPS * (1.0 - EPS);\n        op.divine_mean_base = k_sz * EPS;\n        op.divine_mean_coeff = 1.0 - 2.0 * EPS;\n        op.divine_var_inv = 0.5 / max(1e-9, var);\n    } \n    \n    history.push_back(op);\n    \n    // Update lookup\n    if (op.type == 0) {\n        cell_to_ops[op.r][op.c].push_back(idx);\n        grid_known[op.r][op.c] = op.result_drill;\n    } else {\n        for (auto& p : op.set_points) {\n            cell_to_ops[p.r][p.c].push_back(idx);\n        }\n    }\n}\n\n// Prune valid positions based on known 0s\nvoid prune_positions() {\n    active_indices.assign(M, {});\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < (int)possible_positions[k].size(); ++i) {\n            bool ok = true;\n            const auto& cells = possible_positions[k][i].cells;\n            for (const auto& p : cells) {\n                if (grid_known[p.r][p.c] == 0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                active_indices[k].push_back(i);\n            }\n        }\n    }\n}\n\n// SA State\nstruct State {\n    vector<int> config; // [field_id] -> pos_index\n    vector<vector<int>> counts;\n    vector<int> op_preds; // [op_idx] -> predicted value\n    double energy;\n};\n\ndouble get_op_energy(int op_idx, int pred_val) {\n    const auto& op = history[op_idx];\n    if (op.type == 0) { // Drill\n        return 10000.0 * abs(pred_val - op.result_drill);\n    } else { // Divine\n        double mean = op.divine_mean_base + pred_val * op.divine_mean_coeff;\n        double diff = op.result_divine - mean;\n        return diff * diff * op.divine_var_inv;\n    }\n}\n\nvector<vector<int>> run_sa(int num_solutions, double duration) {\n    vector<vector<int>> solutions;\n    Timer t(duration);\n    \n    // Check valid space exists\n    for (int k = 0; k < M; ++k) {\n        if (active_indices[k].empty()) return {}; \n    }\n\n    while (solutions.size() < (size_t)num_solutions && !t.is_time_over()) {\n        State S;\n        S.config.resize(M);\n        S.counts.assign(N, vector<int>(N, 0));\n        S.op_preds.assign(history.size(), 0);\n        S.energy = 0;\n\n        // Random Init\n        for (int k = 0; k < M; ++k) {\n            int idx = active_indices[k][rng() % active_indices[k].size()];\n            S.config[k] = idx;\n            for (const auto& p : possible_positions[k][idx].cells) {\n                S.counts[p.r][p.c]++;\n                for (int op_idx : cell_to_ops[p.r][p.c]) {\n                    S.op_preds[op_idx]++;\n                }\n            }\n        }\n\n        // Calc initial energy\n        for (int i = 0; i < (int)history.size(); ++i) {\n            S.energy += get_op_energy(i, S.op_preds[i]);\n        }\n\n        double Temp = 5.0;\n        double decay = 0.95;\n        int iter = 0;\n        \n        // Reusable buffer for changed ops to avoid allocation in loop\n        static vector<int> changed_ops;\n        changed_ops.reserve(history.size());\n\n        while (iter < 1000) { \n            iter++;\n            int k = rng() % M;\n            if (active_indices[k].size() <= 1) continue;\n\n            int old_idx = S.config[k];\n            int new_idx = active_indices[k][rng() % active_indices[k].size()];\n            if (old_idx == new_idx) continue;\n\n            const auto& old_cells = possible_positions[k][old_idx].cells;\n            const auto& new_cells = possible_positions[k][new_idx].cells;\n\n            // Identify affected operations\n            changed_ops.clear();\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            sort(changed_ops.begin(), changed_ops.end());\n            changed_ops.erase(unique(changed_ops.begin(), changed_ops.end()), changed_ops.end());\n\n            double delta = 0;\n            // Subtract old\n            for (int op_idx : changed_ops) delta -= get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            // Apply provisional changes\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n            }\n\n            // Add new\n            for (int op_idx : changed_ops) delta += get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            // Metropolis\n            if (delta < 0 || exp(-delta / Temp) > (double)rng() / 4294967296.0) {\n                S.energy += delta;\n                S.config[k] = new_idx;\n                for (const auto& p : old_cells) S.counts[p.r][p.c]--;\n                for (const auto& p : new_cells) S.counts[p.r][p.c]++;\n            } else {\n                // Revert\n                for (const auto& p : new_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n                }\n                for (const auto& p : old_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n                }\n            }\n            Temp *= decay;\n            if (Temp < 0.1) break;\n        }\n        solutions.push_back(S.config);\n    }\n    return solutions;\n}\n\nint main() {\n    cin.tie(nullptr);\n    ios_base::sync_with_stdio(false);\n\n    if (!(cin >> N >> M >> EPS)) return 0;\n\n    fields.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int d; cin >> d;\n        fields[i].shape.resize(d);\n        for (int j = 0; j < d; ++j) {\n            cin >> fields[i].shape[j].r >> fields[i].shape[j].c;\n        }\n    }\n\n    precompute_positions();\n    grid_known.assign(N, vector<int>(N, -1));\n    cell_to_ops.assign(N, vector<vector<int>>(N));\n\n    // 1. Initial Scan: 2x2 blocks\n    for(int r=0; r<N; r+=2) {\n        for(int c=0; c<N; c+=2) {\n            vector<Point> pts;\n            for(int rr=r; rr<min(N, r+2); ++rr) {\n                for(int cc=c; cc<min(N, c+2); ++cc) {\n                    pts.push_back({rr, cc});\n                }\n            }\n            if(pts.size() >= 2) {\n                cout << \"q \" << pts.size();\n                for(auto& p : pts) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                int res; cin >> res;\n                add_history({1, 0, 0, pts, 0, res});\n            }\n        }\n    }\n\n    Timer global_timer(2.8);\n    int max_ops = 2 * N * N;\n\n    while (!global_timer.is_time_over() && (int)history.size() < max_ops) {\n        prune_positions();\n\n        // Run SA\n        vector<vector<int>> solutions = run_sa(20, 0.05);\n\n        // Aggregate\n        vector<vector<int>> pos_counts(N, vector<int>(N, 0));\n        int sol_cnt = solutions.size();\n        \n        if (sol_cnt > 0) {\n            for(const auto& cfg : solutions) {\n                for(int k=0; k<M; ++k) {\n                    int idx = cfg[k];\n                    for(auto& p : possible_positions[k][idx].cells) {\n                        pos_counts[p.r][p.c]++;\n                    }\n                }\n            }\n        }\n\n        // Decision Making\n        vector<Point> answer_candidates;\n        bool confident = true;\n        \n        if (sol_cnt == 0) confident = false;\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                bool include = false;\n                if (grid_known[r][c] != -1) {\n                    if (grid_known[r][c] > 0) include = true;\n                } else {\n                    if (sol_cnt > 0) {\n                        if (pos_counts[r][c] == sol_cnt) include = true;\n                        else if (pos_counts[r][c] == 0) include = false;\n                        else confident = false;\n                    } else {\n                        confident = false;\n                    }\n                }\n                if (include) answer_candidates.push_back({r, c});\n            }\n        }\n        \n        // Submit if confident\n        if (confident && sol_cnt > 0) {\n            cout << \"a \" << answer_candidates.size();\n            for(auto& p : answer_candidates) cout << \" \" << p.r << \" \" << p.c;\n            cout << endl;\n            int res; cin >> res;\n            if (res == 1) return 0;\n            // If wrong, loop continues.\n        }\n        \n        // Select square to drill\n        int best_r = -1, best_c = -1;\n        \n        if (sol_cnt > 0) {\n            int max_ent = -1;\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    if (grid_known[r][c] != -1) continue;\n                    int yes = pos_counts[r][c];\n                    int no = sol_cnt - yes;\n                    int score = min(yes, no);\n                    if (score > max_ent) {\n                        max_ent = score;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n        }\n        \n        // Fallback if SA failed or no ambiguity found (but not submitted/wrong)\n        if (best_r == -1) {\n             vector<Point> undrilled;\n             for(int r=0; r<N; ++r)\n                 for(int c=0; c<N; ++c)\n                     if(grid_known[r][c] == -1) undrilled.push_back({r, c});\n             \n             if (undrilled.empty()) break; \n             int idx = rng() % undrilled.size();\n             best_r = undrilled[idx].r;\n             best_c = undrilled[idx].c;\n        }\n        \n        cout << \"q 1 \" << best_r << \" \" << best_c << endl;\n        int val; cin >> val;\n        add_history({0, best_r, best_c, {}, val, 0});\n    }\n    \n    // Final guess if time out\n    vector<Point> final_ans;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            if(grid_known[r][c] > 0) final_ans.push_back({r, c});\n        }\n    }\n    cout << \"a \" << final_ans.size();\n    for(auto& p : final_ans) cout << \" \" << p.r << \" \" << p.c;\n    cout << endl;\n    int res; cin >> res;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global variables\nint W_GRID; // Will be read from input (fixed at 1000 usually)\nint D, N;\nvector<vector<int>> A;\n\n// Constants\nconst int SHORTAGE_PENALTY = 100;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct ColumnResult {\n    long long cost;\n    vector<vector<int>> cuts;\n};\n\n// Timer for time management\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\n// Solve the 1D packing problem for a specific column across all days\n// items: indices of reservations assigned to this column\n// width: the width assigned to this column\nColumnResult solve_column(const vector<int>& items, int width) {\n    // If no items, no cost.\n    if (items.empty()) return {0, vector<vector<int>>(D)};\n    \n    // If width is invalid but items exist, we incur maximum shortage penalty.\n    // We return dummy cuts (all 0) to allow the program to proceed.\n    if (width <= 0) {\n        long long penalty = 0;\n        for(int d=0; d<D; ++d) {\n            for(int idx : items) penalty += (long long)A[d][idx] * SHORTAGE_PENALTY;\n        }\n        return {penalty, vector<vector<int>>(D, vector<int>(items.size(), 0))};\n    }\n\n    int m = items.size();\n    // cuts[d][i] stores the vertical coordinate of the bottom of the i-th item in the column.\n    // The last item (i = m-1) always ends at W_GRID.\n    vector<vector<int>> cuts(D, vector<int>(m));\n    long long total_cost = 0;\n    \n    // State tracking for partition stability\n    vector<int> prev_cuts(m, 0); \n    \n    for (int d = 0; d < D; ++d) {\n        // 1. Calculate ideal height demand for each item\n        vector<int> needs(m);\n        for(int i=0; i<m; ++i) {\n            // Ceiling division: ceil(Area / Width)\n            needs[i] = (A[d][items[i]] + width - 1) / width;\n        }\n\n        // 2. Calculate Upper Bounds (R)\n        // R[i] is the maximum valid position for cut i such that all subsequent items \n        // (i+1 to m-1) can technically fit within the remaining space up to W_GRID.\n        vector<int> R(m);\n        R[m-1] = W_GRID; \n        long long acc_space = W_GRID;\n        for(int i=m-2; i>=0; --i) {\n            acc_space -= needs[i+1];\n            if (acc_space < 0) acc_space = 0;\n            R[i] = (int)acc_space;\n        }\n\n        // 3. Determine cuts greedily with stability bias\n        vector<int> curr_cuts(m);\n        curr_cuts[m-1] = W_GRID;\n\n        int current_y = 0; // Top of the current item (bottom of previous)\n        \n        for(int i=0; i<m-1; ++i) {\n            // The absolute minimum position for this cut to satisfy the current item's area\n            int min_pos = current_y + needs[i];\n            // The absolute maximum position to leave space for items below\n            int max_pos = R[i];\n            \n            int chosen_pos = min_pos; // Default to satisfying demand (Shortage priority)\n\n            if (min_pos <= max_pos) {\n                // We have a valid range [min_pos, max_pos].\n                // Use this slack to minimize partition movement cost.\n                if (d == 0) {\n                    // On Day 0, just pack tightly to top to leave maximum slack at bottom\n                    chosen_pos = min_pos; \n                } else {\n                    int p = prev_cuts[i];\n                    if (p < min_pos) chosen_pos = min_pos;      // Must move down\n                    else if (p > max_pos) chosen_pos = max_pos; // Must move up\n                    else chosen_pos = p;                        // Stay put (0 move cost)\n                }\n            }\n            // If min_pos > max_pos, the column is oversubscribed. \n            // We choose min_pos to satisfy the current item, pushing shortage to the bottom.\n            // This is optimal because shortage cost is linear.\n            \n            // Clamp to grid boundaries\n            if (chosen_pos > W_GRID) chosen_pos = W_GRID;\n            \n            curr_cuts[i] = chosen_pos;\n            current_y = chosen_pos;\n        }\n        \n        // 4. Calculate Cost for the day\n        long long d_cost = 0;\n        \n        // Shortage Cost\n        int prev_y = 0;\n        for(int i=0; i<m; ++i) {\n            int h = curr_cuts[i] - prev_y;\n            long long area = (long long)h * width;\n            long long req = A[d][items[i]];\n            if (area < req) {\n                d_cost += (req - area) * SHORTAGE_PENALTY;\n            }\n            prev_y = curr_cuts[i];\n        }\n        \n        // Partition Change Cost\n        // Cost is incurred if horizontal separators change position.\n        // A change at index i implies removing the old line (width) and adding new (width) -> 2*width.\n        if (d > 0) {\n            for(int i=0; i<m-1; ++i) {\n                if (curr_cuts[i] != prev_cuts[i]) {\n                    d_cost += width * 2;\n                }\n            }\n        }\n        \n        total_cost += d_cost;\n        cuts[d] = curr_cuts;\n        prev_cuts = curr_cuts;\n    }\n    \n    return {total_cost, cuts};\n}\n\nstruct Solution {\n    vector<vector<int>> partition; // Indices of items in each column\n    vector<int> widths;            // Width of each column\n    long long score;\n};\n\n// Evaluates a specific partitioning of items into columns\nSolution evaluate_partition(const vector<vector<int>>& part) {\n    int K = part.size();\n    vector<int> widths(K);\n    \n    // Determine column widths based on the maximum daily demand in each column.\n    // This helps accommodate peak days without resizing columns (which is very expensive).\n    vector<long long> max_demands(K, 0);\n    long long total_demand = 0;\n    \n    for(int c=0; c<K; ++c) {\n        for(int d=0; d<D; ++d) {\n            long long d_sum = 0;\n            for(int idx : part[c]) d_sum += A[d][idx];\n            if (d_sum > max_demands[c]) max_demands[c] = d_sum;\n        }\n        total_demand += max_demands[c];\n    }\n    \n    if (total_demand == 0) total_demand = 1;\n    \n    // Distribute W_GRID proportional to max demands\n    int current_w = 0;\n    for(int c=0; c<K; ++c) {\n        if (c == K-1) {\n            widths[c] = W_GRID - current_w;\n        } else {\n            long long w = (long long)W_GRID * max_demands[c] / total_demand;\n            if (w < 1) w = 1;\n            widths[c] = (int)w;\n            current_w += widths[c];\n        }\n    }\n    \n    // Corrective pass if the last column ended up with invalid width\n    if (widths[K-1] < 1) {\n        widths[K-1] = 1;\n        current_w = 0;\n        for(int c=0; c<K-1; ++c) current_w += widths[c];\n        \n        // Steal width from previous columns\n        while (current_w >= W_GRID) {\n            bool reduced = false;\n            for(int c=0; c<K-1; ++c) {\n                if (widths[c] > 1) {\n                    widths[c]--;\n                    current_w--;\n                    reduced = true;\n                    if (current_w < W_GRID) break;\n                }\n            }\n            if (!reduced) break; // Should not happen given W=1000 and K small\n        }\n        widths[K-1] = W_GRID - current_w;\n    }\n\n    long long total_score = 0;\n    for(int c=0; c<K; ++c) {\n        ColumnResult res = solve_column(part[c], widths[c]);\n        total_score += res.cost;\n    }\n    \n    return {part, widths, total_score};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Reading input\n    int temp_W;\n    if (!(cin >> temp_W >> D >> N)) return 0;\n    W_GRID = temp_W;\n\n    A.resize(D, vector<int>(N));\n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            cin >> A[d][k];\n        }\n    }\n    \n    long long start_time = get_time_ms();\n    mt19937 rng(42);\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    // Try different numbers of columns K\n    // N is up to 50, so we try a reasonable range of columns.\n    int max_k = min(N, 12); \n    \n    for(int K=1; K<=max_k; ++K) {\n        // Initial Partition: Divide sorted items (0..N-1) into K continuous chunks\n        vector<int> cuts(K+1);\n        cuts[0] = 0;\n        cuts[K] = N;\n        for(int i=1; i<K; ++i) cuts[i] = (N * i) / K;\n        \n        vector<vector<int>> part(K);\n        for(int c=0; c<K; ++c) {\n            for(int i=cuts[c]; i<cuts[c+1]; ++i) part[c].push_back(i);\n        }\n        \n        Solution sol = evaluate_partition(part);\n        if (best_sol.score == -1 || sol.score < best_sol.score) {\n            best_sol = sol;\n        }\n        \n        // Hill Climbing to optimize the boundaries between item groups\n        if (K > 1) {\n            int iter = 0;\n            while (true) {\n                // Check time limit\n                if ((iter & 127) == 0) {\n                    if (get_time_ms() - start_time > 2800) break;\n                }\n                iter++;\n                \n                // Propose a move: shift a boundary between group c and c+1\n                int idx = uniform_int_distribution<int>(1, K-1)(rng);\n                int dir = uniform_int_distribution<int>(0, 1)(rng) ? 1 : -1;\n                \n                vector<int> next_cuts = cuts;\n                next_cuts[idx] += dir;\n                \n                // Ensure boundaries remain valid and strictly increasing\n                if (next_cuts[idx] <= next_cuts[idx-1] || next_cuts[idx] >= next_cuts[idx+1]) continue;\n                \n                vector<vector<int>> next_part(K);\n                for(int c=0; c<K; ++c) {\n                    for(int i=next_cuts[c]; i<next_cuts[c+1]; ++i) next_part[c].push_back(i);\n                }\n                \n                Solution next_sol = evaluate_partition(next_part);\n                if (next_sol.score < sol.score) {\n                    sol = next_sol;\n                    cuts = next_cuts;\n                    if (sol.score < best_sol.score) best_sol = sol;\n                }\n            }\n        }\n        \n        if (get_time_ms() - start_time > 2800) break;\n    }\n    \n    // Reconstruct and print the final result\n    vector<vector<Rect>> final_rects(D, vector<Rect>(N));\n    int current_x = 0;\n    for(int c=0; c<best_sol.partition.size(); ++c) {\n        int w = best_sol.widths[c];\n        ColumnResult res = solve_column(best_sol.partition[c], w);\n        \n        for(int d=0; d<D; ++d) {\n            int prev_y = 0;\n            for(int i=0; i<best_sol.partition[c].size(); ++i) {\n                int item_idx = best_sol.partition[c][i];\n                int y = res.cuts[d][i];\n                // Output format: r0 c0 r1 c1\n                final_rects[d][item_idx] = {prev_y, current_x, y, current_x + w};\n                prev_y = y;\n            }\n        }\n        current_x += w;\n    }\n    \n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            Rect r = final_rects[d][k];\n            cout << r.r0 << \" \" << r.c0 << \" \" << r.r1 << \" \" << r.c1 << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\n\n// Problem Constraints\nconstexpr int N = 9;\nconstexpr long long MOD = 998244353;\n\n// Fast RNG using Xorshift128\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Global Variables\nint M, K;\nlong long initial_board[81];\nlong long stamps[20][9]; // Flattened 3x3 stamps\nint move_indices[49][9]; // Affected board indices for each top-left position\n\nstruct MoveDef {\n    int m;       // Stamp ID\n    int pos_idx; // Position ID (0..48)\n    int p, q;    // Coordinates\n};\nvector<MoveDef> all_moves;\n\n// State Variables\nint current_ops[81]; // Stores index in all_moves, or -1 for empty\nlong long board[81];\nlong long current_score;\n\n// Best Solution Tracking\nint best_ops[81];\nlong long best_score = -1;\n\n// Undo System for efficient rollback\nstruct Undo {\n    int idx;\n    long long val;\n};\nUndo undo_log[20]; // Buffer for changes (max 18 per step)\nint undo_ptr = 0;\n\n// Apply or remove a stamp operation. \n// If adding=true, adds stamp values. If adding=false, subtracts stamp values.\n// Records old values to undo_log.\ninline void apply_change(int move_id, bool adding) {\n    if (move_id == -1) return;\n    const auto& mv = all_moves[move_id];\n    int m = mv.m;\n    int pos = mv.pos_idx;\n    \n    // Unroll loop manually or let compiler optimize. 9 iterations is small.\n    for (int i = 0; i < 9; ++i) {\n        int idx = move_indices[pos][i];\n        long long old_val = board[idx];\n        long long s_val = stamps[m][i];\n        \n        // Record for undo\n        undo_log[undo_ptr++] = {idx, old_val};\n        \n        // Update Score (remove old value contribution)\n        current_score -= old_val;\n        \n        // Calculate new value\n        long long new_val;\n        if (adding) {\n            new_val = old_val + s_val;\n            if (new_val >= MOD) new_val -= MOD;\n        } else {\n            new_val = old_val - s_val;\n            if (new_val < 0) new_val += MOD;\n        }\n        \n        // Apply update\n        board[idx] = new_val;\n        current_score += new_val;\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    int n_in;\n    if (!(cin >> n_in >> M >> K)) return 0;\n    \n    for (int i = 0; i < 81; ++i) cin >> initial_board[i];\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 9; ++i) cin >> stamps[m][i];\n    }\n    \n    // Precompute moves and affected indices\n    // Positions are 0 <= p, q <= N-3 (=6). 7x7 = 49 positions.\n    int pos_cnt = 0;\n    for (int p = 0; p <= N - 3; ++p) {\n        for (int q = 0; q <= N - 3; ++q) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    move_indices[pos_cnt][i * 3 + j] = (p + i) * N + (q + j);\n                }\n            }\n            for (int m = 0; m < M; ++m) {\n                all_moves.push_back({m, pos_cnt, p, q});\n            }\n            pos_cnt++;\n        }\n    }\n    int num_valid_moves = all_moves.size();\n    \n    // Initialize state\n    for (int i = 0; i < 81; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < 81; ++i) current_score += board[i];\n    for (int i = 0; i < K; ++i) current_ops[i] = -1;\n    \n    best_score = current_score;\n    for (int i = 0; i < K; ++i) best_ops[i] = -1;\n    \n    // Greedy Initialization\n    // Sequentially fill slots if it improves the score\n    for (int k = 0; k < K; ++k) {\n        long long best_local_score = current_score;\n        int best_move = -1;\n        \n        // Try all possible moves for this slot\n        for (int mv = 0; mv < num_valid_moves; ++mv) {\n            undo_ptr = 0;\n            long long prev_score = current_score;\n            \n            apply_change(mv, true);\n            \n            if (current_score > best_local_score) {\n                best_local_score = current_score;\n                best_move = mv;\n            }\n            \n            // Revert\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n            current_score = prev_score;\n        }\n        \n        // If we found a beneficial move, apply it permanently\n        if (best_move != -1) {\n            current_ops[k] = best_move;\n            undo_ptr = 0;\n            apply_change(best_move, true);\n        }\n    }\n    \n    // Update global best after greedy\n    if (current_score > best_score) {\n        best_score = current_score;\n        for(int i=0; i<K; ++i) best_ops[i] = current_ops[i];\n    }\n    \n    // Simulated Annealing\n    auto start_clock = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double t0 = 2e8;     // Initial temperature\n    double t1 = 1.0;     // Final temperature\n    \n    long long iter = 0;\n    double current_temp = t0;\n    \n    while (true) {\n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_clock).count();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            current_temp = t0 * pow(t1 / t0, progress);\n        }\n        iter++;\n        \n        // Pick a random slot and a random new move (or empty)\n        int slot = rng.next_int(K);\n        int old_move = current_ops[slot];\n        // Generate new move in range [-1, num_valid_moves-1]\n        int new_move = rng.next_int(num_valid_moves + 1) - 1;\n        \n        if (old_move == new_move) continue;\n        \n        long long prev_score = current_score;\n        undo_ptr = 0;\n        \n        // Apply transition: Remove old move, Add new move\n        apply_change(old_move, false); // Remove old\n        apply_change(new_move, true);  // Add new\n        \n        long long delta = current_score - prev_score;\n        bool accept = false;\n        \n        if (delta >= 0) {\n            accept = true;\n        } else {\n            if (rng.next_double() < exp(delta / current_temp)) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_ops[slot] = new_move;\n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int i = 0; i < K; ++i) best_ops[i] = current_ops[i];\n            }\n        } else {\n            // Revert changes using log (in reverse order)\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n        }\n    }\n    \n    // Output results\n    vector<MoveDef> result_moves;\n    for (int i = 0; i < K; ++i) {\n        if (best_ops[i] != -1) {\n            result_moves.push_back(all_moves[best_ops[i]]);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& mv : result_moves) {\n        cout << mv.m << \" \" << mv.p << \" \" << mv.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <deque>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Crane {\n    int id;\n    Coord pos;\n    bool holding;\n    int container_id; // -1 if none\n    bool dead;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    deque<int> queues[N];\n    Crane cranes[N];\n    int containers_dispatched;\n    vector<string> history;\n    \n    State() {\n        for(int i=0; i<N; ++i)\n            for(int j=0; j<N; ++j)\n                grid[i][j] = -1;\n        containers_dispatched = 0;\n        history.resize(N);\n    }\n};\n\nint dist(Coord a, Coord b) {\n    return std::abs(a.r - b.r) + std::abs(a.c - b.c);\n}\n\nint main() {\n    // Optimize I/O operations\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Input\n    int n_in;\n    if (!(cin >> n_in)) return 0;\n    // N is fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Initialize State\n    State st;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            st.queues[i].push_back(A[i][j]);\n        }\n        st.cranes[i] = {i, {i, 0}, false, -1, false};\n    }\n\n    // Track next needed container for each row\n    // Dispatch gate i needs containers 5*i, 5*i+1, ... in order\n    vector<int> next_needed(N);\n    for(int i=0; i<N; ++i) next_needed[i] = i * N;\n\n    // Main simulation loop\n    for (int turn = 1; turn <= MAX_TURNS; ++turn) {\n        if (st.containers_dispatched == N*N) break;\n\n        // 1. Refill Receiving Gates (Step 1 of turn)\n        for(int i=0; i<N; ++i) {\n            if (!st.queues[i].empty()) {\n                bool empty_sq = (st.grid[i][0] == -1);\n                bool crane_holding = false;\n                // Check if any crane is holding a container at this gate (blocks refill)\n                for(int k=0; k<N; ++k) {\n                    if (!st.cranes[k].dead && st.cranes[k].pos.r == i && st.cranes[k].pos.c == 0 && st.cranes[k].holding) {\n                        crane_holding = true;\n                        break;\n                    }\n                }\n                if (empty_sq && !crane_holding) {\n                    st.grid[i][0] = st.queues[i].front();\n                    st.queues[i].pop_front();\n                }\n            }\n        }\n\n        // 2. Crane Actions (Step 2 of turn)\n        for(int i=0; i<N; ++i) {\n            char act = '.';\n            if (i > 0) {\n                // Small cranes bomb themselves on turn 1 to clear the way\n                if (turn == 1) {\n                    act = 'B';\n                    st.cranes[i].dead = true;\n                } else {\n                    act = '.';\n                }\n            } else {\n                // Large Crane (0) Logic\n                Crane& c = st.cranes[0];\n                \n                auto is_needed = [&](int id) {\n                    if (id == -1) return false;\n                    int row = id / N;\n                    // Only the exact next one is \"needed\" to enforce order\n                    if (next_needed[row] == id) return true;\n                    return false;\n                };\n                \n                char my_act = '.';\n                \n                if (c.holding) {\n                    int held = c.container_id;\n                    if (is_needed(held)) {\n                        // DELIVER: Move to dispatch gate\n                        int row = held / N;\n                        Coord dest = {row, N-1};\n                        \n                        if (c.pos == dest) {\n                            // Drop if square is empty (it will be dispatched in step 3)\n                            if (st.grid[dest.r][dest.c] == -1) {\n                                my_act = 'Q';\n                            } else {\n                                my_act = '.'; // Wait for space\n                            }\n                        } else {\n                            // Move towards destination\n                            if (c.pos.r < dest.r) my_act = 'D';\n                            else if (c.pos.r > dest.r) my_act = 'U';\n                            else if (c.pos.c < dest.c) my_act = 'R';\n                            else if (c.pos.c > dest.c) my_act = 'L';\n                        }\n                    } else {\n                        // STORE: Move garbage to buffer\n                        // Prefer columns 1, 2, 3. Column 0 is last resort.\n                        int best_dist = 999;\n                        Coord best_spot = {-1, -1};\n                        \n                        for(int c_idx : {1, 2, 3, 0}) { \n                             for(int r_idx=0; r_idx<N; ++r_idx) {\n                                 // Skip Dispatch column 4\n                                 if (st.grid[r_idx][c_idx] == -1) {\n                                     int d = dist(c.pos, {r_idx, c_idx});\n                                     if (d < best_dist) {\n                                         best_dist = d;\n                                         best_spot = {r_idx, c_idx};\n                                     }\n                                 }\n                             }\n                        }\n                        \n                        if (best_spot.r != -1) {\n                            if (c.pos == best_spot) {\n                                my_act = 'Q';\n                            } else {\n                                if (c.pos.r < best_spot.r) my_act = 'D';\n                                else if (c.pos.r > best_spot.r) my_act = 'U';\n                                else if (c.pos.c < best_spot.c) my_act = 'R';\n                                else if (c.pos.c > best_spot.c) my_act = 'L';\n                            }\n                        } else {\n                             my_act = '.'; // Stuck (should not happen with N=5)\n                        }\n                    }\n                } else {\n                    // PICK: Find something to pick\n                    int best_dist = 999;\n                    Coord target = {-1, -1};\n                    \n                    // Priority 1: Look for exposed needed items on the grid\n                    for(int r=0; r<N; ++r) {\n                        for(int c_idx=0; c_idx<N; ++c_idx) {\n                            int id = st.grid[r][c_idx];\n                            if (is_needed(id)) {\n                                // Ignore if already at correct dispatch gate (will be auto-dispatched)\n                                int needed_row = id / N;\n                                if (r == needed_row && c_idx == N-1) continue; \n                                \n                                int d = dist(c.pos, {r, c_idx});\n                                if (d < best_dist) {\n                                    best_dist = d;\n                                    target = {r, c_idx};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (target.r != -1) {\n                        // Go pick the visible needed item\n                        if (c.pos == target) {\n                            my_act = 'P';\n                        } else {\n                             if (c.pos.r < target.r) my_act = 'D';\n                             else if (c.pos.r > target.r) my_act = 'U';\n                             else if (c.pos.c < target.c) my_act = 'R';\n                             else if (c.pos.c > target.c) my_act = 'L';\n                        }\n                    } else {\n                        // Priority 2: Dig for buried needed items in queues\n                        int best_depth = 999;\n                        int target_q = -1;\n                        \n                        for(int q=0; q<N; ++q) {\n                            for(int k=0; k<(int)st.queues[q].size(); ++k) {\n                                if (is_needed(st.queues[q][k])) {\n                                    if (k < best_depth) {\n                                        best_depth = k;\n                                        target_q = q;\n                                    }\n                                    break; \n                                }\n                            }\n                        }\n                        \n                        if (target_q != -1) {\n                            // Go to the queue to clear the blocker\n                            Coord t = {target_q, 0};\n                            if (c.pos == t) {\n                                if (st.grid[t.r][t.c] != -1) my_act = 'P';\n                                else my_act = '.'; // Wait for refill\n                            } else {\n                                 if (c.pos.r < t.r) my_act = 'D';\n                                 else if (c.pos.r > t.r) my_act = 'U';\n                                 else if (c.pos.c < t.c) my_act = 'R';\n                                 else if (c.pos.c > t.c) my_act = 'L';\n                            }\n                        } else {\n                            my_act = '.';\n                        }\n                    }\n                }\n                \n                act = my_act;\n                \n                // Update Crane 0 state based on action\n                if (act == 'U') st.cranes[0].pos.r--;\n                else if (act == 'D') st.cranes[0].pos.r++;\n                else if (act == 'L') st.cranes[0].pos.c--;\n                else if (act == 'R') st.cranes[0].pos.c++;\n                else if (act == 'P') {\n                    st.cranes[0].holding = true;\n                    st.cranes[0].container_id = st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c];\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = -1;\n                }\n                else if (act == 'Q') {\n                    st.cranes[0].holding = false;\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = st.cranes[0].container_id;\n                    st.cranes[0].container_id = -1;\n                }\n            }\n            st.history[i] += act;\n        }\n        \n        // 3. Dispatch (Step 3 of turn)\n        for(int i=0; i<N; ++i) {\n            int cid = st.grid[i][N-1];\n            if (cid != -1) {\n                // Item at dispatch gate is removed from grid\n                st.grid[i][N-1] = -1;\n                st.containers_dispatched++;\n                \n                // Update needed index if correct one was dispatched\n                int row = cid / N;\n                if (row == i && cid == next_needed[i]) {\n                    next_needed[i]++;\n                }\n            }\n        }\n    }\n\n    // Output results\n    for(int i=0; i<N; ++i) {\n        cout << st.history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Directions: 0:U, 1:D, 2:L, 3:R\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint N = 20;\nlong long grid_h[20][20];\n\nstruct Job {\n    int id;\n    int start_node;\n    int end_node;\n    long long amount;\n};\n\n// Manhattan distance\nint dist(int u, int v) {\n    int r1 = u / N, c1 = u % N;\n    int r2 = v / N, c2 = v % N;\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (cin >> N) {} \n    \n    // 1. Build Min-Cost Max-Flow Network\n    // Nodes 0..(N*N-1) represent grid cells.\n    // Node S = N*N, T = N*N+1\n    mcf_graph<int, long long> g(N * N + 2);\n    int S = N * N;\n    int T = N * N + 1;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> grid_h[i][j];\n            int u = i * N + j;\n            \n            // Connect sources and sinks to super-source/super-sink\n            if (grid_h[i][j] > 0) {\n                g.add_edge(S, u, grid_h[i][j], 0);\n            } else if (grid_h[i][j] < 0) {\n                g.add_edge(u, T, -grid_h[i][j], 0);\n            }\n            \n            // Connect adjacent cells\n            // Cost is 1 (distance), Capacity is infinite\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int v = ni * N + nj;\n                    g.add_edge(u, v, 1e9, 1);\n                }\n            }\n        }\n    }\n\n    // Solve MCMF\n    g.flow(S, T);\n    \n    // 2. Decompose Flow into Jobs\n    // Build an adjacency list representing the flow solution\n    vector<vector<pair<int, long long>>> adj(N * N + 2);\n    auto edges = g.edges();\n    for (const auto& e : edges) {\n        if (e.flow > 0 && e.from != S && e.to != T) {\n            // We only care about grid-to-grid edges for path reconstruction\n            adj[e.from].push_back({e.to, e.flow});\n        } else if (e.flow > 0 && e.from == S) {\n            // From Source to Grid, we track this as starting capacity\n            // However, for path tracing, we can just start BFS from these nodes\n            // Or better: Add S->u edges to adj to start pathfinding from S\n            adj[e.from].push_back({e.to, e.flow});\n        } else if (e.flow > 0 && e.to == T) {\n            adj[e.from].push_back({e.to, e.flow});\n        }\n    }\n\n    vector<Job> jobs;\n    int job_counter = 0;\n    \n    // Greedily extract paths from S to T in the flow graph\n    while (true) {\n        vector<int> parent(N * N + 2, -1);\n        vector<int> edge_idx(N * N + 2, -1);\n        queue<int> q;\n        \n        q.push(S);\n        parent[S] = S;\n        \n        bool found = false;\n        while(!q.empty()) {\n            int u = q.front(); q.pop();\n            if (u == T) {\n                found = true;\n                break;\n            }\n            for (int i = 0; i < adj[u].size(); ++i) {\n                int v = adj[u][i].first;\n                long long cap = adj[u][i].second;\n                if (cap > 0 && parent[v] == -1) {\n                    parent[v] = u;\n                    edge_idx[v] = i;\n                    q.push(v);\n                }\n            }\n        }\n        \n        if (!found) break;\n        \n        // Backtrack to find path and bottleneck capacity\n        long long path_flow = 1e18;\n        int curr = T;\n        while (curr != S) {\n            int p = parent[curr];\n            int idx = edge_idx[curr];\n            path_flow = min(path_flow, adj[p][idx].second);\n            curr = p;\n        }\n        \n        // Create Job and decrease flow\n        // Path: S -> u_start -> ... -> u_end -> T\n        // We need u_start and u_end\n        int u_start = -1, u_end = -1;\n        \n        curr = T;\n        while (curr != S) {\n            int p = parent[curr];\n            int idx = edge_idx[curr];\n            adj[p][idx].second -= path_flow;\n            \n            if (curr == T) u_end = p;      // Node connected to T\n            if (p == S) u_start = curr;    // Node connected from S\n            \n            curr = p;\n        }\n        \n        if (u_start != -1 && u_end != -1) {\n            jobs.push_back({job_counter++, u_start, u_end, path_flow});\n        }\n    }\n    \n    // 3. Simulate Truck with VRP Heuristic\n    int truck_r = 0, truck_c = 0;\n    long long truck_load = 0;\n    vector<string> ops;\n    \n    vector<bool> is_picked(jobs.size(), false);\n    vector<bool> is_done(jobs.size(), false);\n    int jobs_done_count = 0;\n    \n    while (jobs_done_count < jobs.size()) {\n        int curr_node = truck_r * N + truck_c;\n        \n        // --- Perform Unload Operations ---\n        for (auto &j : jobs) {\n            if (is_picked[j.id] && !is_done[j.id] && j.end_node == curr_node) {\n                ops.push_back(\"-\" + to_string(j.amount));\n                truck_load -= j.amount;\n                is_done[j.id] = true;\n                jobs_done_count++;\n            }\n        }\n        \n        // --- Perform Load Operations ---\n        for (auto &j : jobs) {\n            if (!is_picked[j.id] && j.start_node == curr_node) {\n                ops.push_back(\"+\" + to_string(j.amount));\n                truck_load += j.amount;\n                is_picked[j.id] = true;\n            }\n        }\n        \n        if (jobs_done_count == jobs.size()) break;\n        \n        // --- Select Next Target (Nearest Neighbor) ---\n        int best_target = -1;\n        int min_dist = 1e9;\n        bool target_is_sink = false;\n        \n        for (const auto &j : jobs) {\n            if (is_done[j.id]) continue;\n            \n            if (is_picked[j.id]) {\n                // Job is carrying: Candidate target is Sink\n                int d = dist(curr_node, j.end_node);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_target = j.end_node;\n                    target_is_sink = true;\n                } else if (d == min_dist && !target_is_sink) {\n                    // Tie-breaker: Prefer Unloading to reduce weight\n                    best_target = j.end_node;\n                    target_is_sink = true;\n                }\n            } else {\n                // Job is waiting: Candidate target is Source\n                int d = dist(curr_node, j.start_node);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_target = j.start_node;\n                    target_is_sink = false;\n                }\n            }\n        }\n        \n        // --- Move One Step Towards Target ---\n        if (best_target != -1) {\n            int tr = best_target / N;\n            int tc = best_target % N;\n            \n            int move_dir = -1;\n            // Determine direction (greedy Manhattan)\n            if (tr < truck_r) move_dir = 0;\n            else if (tr > truck_r) move_dir = 1;\n            else if (tc < truck_c) move_dir = 2;\n            else if (tc > truck_c) move_dir = 3;\n            \n            if (move_dir != -1) {\n                ops.push_back(string(1, dir_char[move_dir]));\n                truck_r += dr[move_dir];\n                truck_c += dc[move_dir];\n            }\n        }\n    }\n    \n    // Output results\n    for (const auto& s : ops) cout << s << \"\\n\";\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// Global Constants\nint N, M, T;\nint SEED_COUNT;\nint GRID_SIZE;\n\n// Tunable Parameters\n// K_MIN: We aggressively prioritize having at least this many copies of the max value for each attribute.\nconst int K_MIN = 2;\n// K_TARGET: We mildly prioritize having up to this many copies.\nconst int K_TARGET = 4;\n// Bonuses for the selection scoring\nconst long long BONUS_CRITICAL = 1000000;\nconst long long BONUS_TARGET = 5000;\n// Weights for the edge potential calculation\n// 10 * max + 1 * min prioritizes high potential peaks but breaks ties with stability (min).\nconst int WEIGHT_MAX = 10;\nconst int WEIGHT_MIN = 1;\n\nstruct Seed {\n    int id;\n    vector<int> x;\n    int total_val;\n};\n\n// Random Engine\nmt19937 rng(12345);\n\n// Timer for SA\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool check() {\n        return elapsed() < limit;\n    }\n};\n\n// Adjacency List\nvector<vector<int>> adj;\n\nvoid init_grid() {\n    GRID_SIZE = N * N;\n    adj.assign(GRID_SIZE, vector<int>());\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // Neighbor Down\n            if (r + 1 < N) {\n                int v = (r + 1) * N + c;\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            // Neighbor Right\n            if (c + 1 < N) {\n                int v = r * N + (c + 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n        }\n    }\n}\n\n// Calculate edge score between two seeds\ninline int calc_score(const Seed& a, const Seed& b) {\n    int score = 0;\n    for (int k = 0; k < M; ++k) {\n        int mx = (a.x[k] > b.x[k]) ? a.x[k] : b.x[k];\n        int mn = (a.x[k] < b.x[k]) ? a.x[k] : b.x[k];\n        score += WEIGHT_MAX * mx + WEIGHT_MIN * mn;\n    }\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> T)) return 0;\n    SEED_COUNT = 2 * N * (N - 1);\n    init_grid();\n\n    vector<Seed> seeds(SEED_COUNT);\n    // Initial Input\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        seeds[i].id = i;\n        seeds[i].x.resize(M);\n        seeds[i].total_val = 0;\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i].x[j];\n            seeds[i].total_val += seeds[i].x[j];\n        }\n    }\n\n    for (int t = 0; t < T; ++t) {\n        // --- Selection Phase ---\n        // We need to pick GRID_SIZE (36) seeds out of SEED_COUNT (60).\n        // Strategy: Ensure max values of all attributes are preserved with redundancy, then fill with high-sum seeds.\n        \n        // 1. Identify global max for each attribute\n        vector<int> global_max(M, -1);\n        for(const auto& s : seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] > global_max[j]) global_max[j] = s.x[j];\n            }\n        }\n\n        // 2. Greedy Selection\n        vector<Seed> selected_seeds;\n        selected_seeds.reserve(GRID_SIZE);\n        vector<bool> used(SEED_COUNT, false);\n        vector<int> current_counts(M, 0);\n\n        for(int i = 0; i < GRID_SIZE; ++i) {\n            int best_idx = -1;\n            long long best_eval = -1;\n\n            for(int k = 0; k < SEED_COUNT; ++k) {\n                if(used[k]) continue;\n\n                long long current_eval = seeds[k].total_val;\n                \n                // Add bonuses for covering global maxes\n                for(int j = 0; j < M; ++j) {\n                    if(seeds[k].x[j] == global_max[j]) {\n                        if(current_counts[j] < K_MIN) {\n                            current_eval += BONUS_CRITICAL;\n                        } else if(current_counts[j] < K_TARGET) {\n                            current_eval += BONUS_TARGET;\n                        }\n                    }\n                }\n\n                if(current_eval > best_eval) {\n                    best_eval = current_eval;\n                    best_idx = k;\n                }\n            }\n\n            // Commit selection\n            used[best_idx] = true;\n            selected_seeds.push_back(seeds[best_idx]);\n            for(int j = 0; j < M; ++j) {\n                if(seeds[best_idx].x[j] == global_max[j]) {\n                    current_counts[j]++;\n                }\n            }\n        }\n\n        // --- Placement Phase (Simulated Annealing) ---\n        // Goal: Arrange selected seeds on grid to maximize breeding potential.\n        \n        // Initial layout:\n        // Place high-value seeds in cells with high degree (center).\n        // Sort grid cells by degree\n        vector<pair<int, int>> node_degrees(GRID_SIZE);\n        for(int i=0; i<GRID_SIZE; ++i) node_degrees[i] = { (int)adj[i].size(), i };\n        sort(node_degrees.rbegin(), node_degrees.rend());\n\n        // Sort selected seeds by total value for initial assignment\n        vector<int> p(GRID_SIZE);\n        iota(p.begin(), p.end(), 0);\n        sort(p.begin(), p.end(), [&](int a, int b){\n            return selected_seeds[a].total_val > selected_seeds[b].total_val;\n        });\n\n        // Layout maps Grid Cell Index -> Index in selected_seeds\n        vector<int> layout(GRID_SIZE);\n        for(int i=0; i<GRID_SIZE; ++i) {\n            layout[node_degrees[i].second] = p[i];\n        }\n\n        // Precompute score matrix for all pairs\n        vector<vector<int>> scores(GRID_SIZE, vector<int>(GRID_SIZE));\n        for(int i=0; i<GRID_SIZE; ++i) {\n            for(int j=i+1; j<GRID_SIZE; ++j) {\n                scores[i][j] = scores[j][i] = calc_score(selected_seeds[i], selected_seeds[j]);\n            }\n        }\n\n        // Calculate initial total score\n        long long current_score = 0;\n        for (int u = 0; u < GRID_SIZE; ++u) {\n            for (int v : adj[u]) {\n                if (u < v) {\n                    current_score += scores[layout[u]][layout[v]];\n                }\n            }\n        }\n\n        long long best_score = current_score;\n        vector<int> best_layout = layout;\n\n        // SA Parameters\n        // Total time limit 2.0s, 10 turns => 0.2s per turn.\n        // Use 0.18s to leave buffer for I/O.\n        Timer timer(0.18);\n        double t0 = 1000.0; \n        double t1 = 0.1;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 127) == 0) {\n                if (!timer.check()) break;\n            }\n\n            double progress = timer.elapsed() / 0.18;\n            double temp = t0 * pow(t1/t0, progress);\n\n            // Random swap\n            int c1 = rng() % GRID_SIZE;\n            int c2 = rng() % GRID_SIZE;\n            if (c1 == c2) continue;\n\n            int s1 = layout[c1];\n            int s2 = layout[c2];\n\n            long long delta = 0;\n            \n            // Calculate delta efficiently\n            for (int u : adj[c1]) {\n                if (u != c2) {\n                    delta -= scores[s1][layout[u]];\n                    delta += scores[s2][layout[u]];\n                }\n            }\n            for (int u : adj[c2]) {\n                if (u != c1) {\n                    delta -= scores[s2][layout[u]];\n                    delta += scores[s1][layout[u]];\n                }\n            }\n\n            if (delta >= 0 || bernoulli_distribution(exp(delta / temp))(rng)) {\n                swap(layout[c1], layout[c2]);\n                current_score += delta;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_layout = layout;\n                }\n            }\n        }\n\n        // --- Output ---\n        vector<vector<int>> output_grid(N, vector<int>(N));\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                int cell = r*N + c;\n                int seed_idx = best_layout[cell];\n                output_grid[r][c] = selected_seeds[seed_idx].id;\n            }\n        }\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cout << output_grid[r][c] << (c == N-1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        // --- Input Next Generation ---\n        for(int i=0; i<SEED_COUNT; ++i) {\n            seeds[i].id = i; // Reset IDs 0..59\n            seeds[i].total_val = 0;\n            for(int j=0; j<M; ++j) {\n                cin >> seeds[i].x[j];\n                seeds[i].total_val += seeds[i].x[j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 35;\nconst int MAX_TURNS = 100000;\nconst int DR[] = {0, 1, 0, -1};\nconst int DC[] = {1, 0, -1, 0};\nconst char MOVE_CHARS[] = {'R', 'D', 'L', 'U'};\n\n// Globals\nint N, M, V;\nint s_grid[MAX_N][MAX_N]; // 1 if has takoyaki (Source)\nint t_grid[MAX_N][MAX_N]; // 1 if is target (Drop zone)\nint root_r, root_c;\nint turns = 0;\nint delivered_count = 0;\n\nstruct Leaf {\n    int id;\n    int len;\n    int dir; // 0:R, 1:D, 2:L, 3:U relative to root\n    bool holding;\n};\nvector<Leaf> leaves;\n\n// Helper: Get coord of leaf tip relative to a root position\npair<int, int> get_leaf_pos(int rr, int rc, int len, int dir) {\n    return {rr + DR[dir] * len, rc + DC[dir] * len};\n}\n\n// Helper: Determine rotation char to move from 'current' to 'target' direction\n// Returns '.' if same, 'R'/'L' if 90 deg.\nchar get_rot_char(int current, int target) {\n    if (current == target) return '.';\n    int diff = (target - current + 4) % 4;\n    if (diff == 1) return 'R';\n    if (diff == 3) return 'L';\n    // If diff is 2 (180 deg), we can't reach in 1 turn. \n    // We return R to start rotating.\n    if (diff == 2) return 'R'; \n    return '.';\n}\n\n// Helper: Distance in 90-deg turns between directions\nint get_rot_dist(int current, int target) {\n    int diff = abs(current - target);\n    // 0->0, 0->1(1), 0->2(2), 0->3(1 because 3 is -1)\n    // Actually simply:\n    int d = (target - current + 4) % 4;\n    if (d == 3) return 1;\n    return d;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> V)) return 0;\n    \n    vector<string> s_in(N), t_in(N);\n    for(int i=0; i<N; ++i) cin >> s_in[i];\n    for(int i=0; i<N; ++i) cin >> t_in[i];\n\n    // Initialize Grids\n    // Rules: \n    // s=1, t=0 -> Source\n    // s=0, t=1 -> Target\n    // s=1, t=1 -> Already correct (ignored)\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            bool is_s = (s_in[i][j] == '1');\n            bool is_t = (t_in[i][j] == '1');\n            if (is_s && is_t) {\n                delivered_count++;\n                s_grid[i][j] = 0;\n                t_grid[i][j] = 0;\n            } else {\n                s_grid[i][j] = is_s ? 1 : 0;\n                t_grid[i][j] = is_t ? 1 : 0;\n            }\n        }\n    }\n    \n    // Design Arm\n    // Strategy: Star graph with lengths 1, 2, ..., V-1 to maximize reach variety.\n    // Output V' = V (use all vertices)\n    cout << V << endl;\n    for(int i=1; i<V; ++i) {\n        // Parent 0, Length i\n        // If V is large (e.g. 15) and N small, we might exceed N-1.\n        // But N >= 15, so length up to 14 is always valid.\n        cout << \"0 \" << i << endl;\n    }\n    // Start Root at center\n    root_r = N/2; \n    root_c = N/2;\n    cout << root_r << \" \" << root_c << endl;\n\n    // Initialize Leaves State\n    leaves.resize(V-1);\n    for(int i=0; i<V-1; ++i) {\n        leaves[i].id = i;\n        leaves[i].len = i+1;\n        leaves[i].dir = 0;\n        leaves[i].holding = false;\n    }\n\n    // Main Loop\n    while (delivered_count < M && turns < MAX_TURNS) {\n        \n        // ---------------------------------------------------------\n        // 1. Find the Best Move (Nearest Valid Root Position)\n        // ---------------------------------------------------------\n        \n        int best_dist = 1e9;\n        int best_rr = -1, best_rc = -1;\n        \n        // Optimization: Pre-calculate target lists\n        vector<pair<int, int>> active_picks;\n        vector<pair<int, int>> active_drops;\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                if (s_grid[r][c]) active_picks.push_back({r, c});\n                else if (t_grid[r][c]) active_drops.push_back({r, c});\n            }\n        }\n        \n        // If no tasks left (should be handled by delivered_count check, but safety)\n        if (active_picks.empty() && active_drops.empty()) break;\n\n        // Evaluate potential goals\n        // We iterate over all leaves. If a leaf is free, it targets Pick locations.\n        // If a leaf is holding, it targets Drop locations.\n        // We calculate the root position required to put that leaf on that target.\n        \n        for(const auto& l : leaves) {\n            const vector<pair<int, int>>* targets = l.holding ? &active_drops : &active_picks;\n            \n            for(const auto& p : *targets) {\n                int tr = p.first;\n                int tc = p.second;\n                \n                // Valid root spots are at distance l.len from (tr, tc) in 4 directions\n                for(int d=0; d<4; ++d) {\n                    // If leaf is at direction d relative to root, root is at -d relative to leaf\n                    // root = target - vec(d)*len\n                    int rr = tr - DR[d] * l.len;\n                    int rc = tc - DC[d] * l.len;\n                    \n                    if(rr >=0 && rr < N && rc >= 0 && rc < N) {\n                        int dist = abs(rr - root_r) + abs(rc - root_c);\n                        if (dist < best_dist) {\n                            best_dist = dist;\n                            best_rr = rr;\n                            best_rc = rc;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // ---------------------------------------------------------\n        // 2. Determine Root Movement\n        // ---------------------------------------------------------\n        int move_dir = -1;\n        if (best_rr != -1 && best_dist > 0) {\n            if (best_rr > root_r) move_dir = 1; // D\n            else if (best_rr < root_r) move_dir = 3; // U\n            else if (best_rc > root_c) move_dir = 0; // R\n            else if (best_rc < root_c) move_dir = 2; // L\n        }\n        \n        // Calculate Next Root Position\n        int next_rr = root_r + (move_dir == -1 ? 0 : DR[move_dir]);\n        int next_rc = root_c + (move_dir == -1 ? 0 : DC[move_dir]);\n\n        // ---------------------------------------------------------\n        // 3. Determine Leaf Rotations and Actions (Simultaneously)\n        // ---------------------------------------------------------\n        vector<char> rot_cmds(V-1, '.');\n        vector<char> act_cmds(V, '.'); // Index 1..V-1 for leaves, 0 for root (unused)\n        vector<bool> leaf_busy(V-1, false);\n\n        // Check for tasks executable at next_rr, next_rc\n        // We prioritize Drops, then Picks.\n        \n        for(int i=0; i<V-1; ++i) {\n            int best_task_dir = -1;\n            int best_task_type = -1; // 0: Pick, 1: Drop\n            \n            // Check 4 directions relative to next root\n            for(int d=0; d<4; ++d) {\n                auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, d);\n                if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n                \n                // Check feasibility: rotation must be <= 1 step (90 deg)\n                if (get_rot_dist(leaves[i].dir, d) > 1) continue;\n                \n                if (leaves[i].holding) {\n                    if (t_grid[tr][tc]) {\n                        best_task_dir = d;\n                        best_task_type = 1;\n                        break; // Found Drop (High Prio)\n                    }\n                } else {\n                    if (s_grid[tr][tc]) {\n                        best_task_dir = d;\n                        best_task_type = 0;\n                        // Don't break, might find Drop? No, if not holding, can't drop.\n                        break; \n                    }\n                }\n            }\n            \n            if (best_task_dir != -1) {\n                // Execute Action\n                leaf_busy[i] = true;\n                rot_cmds[i] = get_rot_char(leaves[i].dir, best_task_dir);\n                act_cmds[i+1] = 'P';\n                \n                // Update logical state immediately to prevent double booking\n                auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, best_task_dir);\n                if (best_task_type == 0) { // Pick\n                    s_grid[tr][tc] = 0;\n                    if (t_in[tr][tc] == '1') t_grid[tr][tc] = 1; // Becomes target\n                    leaves[i].holding = true;\n                } else { // Drop\n                    t_grid[tr][tc] = 0; // Occupied target\n                    delivered_count++;\n                    leaves[i].holding = false;\n                }\n            }\n        }\n        \n        // For idle leaves, rotate towards potential useful directions?\n        // To keep it simple and robust, we just let them stay or rotate if we are waiting at goal.\n        // If we are AT the best spot but rotation was wrong (dist > 1), we need to rotate.\n        // The loop above handles dist <= 1. \n        // What if we are at the spot but need 180 turn?\n        // We should rotate towards a task.\n        for(int i=0; i<V-1; ++i) {\n            if (leaf_busy[i]) continue;\n            \n            // If we are not busy, find nearest task for this leaf and rotate towards it\n            // This helps prep for future turns or handling 180 deg turns\n            const vector<pair<int, int>>* targets = leaves[i].holding ? &active_drops : &active_picks;\n            for(const auto& p : *targets) {\n                // Is this task reachable from next_root with SOME rotation?\n                for(int d=0; d<4; ++d) {\n                    auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, d);\n                    if (tr == p.first && tc == p.second) {\n                        // Found a task at this location, just wrong rotation.\n                        // Rotate towards d.\n                        rot_cmds[i] = get_rot_char(leaves[i].dir, d);\n                        goto next_leaf;\n                    }\n                }\n            }\n            next_leaf:;\n        }\n\n        // ---------------------------------------------------------\n        // 4. Output and Finalize State\n        // ---------------------------------------------------------\n        string out_s = \"\";\n        out_s += (move_dir == -1 ? '.' : MOVE_CHARS[move_dir]);\n        for(char c : rot_cmds) out_s += c;\n        for(int k=0; k<V; ++k) out_s += act_cmds[k];\n        cout << out_s << \"\\n\";\n\n        root_r = next_rr;\n        root_c = next_rc;\n        for(int i=0; i<V-1; ++i) {\n            if (rot_cmds[i] == 'R') leaves[i].dir = (leaves[i].dir + 1) % 4;\n            else if (rot_cmds[i] == 'L') leaves[i].dir = (leaves[i].dir + 3) % 4;\n        }\n        turns++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <map>\n#include <set>\n#include <queue>\n#include <cassert>\n#include <chrono>\n\nusing namespace std;\n\n// Constants and Parameters\nconst int MAX_COORD = 100000;\nconst int MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\nconst double TIME_LIMIT = 1.95;\n\nstruct Point {\n    int x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Timing utility\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\nlong long start_time;\n\n// Polygon is a list of vertices\ntypedef vector<Point> Polygon;\n\n// Check if point inside polygon (Ray casting)\n// Points on edges are considered inside\nbool is_inside(const Polygon& poly, const Point& p) {\n    bool inside = false;\n    int n = poly.size();\n    for (int i = 0; i < n; ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % n];\n        \n        // Check if point is on segment (horizontal or vertical)\n        if (p1.x == p2.x && p1.x == p.x) {\n            if (p.y >= min(p1.y, p2.y) && p.y <= max(p1.y, p2.y)) return true;\n        }\n        if (p1.y == p2.y && p1.y == p.y) {\n            if (p.x >= min(p1.x, p2.x) && p.x <= max(p1.x, p2.x)) return true;\n        }\n        \n        // Standard Ray Casting\n        if ((p1.y > p.y) != (p2.y > p.y)) {\n            double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x;\n            if (p.x < intersect_x) {\n                inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score for a polygon\nint raw_score(const Polygon& poly) {\n    int m = 0, s = 0;\n    int min_x = MAX_COORD, max_x = 0, min_y = MAX_COORD, max_y = 0;\n    for (auto& p : poly) {\n        min_x = min(min_x, p.x);\n        max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y);\n        max_y = max(max_y, p.y);\n    }\n    \n    // Bounding box check for speed\n    for (const auto& p : mackerels) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) m++;\n    }\n    for (const auto& p : sardines) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) s++;\n    }\n    return m - s;\n}\n\nlong long perimeter(const Polygon& poly) {\n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        perim += abs(poly[i].x - poly[(i + 1) % poly.size()].x) + abs(poly[i].y - poly[(i + 1) % poly.size()].y);\n    }\n    return perim;\n}\n\n// Grid-based Solver\nstruct GridSolver {\n    int cell_size;\n    int offset_x, offset_y;\n    int GX, GY;\n    vector<vector<int>> grid_score;\n    \n    GridSolver(int cs, int ox, int oy) : cell_size(cs), offset_x(ox), offset_y(oy) {\n        // Ensure grid covers the range [0, MAX_COORD]\n        // Coordinates map to: (coord + offset) / cell_size\n        GX = (MAX_COORD + offset_x) / cell_size + 2; \n        GY = (MAX_COORD + offset_y) / cell_size + 2;\n        grid_score.assign(GX, vector<int>(GY, 0));\n    }\n    \n    void build() {\n        for (const auto& p : mackerels) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]++;\n        }\n        for (const auto& p : sardines) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]--;\n        }\n    }\n    \n    Polygon solve() {\n        // Find connected components of positive cells\n        vector<vector<bool>> visited(GX, vector<bool>(GY, false));\n        vector<pair<int, vector<pair<int, int>>>> components;\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (grid_score[x][y] > 0 && !visited[x][y]) {\n                    int comp_score = 0;\n                    vector<pair<int, int>> comp_cells;\n                    queue<pair<int, int>> q;\n                    \n                    q.push({x, y});\n                    visited[x][y] = true;\n                    while(!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        comp_score += grid_score[cx][cy];\n                        comp_cells.push_back({cx, cy});\n                        \n                        // 4-neighbor connectivity\n                        int dx[] = {1, -1, 0, 0};\n                        int dy[] = {0, 0, 1, -1};\n                        for(int k=0; k<4; ++k) {\n                            int nx = cx + dx[k];\n                            int ny = cy + dy[k];\n                            if (nx >= 0 && nx < GX && ny >= 0 && ny < GY && !visited[nx][ny] && grid_score[nx][ny] > 0) {\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    components.push_back({comp_score, comp_cells});\n                }\n            }\n        }\n        \n        if (components.empty()) return {};\n        \n        // Pick the component with the highest score\n        sort(components.rbegin(), components.rend());\n        set<pair<int, int>> selected_cells(components[0].second.begin(), components[0].second.end());\n        \n        return trace_boundary(selected_cells);\n    }\n    \n    // Trace the outer boundary of the set of grid cells\n    Polygon trace_boundary(const set<pair<int, int>>& cells) {\n        if (cells.empty()) return {};\n        \n        // Find starting cell (bottom-leftmost)\n        int start_x = GX + 1, start_y = GY + 1;\n        for(auto p : cells) {\n            if (p.second < start_y || (p.second == start_y && p.x < start_x)) {\n                start_x = p.x;\n                start_y = p.second;\n            }\n        }\n        \n        // Start tracing from the bottom-left corner of the start cell\n        // Movement directions: 0=Right, 1=Up, 2=Left, 3=Down\n        // \"Polygon on Left\" rule (CCW traversal)\n        // We start at Bottom-Left corner of cell (start_x, start_y).\n        // The bottom edge of this cell is boundary because (start_x, start_y-1) is not in set (since we picked min y).\n        // We move Right along the bottom edge.\n        \n        int vx = start_x;\n        int vy = start_y; // Using grid indices as corner coordinates implies (vx, vy) is bottom-left of cell (vx, vy)\n        // Wait, let's define grid coordinates: cell (x, y) spans [x, x+1] x [y, y+1].\n        // Bottom-left corner is (x, y).\n        \n        int dir = 0; // Moving Right (x increasing)\n        vector<pair<int, int>> path;\n        path.push_back({vx, vy});\n        \n        int initial_vx = vx, initial_vy = vy, initial_dir = dir;\n        int steps = 0;\n        \n        auto check = [&](int gx, int gy) {\n            return cells.count({gx, gy});\n        };\n        \n        do {\n            // Determine next direction\n            // We are at vertex (vx, vy). Incoming direction was 'dir'.\n            // We check 4 cells around (vx, vy) to decide where to turn.\n            // Standard Wall Following (Left Hand Rule):\n            // Try to turn Left (relative). If wall exists, turn.\n            // Else try Straight.\n            // Else Turn Right.\n            // Else Turn Back.\n            // \"Wall\" here means the boundary between IN and OUT cells.\n            // We want to keep IN cells on our Left.\n            \n            // Relative directions: \n            // Left turn: (dir + 1) % 4\n            // Straight: dir\n            // Right turn: (dir + 3) % 4\n            // Back: (dir + 2) % 4\n            \n            int next_dir = -1;\n            // Priority: Left -> Straight -> Right -> Back\n            int search_order[] = {(dir + 1) % 4, dir, (dir + 3) % 4, (dir + 2) % 4};\n            \n            for (int nd : search_order) {\n                // Check if moving in 'nd' is a valid boundary with IN cell on Left\n                // Identification of Left/Right cells relative to edge 'nd' starting at (vx, vy)\n                // nd=0 (Right): Left Cell (vx, vy), Right Cell (vx, vy-1)\n                // nd=1 (Up): Left Cell (vx, vy), Right Cell (vx-1, vy) ?? No.\n                // Let's map carefully.\n                // Cell coords relative to vertex (vx, vy):\n                // Q1 (Top-Right): (vx, vy)\n                // Q2 (Top-Left): (vx-1, vy)\n                // Q3 (Bottom-Left): (vx-1, vy-1)\n                // Q4 (Bottom-Right): (vx, vy-1)\n                \n                // Edge 0 (Right): Sep Q1 and Q4. Left is Q1 (vx, vy). Right is Q4 (vx, vy-1).\n                // Edge 1 (Up): Sep Q2 and Q1. Left is Q2 (vx-1, vy). Right is Q1 (vx, vy).\n                // Edge 2 (Left): Sep Q3 and Q2. Left is Q3 (vx-1, vy-1). Right is Q2 (vx-1, vy).\n                // Edge 3 (Down): Sep Q4 and Q3. Left is Q4 (vx, vy-1). Right is Q3 (vx-1, vy-1).\n                \n                pair<int,int> l_c, r_c;\n                if (nd == 0) { l_c = {vx, vy}; r_c = {vx, vy-1}; }\n                else if (nd == 1) { l_c = {vx-1, vy}; r_c = {vx, vy}; }\n                else if (nd == 2) { l_c = {vx-1, vy-1}; r_c = {vx-1, vy}; }\n                else { l_c = {vx, vy-1}; r_c = {vx-1, vy-1}; }\n                \n                if (check(l_c.first, l_c.second) && !check(r_c.first, r_c.second)) {\n                    next_dir = nd;\n                    break;\n                }\n            }\n            \n            if (next_dir == -1) break; // Should not happen on valid boundary\n            \n            dir = next_dir;\n            if (dir == 0) vx++;\n            else if (dir == 1) vy++;\n            else if (dir == 2) vx--;\n            else vy--;\n            \n            path.push_back({vx, vy});\n            steps++;\n            if (steps > 20000) break; // Safety break\n            \n        } while (vx != initial_vx || vy != initial_vy);\n        \n        // Map grid coords back to world coords and simplify collinear\n        Polygon poly;\n        if (path.empty()) return {};\n        \n        // Helper to map grid vertex to point\n        auto get_pt = [&](pair<int,int> p) {\n            int X = p.first * cell_size - offset_x;\n            int Y = p.second * cell_size - offset_y;\n            return Point{clamp(X, 0, MAX_COORD), clamp(Y, 0, MAX_COORD)};\n        };\n        \n        // Simplify path (remove collinear vertices)\n        // path contains the loop of grid vertices.\n        // We iterate and keep only corners.\n        if (path.back() == path[0]) path.pop_back();\n        \n        vector<Point> corners;\n        if (!path.empty()) {\n            // Add first point temporarily\n            corners.push_back(get_pt(path[0]));\n            for(size_t i = 1; i < path.size(); ++i) {\n                Point curr = get_pt(path[i]);\n                Point prev = corners.back();\n                // Check if we extended the last segment or started a new one\n                if (corners.size() >= 2) {\n                    Point pprev = corners[corners.size()-2];\n                    bool prev_horz = (prev.y == pprev.y);\n                    bool curr_horz = (curr.y == prev.y);\n                    if (prev_horz == curr_horz) {\n                        corners.back() = curr; // Extend\n                    } else {\n                        corners.push_back(curr); // Turn\n                    }\n                } else {\n                    corners.push_back(curr);\n                }\n            }\n            \n            // Handle wrap-around collinearity\n            if (corners.size() > 2) {\n                Point first = corners[0];\n                Point last = corners.back();\n                Point prev = corners[corners.size()-2];\n                \n                bool last_seg_horz = (last.y == prev.y);\n                bool first_seg_horz = (corners[1].y == first.y); \n                // Actually we need to check the closing edge (last -> first)\n                // Logic: if edge(prev->last) and edge(last->first) are collinear\n                // AND edge(last->first) and edge(first->second) are collinear -> rare\n                // Just check last->first merge with prev->last\n                bool closing_horz = (first.y == last.y);\n                \n                if (last_seg_horz == closing_horz) {\n                    // Merge last into first? \n                    // If last->first is same dir as prev->last, then 'last' is redundant.\n                    corners.pop_back();\n                    last = corners.back(); // new last\n                }\n                \n                // Now check if (new) last -> first matches first -> second\n                bool closing_horz2 = (first.y == last.y);\n                if (closing_horz2 == first_seg_horz) {\n                    corners.erase(corners.begin());\n                }\n            }\n        }\n        \n        return corners;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = get_time_ms();\n    \n    if (!(cin >> N)) return 0;\n    mackerels.resize(N);\n    for(int i=0; i<N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    sardines.resize(N);\n    for(int i=0; i<N; ++i) cin >> sardines[i].x >> sardines[i].y;\n    \n    Polygon best_poly;\n    int best_score = -1;\n    \n    // Random number generator\n    mt19937 rng(1337);\n    \n    // Try different grid sizes to capture clusters of varying density\n    vector<int> grid_sizes = {4000, 2500, 2000, 1500, 1000, 5000, 800};\n    int iter = 0;\n    \n    while (get_time_ms() - start_time < TIME_LIMIT * 1000) {\n        iter++;\n        int cs = grid_sizes[(iter - 1) % grid_sizes.size()];\n        // Randomize selection after first pass\n        if (iter > (int)grid_sizes.size()) {\n            cs = grid_sizes[rng() % grid_sizes.size()];\n        }\n        \n        // Random offset\n        int ox = rng() % cs;\n        int oy = rng() % cs;\n        \n        GridSolver solver(cs, ox, oy);\n        solver.build();\n        Polygon poly = solver.solve();\n        \n        // Validate constraints\n        if (poly.size() < 4) continue;\n        if (poly.size() > MAX_VERTICES) continue; // Too complex, skip\n        if (perimeter(poly) > MAX_PERIMETER) continue;\n        \n        int current_score = raw_score(poly);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_poly = poly;\n        }\n    }\n    \n    // Output\n    if (best_poly.empty()) {\n        // Fallback: just a tiny square somewhere\n        cout << \"4\\n0 0\\n1 0\\n1 1\\n0 1\\n\";\n    } else {\n        cout << best_poly.size() << \"\\n\";\n        for (const auto& p : best_poly) {\n            cout << p.x << \" \" << p.y << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Structures ---\nstruct Op {\n    int p; // index of rect (must be i)\n    int r; // rotation 0: no, 1: yes\n    int d; // direction 0:U, 1:L\n    int b; // base rect index (-1 or 0..i-1)\n};\n\nstruct PlacedRect {\n    int x, y, w, h;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    int W, H;\n    long long score;\n};\n\n// --- Global State ---\nint N, T, sigma_val;\nvector<int> w_prime, h_prime;\nvector<double> w_est, h_est;\nSolution best_global_sol;\nmt19937 rng(12345);\n\n// --- Simulation Function ---\n// Simulates the placement of rectangles based on operations and dimensions.\n// Returns {Width, Height} of the bounding box.\npair<int, int> simulate(const vector<Op>& ops, const vector<double>& ws, const vector<double>& hs, vector<PlacedRect>& out_rects) {\n    out_rects.clear();\n    out_rects.resize(N);\n    \n    int W = 0, H = 0;\n    \n    for (const auto& op : ops) {\n        int i = op.p;\n        // Determine dimensions based on rotation\n        int rw = (int)lround(op.r ? hs[i] : ws[i]);\n        int rh = (int)lround(op.r ? ws[i] : hs[i]);\n        if (rw < 1) rw = 1;\n        if (rh < 1) rh = 1;\n        \n        int x = 0, y = 0;\n        \n        if (op.d == 0) { // U: Moves Upward (decreasing y), stops at bottom of others or y=0.\n            // In our coord system (y increases downwards), this stacks in +y direction starting from y=0 or other rects.\n            // x is determined by reference b\n            if (op.b != -1) {\n                const auto& b_rect = out_rects[op.b];\n                x = b_rect.x + b_rect.w;\n            } else {\n                x = 0;\n            }\n            \n            // y is determined by gravity (stacking on existing rects)\n            y = 0;\n            for (int j = 0; j < i; ++j) {\n                // Check x-interval overlap: [x, x+rw) vs [j.x, j.x+j.w)\n                if (max(x, out_rects[j].x) < min(x + rw, out_rects[j].x + out_rects[j].w)) {\n                    y = max(y, out_rects[j].y + out_rects[j].h);\n                }\n            }\n        } else { // L: Moves Leftward (decreasing x), stops at right of others or x=0.\n            // Stacks in +x direction.\n            // y is determined by reference b\n            if (op.b != -1) {\n                const auto& b_rect = out_rects[op.b];\n                y = b_rect.y + b_rect.h;\n            } else {\n                y = 0;\n            }\n            \n            // x is determined by gravity\n            x = 0;\n            for (int j = 0; j < i; ++j) {\n                // Check y-interval overlap\n                if (max(y, out_rects[j].y) < min(y + rh, out_rects[j].y + out_rects[j].h)) {\n                    x = max(x, out_rects[j].x + out_rects[j].w);\n                }\n            }\n        }\n        \n        out_rects[i] = {x, y, rw, rh};\n        W = max(W, x + rw);\n        H = max(H, y + rh);\n    }\n    return {W, H};\n}\n\n// --- Parameter Update ---\n// Updates w_est and h_est based on observed error and critical paths.\nvoid update_estimates(const vector<Op>& last_ops, int W_obs, int H_obs) {\n    vector<PlacedRect> rects;\n    pair<int, int> dim = simulate(last_ops, w_est, h_est, rects);\n    int W_sim = dim.first;\n    int H_sim = dim.second;\n    \n    int diff_W = W_obs - W_sim;\n    int diff_H = H_obs - H_sim;\n    \n    // Build dependency graph to trace critical paths\n    vector<int> parent_x(N, -1);\n    vector<int> parent_y(N, -1);\n    \n    for (int i = 0; i < N; ++i) {\n        const auto& op = last_ops[i];\n        int rw = rects[i].w;\n        int rh = rects[i].h;\n        \n        if (op.d == 0) { // U\n            parent_x[i] = op.b; // X fixed by reference\n            // Y fixed by collision\n            int best_j = -1;\n            int max_y = 0;\n            for(int j=0; j<i; ++j) {\n                if (max(rects[i].x, rects[j].x) < min(rects[i].x + rw, rects[j].x + rects[j].w)) {\n                    if (rects[j].y + rects[j].h > max_y) {\n                        max_y = rects[j].y + rects[j].h;\n                        best_j = j;\n                    }\n                }\n            }\n            parent_y[i] = best_j;\n        } else { // L\n            parent_y[i] = op.b; // Y fixed by reference\n            // X fixed by collision\n            int best_j = -1;\n            int max_x = 0;\n            for(int j=0; j<i; ++j) {\n                if (max(rects[i].y, rects[j].y) < min(rects[i].y + rh, rects[j].y + rects[j].h)) {\n                    if (rects[j].x + rects[j].w > max_x) {\n                        max_x = rects[j].x + rects[j].w;\n                        best_j = j;\n                    }\n                }\n            }\n            parent_x[i] = best_j;\n        }\n    }\n    \n    // Trace Critical Path for W\n    vector<bool> on_path_W(N, false);\n    vector<int> q;\n    for(int i=0; i<N; ++i) if(rects[i].x + rects[i].w == W_sim) {\n        on_path_W[i] = true;\n        q.push_back(i);\n    }\n    int head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        int p = parent_x[u];\n        if(p != -1 && !on_path_W[p]){\n            on_path_W[p] = true;\n            q.push_back(p);\n        }\n    }\n    \n    // Trace Critical Path for H\n    vector<bool> on_path_H(N, false);\n    q.clear();\n    for(int i=0; i<N; ++i) if(rects[i].y + rects[i].h == H_sim) {\n        on_path_H[i] = true;\n        q.push_back(i);\n    }\n    head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        int p = parent_y[u];\n        if(p != -1 && !on_path_H[p]){\n            on_path_H[p] = true;\n            q.push_back(p);\n        }\n    }\n    \n    int cnt_W = 0; for(bool b : on_path_W) if(b) cnt_W++;\n    int cnt_H = 0; for(bool b : on_path_H) if(b) cnt_H++;\n    \n    // Update rule\n    double lr = 0.15; \n    \n    if (cnt_W > 0) {\n        double delta = (double)diff_W / cnt_W * lr;\n        for(int i=0; i<N; ++i) {\n            if(on_path_W[i]) {\n                if (last_ops[i].r == 0) w_est[i] += delta;\n                else h_est[i] += delta;\n            }\n        }\n    }\n    \n    if (cnt_H > 0) {\n        double delta = (double)diff_H / cnt_H * lr;\n        for(int i=0; i<N; ++i) {\n            if(on_path_H[i]) {\n                if (last_ops[i].r == 0) h_est[i] += delta;\n                else w_est[i] += delta;\n            }\n        }\n    }\n    \n    // Clamp\n    for(auto& v : w_est) if(v < 1) v = 1;\n    for(auto& v : h_est) if(v < 1) v = 1;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> T >> sigma_val)) return 0;\n    \n    w_prime.resize(N);\n    h_prime.resize(N);\n    w_est.resize(N);\n    h_est.resize(N);\n    \n    for(int i=0; i<N; ++i) {\n        cin >> w_prime[i] >> h_prime[i];\n        w_est[i] = w_prime[i];\n        h_est[i] = h_prime[i];\n    }\n    \n    // Initialize random solution\n    Solution curr_sol;\n    curr_sol.ops.resize(N);\n    for(int i=0; i<N; ++i) {\n        curr_sol.ops[i] = {i, (int)(rng()%2), (int)(rng()%2), (int)(rng()%(i+1)) - 1};\n    }\n    \n    vector<PlacedRect> dummy_rects;\n    auto dims = simulate(curr_sol.ops, w_est, h_est, dummy_rects);\n    curr_sol.W = dims.first;\n    curr_sol.H = dims.second;\n    curr_sol.score = curr_sol.W + curr_sol.H;\n    \n    best_global_sol = curr_sol;\n    \n    auto start_time = chrono::steady_clock::now();\n    double total_time_limit = 2.9; // sec\n    \n    for (int t = 0; t < T; ++t) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = total_time_limit - elapsed;\n        double time_for_turn = remaining / (T - t);\n        if (time_for_turn < 0.005) time_for_turn = 0.005; // Minimum 5ms\n        if (time_for_turn > 0.100) time_for_turn = 0.100; // Cap to allow distribution\n        \n        auto turn_start = chrono::steady_clock::now();\n        \n        // Re-evaluate best solution with updated estimates\n        {\n             auto d = simulate(best_global_sol.ops, w_est, h_est, dummy_rects);\n             best_global_sol.W = d.first;\n             best_global_sol.H = d.second;\n             best_global_sol.score = d.first + d.second;\n        }\n        curr_sol = best_global_sol; // Start SA from best known\n        \n        // SA Parameters\n        double T0 = 20000.0; \n        double T1 = 10.0;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 127) == 0) {\n                double turn_elapsed = chrono::duration<double>(chrono::steady_clock::now() - turn_start).count();\n                if (turn_elapsed > time_for_turn) break;\n            }\n            \n            // Perturbation\n            int i = rng() % N;\n            int type = rng() % 3;\n            \n            Op saved = curr_sol.ops[i];\n            \n            if (type == 0) { // Change rotation\n                curr_sol.ops[i].r = 1 - curr_sol.ops[i].r;\n            } else if (type == 1) { // Change direction\n                curr_sol.ops[i].d = 1 - curr_sol.ops[i].d;\n            } else { // Change reference\n                int new_b = (int)(rng() % (i + 1)) - 1;\n                if (new_b == curr_sol.ops[i].b && i > 0) {\n                    // try to force a change\n                    new_b = (new_b + 2) % (i + 1) - 1;\n                }\n                curr_sol.ops[i].b = new_b;\n            }\n            \n            // Evaluate\n            auto res = simulate(curr_sol.ops, w_est, h_est, dummy_rects);\n            long long new_score = res.first + res.second;\n            \n            double delta = new_score - curr_sol.score;\n            \n            // Temperature schedule\n            double turn_elapsed = chrono::duration<double>(chrono::steady_clock::now() - turn_start).count();\n            double progress = turn_elapsed / time_for_turn;\n            double temp = T0 * pow(T1/T0, progress);\n            \n            if (delta <= 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                curr_sol.W = res.first;\n                curr_sol.H = res.second;\n                curr_sol.score = new_score;\n                \n                if (curr_sol.score < best_global_sol.score) {\n                    best_global_sol = curr_sol;\n                }\n            } else {\n                // Revert\n                curr_sol.ops[i] = saved;\n            }\n        }\n        \n        // Output best solution\n        cout << N << \"\\n\"; \n        for(int i=0; i<N; ++i) {\n            const auto& op = best_global_sol.ops[i];\n            char d_char = (op.d == 0) ? 'U' : 'L';\n            cout << op.p << \" \" << op.r << \" \" << d_char << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read feedback\n        int W_obs, H_obs;\n        cin >> W_obs >> H_obs;\n        \n        // Update parameter estimates\n        update_estimates(best_global_sol.ops, W_obs, H_obs);\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Problem Constants\nconst int MAXN = 1005;\nconst int H_LIMIT = 10;\n\n// Global Variables\nint N, M, H_in;\nint A[MAXN];\nvector<int> adj[MAXN]; // Adjacency list\n\n// State Variables\nint p[MAXN];                // Parent of node i (-1 if root)\nint S[MAXN];                // Sum of A values in the subtree rooted at i\nint d_max[MAXN];            // Height of subtree at i (max distance to a descendant)\nint cnt_h[MAXN][H_LIMIT + 2]; // Frequency of children heights. indices 0..10 are valid.\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// Utility: Get depth of v (0-indexed) by walking up\n// O(H)\nint get_depth(int v) {\n    int d = 0;\n    while (v != -1) {\n        v = p[v];\n        d++;\n    }\n    return d - 1; // Root is depth 0\n}\n\n// Check if u is a descendant of v\n// Optimization: use depths if available, but here we just walk.\n// O(H)\nbool is_descendant(int u, int v) {\n    if (v == -1) return false;\n    if (u == v) return true;\n    while (u != -1) {\n        if (u == v) return true;\n        u = p[u];\n    }\n    return false;\n}\n\n// Update S (beauty sum) upwards\nvoid update_S_up(int u, int diff) {\n    while (u != -1) {\n        S[u] += diff;\n        u = p[u];\n    }\n}\n\n// Update d_max upwards after adding a child with height h_child\nvoid update_d_max_add(int u, int h_child) {\n    int curr = u;\n    int h = h_child;\n    while (curr != -1) {\n        cnt_h[curr][h]++;\n        if (h + 1 > d_max[curr]) {\n            int old_h = d_max[curr];\n            d_max[curr] = h + 1;\n            \n            int next_p = p[curr];\n            if (next_p != -1) {\n                // For the parent, 'curr' changed from old_h to d_max[curr]\n                // We need to remove old_h stats and add new.\n                // Since we are in 'add' logic (height strictly increases), \n                // we decrement old_h count and loop to increment new height.\n                if (cnt_h[next_p][old_h] > 0) cnt_h[next_p][old_h]--; \n                h = d_max[curr];\n                curr = next_p;\n            } else {\n                break;\n            }\n        } else {\n            // Max height didn't change, propagation stops\n            break;\n        }\n    }\n}\n\n// Update d_max upwards after removing a child with height h_child\nvoid update_d_max_remove(int u, int h_child) {\n    int curr = u;\n    int h = h_child;\n    while (curr != -1) {\n        if (cnt_h[curr][h] > 0) cnt_h[curr][h]--;\n        \n        bool shape_changed = false;\n        // If the removed height was defining the max height\n        if (h + 1 == d_max[curr]) {\n            if (cnt_h[curr][h] == 0) {\n                // Find new max\n                int new_max = 0;\n                for (int k = h - 1; k >= 0; --k) {\n                    if (cnt_h[curr][k] > 0) {\n                        new_max = k + 1;\n                        break;\n                    }\n                }\n                d_max[curr] = new_max;\n                shape_changed = true;\n            }\n        }\n        \n        if (shape_changed) {\n            int next_p = p[curr];\n            if (next_p != -1) {\n                // 'curr' height reduced.\n                // We need to add the NEW height to parent, and continue loop to remove OLD height.\n                // Add new height stats:\n                update_d_max_add(next_p, d_max[curr]);\n                \n                // Prepare to remove old height from parent in next iteration\n                h = h + 1; // old d_max was h+1\n                curr = next_p;\n            } else {\n                break;\n            }\n        } else {\n            // Max height didn't change\n            break;\n        }\n    }\n}\n\n// Calculate total score\nlong long calc_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        int h = 0;\n        int curr = p[i];\n        while(curr != -1) {\n            h++;\n            curr = p[curr];\n        }\n        score += (long long)(h + 1) * A[i];\n    }\n    return score;\n}\n\n// Initialize state\nvoid init_state() {\n    for (int i = 0; i < N; ++i) {\n        p[i] = -1;\n        S[i] = A[i];\n        d_max[i] = 0;\n        for(int k=0; k<=H_LIMIT+1; ++k) cnt_h[i][k] = 0;\n    }\n}\n\nint main() {\n    // Fast IO\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    if (!(cin >> N >> M >> H_in)) return 0;\n    for(int i=0; i<N; ++i) cin >> A[i];\n    for(int i=0; i<M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for(int i=0; i<N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    // Best solution tracking\n    vector<int> best_p(N);\n    long long best_score = -1;\n    \n    // Multiple Greedy Starts\n    // We sort by A, but we can introduce slight noise to order for diversity\n    int num_greedy_tries = 20;\n    \n    for (int t = 0; t < num_greedy_tries; ++t) {\n        init_state();\n        \n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        \n        if (t == 0) {\n            // Deterministic sort\n            sort(order.begin(), order.end(), [&](int a, int b){\n                return A[a] < A[b];\n            });\n        } else {\n            // Noisy sort\n            vector<double> noisy_A(N);\n            for(int i=0; i<N; ++i) noisy_A[i] = A[i] + (rng() % 100) * 0.01;\n            sort(order.begin(), order.end(), [&](int a, int b){\n                return noisy_A[a] < noisy_A[b];\n            });\n        }\n        \n        // Construct\n        for (int v : order) {\n            int best_u = -1;\n            int best_depth = 0; // Depth if root\n            \n            // Current v is root. d_max[v] is 0 (since it has no children yet in this process? \n            // Wait, we are building incrementally. v is a root of a single node tree initially.\n            // No, in init_state everyone is root. \n            // But as we link, trees merge.\n            // When we process v, v might already have children from previous steps \n            // (nodes processed earlier that attached to v).\n            // So d_max[v] is valid.\n            \n            vector<int> candidates = adj[v];\n            shuffle(candidates.begin(), candidates.end(), rng);\n            \n            for (int u : candidates) {\n                if (is_descendant(u, v)) continue;\n                \n                int depth_u = get_depth(u); // 0-based depth of u\n                // If we attach v to u, v's new depth is depth_u + 1.\n                // Check height constraint: new_depth + d_max[v] <= H\n                if (depth_u + 1 + d_max[v] <= H_LIMIT) {\n                    if (depth_u + 1 > best_depth) {\n                        best_depth = depth_u + 1;\n                        best_u = u;\n                    }\n                }\n            }\n            \n            if (best_u != -1) {\n                p[v] = best_u;\n                update_S_up(best_u, S[v]);\n                update_d_max_add(best_u, d_max[v]);\n            }\n        }\n        \n        long long current_score = calc_score();\n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) best_p[i] = p[i];\n        }\n    }\n    \n    // Restore best greedy solution for SA\n    init_state();\n    for(int i=0; i<N; ++i) {\n        p[i] = best_p[i];\n    }\n    // Rebuild S and d_max/cnt_h\n    // Since order matters for d_max update (children before parents), \n    // and p array defines a forest, we can rebuild by processing by depth (deep to shallow) or just naive N passes?\n    // Better: rebuild from scratch using p.\n    // Compute depths\n    vector<int> depths(N);\n    vector<vector<int>> nodes_by_depth(H_LIMIT + 2);\n    for(int i=0; i<N; ++i) {\n        depths[i] = get_depth(i); // p is set\n        if(depths[i] > H_LIMIT) depths[i] = H_LIMIT + 1; // Should not happen\n        nodes_by_depth[depths[i]].push_back(i);\n    }\n    // Process bottom up\n    for (int d = H_LIMIT; d >= 0; --d) {\n        for (int u : nodes_by_depth[d]) {\n            S[u] = A[u];\n            d_max[u] = 0;\n            // Add children stats\n            // This requires knowing children.\n            // We don't have children lists.\n            // Simple way: iterate all nodes, find children of u.\n            // N^2 is fine once.\n            for(int c=0; c<N; ++c) {\n                if (p[c] == u) {\n                    S[u] += S[c];\n                    cnt_h[u][d_max[c]]++;\n                    d_max[u] = max(d_max[u], d_max[c] + 1);\n                }\n            }\n        }\n    }\n    \n    // Simulated Annealing\n    double time_limit = 1.98;\n    double T_start = 150.0;\n    double T_end = 0.1;\n    \n    int iter = 0;\n    \n    while (true) {\n        iter++;\n        if ((iter & 1023) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        \n        // Pick random node v\n        int v = rng() % N;\n        int old_p = p[v];\n        \n        // Pick new parent u\n        int u = -1;\n        if (!adj[v].empty()) {\n            // Uniform choice from neighbors + {-1}\n            // To favor -1 less, maybe 1/(deg+5)?\n            int idx = rng() % (adj[v].size() + 1);\n            if (idx < (int)adj[v].size()) u = adj[v][idx];\n        }\n        \n        if (u == old_p) continue;\n        \n        // 1. Cycle Check\n        // Optimization: If depth[u] < depth[v], u cannot be descendant (unless u is not in v's tree at all, which is allowed)\n        // Wait, depth logic is valid for rejecting descendants.\n        // Descendant depth > ancestor depth.\n        // So if depth[u] <= depth[v], u is NOT a descendant (safe).\n        // If u == -1, safe.\n        int depth_v = -1; // Compute only if needed\n        int depth_u = -1;\n        \n        if (u != -1) {\n            // Need check\n            // Calculate depth on fly\n            depth_v = get_depth(v); // O(H)\n            depth_u = get_depth(u); // O(H)\n            \n            if (depth_u > depth_v) {\n                if (is_descendant(u, v)) continue;\n            } else if (depth_u == depth_v) {\n                if (u == v) continue; // self loop\n                // Else safe (u not descendant)\n            }\n            // If depth_u < depth_v, u is definitely not descendant.\n        }\n        \n        // 2. Height Constraint\n        // new_depth_v = depth_u + 1\n        // check: depth_u + 1 + d_max[v] <= H\n        int new_depth_v = (u == -1) ? 0 : (depth_u != -1 ? depth_u : get_depth(u)) + 1;\n        if (new_depth_v + d_max[v] > H_LIMIT) continue;\n        \n        // 3. Score Delta\n        // Gain = (new_depth_v - old_depth_v) * S[v]\n        int old_depth_v = (depth_v != -1) ? depth_v : get_depth(v);\n        long long diff = (long long)(new_depth_v - old_depth_v) * S[v];\n        \n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            double progress = elapsed / time_limit;\n            double T = T_start * pow(T_end / T_start, progress);\n            if (generate_canonical<double, 10>(rng) < exp(diff / T)) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            // Execute Move\n            // 1. Remove from old parent\n            if (old_p != -1) {\n                update_S_up(old_p, -S[v]);\n                update_d_max_remove(old_p, d_max[v]);\n            }\n            \n            // 2. Link to new parent\n            p[v] = u;\n            \n            // 3. Add to new parent\n            if (u != -1) {\n                update_S_up(u, S[v]);\n                update_d_max_add(u, d_max[v]);\n            }\n        }\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << p[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <array>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_OPS = 4 * N * N; // 1600\nconst int INF = 1e9;\n\n// Directions: 0: L, 1: R, 2: U, 3: D\nconst char DIR_CHARS[] = {'L', 'R', 'U', 'D'};\n\nstruct Move {\n    char d;\n    int p; // row or column index\n};\n\nstruct State {\n    array<string, N> board;\n    vector<Move> history;\n    int score; // Heuristic score (lower is better)\n    int cost;  // Number of moves so far\n    int removed_oni; // Number of Oni removed\n\n    // For sorting in priority queue or sort function\n    bool operator>(const State& other) const {\n        return score > other.score;\n    }\n};\n\n// Helper to calculate distance to edge for a specific cell and direction\n// Returns -1 if blocked by 'o'\nint get_dist(const array<string, N>& board, int r, int c, int dir) {\n    if (dir == 0) { // L\n        for (int k = 0; k < c; ++k) if (board[r][k] == 'o') return -1;\n        return c + 1;\n    } else if (dir == 1) { // R\n        for (int k = c + 1; k < N; ++k) if (board[r][k] == 'o') return -1;\n        return N - c;\n    } else if (dir == 2) { // U\n        for (int k = 0; k < r; ++k) if (board[k][c] == 'o') return -1;\n        return r + 1;\n    } else { // D\n        for (int k = r + 1; k < N; ++k) if (board[k][c] == 'o') return -1;\n        return N - r;\n    }\n}\n\n// Calculate heuristic score\n// Heuristic = Sum of min_dist for all remaining Oni + Penalties\nint calculate_heuristic(const array<string, N>& board) {\n    int total_dist = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 'x') {\n                int min_d = INF;\n                int blocked_cnt = 0;\n                for (int d = 0; d < 4; ++d) {\n                    int dist = get_dist(board, r, c, d);\n                    if (dist != -1) {\n                        if (dist < min_d) min_d = dist;\n                    } else {\n                        blocked_cnt++;\n                    }\n                }\n                if (min_d == INF) {\n                    total_dist += 200; // Heavy penalty if blocked in all directions\n                } else {\n                    total_dist += min_d;\n                }\n                total_dist += blocked_cnt * 2; // Penalty for reduced options\n            }\n        }\n    }\n    return total_dist;\n}\n\n// Apply shift to the board\nvoid apply_shift(array<string, N>& board, int type, int idx) {\n    if (type == 0) { // L\n        for (int j = 0; j < N - 1; ++j) board[idx][j] = board[idx][j+1];\n        board[idx][N-1] = '.';\n    } else if (type == 1) { // R\n        for (int j = N - 1; j > 0; --j) board[idx][j] = board[idx][j-1];\n        board[idx][0] = '.';\n    } else if (type == 2) { // U\n        for (int i = 0; i < N - 1; ++i) board[i][idx] = board[i+1][idx];\n        board[N-1][idx] = '.';\n    } else { // D\n        for (int i = N - 1; i > 0; --i) board[i][idx] = board[i-1][idx];\n        board[0][idx] = '.';\n    }\n}\n\n// Count Oni on the board\nint count_oni(const array<string, N>& board) {\n    int c = 0;\n    for (const auto& row : board) \n        for (char ch : row) if (ch == 'x') c++;\n    return c;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    if (cin >> n_dummy) {} \n\n    State initial_state;\n    initial_state.cost = 0;\n    for (int i = 0; i < N; ++i) cin >> initial_state.board[i];\n    \n    int initial_total_oni = count_oni(initial_state.board);\n    initial_state.removed_oni = 0; \n    initial_state.score = calculate_heuristic(initial_state.board);\n\n    // Beam search organized by number of removed Oni\n    // beams[k] holds states with k Oni removed\n    vector<vector<State>> beams(2 * N + 1);\n    beams[0].push_back(initial_state);\n\n    int BEAM_WIDTH = 30; \n\n    // Iterate through progress levels\n    for (int k = 0; k < initial_total_oni; ++k) {\n        if (beams[k].empty()) continue;\n        \n        // Sort by score (lower is better) and keep top BEAM_WIDTH\n        sort(beams[k].begin(), beams[k].end(), [](const State& a, const State& b){\n            return a.score < b.score;\n        });\n        if (beams[k].size() > BEAM_WIDTH) {\n            beams[k].resize(BEAM_WIDTH);\n        }\n        \n        for (const auto& state : beams[k]) {\n            // Try all directions and lines\n            for (int dir = 0; dir < 4; ++dir) {\n                for (int line = 0; line < N; ++line) {\n                    // Calculate safe shift limit\n                    int max_safe = 0;\n                    int first_fuku = -1;\n                    \n                    if (dir == 0) { // L\n                        for(int c=0; c<N; ++c) if(state.board[line][c] == 'o') { first_fuku = c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=0; --c) if(state.board[line][c] == 'o') { first_fuku = (N-1)-c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<N; ++r) if(state.board[r][line] == 'o') { first_fuku = r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else { // D\n                        for(int r=N-1; r>=0; --r) if(state.board[r][line] == 'o') { first_fuku = (N-1)-r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    }\n                    \n                    if (max_safe == 0) continue;\n                    \n                    // Identify Oni positions that can be removed\n                    vector<int> oni_shifts;\n                    if (dir == 0) { // L\n                        for(int c=0; c<max_safe; ++c) if(state.board[line][c] == 'x') oni_shifts.push_back(c + 1);\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=N-max_safe; --c) if(state.board[line][c] == 'x') oni_shifts.push_back((N-1)-c + 1);\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<max_safe; ++r) if(state.board[r][line] == 'x') oni_shifts.push_back(r + 1);\n                    } else { // D\n                        for(int r=N-1; r>=N-max_safe; --r) if(state.board[r][line] == 'x') oni_shifts.push_back((N-1)-r + 1);\n                    }\n                    \n                    if (oni_shifts.empty()) continue;\n\n                    // Only consider:\n                    // 1. Shift to remove the FIRST Oni (minimal progress)\n                    // 2. Shift to remove the LAST safe Oni (maximal progress in this line)\n                    vector<int> candidates;\n                    candidates.push_back(oni_shifts[0]);\n                    if (oni_shifts.back() != oni_shifts[0]) {\n                        candidates.push_back(oni_shifts.back());\n                    }\n\n                    for (int shift_amt : candidates) {\n                        // Option 1: Eject (Permanent Change)\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            next_state.cost += shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                        \n                        // Option 2: Eject & Restore (Safe fallback)\n                        // Costs 2x but preserves board structure\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            int opp_dir = (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? 3 : 2;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, opp_dir, line);\n                                next_state.history.push_back({DIR_CHARS[opp_dir], line});\n                            }\n                            next_state.cost += 2 * shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Select best solution from states that removed all Oni\n    int final_idx = initial_total_oni;\n    // Fallback to best available if full solution not found\n    while (final_idx >= 0 && beams[final_idx].empty()) {\n        final_idx--;\n    }\n    \n    State* best = nullptr;\n    if (final_idx >= 0) {\n        for (auto& s : beams[final_idx]) {\n            if (!best || s.cost < best->cost) {\n                best = &s;\n            }\n        }\n    }\n    \n    if (best) {\n        for (const auto& mv : best->history) {\n            cout << mv.d << \" \" << mv.p << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <queue>\n\nusing namespace std;\n\nconst int N = 100;\nconst int L_TOTAL = 500000;\n\nint T[N];\nint A[N], B[N];\nint best_A[N], best_B[N];\n\n// Simulation variables\nint counts_sim[N];\n\n// Function to run the simulation\n// Returns the sum of absolute errors\nlong long simulate(int steps, const vector<int>& targets, int* counts_out) {\n    // Reset counts\n    for(int i=0; i<N; ++i) counts_out[i] = 0;\n    \n    int curr = 0;\n    counts_out[0]++;\n    \n    // Simulate step by step\n    for (int k = 1; k < steps; ++k) {\n        int prev = curr;\n        // Get the number of times prev had cleaned by the end of last week\n        int t = counts_out[prev];\n        if (t & 1) { // odd\n            curr = A[prev];\n        } else { // even\n            curr = B[prev];\n        }\n        counts_out[curr]++;\n    }\n    \n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts_out[i] - targets[i]);\n    }\n    return error;\n}\n\nstruct Plug {\n    int u;\n    int type; // 0 for A, 1 for B\n    int size; // Estimated flow\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, l_in;\n    if (cin >> n_in >> l_in) {} // Read N and L\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // --- Initial Construction Phase ---\n    // Use a greedy bin-packing strategy to assign A[i] and B[i]\n    // such that the expected inflow to each node j matches T[j].\n    \n    vector<Plug> plugs;\n    for (int i = 0; i < N; ++i) {\n        // If T[i] > 0, this employee will clean and thus trigger a transition.\n        // The transitions alternate between A[i] (odd visits) and B[i] (even visits).\n        // Number of odd visits is ceil(T[i]/2), even is floor(T[i]/2).\n        if (T[i] > 0) {\n            plugs.push_back({i, 0, (T[i] + 1) / 2});\n            if (T[i] > 1) plugs.push_back({i, 1, T[i] / 2});\n        }\n    }\n    \n    // Sort plugs descending by size to fit largest flow requirements first\n    sort(plugs.begin(), plugs.end(), [](const Plug& a, const Plug& b){\n        return a.size > b.size;\n    });\n    \n    // Priority Queue for sockets (nodes receiving flow)\n    // Stores {remaining_capacity, node_index}\n    // Start node 0 has 1 automatic visit, so its capacity for incoming edges is T[0] - 1.\n    priority_queue<pair<int, int>> pq;\n    for (int i = 0; i < N; ++i) {\n        int cap = T[i];\n        if (i == 0) cap = max(0, cap - 1);\n        // Only consider nodes that are expected to be visited\n        if (cap > 0 || (i == 0 && T[0] > 0)) pq.push({cap, i});\n    }\n    \n    // Initialize A and B to valid values (defaults)\n    for(int i=0; i<N; ++i) { \n        A[i] = (i + 1) % N; \n        B[i] = (i + 1) % N; \n    }\n\n    // Assign plugs to sockets\n    for (const auto& p : plugs) {\n        int target = 0;\n        if (!pq.empty()) {\n            auto top = pq.top();\n            pq.pop();\n            target = top.second;\n            // Decrease capacity\n            int rem = top.first - p.size;\n            // Push back with updated capacity. \n            // We allow negative capacity (overflow) to handle total flow matching.\n            pq.push({rem, target}); \n        } else {\n            target = rand() % N;\n        }\n        \n        if (p.type == 0) A[p.u] = target;\n        else B[p.u] = target;\n    }\n    \n    // Save initial solution\n    copy(begin(A), end(A), begin(best_A));\n    copy(begin(B), end(B), begin(best_B));\n    \n    // --- Optimization Phase ---\n    // Use Simulated Annealing / Hill Climbing to minimize error.\n    // We gradually increase the simulation length from a small value to L_TOTAL.\n    \n    mt19937 rng(12345);\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.90; // Slightly less than 2.0s\n    \n    int current_L = 10000; // Start with shorter simulation\n    vector<int> current_T(N);\n    \n    long long current_score = -1;\n    long long global_best_score_full = -1; \n\n    double temp = 150.0; // Initial temperature\n    bool counts_valid = false; // Tracks if counts_sim matches current A/B\n    \n    while (true) {\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        double progress = elapsed.count() / time_limit;\n        \n        // Adaptive Simulation Length\n        int next_L;\n        if (progress < 0.35) next_L = 20000;\n        else if (progress < 0.65) next_L = 100000;\n        else next_L = L_TOTAL;\n        \n        bool l_changed = (next_L != current_L);\n        if (l_changed || current_score == -1) {\n            current_L = next_L;\n            // Scale target counts T for the current length\n            long long sum = 0;\n            for(int i=0; i<N; ++i) {\n                current_T[i] = (long long)T[i] * current_L / L_TOTAL;\n                sum += current_T[i];\n            }\n            // Adjust rounding errors to ensure sum equals current_L\n            while(sum < current_L) {\n                int idx = rng() % N;\n                if (T[idx] > 0) { current_T[idx]++; sum++; }\n            }\n            while(sum > current_L) {\n                int idx = rng() % N;\n                if (current_T[idx] > 0) { current_T[idx]--; sum--; }\n            }\n            // Re-evaluate current configuration with new length\n            current_score = simulate(current_L, current_T, counts_sim);\n            counts_valid = true;\n        }\n        \n        // Temperature decay\n        double cur_temp = temp * (1.0 - progress) * (1.0 - progress);\n        if (cur_temp < 0.5) cur_temp = 0.5;\n        \n        // Generate Move\n        // We store undo information to revert if rejected\n        vector<tuple<int, int, int>> undo;\n        \n        // Move Types:\n        // 1. Directed Redirect: Move a plug from a surplus node to a deficit node.\n        // 2. Swap: Swap destinations of two plugs.\n        // 3. Random Redirect: Randomly change a plug's destination.\n        \n        int move_type = rng() % 100;\n        bool directed_possible = false;\n\n        if (move_type < 65 && counts_valid) { \n            // Directed Redirect Strategy\n            vector<int> sur, def;\n            for(int i=0; i<N; ++i) {\n                if (counts_sim[i] > current_T[i]) sur.push_back(i);\n                if (counts_sim[i] < current_T[i]) def.push_back(i);\n            }\n            \n            if (!sur.empty() && !def.empty()) {\n                int v = def[rng() % def.size()]; // Target (Deficit)\n                int u = sur[rng() % sur.size()]; // Source (Surplus)\n                \n                // Find plugs pointing to u\n                vector<pair<int,int>> candidates;\n                for(int i=0; i<N; ++i) {\n                    if (A[i] == u) candidates.push_back({i, 0});\n                    if (B[i] == u) candidates.push_back({i, 1});\n                }\n                \n                if (!candidates.empty()) {\n                    auto cand = candidates[rng() % candidates.size()];\n                    int node = cand.first;\n                    int type = cand.second;\n                    int old_val = (type==0 ? A[node] : B[node]);\n                    \n                    // Don't move if already pointing to v\n                    if (old_val != v) {\n                        undo.emplace_back(node, type, old_val);\n                        if (type==0) A[node] = v; else B[node] = v;\n                        directed_possible = true;\n                    }\n                }\n            }\n        } \n        \n        if (!directed_possible) {\n            if (move_type < 85) { // Swap Move\n                int u1 = rng() % N; int t1 = rng() % 2;\n                int u2 = rng() % N; int t2 = rng() % 2;\n                int v1 = (t1==0 ? A[u1] : B[u1]);\n                int v2 = (t2==0 ? A[u2] : B[u2]);\n                if (v1 != v2) {\n                    undo.emplace_back(u1, t1, v1);\n                    undo.emplace_back(u2, t2, v2);\n                    if (t1==0) A[u1] = v2; else B[u1] = v2;\n                    if (t2==0) A[u2] = v1; else B[u2] = v1;\n                }\n            } else { // Random Redirect Move\n                int u = rng() % N;\n                int t = rng() % 2;\n                int v = rng() % N;\n                int old = (t==0 ? A[u] : B[u]);\n                if (old != v) {\n                    undo.emplace_back(u, t, old);\n                    if (t==0) A[u] = v; else B[u] = v;\n                }\n            }\n        }\n        \n        if (undo.empty()) continue;\n        \n        // Evaluate\n        long long new_score = simulate(current_L, current_T, counts_sim);\n        long long delta = new_score - current_score;\n        \n        // Acceptance Criteria\n        bool accept = false;\n        if (delta <= 0) accept = true;\n        else {\n             if (generate_canonical<double, 10>(rng) < exp(-delta/cur_temp)) accept = true;\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            counts_valid = true; // counts_sim is valid for current A/B\n            \n            // Update global best if we are simulating the full problem\n            if (current_L == L_TOTAL) {\n                if (global_best_score_full == -1 || current_score < global_best_score_full) {\n                    global_best_score_full = current_score;\n                    copy(begin(A), end(A), begin(best_A));\n                    copy(begin(B), end(B), begin(best_B));\n                }\n            } else {\n                // Keep track of the best configuration found so far\n                copy(begin(A), end(A), begin(best_A));\n                copy(begin(B), end(B), begin(best_B));\n            }\n        } else {\n            // Revert changes\n            for (auto it = undo.rbegin(); it != undo.rend(); ++it) {\n                auto [u, t, v] = *it;\n                if (t==0) A[u] = v; else B[u] = v;\n            }\n            // counts_sim contains counts from the rejected simulation.\n            // It is invalid for the current (reverted) state.\n            counts_valid = false;\n        }\n    }\n\n    // Output the best solution found\n    for (int i = 0; i < N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <set>\n#include <array>\n\nusing namespace std;\n\n// Global Constants & Inputs\nint N, M, Q, L, W;\nvector<int> G;\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    int x, y; \n};\nvector<City> cities;\nvector<int> city_group; // city_id -> group_index\nvector<vector<int>> groups;\n\n// Geometry\nlong long dist_sq(int i, int j) {\n    long long dx = cities[i].x - cities[j].x;\n    long long dy = cities[i].y - cities[j].y;\n    return dx * dx + dy * dy;\n}\n\n// Precomputed Data\nstruct Edge {\n    int u, v;\n    long long w; // squared dist\n    double sqrt_w;\n};\nvector<Edge> global_knn_edges;\nvector<vector<int>> knn_neighbors; // for guided swap\nconst int K_NN = 16;\nconst int DENSE_THRESHOLD = 50; // If group size > this, try sparse first\n\n// DSU for MST\nstruct DSU {\n    vector<int> p;\n    DSU(int n) : p(n, -1) {}\n    void reset() { fill(p.begin(), p.end(), -1); } \n    int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (p[x] > p[y]) swap(x, y);\n        p[x] += p[y];\n        p[y] = x;\n        return true;\n    }\n    int size(int x) { return -p[find(x)]; }\n};\n\n// Hilbert Curve for spatial sorting\nlong long hilbert(int x, int y, int pow, int rotate) {\n    if (pow == 0) return 0;\n    int hpow = 1 << (pow - 1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rotate) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rotate + rotateDelta[seg]) & 3;\n    long long subSquareSize = 1LL << (2 * pow - 2);\n    long long ans = seg * subSquareSize;\n    long long add = hilbert(nx, ny, pow - 1, nrot);\n    ans += (seg == 1 || seg == 2) ? add : (subSquareSize - 1 - add);\n    return ans;\n}\n\n// Dense MST (Prim's)\ndouble compute_dense_mst(const vector<int>& grp) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    vector<long long> min_dist(k, 4e18);\n    vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    double total = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        long long cur_min = 4e18;\n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur_min) {\n                cur_min = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        if(i > 0) total += sqrt(cur_min);\n        \n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                long long d = dist_sq(city_u, grp[v]);\n                if(d < min_dist[v]) min_dist[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\n// Sparse MST (Kruskal on global KNN edges)\n// Returns -1.0 if disconnected\nDSU global_dsu(805); \ndouble compute_sparse_mst(const vector<int>& grp, int group_idx) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    global_dsu.reset();\n    \n    int edges_count = 0;\n    double total = 0;\n    \n    // global_knn_edges is sorted by weight\n    for (const auto& e : global_knn_edges) {\n        if (city_group[e.u] == group_idx && city_group[e.v] == group_idx) {\n            if (global_dsu.unite(e.u, e.v)) {\n                total += e.sqrt_w;\n                edges_count++;\n                if (edges_count == k - 1) return total;\n            }\n        }\n    }\n    \n    // Check connectivity\n    // Just checking edges_count == k-1 is sufficient for tree in DSU\n    // But we might have formed a forest if KNN graph doesn't fully connect the group\n    if (edges_count < k - 1) return -1.0;\n    \n    return total;\n}\n\ndouble get_group_cost(const vector<int>& grp, int group_idx) {\n    if (grp.size() <= DENSE_THRESHOLD) {\n        return compute_dense_mst(grp);\n    } else {\n        double res = compute_sparse_mst(grp, group_idx);\n        if (res < 0) return compute_dense_mst(grp);\n        return res;\n    }\n}\n\n// MST Edge Retrieval for Output\nvector<pair<int, int>> get_mst_edges(const vector<int>& grp) {\n    if (grp.size() <= 1) return {};\n    int k = grp.size();\n    vector<long long> min_dist(k, 4e18);\n    vector<int> parent(k, -1);\n    vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        long long cur = 4e18;\n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur) {\n                cur = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                long long d = dist_sq(city_u, grp[v]);\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    vector<pair<int, int>> edges;\n    for(int i=1; i<k; ++i) {\n        if(parent[i] != -1) edges.push_back({grp[i], grp[parent[i]]});\n    }\n    return edges;\n}\n\n// Query Logic\nvector<int> rem_nodes;\nvector<vector<int>> planned_queries;\nvector<vector<int>> adj;\n\nvoid dfs_query(int u, int p) {\n    int subtree_start = rem_nodes.size();\n    for (int v : adj[u]) {\n        if (v == p) continue;\n        dfs_query(v, u);\n    }\n    rem_nodes.push_back(u);\n    \n    int count = rem_nodes.size() - subtree_start;\n    while (count >= L) {\n        vector<int> q;\n        q.push_back(u); \n        for (int i = 0; i < L - 1; ++i) {\n            q.push_back(rem_nodes[subtree_start]);\n            rem_nodes.erase(rem_nodes.begin() + subtree_start);\n        }\n        planned_queries.push_back(q);\n        count -= (L - 1);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].x = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].y = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // Precompute Distances and KNN\n    vector<vector<pair<long long, int>>> dists(N, vector<pair<long long, int>>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            dists[i][j] = {dist_sq(i, j), j};\n        }\n        nth_element(dists[i].begin(), dists[i].begin() + min(N, K_NN + 1), dists[i].end());\n    }\n\n    knn_neighbors.resize(N);\n    set<pair<int, int>> added_edges;\n    for(int i=0; i<N; ++i) {\n        for(int k=1; k<=K_NN && k < N; ++k) {\n            int j = dists[i][k].second;\n            long long d = dists[i][k].first;\n            knn_neighbors[i].push_back(j);\n            int u = min(i, j), v = max(i, j);\n            if(added_edges.find({u, v}) == added_edges.end()) {\n                added_edges.insert({u, v});\n                global_knn_edges.push_back({u, v, d, sqrt(d)});\n            }\n        }\n    }\n    sort(global_knn_edges.begin(), global_knn_edges.end(), [](const Edge& a, const Edge& b){\n        return a.w < b.w;\n    });\n\n    // Initial Grouping\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int i, int j) {\n        return hilbert(cities[i].x, cities[i].y, 14, 0) < hilbert(cities[j].x, cities[j].y, 14, 0);\n    });\n\n    groups.resize(M);\n    city_group.resize(N);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        for (int k = 0; k < G[i]; ++k) {\n            int u = p[current_idx++];\n            groups[i].push_back(u);\n            city_group[u] = i;\n        }\n    }\n\n    // SA\n    vector<double> group_costs(M);\n    double total_cost = 0;\n    for(int i=0; i<M; ++i) {\n        group_costs[i] = get_group_cost(groups[i], i);\n        total_cost += group_costs[i];\n    }\n\n    mt19937 rng(42);\n    double time_limit = 1.75; \n    double start_temp = 500.0;\n    \n    int iter = 0;\n    while(true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        int u = uniform_int_distribution<int>(0, N - 1)(rng);\n        int g1 = city_group[u];\n        int g2 = -1;\n        int v = -1;\n\n        // Guided selection\n        bool guided = false;\n        if (uniform_real_distribution<double>(0, 1)(rng) < 0.7) {\n            for (int neighbor : knn_neighbors[u]) {\n                if (city_group[neighbor] != g1) {\n                    g2 = city_group[neighbor];\n                    guided = true;\n                    break; \n                }\n            }\n            if (guided) {\n                int idx_v = uniform_int_distribution<int>(0, groups[g2].size() - 1)(rng);\n                v = groups[g2][idx_v];\n            }\n        }\n\n        if (!guided) {\n            g2 = uniform_int_distribution<int>(0, M - 1)(rng);\n            if (g1 == g2) continue;\n            if (groups[g1].empty() || groups[g2].empty()) continue; \n            int idx_v = uniform_int_distribution<int>(0, groups[g2].size() - 1)(rng);\n            v = groups[g2][idx_v];\n        }\n\n        auto it_u = find(groups[g1].begin(), groups[g1].end(), u);\n        auto it_v = find(groups[g2].begin(), groups[g2].end(), v);\n        \n        *it_u = v;\n        *it_v = u;\n        city_group[u] = g2;\n        city_group[v] = g1;\n\n        double new_cost_g1 = get_group_cost(groups[g1], g1);\n        double new_cost_g2 = get_group_cost(groups[g2], g2);\n        \n        double diff = (new_cost_g1 + new_cost_g2) - (group_costs[g1] + group_costs[g2]);\n        \n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n        double temp = start_temp * (1.0 - elapsed / time_limit);\n        if (temp < 1e-9) temp = 1e-9;\n\n        if (diff < 0 || bernoulli_distribution(exp(-diff / temp))(rng)) {\n            total_cost += diff;\n            group_costs[g1] = new_cost_g1;\n            group_costs[g2] = new_cost_g2;\n        } else {\n            *it_u = u;\n            *it_v = v;\n            city_group[u] = g1;\n            city_group[v] = g2;\n        }\n    }\n\n    // Query Planning\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if ((int)groups[i].size() <= L) {\n            planned_queries.push_back(groups[i]);\n        } else {\n            vector<pair<int, int>> mst = get_mst_edges(groups[i]);\n            adj.assign(N, {});\n            for (auto& e : mst) {\n                adj[e.first].push_back(e.second);\n                adj[e.second].push_back(e.first);\n            }\n            \n            rem_nodes.clear();\n            dfs_query(groups[i][0], -1);\n            \n            while (!rem_nodes.empty()) {\n                if ((int)rem_nodes.size() <= L) {\n                    if (rem_nodes.size() > 1) planned_queries.push_back(rem_nodes);\n                    rem_nodes.clear();\n                } else {\n                    vector<int> q;\n                    for(int k=0; k<L; ++k) q.push_back(rem_nodes[k]);\n                    planned_queries.push_back(q);\n                    rem_nodes.erase(rem_nodes.begin(), rem_nodes.begin() + L - 1);\n                }\n            }\n        }\n    }\n\n    // Execute Queries\n    shuffle(planned_queries.begin(), planned_queries.end(), rng);\n    int queries_to_run = min((int)planned_queries.size(), Q);\n    \n    vector<vector<pair<int, int>>> confirmed_edges(M);\n    \n    for(int i=0; i<queries_to_run; ++i) {\n        cout << \"? \" << planned_queries[i].size();\n        for(int c : planned_queries[i]) cout << \" \" << c;\n        cout << endl;\n        for(size_t k=0; k<planned_queries[i].size()-1; ++k) {\n            int u, v;\n            cin >> u >> v;\n            confirmed_edges[city_group[u]].push_back({u, v});\n        }\n    }\n\n    cout << \"!\" << endl;\n    for(int i=0; i<M; ++i) {\n        for(size_t k=0; k<groups[i].size(); ++k) {\n            cout << groups[i][k] << (k==groups[i].size()-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n        \n        vector<pair<double, pair<int, int>>> all_edges;\n        for(auto& e : confirmed_edges[i]) {\n            all_edges.push_back({-1.0, e}); \n        }\n        \n        vector<pair<int, int>> est_mst = get_mst_edges(groups[i]);\n        for(auto& e : est_mst) {\n            double w = sqrt(dist_sq(e.first, e.second));\n            all_edges.push_back({w, e});\n        }\n        \n        sort(all_edges.begin(), all_edges.end());\n        \n        global_dsu.reset(); \n        \n        vector<pair<int, int>> final_roads;\n        int edges_needed = groups[i].size() - 1;\n        int edges_added = 0;\n        \n        for(auto& item : all_edges) {\n            int u = item.second.first;\n            int v = item.second.second;\n            if(global_dsu.unite(u, v)) {\n                final_roads.push_back({u, v});\n                edges_added++;\n                if (edges_added == edges_needed) break;\n            }\n        }\n        \n        for(auto& e : final_roads) {\n            cout << e.first << \" \" << e.second << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <map>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const { return tie(r, c) < tie(other.r, other.c); }\n};\n\nstruct State {\n    int dist;\n    int r, c;\n    bool operator>(const State& other) const { return dist > other.dist; }\n};\n\nstruct Action {\n    char type; // 'M', 'S', 'A'\n    char dir;  // 'U', 'D', 'L', 'R'\n};\n\nPoint start_pos;\nbool grid[N][N]; // true if block present\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_chars[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Simulate sliding from (r, c) in direction d\nPoint get_slide_end(int r, int c, int d, const bool current_grid[N][N]) {\n    int cr = r, cc = c;\n    while (true) {\n        int nr = cr + dr[d];\n        int nc = cc + dc[d];\n        if (!is_valid(nr, nc) || current_grid[nr][nc]) {\n            return {cr, cc};\n        }\n        cr = nr;\n        cc = nc;\n    }\n}\n\nstruct Node {\n    int dist = 1e9;\n    Point parent = {-1, -1};\n    Action action = {' ', ' '};\n    bool break_block = false; // If true, action was Move into block (breaking it)\n};\n\n// Run Dijkstra from start_p with current grid\nvoid run_dijkstra(Point start_p, const bool current_grid[N][N], Node nodes[N][N]) {\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) nodes[i][j] = Node();\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    nodes[start_p.r][start_p.c].dist = 0;\n    pq.push({0, start_p.r, start_p.c});\n\n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        int r = top.r;\n        int c = top.c;\n        int d = top.dist;\n\n        if (d > nodes[r][c].dist) continue;\n\n        // Moves & Breaks\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k];\n            int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int cost = 1;\n                bool is_break = false;\n                if (current_grid[nr][nc]) {\n                    cost = 2;\n                    is_break = true;\n                }\n                if (nodes[nr][nc].dist > d + cost) {\n                    nodes[nr][nc].dist = d + cost;\n                    nodes[nr][nc].parent = {r, c};\n                    nodes[nr][nc].action = {'M', dir_chars[k]};\n                    nodes[nr][nc].break_block = is_break;\n                    pq.push({nodes[nr][nc].dist, nr, nc});\n                }\n            }\n        }\n\n        // Slides\n        for (int k = 0; k < 4; ++k) {\n            Point end_p = get_slide_end(r, c, k, current_grid);\n            if (end_p.r != r || end_p.c != c) {\n                if (nodes[end_p.r][end_p.c].dist > d + 1) {\n                    nodes[end_p.r][end_p.c].dist = d + 1;\n                    nodes[end_p.r][end_p.c].parent = {r, c};\n                    nodes[end_p.r][end_p.c].action = {'S', dir_chars[k]};\n                    nodes[end_p.r][end_p.c].break_block = false;\n                    pq.push({nodes[end_p.r][end_p.c].dist, end_p.r, end_p.c});\n                }\n            }\n        }\n    }\n}\n\nvector<Action> reconstruct_path(Point start_p, Point end_p, Node nodes[N][N], vector<Point>& path_points) {\n    vector<Action> path;\n    Point cur = end_p;\n    while (cur != start_p) {\n        Node& n = nodes[cur.r][cur.c];\n        path_points.push_back(cur);\n        if (n.break_block) {\n            path.push_back({'M', n.action.dir});\n            path.push_back({'A', n.action.dir});\n        } else {\n            path.push_back(n.action);\n        }\n        cur = n.parent;\n    }\n    path_points.push_back(start_p);\n    reverse(path.begin(), path.end());\n    reverse(path_points.begin(), path_points.end());\n    return path;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int _n, _m;\n    if (!(cin >> _n >> _m)) return 0;\n    \n    cin >> start_pos.r >> start_pos.c;\n    \n    vector<Point> all_points(M);\n    all_points[0] = start_pos;\n    for(int k=1; k<M; ++k) {\n        cin >> all_points[k].r >> all_points[k].c;\n    }\n\n    for(int i=0; i<N; ++i) fill(grid[i], grid[i]+N, false);\n\n    Point current_pos = start_pos;\n    \n    vector<pair<char, char>> final_actions;\n\n    for (int k = 1; k < M; ++k) {\n        Point target = all_points[k];\n        \n        // 1. Standard Dijkstra\n        static Node nodes_std[N][N];\n        run_dijkstra(current_pos, grid, nodes_std);\n        \n        int best_cost = nodes_std[target.r][target.c].dist;\n        bool use_helper = false;\n        \n        Point best_helper_B = {-1, -1};\n        Point best_helper_NB = {-1, -1};\n        Point best_helper_L = {-1, -1};\n        Node nodes_helper[N][N];\n        \n        // 2. Helper Block Strategy\n        // Try to place a block at neighbor B of Target to enable sliding\n        for (int d = 0; d < 4; ++d) {\n            int br = target.r + dr[d];\n            int bc = target.c + dc[d];\n            \n            if (!is_valid(br, bc)) continue;\n            if (grid[br][bc]) continue; \n            \n            Point B = {br, bc};\n            \n            // Need to reach a neighbor of B to place it\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int nbr = br + dr[d2];\n                int nbc = bc + dc[d2];\n                if (!is_valid(nbr, nbc)) continue;\n                \n                Point NB = {nbr, nbc};\n                int cost_to_NB = nodes_std[nbr][nbc].dist;\n                if (cost_to_NB > 1e8) continue;\n                \n                // Temporarily assume B is blocked for distance calculation from NB\n                static Node nodes_local[N][N];\n                bool saved_val = grid[br][bc];\n                grid[br][bc] = true;\n                run_dijkstra(NB, grid, nodes_local);\n                grid[br][bc] = saved_val;\n                \n                // Find valid Launch position L\n                // To hit B from L via Slide, L must be upstream.\n                // Slide direction must be 'd' (towards B).\n                // L = G - k * vec[d].\n                int opp_d;\n                if (d==0) opp_d=1; else if(d==1) opp_d=0; else if(d==2) opp_d=3; else opp_d=2;\n                \n                int curr = target.r + dr[opp_d];\n                int curc = target.c + dc[opp_d];\n                \n                while (is_valid(curr, curc)) {\n                    if (grid[curr][curc]) break; \n                    \n                    int cost_NB_L = nodes_local[curr][curc].dist;\n                    if (cost_NB_L < 1e8) {\n                        int total_helper = cost_to_NB + 1 + cost_NB_L + 1; // 1 Alter, 1 Slide\n                        if (total_helper < best_cost) {\n                            best_cost = total_helper;\n                            use_helper = true;\n                            best_helper_B = B;\n                            best_helper_NB = NB;\n                            best_helper_L = {curr, curc};\n                            for(int ii=0; ii<N; ++ii) for(int jj=0; jj<N; ++jj) nodes_helper[ii][jj] = nodes_local[ii][jj];\n                        }\n                    }\n                    curr += dr[opp_d];\n                    curc += dc[opp_d];\n                }\n            }\n        }\n\n        // 3. Execute Plan\n        auto execute_move = [&](char type, char dir, Point& pos) {\n            if (type == 'A') {\n                 int nr = pos.r, nc = pos.c;\n                 if (dir == 'U') nr--; else if (dir == 'D') nr++; else if (dir == 'L') nc--; else if (dir == 'R') nc++;\n                 if (is_valid(nr, nc)) grid[nr][nc] = !grid[nr][nc];\n            } else if (type == 'M') {\n                 if (dir == 'U') pos.r--; else if (dir == 'D') pos.r++; else if (dir == 'L') pos.c--; else if (dir == 'R') pos.c++;\n            } else if (type == 'S') {\n                 pos = get_slide_end(pos.r, pos.c, (dir=='U'?0:(dir=='D'?1:(dir=='L'?2:3))), grid);\n            }\n            final_actions.push_back({type, dir});\n        };\n\n        if (use_helper) {\n            vector<Point> pts;\n            vector<Action> p1 = reconstruct_path(current_pos, best_helper_NB, nodes_std, pts);\n            for (auto a : p1) execute_move(a.type, a.dir, current_pos);\n            \n            // Alter B\n            int d_alter = -1;\n            for(int dd=0; dd<4; ++dd) if (best_helper_NB.r + dr[dd] == best_helper_B.r && best_helper_NB.c + dc[dd] == best_helper_B.c) d_alter = dd;\n            execute_move('A', dir_chars[d_alter], current_pos);\n            \n            vector<Point> pts2;\n            vector<Action> p2 = reconstruct_path(best_helper_NB, best_helper_L, nodes_helper, pts2);\n            for (auto a : p2) execute_move(a.type, a.dir, current_pos);\n            \n            // Slide to Target\n            int d_slide = -1;\n            if (target.r > best_helper_L.r) d_slide = 1;\n            else if (target.r < best_helper_L.r) d_slide = 0;\n            else if (target.c > best_helper_L.c) d_slide = 3;\n            else d_slide = 2;\n            execute_move('S', dir_chars[d_slide], current_pos);\n\n        } else {\n            vector<Point> pts;\n            vector<Action> p = reconstruct_path(current_pos, target, nodes_std, pts);\n            for (auto a : p) execute_move(a.type, a.dir, current_pos);\n        }\n    }\n    \n    for(auto p : final_actions) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}"},"4":{"ahc001":"/**\n * Solution for AtCoder Heuristic Contest 001\n * Approach: Recursive Binary Space Partitioning with Tree Optimization\n * \n * Key improvements:\n * 1. Structure: Uses a Binary Space Partition (BSP) tree to guarantee a valid, gap-free initial topology.\n * 2. Construction: Randomized recursive construction that respects point constraints.\n * 3. Optimization: Instead of moving individual rectangles (which causes collisions), we optimize the \n *    split positions within the BSP tree. This adjusts the aspect ratios and areas of all descendant \n *    rectangles simultaneously while maintaining the partition integrity.\n * 4. Post-processing: Shrinks rectangles that are larger than their target area to achieve perfect local scores.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <functional>\n\nusing namespace std;\n\n// --- Constants & Globals ---\nconst int W = 10000;\nconst int H = 10000;\nconst double TIME_LIMIT = 4.90;\n\nstruct Point {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n};\n\nint N;\nvector<Point> points;\n\n// Fast Random Number Generator (Xorshift128+)\nuint64_t xorshift_state[2] = {0x123456789LL, 0x987654321LL};\ninline uint64_t xorshift() {\n    uint64_t s1 = xorshift_state[0];\n    uint64_t s0 = xorshift_state[1];\n    xorshift_state[0] = s0;\n    s1 ^= s1 << 23;\n    xorshift_state[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);\n    return xorshift_state[1] + s0;\n}\ninline int rand_int(int n) { return xorshift() % n; }\ninline double rand_double() { return (xorshift() & 0xFFFFFFFFFFF) * (1.0 / 17592186044416.0); }\n\n// --- Score Calculation ---\n// Calculates the individual satisfaction score for a company\ninline double calc_leaf_score(int r, long long s) {\n    if (s >= r) return 1.0; // We can always shrink to fit r perfectly if s >= r\n    double ratio = (double)s / r;\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// --- Partition Tree Structures ---\nstruct Node {\n    int id;      // unique node index in pool\n    bool is_leaf;\n    \n    // Leaf data\n    int p_idx;   // index in points vector\n    \n    // Internal node data\n    int child_l; // index of left/top child\n    int child_r; // index of right/bottom child\n    int axis;    // 0: vertical split (x), 1: horizontal split (y)\n    int split_pos;\n    \n    // Dynamic Bounding box (updated during optimization)\n    Rect box;\n};\n\nvector<Node> node_pool;\nint root_node_idx;\n\n// Solution storage\nstruct Solution {\n    vector<Rect> rects;\n    double score;\n};\nSolution best_sol;\n\n// --- Tree Construction ---\n\n// Allocate a new node\nint new_node() {\n    node_pool.emplace_back();\n    return node_pool.size() - 1;\n}\n\n// Recursively build the partition tree\nint build_recursive(const vector<int>& p_idxs, Rect r) {\n    int u = new_node();\n    node_pool[u].box = r;\n    \n    // Base case: only one point in this region\n    if (p_idxs.size() == 1) {\n        node_pool[u].is_leaf = true;\n        node_pool[u].p_idx = p_idxs[0];\n        node_pool[u].child_l = -1;\n        node_pool[u].child_r = -1;\n        return u;\n    }\n    \n    node_pool[u].is_leaf = false;\n    \n    long long total_r = 0;\n    for(int idx : p_idxs) total_r += points[idx].r;\n    \n    // Candidates for splitting\n    struct Cand { int axis; int pos; double cost; };\n    vector<Cand> cands;\n    cands.reserve(20); \n\n    // Function to evaluate potential splits along an axis\n    auto analyze = [&](int axis) {\n        vector<int> sorted = p_idxs;\n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n        \n        long long current_r = 0;\n        int min_coord = (axis==0) ? r.x1 : r.y1;\n        int max_coord = (axis==0) ? r.x2 : r.y2;\n        int span = max_coord - min_coord;\n        \n        // We try to split between every adjacent pair of points\n        for(size_t i=0; i<sorted.size()-1; ++i) {\n            current_r += points[sorted[i]].r;\n            \n            int p1 = (axis==0) ? points[sorted[i]].x : points[sorted[i]].y;\n            int p2 = (axis==0) ? points[sorted[i+1]].x : points[sorted[i+1]].y;\n            \n            if (p1 >= p2) continue; // Should not happen if points distinct\n            \n            // Valid range for cut: (p1, p2]\n            int low = p1 + 1;\n            int high = p2;\n            if (low > high) continue;\n            \n            // Ideal split position based on area requirements\n            double ratio = (double)current_r / total_r;\n            int ideal = min_coord + (int)round(span * ratio);\n            \n            // Clamp to valid range\n            int pos = std::clamp(ideal, low, high);\n            \n            // Cost is distance from ideal position\n            double cost = std::abs(pos - ideal);\n            \n            cands.push_back({axis, pos, cost});\n        }\n    };\n    \n    analyze(0);\n    analyze(1);\n    \n    // Fallback if no valid cuts found (rare)\n    if (cands.empty()) {\n        // Default split in middle of index list\n        int axis = (r.x2 - r.x1 > r.y2 - r.y1) ? 0 : 1;\n        vector<int> sorted = p_idxs;\n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n        \n        int mid = sorted.size() / 2;\n        int p1 = (axis==0) ? points[sorted[mid-1]].x : points[sorted[mid-1]].y;\n        int p2 = (axis==0) ? points[sorted[mid]].x : points[sorted[mid]].y;\n        int pos = (p1 + p2 + 1) / 2;\n        // Ensure valid cut\n        pos = max((axis==0?r.x1:r.y1)+1, min((axis==0?r.x2:r.y2)-1, pos));\n        \n        node_pool[u].axis = axis;\n        node_pool[u].split_pos = pos;\n        \n        vector<int> L_set(sorted.begin(), sorted.begin() + mid);\n        vector<int> R_set(sorted.begin() + mid, sorted.end());\n        \n        Rect rL = r, rR = r;\n        if (axis==0) { rL.x2 = pos; rR.x1 = pos; }\n        else         { rL.y2 = pos; rR.y1 = pos; }\n        \n        node_pool[u].child_l = build_recursive(L_set, rL);\n        node_pool[u].child_r = build_recursive(R_set, rR);\n        return u;\n    }\n    \n    // Probabilistic Selection strategy\n    // Sort candidates by cost (lower is better)\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b){ return a.cost < b.cost; });\n    \n    // Pick from top K candidates to introduce variety for the optimizer\n    int K = min((int)cands.size(), 4);\n    int idx = 0;\n    // 40% chance to greedily pick best, else pick random from top K\n    if (rand_double() < 0.4) idx = 0; \n    else idx = rand_int(K);\n    \n    Cand c = cands[idx];\n    node_pool[u].axis = c.axis;\n    node_pool[u].split_pos = c.pos;\n    \n    // Distribute points\n    vector<int> L_set, R_set;\n    L_set.reserve(p_idxs.size());\n    R_set.reserve(p_idxs.size());\n    \n    for(int pi : p_idxs) {\n        int coord = (c.axis==0) ? points[pi].x : points[pi].y;\n        if (coord < c.pos) L_set.push_back(pi);\n        else R_set.push_back(pi);\n    }\n    \n    Rect rL = r, rR = r;\n    if (c.axis==0) { rL.x2 = c.pos; rR.x1 = c.pos; }\n    else           { rL.y2 = c.pos; rR.y1 = c.pos; }\n    \n    node_pool[u].child_l = build_recursive(L_set, rL);\n    node_pool[u].child_r = build_recursive(R_set, rR);\n    \n    return u;\n}\n\n// --- Tree Optimization Helpers ---\n\n// Collect leaf node indices for a subtree\nvoid get_leaves(int u, vector<int>& leaves) {\n    if (node_pool[u].is_leaf) {\n        leaves.push_back(u);\n        return;\n    }\n    get_leaves(node_pool[u].child_l, leaves);\n    get_leaves(node_pool[u].child_r, leaves);\n}\n\n// Calculate score sum for a set of leaves\ndouble evaluate_leaves(const vector<int>& leaves) {\n    double score = 0;\n    for (int u : leaves) {\n        long long s = node_pool[u].box.area();\n        score += calc_leaf_score(points[node_pool[u].p_idx].r, s);\n    }\n    return score;\n}\n\n// Recursively update bounding boxes in a subtree after a split change\nvoid update_boxes(int u, Rect r) {\n    node_pool[u].box = r;\n    if (node_pool[u].is_leaf) return;\n    \n    Rect rL = r, rR = r;\n    if (node_pool[u].axis == 0) {\n        rL.x2 = node_pool[u].split_pos;\n        rR.x1 = node_pool[u].split_pos;\n    } else {\n        rL.y2 = node_pool[u].split_pos;\n        rR.y1 = node_pool[u].split_pos;\n    }\n    update_boxes(node_pool[u].child_l, rL);\n    update_boxes(node_pool[u].child_r, rR);\n}\n\n// Determine valid min/max for split position by checking max coord in L and min coord in R\nvoid get_valid_range(int u, int& min_val, int& max_val) {\n    int axis = node_pool[u].axis;\n    int mx_l = -20000;\n    int mn_r = 20000;\n    \n    // DFS to find max coord in left subtree\n    auto find_max_l = [&](auto&& self, int node) -> void {\n        if (node_pool[node].is_leaf) {\n            int coord = (axis == 0) ? points[node_pool[node].p_idx].x : points[node_pool[node].p_idx].y;\n            if (coord > mx_l) mx_l = coord;\n            return;\n        }\n        self(self, node_pool[node].child_l);\n        self(self, node_pool[node].child_r);\n    };\n    \n    // DFS to find min coord in right subtree\n    auto find_min_r = [&](auto&& self, int node) -> void {\n        if (node_pool[node].is_leaf) {\n            int coord = (axis == 0) ? points[node_pool[node].p_idx].x : points[node_pool[node].p_idx].y;\n            if (coord < mn_r) mn_r = coord;\n            return;\n        }\n        self(self, node_pool[node].child_l);\n        self(self, node_pool[node].child_r);\n    };\n    \n    find_max_l(find_max_l, node_pool[u].child_l);\n    find_min_r(find_min_r, node_pool[u].child_r);\n    \n    min_val = mx_l + 1;\n    max_val = mn_r;\n}\n\n// Iteratively improve the tree cuts\nvoid optimize_tree() {\n    vector<int> internal_nodes;\n    internal_nodes.reserve(N);\n    \n    // Collect all internal nodes\n    vector<int> q; q.push_back(root_node_idx);\n    int head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        if(!node_pool[u].is_leaf){\n            internal_nodes.push_back(u);\n            q.push_back(node_pool[u].child_l);\n            q.push_back(node_pool[u].child_r);\n        }\n    }\n    \n    // Local search loop\n    // We repeat the scan of all cuts a few times\n    for(int pass=0; pass < 12; ++pass) { \n        bool changed_any = false;\n        \n        // Random shuffle to prevent order bias\n        // shuffle(internal_nodes.begin(), internal_nodes.end(), mt19937(xorshift()));\n\n        for (int u : internal_nodes) {\n            int min_v, max_v;\n            get_valid_range(u, min_v, max_v);\n            if (min_v > max_v) continue;\n            \n            int old_pos = node_pool[u].split_pos;\n            \n            // Identify affected leaves\n            vector<int> leaves;\n            get_leaves(u, leaves);\n            \n            // Helper to evaluate a position\n            auto score_at = [&](int p) {\n                node_pool[u].split_pos = p;\n                update_boxes(u, node_pool[u].box); // Propagate changes\n                return evaluate_leaves(leaves);\n            };\n            \n            double best_local = score_at(old_pos);\n            int best_pos = old_pos;\n            \n            // Calculate \"Ideal\" position based on area requirements of L vs R subtrees\n            long long total_req = 0;\n            long long l_req = 0;\n            vector<int> l_leaves;\n            get_leaves(node_pool[u].child_l, l_leaves);\n            \n            for(int lu : l_leaves) l_req += points[node_pool[lu].p_idx].r;\n            for(int leaf_u : leaves) total_req += points[node_pool[leaf_u].p_idx].r;\n            \n            int range_size = (node_pool[u].axis==0) ? \n                             (node_pool[u].box.x2 - node_pool[u].box.x1) : \n                             (node_pool[u].box.y2 - node_pool[u].box.y1);\n            int start_coord = (node_pool[u].axis==0) ? node_pool[u].box.x1 : node_pool[u].box.y1;\n            \n            int ideal = start_coord + (int)((double)range_size * l_req / total_req);\n            ideal = std::clamp(ideal, min_v, max_v);\n            \n            // Candidates to test:\n            // 1. Boundaries\n            // 2. Neighbors of current\n            // 3. Ideal\n            // 4. Midpoint between bounds\n            vector<int> tests;\n            tests.push_back(min_v);\n            tests.push_back(max_v);\n            if(old_pos > min_v) tests.push_back(old_pos - 1);\n            if(old_pos < max_v) tests.push_back(old_pos + 1);\n            tests.push_back(ideal);\n            \n            // Test candidates\n            for (int val : tests) {\n                if (val == best_pos) continue;\n                double s = score_at(val);\n                if (s > best_local + 1e-9) { // Slight epsilon\n                    best_local = s;\n                    best_pos = val;\n                    changed_any = true;\n                }\n            }\n            \n            // Set best found\n            node_pool[u].split_pos = best_pos;\n            update_boxes(u, node_pool[u].box);\n        }\n        if (!changed_any) break;\n    }\n}\n\n// --- Output Extraction ---\nvoid extract_solution(vector<Rect>& out_rects) {\n    out_rects.resize(N);\n    for (const auto& node : node_pool) {\n        if (node.is_leaf) {\n            int pid = node.p_idx;\n            Rect r = node.box;\n            \n            // Post-processing: Shrink if allocated area > desired area\n            long long area = r.area();\n            int req = points[pid].r;\n            \n            if (area > req) {\n                // Shrink greedily to maintain point inclusion and minimize area\n                // We assume minimizing max deviation of distances to point is good visually\n                while (r.area() > req) {\n                    // Distances from point to edges\n                    int dl = points[pid].x - r.x1;\n                    int dr = r.x2 - 1 - points[pid].x;\n                    int du = points[pid].y - r.y1;\n                    int dd = r.y2 - 1 - points[pid].y;\n                    \n                    // Find the edge furthest from the point to shrink\n                    int max_dist = -1;\n                    int move = -1; // 0:x1+, 1:x2-, 2:y1+, 3:y2-\n                    \n                    if (dl >= max_dist) { max_dist = dl; move = 0; }\n                    if (dr > max_dist) { max_dist = dr; move = 1; }\n                    if (du > max_dist) { max_dist = du; move = 2; }\n                    if (dd > max_dist) { max_dist = dd; move = 3; }\n                    \n                    if (move == 0) r.x1++;\n                    else if (move == 1) r.x2--;\n                    else if (move == 2) r.y1++;\n                    else r.y2--;\n                }\n            }\n            out_rects[pid] = r;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N)) return 0;\n    points.resize(N);\n    vector<int> p_indices(N);\n    for(int i=0; i<N; ++i) {\n        cin >> points[i].x >> points[i].y >> points[i].r;\n        points[i].id = i;\n        p_indices[i] = i;\n    }\n\n    best_sol.score = -1.0;\n    best_sol.rects.resize(N);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    // Loop until time limit\n    while (true) {\n        auto curr_time = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(curr_time - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        // Clean slate for new tree\n        node_pool.clear();\n        node_pool.reserve(N * 4);\n        \n        // 1. Generate Random Partition Topology\n        root_node_idx = build_recursive(p_indices, {0, 0, W, H});\n        \n        // 2. Optimize Split Positions\n        optimize_tree();\n        \n        // 3. Extract Rectangles & Evaluate\n        vector<Rect> current_rects;\n        extract_solution(current_rects);\n        \n        double current_score_sum = 0;\n        for(int i=0; i<N; ++i) {\n            current_score_sum += calc_leaf_score(points[i].r, current_rects[i].area());\n        }\n        double current_final_score = 1e9 * current_score_sum / N;\n        \n        if (current_final_score > best_sol.score) {\n            best_sol.score = current_final_score;\n            best_sol.rects = current_rects;\n        }\n    }\n    \n    // Final Output\n    for(int i=0; i<N; ++i) {\n        cout << best_sol.rects[i].x1 << \" \" << best_sol.rects[i].y1 << \" \"\n             << best_sol.rects[i].x2 << \" \" << best_sol.rects[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Problem Constants\nconst int H = 50;\nconst int W_GRID = 50;\nconst int MAX_TILES = 2500;\n\n// Algorithm Parameters\n// Beam Width: Number of states kept per step. \n// 2500 is a balance between depth of search and speed, allowing multiple iterations.\nconst int BEAM_WIDTH = 2500; \n// Diversity: Max states to keep that end at the same cell.\n// Keeps the beam from converging too early on one area.\nconst int MAX_PER_CELL = 3;  \n// Time limit in seconds (slightly less than 2.0 to be safe)\nconst double TIME_LIMIT = 1.96;\n\n// Grid Data\nint si, sj;\nint tiles[H][W_GRID];\nint points[H][W_GRID];\nint iter_points[H][W_GRID]; // Points with added noise for the current iteration\n\n// Directions: U, D, L, R\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dchar[4] = {'U', 'D', 'L', 'R'};\n\n// Tree node for efficient path reconstruction\n// We store the search tree in a flat vector to avoid pointer overhead.\nstruct TreeNode {\n    int parent_idx;\n    char move_char;\n};\n// Global tree buffer\nvector<TreeNode> tree;\n\n// State definition\nstruct State {\n    int coord;      // Current position (r * 50 + c)\n    int eval_score; // Score + Noise (used for beam selection)\n    int real_score; // Actual Score (used for tracking the best answer)\n    int tree_idx;   // Index in the tree vector\n    bitset<MAX_TILES> visited; // Set of visited tiles\n};\n\n// Helper for bucketing candidates\nstruct Candidate {\n    int score;     // eval_score\n    int state_idx; // Index in 'next_states'\n};\n\n// Global buffers to avoid repeated allocations\nvector<State> current_beam;\nvector<State> next_states;\nvector<Candidate> cell_buckets[2500]; // One bucket per grid cell to manage spatial diversity\nvector<int> touched_buckets;          // To clear buckets efficiently\n\n// Global best result\nint global_best_score = -1;\nstring global_best_path = \"\";\n\nint main() {\n    // Optimization for fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_clock = chrono::system_clock::now();\n\n    // Read Input\n    if (!(cin >> si >> sj)) return 0;\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> tiles[i][j];\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W_GRID; ++j) {\n            cin >> points[i][j];\n        }\n    }\n\n    // Memory Reservation\n    // Tree needs to hold nodes for one full iteration.\n    // With pruning, 10M nodes is sufficient and fits within 1024MiB.\n    tree.reserve(10000000);\n    current_beam.reserve(BEAM_WIDTH);\n    next_states.reserve(BEAM_WIDTH * 4);\n    touched_buckets.reserve(2500);\n    for (int i = 0; i < 2500; ++i) {\n        cell_buckets[i].reserve(MAX_PER_CELL + 1);\n    }\n\n    // Random Number Generation\n    mt19937 rng(12345);\n    // Noise distribution: enough to reorder candidates but correlated with real score\n    // Points are 0-99, so 0-25 is a reasonable perturbation.\n    uniform_int_distribution<int> noise_dist(0, 25);\n\n    int iteration = 0;\n\n    // Iterative Loop\n    while (true) {\n        // Check time limit at the start of iteration\n        auto now = chrono::system_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_clock).count() / 1000.0;\n        if (elapsed > TIME_LIMIT) break;\n\n        iteration++;\n\n        // 1. Set up weights for this iteration\n        for (int i = 0; i < H; ++i) {\n            for (int j = 0; j < W_GRID; ++j) {\n                if (iteration == 1) {\n                    // First run: pure greedy (baseline)\n                    iter_points[i][j] = points[i][j];\n                } else {\n                    // Subsequent runs: add noise to encourage exploration\n                    iter_points[i][j] = points[i][j] + noise_dist(rng);\n                }\n            }\n        }\n\n        // 2. Reset Search State\n        tree.clear();\n        current_beam.clear();\n\n        State start_node;\n        start_node.coord = si * W_GRID + sj;\n        start_node.real_score = points[si][sj];\n        start_node.eval_score = iter_points[si][sj];\n        start_node.tree_idx = -1; // Root\n        start_node.visited.reset();\n        start_node.visited.set(tiles[si][sj]);\n\n        current_beam.push_back(start_node);\n\n        // Track best immediately\n        if (start_node.real_score > global_best_score) {\n            global_best_score = start_node.real_score;\n            global_best_path = \"\";\n        }\n\n        // 3. Run Beam Search\n        for (int step = 0; step < MAX_TILES; ++step) {\n            if (current_beam.empty()) break;\n\n            // Periodic time check inside the loop (every 128 steps) to prevent TLE\n            if ((step & 127) == 0) {\n                auto n = chrono::system_clock::now();\n                double el = chrono::duration_cast<chrono::milliseconds>(n - start_clock).count() / 1000.0;\n                if (el > TIME_LIMIT) goto end_search;\n            }\n\n            next_states.clear();\n            touched_buckets.clear();\n\n            // Expansion Phase\n            for (const auto& s : current_beam) {\n                int r = s.coord / W_GRID;\n                int c = s.coord % W_GRID;\n                int cur_tile = tiles[r][c];\n\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n\n                    // Boundary Check\n                    if (nr < 0 || nr >= H || nc < 0 || nc >= W_GRID) continue;\n\n                    int next_tile = tiles[nr][nc];\n                    \n                    // Constraint Check: Must move to different tile & tile not visited\n                    if (next_tile != cur_tile && !s.visited.test(next_tile)) {\n                        \n                        // Record move in tree\n                        tree.push_back({s.tree_idx, dchar[d]});\n                        int new_tree_idx = (int)tree.size() - 1;\n\n                        State ns;\n                        ns.coord = nr * W_GRID + nc;\n                        // Use noisy score for evaluation\n                        ns.eval_score = s.eval_score + iter_points[nr][nc];\n                        // Use real score for tracking result\n                        ns.real_score = s.real_score + points[nr][nc];\n                        ns.tree_idx = new_tree_idx;\n                        ns.visited = s.visited;\n                        ns.visited.set(next_tile);\n\n                        next_states.push_back(ns);\n                    }\n                }\n            }\n\n            if (next_states.empty()) break;\n\n            // Pruning Phase: Bucket by cell coordinate\n            // This is crucial for performance and diversity.\n            for (int i = 0; i < (int)next_states.size(); ++i) {\n                int c = next_states[i].coord;\n                int sc = next_states[i].eval_score;\n                \n                auto& bucket = cell_buckets[c];\n                if (bucket.empty()) {\n                    touched_buckets.push_back(c);\n                    bucket.push_back({sc, i});\n                } else {\n                    // Keep top MAX_PER_CELL candidates per cell\n                    // Use simple insertion logic since list is tiny (<= 3)\n                    bool inserted = false;\n                    for (auto it = bucket.begin(); it != bucket.end(); ++it) {\n                        if (sc > it->score) {\n                            bucket.insert(it, {sc, i});\n                            inserted = true;\n                            break;\n                        }\n                    }\n                    if (!inserted && bucket.size() < MAX_PER_CELL) {\n                        bucket.push_back({sc, i});\n                    }\n                    if (bucket.size() > MAX_PER_CELL) {\n                        bucket.pop_back();\n                    }\n                }\n            }\n\n            // Selection Phase: Gather survivors and check global best\n            vector<int> survivors;\n            survivors.reserve(BEAM_WIDTH + 200);\n\n            for (int c : touched_buckets) {\n                for (const auto& cand : cell_buckets[c]) {\n                    survivors.push_back(cand.state_idx);\n\n                    // Update Global Best\n                    // We check every candidate because a sub-optimal local path (in eval_score)\n                    // might currently have the highest real_score seen so far.\n                    const auto& st = next_states[cand.state_idx];\n                    if (st.real_score > global_best_score) {\n                        global_best_score = st.real_score;\n                        // Reconstruct path\n                        string p;\n                        p.reserve(step + 1);\n                        int curr = st.tree_idx;\n                        while (curr != -1) {\n                            p += tree[curr].move_char;\n                            curr = tree[curr].parent_idx;\n                        }\n                        reverse(p.begin(), p.end());\n                        global_best_path = p;\n                    }\n                }\n                cell_buckets[c].clear();\n            }\n\n            // Global Truncation if too many states across all cells\n            if ((int)survivors.size() > BEAM_WIDTH) {\n                nth_element(survivors.begin(), survivors.begin() + BEAM_WIDTH, survivors.end(),\n                    [&](int a, int b) {\n                        return next_states[a].eval_score > next_states[b].eval_score;\n                    });\n                survivors.resize(BEAM_WIDTH);\n            }\n\n            // Form new beam\n            current_beam.clear();\n            for (int idx : survivors) {\n                current_beam.push_back(next_states[idx]);\n            }\n        }\n    }\n\n    end_search:;\n    cout << global_best_path << endl;\n\n    return 0;\n}","ahc003":"/**\n * AtCoder Heuristic Contest Solution\n * Problem: Shortest Path with Unknown Edge Lengths\n * \n * Changes:\n * 1. Fixed critical Out-Of-Bounds bug in vertical regularization loop that caused WA.\n *    (Loop limit changed from r < N-1 to r < N-2).\n * 2. Maintained adaptive SGD batch/iteration sizes to balance learning vs time limit.\n * 3. Maintained strict execution time cutoff to prevent TLE.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst int NUM_H = N * (N - 1); \nconst int NUM_V = (N - 1) * N; \nconst int NUM_EDGES = NUM_H + NUM_V; \n\n// Helper to get edge indices\ninline int get_h_idx(int r, int c) { return r * (N - 1) + c; }\ninline int get_v_idx(int r, int c) { return NUM_H + r * N + c; }\n\nstruct Query {\n    vector<int> path_edges;\n    int measured_dist;\n};\n\nclass Solver {\nprivate:\n    // Model parameters\n    vector<double> weights;\n    vector<double> m, v; // Adam moments\n    double beta1 = 0.9;\n    double beta2 = 0.999;\n    double epsilon = 1e-8;\n    \n    // Hyperparameters\n    double learning_rate = 120.0; \n    double lambda_smooth = 1.0e-5; \n    \n    long long updates_count = 0;\n    vector<Query> history;\n    mt19937 rng;\n\n    // Pre-allocated buffers for Dijkstra\n    vector<double> dist;\n    vector<int> parent_edge;\n    vector<int> parent_node;\n    \n    // Time management\n    chrono::steady_clock::time_point start_time;\n\npublic:\n    Solver() {\n        // Initialize weights with mean value (edges range 1000-9000)\n        weights.assign(NUM_EDGES, 5000.0);\n        m.assign(NUM_EDGES, 0.0);\n        v.assign(NUM_EDGES, 0.0);\n        rng.seed(42);\n        \n        dist.resize(N * N);\n        parent_edge.resize(N * N);\n        parent_node.resize(N * N);\n        \n        start_time = chrono::steady_clock::now();\n    }\n\n    pair<string, vector<int>> find_path(int si, int sj, int ti, int tj) {\n        // Reset distances\n        fill(dist.begin(), dist.end(), 1e18);\n        \n        auto get_node = [&](int r, int c) { return r * N + c; };\n        int start_node = get_node(si, sj);\n        int target_node = get_node(ti, tj);\n        \n        dist[start_node] = 0;\n        \n        using State = pair<double, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, start_node});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            if (u == target_node) break;\n            \n            int r = u / N;\n            int c = u % N;\n            \n            // Explore Neighbors: Up, Down, Left, Right\n            \n            // Up: move to (r-1, c) via vertical edge at (r-1, c)\n            if (r > 0) {\n                int v_node = u - N; \n                int e_idx = NUM_H + (r - 1) * N + c; \n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Down: move to (r+1, c) via vertical edge at (r, c)\n            if (r < N - 1) {\n                int v_node = u + N;\n                int e_idx = NUM_H + r * N + c; \n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Left: move to (r, c-1) via horizontal edge at (r, c-1)\n            if (c > 0) {\n                int v_node = u - 1;\n                int e_idx = r * (N - 1) + (c - 1); \n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n            // Right: move to (r, c+1) via horizontal edge at (r, c)\n            if (c < N - 1) {\n                int v_node = u + 1;\n                int e_idx = r * (N - 1) + c; \n                double w = weights[e_idx];\n                if (dist[u] + w < dist[v_node]) {\n                    dist[v_node] = dist[u] + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node], v_node});\n                }\n            }\n        }\n        \n        // Reconstruct path from target to start\n        string path = \"\";\n        vector<int> edges;\n        int curr = target_node;\n        while (curr != start_node) {\n            int prev = parent_node[curr];\n            int e_idx = parent_edge[curr];\n            edges.push_back(e_idx);\n            \n            int diff = curr - prev;\n            if (diff == N) path += 'D';\n            else if (diff == -N) path += 'U';\n            else if (diff == 1) path += 'R';\n            else path += 'L';\n            \n            curr = prev;\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges.begin(), edges.end());\n        return {path, edges};\n    }\n\n    void train(const vector<int>& path_edges, int measured) {\n        // 1. Time Check\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        // Strict cutoff to prevent TLE (Limit is 2.0s)\n        if (elapsed > 1.85) return; \n        \n        history.push_back({path_edges, measured});\n        \n        // 2. Dynamic Complexity Adjustment\n        int base_batch = 100; \n        int base_iter = 20; \n        \n        // Train more intensely on early queries to adapt quickly\n        if (history.size() < 50) {\n            base_batch = 120;\n            base_iter = 40;\n        } else if (history.size() < 200) {\n            base_batch = 110;\n            base_iter = 30;\n        }\n\n        // Throttle if getting tight on time\n        if (elapsed > 1.5) {\n            base_iter = 10;\n            base_batch = 50;\n        }\n\n        int batch_size = base_batch;\n        int iterations = base_iter;\n        \n        static vector<double> grad(NUM_EDGES);\n        vector<int> indices;\n        indices.reserve(batch_size);\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            fill(grad.begin(), grad.end(), 0.0);\n            updates_count++;\n            \n            // Prepare Mini-batch with Stratified Sampling\n            indices.clear();\n            int hist_size = history.size();\n            \n            // 1. Recent history (last 20 queries)\n            int recent_count = min(hist_size, 20); \n            for(int i = 0; i < recent_count; ++i) indices.push_back(hist_size - 1 - i);\n            \n            // 2. Random historical queries\n            int needed = batch_size - recent_count;\n            if (needed > 0 && hist_size > 0) {\n                 for(int i = 0; i < needed; ++i) {\n                    indices.push_back(rng() % hist_size);\n                }\n            }\n\n            // --- Gradient Calculation ---\n\n            // 1. Prediction Error Term\n            for (int idx : indices) {\n                const auto& q = history[idx];\n                double pred = 0;\n                for (int e : q.path_edges) pred += weights[e];\n                \n                double y = q.measured_dist;\n                double diff = pred - y;\n                // Gradient of squared relative error: (pred - y)^2 / y^2\n                double g_factor = 2.0 * diff / (y * y);\n                \n                for (int e : q.path_edges) {\n                    grad[e] += g_factor;\n                }\n            }\n            \n            // 2. Smoothness (L1 Regularization) Term\n            \n            // Horizontal edges: smooth row-wise\n            // Rows 0..29. Horizontal edges in row r are (r,0)->(r,1) ... (r,N-2)->(r,N-1)\n            // Indices are contiguous.\n            for (int r = 0; r < N; ++r) {\n                int start = r * (N - 1);\n                // We compare e_c and e_{c+1}. c goes 0 to N-3.\n                for (int c = 0; c < N - 2; ++c) {\n                    int e1 = start + c;\n                    int e2 = e1 + 1;\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    // L1 gradient is constant sign(diff)\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // Vertical edges: smooth column-wise\n            // Vertical edges exist for rows 0 to N-2.\n            // We compare e_r and e_{r+1}. r goes 0 to N-3.\n            int v_offset = NUM_H;\n            for (int r = 0; r < N - 2; ++r) { // Corrected limit: r < N-2\n                int row_start = v_offset + r * N;\n                for (int c = 0; c < N; ++c) {\n                    int e1 = row_start + c;\n                    int e2 = e1 + N; // Edge at (r+1, c)\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // --- Adam Update ---\n            double bias_corr1 = 1.0 - pow(beta1, updates_count);\n            double bias_corr2 = 1.0 - pow(beta2, updates_count);\n            \n            for (int i = 0; i < NUM_EDGES; ++i) {\n                double g = grad[i];\n                \n                m[i] = beta1 * m[i] + (1 - beta1) * g;\n                v[i] = beta2 * v[i] + (1 - beta2) * g * g;\n                \n                double m_hat = m[i] / bias_corr1;\n                double v_hat = v[i] / bias_corr2;\n                \n                weights[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);\n                \n                // Clamp weights to reasonable physical bounds\n                if (weights[i] < 500.0) weights[i] = 500.0;\n                if (weights[i] > 9500.0) weights[i] = 9500.0;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    Solver solver;\n    \n    int query_count = 1000;\n    for (int k = 0; k < query_count; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        \n        // 1. Output Path\n        auto [path_str, path_edges] = solver.find_path(si, sj, ti, tj);\n        cout << path_str << endl;\n        \n        // 2. Read Feedback\n        int measured;\n        cin >> measured;\n        \n        // 3. Update Model\n        solver.train(path_edges, measured);\n    }\n    \n    return 0;\n}","ahc004":"/**\n * Problem: AHC004 - Genetic Information\n * Approach: Multi-start Simulated Annealing with Gibbs Sampling (Heat Bath)\n * \n * Key Optimizations:\n * 1. Gibbs Sampling / Heat Bath Strategy:\n *    - Instead of proposing one random change, we evaluate ALL 8 possible characters \n *      for a selected cell at each step.\n *    - We select the new character probabilistically based on the calculated scores \n *      and current temperature (Softmax selection).\n *    - This converges significantly faster than standard Metropolis-Hastings because \n *      every step effectively picks a \"good\" local move.\n * \n * 2. Efficient Delta Calculation:\n *    - To support Gibbs Sampling, we need to query \"what if this cell was 'A'?\", \"what if 'B'?\", etc.\n *    - We implemented `eval_val` to compute potential score gains without modifying the global state.\n *    - Rolling hashes are computed efficiently using line buffers to minimize memory access and modulo operations.\n * \n * 3. Data Structures:\n *    - FastHashMap for O(1) string matching.\n *    - Fixed-size buffers for row/column extraction.\n * \n * 4. Meta-Heuristics:\n *    - Multi-start strategy to escape deep local optima.\n *    - Refinement phase on the best found solution.\n *    - Dot optimization (greedy) only applied when perfect coverage is achieved.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <cmath>\n#include <map>\n\nusing namespace std;\n\n// Global Constants\nconstexpr int N = 20;\nconstexpr int TIMEOUT_MS = 2950;\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint64_t state = 0x123456789ABCDEF;\n    inline uint64_t next() {\n        uint64_t x = state;\n        x ^= x << 13;\n        x ^= x >> 7;\n        x ^= x << 17;\n        return state = x;\n    }\n    inline int next_int(int n) { return next() % n; }\n    inline int next_char() { return next() & 7; } // 0-7\n    inline double next_double() { return (next() & 0xFFFFFFFF) / 4294967296.0; }\n};\n\nXorshift rng;\n\nstruct Target {\n    int id;\n    int weight;\n};\n\n// Custom Hash Map for performance\nconstexpr int HASH_MAP_SIZE = 4096;\nconstexpr int HASH_MAP_MASK = HASH_MAP_SIZE - 1;\n\nstruct FastHashMap {\n    uint64_t keys[HASH_MAP_SIZE];\n    int ids[HASH_MAP_SIZE]; // 0 = empty, val = id + 1\n    \n    FastHashMap() { memset(ids, 0, sizeof(ids)); }\n    void clear() { memset(ids, 0, sizeof(ids)); }\n    \n    inline void insert(uint64_t key, int id) {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return; \n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        keys[idx] = key;\n        ids[idx] = id + 1;\n    }\n    \n    inline int get(uint64_t key) const {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return ids[idx] - 1;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        return -1;\n    }\n};\n\nstruct Solver {\n    int M;\n    int max_possible_weight;\n    \n    FastHashMap maps[13];\n    vector<Target> targets_info; \n    vector<int> active_lengths;\n    \n    int grid[N][N];\n    vector<int> occ; \n    int current_score;\n    \n    int best_grid[N][N];\n    int best_score;\n    \n    // Buffer for extracting rows/cols with wrap-around\n    int line_buf[32]; \n\n    Solver() { best_score = -1; }\n\n    void read_input() {\n        int n_dummy;\n        if (!(cin >> n_dummy >> M)) return;\n        \n        map<string, int> counts;\n        for (int i = 0; i < M; ++i) {\n            string s; cin >> s; counts[s]++;\n        }\n        \n        max_possible_weight = M;\n        int id_counter = 0;\n        targets_info.reserve(counts.size());\n        \n        vector<bool> len_active(13, false);\n        for (auto const& [s, count] : counts) {\n            int len = s.length();\n            uint64_t h = 0;\n            for (char c : s) h = (h << 3) | (c - 'A');\n            \n            maps[len].insert(h, id_counter);\n            targets_info.push_back({id_counter, count});\n            len_active[len] = true;\n            id_counter++;\n        }\n        \n        for(int l=2; l<=12; ++l) if (len_active[l]) active_lengths.push_back(l);\n        occ.resize(id_counter, 0);\n    }\n    \n    // Modifies `occ` and returns score difference.\n    // sign = -1 to remove strings passing through (r,c) with value `val`.\n    // sign = 1 to add strings.\n    inline int update_occ(int r, int c, int val, int sign) {\n        int diff = 0;\n        \n        // Horizontal extraction\n        for(int j=0; j<N; ++j) line_buf[j] = grid[r][j];\n        line_buf[c] = val;\n        for(int j=0; j<12; ++j) line_buf[N+j] = line_buf[j];\n        \n        // Check all active lengths\n        for (int l : active_lengths) {\n            // Windows of length l that contain index c\n            // Start indices relative to the unwrapped buffer range [c - l + 1, c]\n            // We map these to positive indices in line_buf\n            for (int k = 0; k < l; ++k) {\n                int start_col = (c - l + 1 + k + N) % N;\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) h = (h << 3) | line_buf[start_col + i];\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    if (sign > 0) {\n                        if (occ[id] == 0) diff += targets_info[id].weight;\n                        occ[id]++;\n                    } else {\n                        if (occ[id] == 1) diff -= targets_info[id].weight;\n                        occ[id]--;\n                    }\n                }\n            }\n        }\n        \n        // Vertical extraction\n        for(int i=0; i<N; ++i) line_buf[i] = grid[i][c];\n        line_buf[r] = val;\n        for(int i=0; i<12; ++i) line_buf[N+i] = line_buf[i];\n        \n        for (int l : active_lengths) {\n            for (int k = 0; k < l; ++k) {\n                int start_row = (r - l + 1 + k + N) % N;\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) h = (h << 3) | line_buf[start_row + i];\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    if (sign > 0) {\n                        if (occ[id] == 0) diff += targets_info[id].weight;\n                        occ[id]++;\n                    } else {\n                        if (occ[id] == 1) diff -= targets_info[id].weight;\n                        occ[id]--;\n                    }\n                }\n            }\n        }\n        return diff;\n    }\n\n    // Evaluates the score gain of placing `val` at (r, c), assuming the cell is currently empty.\n    // Does NOT modify `occ`. Used for Gibbs sampling look-ahead.\n    inline int eval_val(int r, int c, int val) {\n        int gain = 0;\n        \n        // Horizontal\n        for(int j=0; j<N; ++j) line_buf[j] = grid[r][j];\n        line_buf[c] = val;\n        for(int j=0; j<12; ++j) line_buf[N+j] = line_buf[j];\n        \n        for (int l : active_lengths) {\n            for (int k = 0; k < l; ++k) {\n                int start_col = (c - l + 1 + k + N) % N;\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) h = (h << 3) | line_buf[start_col + i];\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    // Check if this target needs satisfaction\n                    if (occ[id] == 0) gain += targets_info[id].weight;\n                }\n            }\n        }\n        \n        // Vertical\n        for(int i=0; i<N; ++i) line_buf[i] = grid[i][c];\n        line_buf[r] = val;\n        for(int i=0; i<12; ++i) line_buf[N+i] = line_buf[i];\n        \n        for (int l : active_lengths) {\n            for (int k = 0; k < l; ++k) {\n                int start_row = (r - l + 1 + k + N) % N;\n                uint64_t h = 0;\n                for (int i = 0; i < l; ++i) h = (h << 3) | line_buf[start_row + i];\n                \n                int id = maps[l].get(h);\n                if (id != -1) {\n                    if (occ[id] == 0) gain += targets_info[id].weight;\n                }\n            }\n        }\n        return gain;\n    }\n\n    int calc_full_score() {\n        fill(occ.begin(), occ.end(), 0);\n        int score = 0;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int l : active_lengths) {\n                    // Horz\n                    uint64_t h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[r][(c+k)%N];\n                    int id = maps[l].get(h);\n                    if (id != -1) {\n                        if (occ[id] == 0) score += targets_info[id].weight;\n                        occ[id]++;\n                    }\n                    // Vert\n                    h = 0;\n                    for(int k=0; k<l; ++k) h = (h << 3) | grid[(r+k)%N][c];\n                    id = maps[l].get(h);\n                    if (id != -1) {\n                        if (occ[id] == 0) score += targets_info[id].weight;\n                        occ[id]++;\n                    }\n                }\n            }\n        }\n        return score;\n    }\n\n    void run_sa(double duration_ms, bool refinement) {\n        auto start_time = chrono::steady_clock::now();\n        \n        double t0 = refinement ? 0.2 : 1.0;\n        double t1 = 0.02;\n        \n        int64_t steps = 0;\n        int gains[8];\n        \n        while (true) {\n            steps++;\n            if ((steps & 511) == 0) {\n                auto curr = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n                if (elapsed > duration_ms) break;\n            }\n            \n            // Pick random cell\n            int r = rng.next_int(N);\n            int c = rng.next_int(N);\n            int old_val = grid[r][c];\n            \n            // 1. Remove old_val contribution from occ\n            int loss = update_occ(r, c, old_val, -1);\n            int base_score = current_score + loss; \n            \n            // 2. Evaluate all 8 character options\n            int max_gain = -1e9;\n            for(int v=0; v<8; ++v) {\n                if (v == old_val) {\n                    gains[v] = -loss; // Reverting gives back what we lost\n                } else {\n                    gains[v] = eval_val(r, c, v);\n                }\n                if (gains[v] > max_gain) max_gain = gains[v];\n            }\n            \n            // 3. Gibbs Sampling / Heat Bath selection\n            // Calculate temp\n            auto curr = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n            double temp = t0 + (t1 - t0) * (elapsed / duration_ms);\n            \n            double weights[8];\n            double sum_w = 0;\n            for(int v=0; v<8; ++v) {\n                // Subtract max_gain to prevent overflow, exp is shift-invariant for ratios\n                weights[v] = exp((gains[v] - max_gain) / temp);\n                sum_w += weights[v];\n            }\n            \n            double rnd = rng.next_double() * sum_w;\n            int selected = 0;\n            for(; selected < 7; ++selected) {\n                rnd -= weights[selected];\n                if(rnd <= 0) break;\n            }\n            \n            // 4. Apply the selected character\n            int apply_gain = update_occ(r, c, selected, 1);\n            \n            current_score = base_score + apply_gain;\n            grid[r][c] = selected;\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                memcpy(best_grid, grid, sizeof(grid));\n            }\n        }\n    }\n    \n    void optimize_dots() {\n        // Only useful if we have a perfect coverage\n        if (best_score < max_possible_weight) return;\n        \n        memcpy(grid, best_grid, sizeof(grid));\n        current_score = calc_full_score(); // Reset occ to best state\n        \n        vector<pair<int,int>> cells;\n        cells.reserve(N*N);\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) cells.push_back({i,j});\n        // Shuffle\n        for(int i=cells.size()-1; i>0; --i) swap(cells[i], cells[rng.next_int(i+1)]);\n        \n        for(auto p : cells) {\n            int r = p.first;\n            int c = p.second;\n            int old_val = grid[r][c];\n            if (old_val == -1) continue;\n            \n            // Try removing it\n            int diff = update_occ(r, c, old_val, -1);\n            \n            // If score remains max_possible_weight, we can keep it as a dot\n            if (current_score + diff == max_possible_weight) {\n                current_score += diff;\n                grid[r][c] = -1; \n                memcpy(best_grid, grid, sizeof(grid)); \n            } else {\n                // Revert\n                update_occ(r, c, old_val, 1);\n            }\n        }\n    }\n\n    void solve() {\n        auto global_start = chrono::steady_clock::now();\n        \n        best_score = -1;\n        int run_count = 0;\n        \n        // Main loop: Multi-start\n        while(true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - global_start).count();\n            \n            // Stop if close to timeout\n            if (elapsed > TIMEOUT_MS - 200 && run_count > 0) break;\n            \n            // Initialize random grid\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = rng.next_char();\n            current_score = calc_full_score();\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                memcpy(best_grid, grid, sizeof(grid));\n            }\n            \n            // Determine duration for this run\n            double run_duration = 600.0; \n            if (elapsed + run_duration > TIMEOUT_MS - 100) {\n                run_duration = TIMEOUT_MS - elapsed - 100;\n            }\n            \n            if (run_duration < 100) break;\n            \n            run_sa(run_duration, false);\n            run_count++;\n        }\n        \n        // Refinement Phase: Run a short, low-temp SA on the best solution\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double, milli>(now - global_start).count();\n        if (elapsed < TIMEOUT_MS - 50) {\n            memcpy(grid, best_grid, sizeof(grid));\n            current_score = calc_full_score();\n            run_sa(TIMEOUT_MS - elapsed - 20, true);\n        }\n        \n        // Optimization Phase: Insert dots if perfect\n        optimize_dots();\n        \n        // Output Result\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                int val = best_grid[i][j];\n                if (val >= 0) cout << (char)('A' + val);\n                else cout << '.';\n            }\n            cout << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver s;\n    s.read_input();\n    s.solve();\n    return 0;\n}","ahc005":"/**\n * Problem Analysis & Solution Strategy:\n *\n * 1. Core Concept:\n *    This is a path planning problem that requires covering all road cells.\n *    A road cell is \"covered\" if we visit its corresponding horizontal segment (H-seg) or vertical segment (V-seg).\n *    This is a variation of the Set Cover or Vertex Cover problem on a bipartite graph, combined with TSP-like movement.\n *\n * 2. Algorithm - Iterative Greedy with Lookahead (Min-Weight Vertex Cover):\n *    We construct the solution step-by-step from the current position.\n *    \n *    Step A: Evaluate Costs\n *      Calculate shortest path distances from the current position to all other road cells using Dijkstra.\n *      \n *    Step B: Determine Necessary Targets (MWVC)\n *      We need to decide which segments to visit next. A purely greedy approach (visit closest unvisited segment)\n *      fails to account for the global structure (e.g., picking a set of segments that cover everything efficiently).\n *      We model the *remaining* uncovered cells as a bipartite graph.\n *      We solve the Min-Weight Vertex Cover (MWVC) on this graph.\n *      - Nodes: H-segments and V-segments.\n *      - Weights: Approximate cost to visit the segment (distance from current pos + random noise).\n *      - Edges: Uncovered road cells connect their H-seg and V-seg.\n *      The Minimum Cut (via Max Flow) gives us the optimal set of segments (Vertex Cover) to visit to cover all current gaps.\n *\n *    Step C: Select Best Destination\n *      From the set of \"Target Segments\" identified by MWVC, we must pick a specific cell to move to.\n *      - We scan *all* reachable road cells.\n *      - If a cell belongs to a Target H-segment, it gives 1 point of Gain.\n *      - If a cell belongs to a Target V-segment, it gives 1 point of Gain.\n *      - A cell can give 2 points of Gain (Intersection of two required segments).\n *      \n *      Scoring Metric: `Score = Distance * Multiplier`.\n *      - If Gain = 1: Multiplier = 1.0.\n *      - If Gain = 2: Multiplier = alpha (randomized, e.g., 0.5 - 0.8).\n *      We move to the cell with the minimum Score. This naturally biases towards intersections if they are reasonably close,\n *      avoiding large detours for double gains while capturing easy ones.\n *\n * 3. Randomization & Time Management:\n *    Since the grid is small (N <= 69), we can run this simulation many times within 3 seconds.\n *    We randomize the segment weights and the 'double gain' discount factor to explore different strategies.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\n// Use AtCoder Library for MaxFlow\n#include <atcoder/maxflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconst int INF = 1e9;\nconst int DX[] = {-1, 1, 0, 0};\nconst int DY[] = {0, 0, -1, 1};\nconst char DIR_CHAR[] = {'U', 'D', 'L', 'R'};\n\n// Global Grid Info\nint N;\nint SI, SJ;\nvector<string> GRID;\nvector<vector<int>> COSTS;\nbool IS_ROAD[70][70];\nvector<pair<int,int>> ROAD_CELLS;\n\n// Data Structures\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\nstruct Segment {\n    int id;\n    int type; // 0: Horizontal, 1: Vertical\n    vector<Point> cells;\n};\n\nvector<Segment> H_SEGS, V_SEGS;\nint H_ID[70][70];\nint V_ID[70][70];\n\n// RNG\nmt19937 rng(12345);\n\n// Input Parsing\nvoid parse_input() {\n    if (!(cin >> N >> SI >> SJ)) return;\n    GRID.resize(N);\n    COSTS.assign(N, vector<int>(N, 0));\n    ROAD_CELLS.clear();\n    for (int i = 0; i < N; ++i) {\n        cin >> GRID[i];\n        for (int j = 0; j < N; ++j) {\n            if (GRID[i][j] != '#') {\n                COSTS[i][j] = GRID[i][j] - '0';\n                IS_ROAD[i][j] = true;\n                ROAD_CELLS.push_back({i, j});\n            } else {\n                IS_ROAD[i][j] = false;\n            }\n        }\n    }\n\n    // Identify Horizontal Segments\n    H_SEGS.clear();\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) H_ID[i][j] = -1;\n    int h_count = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (!IS_ROAD[i][j]) { j++; continue; }\n            int k = j;\n            while (k < N && IS_ROAD[i][k]) k++;\n            Segment seg; seg.id = h_count; seg.type = 0;\n            for (int c = j; c < k; ++c) {\n                seg.cells.push_back({i, c});\n                H_ID[i][c] = h_count;\n            }\n            H_SEGS.push_back(seg);\n            h_count++;\n            j = k;\n        }\n    }\n\n    // Identify Vertical Segments\n    V_SEGS.clear();\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) V_ID[i][j] = -1;\n    int v_count = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (!IS_ROAD[i][j]) { i++; continue; }\n            int k = i;\n            while (k < N && IS_ROAD[k][j]) k++;\n            Segment seg; seg.id = v_count; seg.type = 1;\n            for (int r = i; r < k; ++r) {\n                seg.cells.push_back({r, j});\n                V_ID[r][j] = v_count;\n            }\n            V_SEGS.push_back(seg);\n            v_count++;\n            i = k;\n        }\n    }\n}\n\n// Dijkstra's Algorithm\nvoid get_dist_matrix(Point start, vector<vector<int>>& dist, vector<vector<int>>& parent_dir) {\n    dist.assign(N, vector<int>(N, INF));\n    parent_dir.assign(N, vector<int>(N, -1));\n    \n    priority_queue<pair<int, pair<int,int>>, vector<pair<int, pair<int,int>>>, greater<pair<int, pair<int,int>>>> pq;\n    \n    dist[start.r][start.c] = 0;\n    pq.push({0, {start.r, start.c}});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d > dist[u.first][u.second]) continue;\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = u.first + DX[k], nc = u.second + DY[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && IS_ROAD[nr][nc]) {\n                int w = COSTS[nr][nc];\n                if (dist[u.first][u.second] + w < dist[nr][nc]) {\n                    dist[nr][nc] = dist[u.first][u.second] + w;\n                    parent_dir[nr][nc] = k;\n                    pq.push({dist[nr][nc], {nr, nc}});\n                }\n            }\n        }\n    }\n}\n\n// Path Reconstruction\nstring get_path_str(Point start, Point end, const vector<vector<int>>& parent_dir) {\n    string path = \"\";\n    int r = end.r, c = end.c;\n    while (r != start.r || c != start.c) {\n        int dir = parent_dir[r][c];\n        if (dir == -1) break;\n        path += DIR_CHAR[dir];\n        r -= DX[dir];\n        c -= DY[dir];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Result {\n    string path;\n    long long score;\n    int time_cost;\n};\n\n// Solver Logic\nResult solve(int seed) {\n    rng.seed(seed);\n    \n    // Parameters for randomization\n    uniform_real_distribution<double> weight_noise(0.8, 1.2);\n    uniform_real_distribution<double> double_cover_dist(0.55, 0.85); \n    \n    double alpha = double_cover_dist(rng); // Discount factor for double-coverage intersections\n\n    vector<vector<bool>> covered(N, vector<bool>(N, false));\n    int covered_cnt = 0;\n    int total_cells = ROAD_CELLS.size();\n\n    // Coverage Helper\n    auto visit_cell = [&](int r, int c) {\n        if (!covered[r][c]) {\n            covered[r][c] = true;\n            covered_cnt++;\n        }\n    };\n    auto visit_pos = [&](Point p) {\n        int hid = H_ID[p.r][p.c];\n        if (hid != -1) {\n            for (auto& c : H_SEGS[hid].cells) visit_cell(c.r, c.c);\n        }\n        int vid = V_ID[p.r][p.c];\n        if (vid != -1) {\n            for (auto& c : V_SEGS[vid].cells) visit_cell(c.r, c.c);\n        }\n    };\n\n    Point current = {SI, SJ};\n    visit_pos(current);\n\n    string full_path = \"\";\n    int total_cost = 0;\n\n    while (covered_cnt < total_cells) {\n        // 1. Calculate distances from current\n        vector<vector<int>> dist, parent;\n        get_dist_matrix(current, dist, parent);\n\n        // 2. Calculate min distance to each segment (for weighting)\n        vector<int> h_dist(H_SEGS.size(), INF);\n        vector<int> v_dist(V_SEGS.size(), INF);\n        \n        for (auto& seg : H_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < h_dist[seg.id]) h_dist[seg.id] = dist[p.r][p.c];\n            }\n        }\n        for (auto& seg : V_SEGS) {\n            for (auto& p : seg.cells) {\n                if (dist[p.r][p.c] < v_dist[seg.id]) v_dist[seg.id] = dist[p.r][p.c];\n            }\n        }\n\n        // 3. Build MWVC Graph\n        int S = H_SEGS.size() + V_SEGS.size();\n        int T = S + 1;\n        mf_graph<long long> g(T + 1);\n\n        // Weights roughly proportional to distance, with noise\n        for (auto& seg : H_SEGS) {\n            long long w = (long long)(h_dist[seg.id] * weight_noise(rng)) + 50;\n            g.add_edge(S, seg.id, w);\n        }\n        for (auto& seg : V_SEGS) {\n            long long w = (long long)(v_dist[seg.id] * weight_noise(rng)) + 50;\n            g.add_edge(H_SEGS.size() + seg.id, T, w);\n        }\n\n        // Constraint edges for uncovered cells\n        bool needed = false;\n        for (auto& p : ROAD_CELLS) {\n            if (!covered[p.first][p.second]) {\n                int h = H_ID[p.first][p.second];\n                int v = V_ID[p.first][p.second];\n                g.add_edge(h, H_SEGS.size() + v, 1e18); // Infinite capacity\n                needed = true;\n            }\n        }\n        if (!needed) break;\n\n        // Solve Min Cut\n        g.flow(S, T);\n        auto cut = g.min_cut(S);\n\n        // Identify Vertex Cover (Target Segments)\n        vector<bool> target_h(H_SEGS.size(), false);\n        vector<bool> target_v(V_SEGS.size(), false);\n        \n        // S-set nodes on left are NOT in VC. T-set nodes on left (cut edge) ARE in VC.\n        // S-set nodes on right (cut edge) ARE in VC. T-set nodes on right are NOT.\n        // Note: maxflow lib returns true if reachable from S.\n        // Left Node i: if reachable (cut[i]), edge S->i is NOT cut. If !reachable, edge S->i IS cut.\n        // Capacity is on S->i. Min cut cuts S->i if i is T-side. So VC includes i if !cut[i].\n        for (int i = 0; i < (int)H_SEGS.size(); ++i) if (!cut[i]) target_h[i] = true;\n        \n        // Right Node j: edge j->T. Cut if j is S-side. VC includes j if cut[j].\n        for (int i = 0; i < (int)V_SEGS.size(); ++i) if (cut[H_SEGS.size() + i]) target_v[i] = true;\n\n        // 4. Select Best Destination Cell\n        Point best_p = {-1, -1};\n        double best_score = 1e18;\n\n        for (auto& rc : ROAD_CELLS) {\n            int r = rc.first;\n            int c = rc.second;\n            if (dist[r][c] == INF) continue;\n\n            int h = H_ID[r][c];\n            int v = V_ID[r][c];\n            \n            bool is_h_target = (h != -1 && target_h[h]);\n            bool is_v_target = (v != -1 && target_v[v]);\n            \n            if (!is_h_target && !is_v_target) continue; // Provides no useful coverage\n\n            // Score logic: Lower is better\n            double score = (double)dist[r][c];\n            \n            // If this cell covers TWO targets, it's efficient. Apply discount.\n            if (is_h_target && is_v_target) {\n                score *= alpha;\n            }\n\n            if (score < best_score) {\n                best_score = score;\n                best_p = {r, c};\n            }\n        }\n\n        if (best_p.r == -1) break; // Should not happen if needed is true\n\n        // 5. Move\n        string sub = get_path_str(current, best_p, parent);\n        full_path += sub;\n        total_cost += dist[best_p.r][best_p.c];\n        \n        // Update coverage along the path\n        Point temp = current;\n        for (char c : sub) {\n            int dir = -1;\n            if (c == 'U') dir = 0; else if (c == 'D') dir = 1;\n            else if (c == 'L') dir = 2; else if (c == 'R') dir = 3;\n            temp.r += DX[dir]; temp.c += DY[dir];\n            visit_pos(temp);\n        }\n        current = best_p;\n        visit_pos(current);\n    }\n\n    // Return to start\n    if (current.r != SI || current.c != SJ) {\n        vector<vector<int>> dist, parent;\n        get_dist_matrix(current, dist, parent);\n        string sub = get_path_str(current, {SI, SJ}, parent);\n        full_path += sub;\n        total_cost += dist[SI][SJ];\n    }\n\n    Result res;\n    res.path = full_path;\n    res.time_cost = max(1, total_cost);\n    res.score = 10000 + (long long)(1e7 * N / res.time_cost);\n    return res;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    parse_input();\n\n    auto start_clock = chrono::high_resolution_clock::now();\n    double time_limit = 2.9;\n\n    Result best_res;\n    best_res.score = -1;\n\n    int seed = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_clock;\n        if (elapsed.count() > time_limit) break;\n\n        Result res = solve(seed++);\n        if (res.score > best_res.score) {\n            best_res = res;\n        }\n    }\n\n    cout << best_res.path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Structure to hold Task information\nstruct Task {\n    int id;\n    vector<int> d; // Required skill levels\n    vector<int> children; // Dependent tasks\n    int unresolved_deps; // Count of unsatisfied dependencies\n    double est_avg_duration; // Estimated duration based on average skills\n    double cpm_height; // Critical Path Height (priority)\n};\n\n// Structure to hold Member information\nstruct Member {\n    int id;\n    vector<int> s; // Estimated skill levels\n    vector<pair<int, int>> history; // Log of (task_id, actual_duration)\n    int current_task; // Currently assigned task ID, -1 if free\n    int start_day; // Day the current task started\n};\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<int> task_status; // 0: waiting, 1: running, 2: completed\nmt19937 rng(5489);\n\n// Calculate workload w_{i,j} = sum(max(0, d_{i,k} - s_{j,k}))\nint calc_w(const vector<int>& d, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; ++k) {\n        w += max(0, d[k] - s[k]);\n    }\n    return w;\n}\n\n// Predict days needed based on workload w\n// If w=0, t=1. If w>0, t ~ w.\nint predict_days(int w) {\n    if (w == 0) return 1;\n    return max(1, w);\n}\n\n// Update the skill estimates for a member using randomized local search (Coordinate Descent)\n// Minimizes error between predicted w and bounds derived from actual duration\nvoid update_member_skills(int m_idx) {\n    Member& m = members[m_idx];\n    \n    // Error function: sum of squared distances from valid ranges\n    auto error_func = [&](const vector<int>& s_curr) -> long long {\n        long long err = 0;\n        for (auto& h : m.history) {\n            int tid = h.first;\n            int actual = h.second;\n            int w = calc_w(tasks[tid].d, s_curr);\n            \n            // Constraints derived from problem statement:\n            // t = 1 => w <= 4\n            // t > 1 => t - 3 <= w <= t + 3\n            int lb, ub;\n            if (actual == 1) {\n                lb = 0; ub = 4;\n            } else {\n                lb = max(0, actual - 3);\n                ub = actual + 3;\n            }\n            \n            if (w < lb) err += (long long)(lb - w) * (lb - w);\n            else if (w > ub) err += (long long)(w - ub) * (w - ub);\n        }\n        return err;\n    };\n\n    long long current_err = error_func(m.s);\n    \n    // Iterate to improve skill estimation\n    int iterations = 600; \n    \n    for (int iter = 0; iter < iterations; ++iter) {\n        int k = rng() % K;\n        int original = m.s[k];\n        int best_val = original;\n        long long best_err = current_err;\n        \n        // Try small perturbations\n        for (int delta : {-2, -1, 1, 2}) {\n            int next_val = original + delta;\n            if (next_val < 0) continue; // Skills must be non-negative\n            \n            m.s[k] = next_val;\n            long long new_err = error_func(m.s);\n            \n            if (new_err < best_err) {\n                best_err = new_err;\n                best_val = next_val;\n            } else if (new_err == best_err) {\n                // Regularization tie-break: prefer lower skills to avoid overestimation\n                if (next_val < best_val) best_val = next_val;\n            }\n            m.s[k] = original; // Revert for next iteration\n        }\n        \n        if (best_val != original) {\n            m.s[k] = best_val;\n            current_err = best_err;\n        }\n    }\n}\n\n// Recompute Critical Path priorities based on current skill estimates\nvoid update_cpm() {\n    // 1. Compute average skill vector across all members\n    vector<int> avg_s(K, 0);\n    for (int j = 0; j < M; ++j) {\n        for (int k = 0; k < K; ++k) avg_s[k] += members[j].s[k];\n    }\n    for (int k = 0; k < K; ++k) avg_s[k] /= M;\n\n    // 2. Estimate duration for each task using average skills\n    for (int i = 0; i < N; ++i) {\n        int w = calc_w(tasks[i].d, avg_s);\n        tasks[i].est_avg_duration = (double)predict_days(w);\n    }\n\n    // 3. Compute CPM Height (Longest path to sink in DAG) using Memoization\n    vector<double> memo(N, -1.0);\n    auto get_h = [&](auto&& self, int u) -> double {\n        if (memo[u] >= 0) return memo[u];\n        double max_child_h = 0;\n        for (int v : tasks[u].children) {\n            max_child_h = max(max_child_h, self(self, v));\n        }\n        return memo[u] = tasks[u].est_avg_duration + max_child_h;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        tasks[i].cpm_height = get_h(get_h, i);\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) cin >> tasks[i].d[k];\n        tasks[i].unresolved_deps = 0;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; // 0-based indexing\n        tasks[u].children.push_back(v);\n        tasks[v].unresolved_deps++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].s.assign(K, 0);\n        members[i].current_task = -1;\n    }\n\n    task_status.assign(N, 0);\n    \n    // Initial CPM calculation\n    update_cpm();\n\n    int day = 0;\n\n    // Simulation Loop\n    while (true) {\n        day++;\n        \n        // 1. Identify available tasks and free members\n        vector<int> available_tasks;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 0 && tasks[i].unresolved_deps == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        vector<int> free_members;\n        for (int i = 0; i < M; ++i) {\n            if (members[i].current_task == -1) {\n                free_members.push_back(i);\n            }\n        }\n\n        // 2. Sort tasks by Priority (CPM Height)\n        update_cpm(); // Refresh priorities with latest skill info\n        sort(available_tasks.begin(), available_tasks.end(), [&](int a, int b) {\n            return tasks[a].cpm_height > tasks[b].cpm_height;\n        });\n\n        // 3. Greedy Assignment: Critical Tasks to Best Fit Members\n        vector<pair<int, int>> commands;\n        vector<bool> member_taken(M, false);\n\n        for (int t_id : available_tasks) {\n            int best_m = -1;\n            int min_days = 1e9;\n            long long best_waste = 1e18; // Metric to save experts\n\n            for (int m_id : free_members) {\n                if (member_taken[m_id]) continue;\n\n                int pred_days = predict_days(calc_w(tasks[t_id].d, members[m_id].s));\n                \n                // Calculate total skill of member as a proxy for \"expertise\"\n                long long current_sum_s = 0;\n                for (int val : members[m_id].s) current_sum_s += val;\n\n                if (pred_days < min_days) {\n                    min_days = pred_days;\n                    best_m = m_id;\n                    best_waste = current_sum_s;\n                } else if (pred_days == min_days) {\n                    // Tie-break: Choose member with LESS skill sum to save experts for harder tasks\n                    if (current_sum_s < best_waste) {\n                        best_m = m_id;\n                        best_waste = current_sum_s;\n                    }\n                }\n            }\n\n            if (best_m != -1) {\n                commands.push_back({best_m, t_id});\n                member_taken[best_m] = true;\n            }\n        }\n\n        // 4. Output Assignments\n        cout << commands.size();\n        for (auto& p : commands) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n            members[p.first].current_task = p.second;\n            members[p.first].start_day = day;\n            task_status[p.second] = 1; \n        }\n        cout << endl; // Flush output\n\n        // 5. Read Daily Completions\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break; // End of simulation\n\n        for (int i = 0; i < n_finished; ++i) {\n            int m_id_in; cin >> m_id_in;\n            int m_id = m_id_in - 1;\n            \n            int t_id = members[m_id].current_task;\n            int duration = day - members[m_id].start_day + 1;\n            \n            // Record history\n            members[m_id].history.push_back({t_id, duration});\n            members[m_id].current_task = -1;\n            \n            // Update Task Status and Dependencies\n            task_status[t_id] = 2;\n            \n            for (int child : tasks[t_id].children) {\n                tasks[child].unresolved_deps--;\n            }\n            \n            // Learn Skills\n            update_member_skills(m_id);\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <set>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconst int NUM_ORDERS = 1000;\nconst int TARGET_ORDERS = 50;\nconst int OFFICE_X = 400;\nconst int OFFICE_Y = 400;\n\n// Data structures\nstruct Order {\n    int id;\n    int a, b, c, d; // (a,b) pickup, (c,d) delivery\n};\n\nstruct Node {\n    int id; // Internal ID: 0..999 for Pickup, 1000..1999 for Delivery\n    int x, y;\n    bool is_pickup;\n    int order_idx;\n};\n\nstruct Solution {\n    vector<int> route; // Stores node IDs. Does not include Office.\n    bool selected[NUM_ORDERS];\n    int total_dist;\n};\n\n// Globals\nOrder orders[NUM_ORDERS];\n\n// Utils\ninline int dist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline Node get_node(int val) {\n    if (val < 1000) {\n        return {val, orders[val].a, orders[val].b, true, val};\n    } else {\n        return {val, orders[val - 1000].c, orders[val - 1000].d, false, val - 1000};\n    }\n}\n\n// Calculate total distance of a route\nint calc_route_dist(const vector<int>& route) {\n    int d = 0;\n    int cx = OFFICE_X;\n    int cy = OFFICE_Y;\n    for (int val : route) {\n        Node n = get_node(val);\n        d += dist(cx, cy, n.x, n.y);\n        cx = n.x;\n        cy = n.y;\n    }\n    d += dist(cx, cy, OFFICE_X, OFFICE_Y);\n    return d;\n}\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        return next() % n;\n    }\n    double next_double() {\n        return next() / 4294967295.0;\n    }\n} rng;\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Read Input\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        orders[i].id = i;\n        cin >> orders[i].a >> orders[i].b >> orders[i].c >> orders[i].d;\n    }\n\n    // Initial Solution Construction\n    Solution curr_sol;\n    fill(curr_sol.selected, curr_sol.selected + NUM_ORDERS, false);\n    \n    // Heuristic: Find order closest to office to start a cluster\n    int start_order = -1;\n    int min_d = 1e9;\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        int d = dist(OFFICE_X, OFFICE_Y, orders[i].a, orders[i].b);\n        if(d < min_d) {\n            min_d = d;\n            start_order = i;\n        }\n    }\n    \n    // Select 50 orders based on proximity to the start_order\n    vector<pair<int,int>> dists;\n    dists.reserve(NUM_ORDERS);\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        // Distance metric: dist(start_P, i_P)\n        int d = dist(orders[start_order].a, orders[start_order].b, orders[i].a, orders[i].b); \n        dists.push_back({d, i});\n    }\n    sort(dists.begin(), dists.end());\n    \n    for(int k=0; k<TARGET_ORDERS; ++k) {\n        int idx = dists[k].second;\n        curr_sol.selected[idx] = true;\n        curr_sol.route.push_back(idx);        // Pickup\n        curr_sol.route.push_back(idx + 1000); // Delivery\n    }\n    \n    curr_sol.total_dist = calc_route_dist(curr_sol.route);\n    Solution best_sol = curr_sol;\n\n    // Simulated Annealing\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95;\n    double temp_start = 200.0;\n    double temp_end = 1.0;\n    \n    int iter = 0;\n    \n    // Pos array for quick lookups in validity checks\n    vector<int> pos_cache(2000); \n\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            chrono::duration<double> diff = now - start_time;\n            if (diff.count() > time_limit) break;\n        }\n        \n        // Temperature Schedule\n        // Simple linear interpolation based on time isn't strictly exponential but works well\n        auto now = chrono::high_resolution_clock::now();\n        double progress = (now - start_time).count() / 1e9 / time_limit; \n        // Actually proper annealing uses exponential decay\n        double cur_time = (double)(iter) / 500000.0; // approximate scaling\n        if (progress > 1.0) break;\n        \n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int type = rng.next_int(100);\n        \n        if (type < 15) { \n            // ==========================================\n            // Move Type 1: Swap Order (Remove one, Add one)\n            // ==========================================\n            \n            // 1. Pick random order to remove from route\n            int r_idx = rng.next_int(curr_sol.route.size());\n            int val = curr_sol.route[r_idx];\n            int rem_order = (val < 1000) ? val : val - 1000;\n            \n            // 2. Remove P and D from temporary route\n            vector<int> next_route = curr_sol.route;\n            // Remove larger index first to keep smaller index valid\n            int p_pos = -1, d_pos = -1;\n            for(size_t i=0; i<next_route.size(); ++i) {\n                int ov = next_route[i];\n                if (ov == rem_order) p_pos = i;\n                else if (ov == rem_order + 1000) d_pos = i;\n            }\n            \n            if (d_pos > p_pos) {\n                next_route.erase(next_route.begin() + d_pos);\n                next_route.erase(next_route.begin() + p_pos);\n            } else {\n                next_route.erase(next_route.begin() + p_pos);\n                next_route.erase(next_route.begin() + d_pos);\n            }\n            \n            // 3. Pick random new order\n            int new_order = -1;\n            while(true) {\n                int cand = rng.next_int(NUM_ORDERS);\n                if (!curr_sol.selected[cand]) {\n                    new_order = cand;\n                    break;\n                }\n            }\n            \n            // 4. Greedy Insertion: Find best valid positions for P and D of new_order\n            // We need to insert P at i, D at j (j >= i).\n            \n            // Calculate base distance of the route without the new order\n            int base_dist = calc_route_dist(next_route);\n            \n            Node P = get_node(new_order);\n            Node D = get_node(new_order + 1000);\n            \n            int best_cost = 2e9;\n            int best_i = -1, best_j = -1;\n            \n            int n_size = next_route.size();\n            \n            // Optimization: Pre-calculate node coordinates for fast access\n            // Adding Office at start and end virtually\n            \n            for(int i=0; i<=n_size; ++i) {\n                // Context for P insertion: between (i-1) and (i)\n                int prev_x = (i==0) ? OFFICE_X : get_node(next_route[i-1]).x;\n                int prev_y = (i==0) ? OFFICE_Y : get_node(next_route[i-1]).y;\n                int next_x = (i==n_size) ? OFFICE_X : get_node(next_route[i]).x;\n                int next_y = (i==n_size) ? OFFICE_Y : get_node(next_route[i]).y;\n                \n                // Delta for inserting P\n                int delta_P = dist(prev_x, prev_y, P.x, P.y) + dist(P.x, P.y, next_x, next_y) \n                              - dist(prev_x, prev_y, next_x, next_y);\n                \n                // Pruning: if delta_P alone makes it worse than best known, maybe skip? \n                // No, because D insertion adds cost, so cost always increases.\n                \n                // Try inserting D at j >= i\n                // If j == i, D is inserted immediately after P.\n                // If j > i, D is inserted at position j in the *original* next_route indices\n                // which corresponds to between next_route[j-1] and next_route[j].\n                \n                for(int j=i; j<=n_size; ++j) {\n                    int current_val = base_dist + delta_P;\n                    int delta_D = 0;\n                    \n                    if (j == i) {\n                        // Sequence: prev -> P -> D -> next\n                        // Currently delta_P accounts for prev->P->next.\n                        // We need to change P->next to P->D->next.\n                        delta_D = dist(P.x, P.y, D.x, D.y) + dist(D.x, D.y, next_x, next_y)\n                                  - dist(P.x, P.y, next_x, next_y);\n                    } else {\n                        // Sequence around j (j > i): node[j-1] -> D -> node[j]\n                        int d_prev_x = get_node(next_route[j-1]).x;\n                        int d_prev_y = get_node(next_route[j-1]).y;\n                        int d_next_x = (j==n_size) ? OFFICE_X : get_node(next_route[j]).x;\n                        int d_next_y = (j==n_size) ? OFFICE_Y : get_node(next_route[j]).y;\n                        \n                        delta_D = dist(d_prev_x, d_prev_y, D.x, D.y) + dist(D.x, D.y, d_next_x, d_next_y)\n                                  - dist(d_prev_x, d_prev_y, d_next_x, d_next_y);\n                    }\n                    \n                    if (current_val + delta_D < best_cost) {\n                        best_cost = current_val + delta_D;\n                        best_i = i;\n                        best_j = j;\n                    }\n                }\n            }\n            \n            int delta = best_cost - curr_sol.total_dist;\n            if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                curr_sol.selected[rem_order] = false;\n                curr_sol.selected[new_order] = true;\n                curr_sol.route = next_route;\n                curr_sol.route.insert(curr_sol.route.begin() + best_i, new_order);\n                // Since P inserted at i, indices >= i shift by 1. \n                // If j was index in next_route, now it's j+1 relative to new array start\n                // Exception: if j=i, we insert D after P, so at i+1.\n                // If j > i, we insert after original j-1 (now j), so at j+1.\n                curr_sol.route.insert(curr_sol.route.begin() + best_j + 1, new_order + 1000);\n                curr_sol.total_dist = best_cost;\n                \n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 65) {\n            // ==========================================\n            // Move Type 2: 2-opt (Reverse segment)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int l = rng.next_int(sz - 1);\n            int r = rng.next_int(sz - l - 1) + l + 1; // l < r < sz\n            \n            // Validity Check: Reversed segment [l, r] must not contain P_k and D_k for any k.\n            // Efficient check:\n            bool valid = true;\n            \n            // Fill cache for current route positions\n            for(int k=0; k<sz; ++k) pos_cache[curr_sol.route[k]] = k;\n            \n            for(int k=l; k<=r; ++k) {\n                int val = curr_sol.route[k];\n                int partner = (val < 1000) ? val + 1000 : val - 1000;\n                // If partner is also in [l, r], invalid\n                int p_idx = pos_cache[partner];\n                if (p_idx >= l && p_idx <= r) {\n                    valid = false;\n                    break;\n                }\n            }\n            \n            if (valid) {\n                Node n_prev = (l==0) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[l-1]);\n                Node n_l = get_node(curr_sol.route[l]);\n                Node n_r = get_node(curr_sol.route[r]);\n                Node n_next = (r==sz-1) ? Node{-1, OFFICE_X, OFFICE_Y, false, -1} : get_node(curr_sol.route[r+1]);\n                \n                int cur_seg = dist(n_prev.x, n_prev.y, n_l.x, n_l.y) + dist(n_r.x, n_r.y, n_next.x, n_next.y);\n                int new_seg = dist(n_prev.x, n_prev.y, n_r.x, n_r.y) + dist(n_l.x, n_l.y, n_next.x, n_next.y);\n                \n                int delta = new_seg - cur_seg;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    reverse(curr_sol.route.begin() + l, curr_sol.route.begin() + r + 1);\n                    curr_sol.total_dist += delta;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n\n        } else {\n            // ==========================================\n            // Move Type 3: Relocate (Move single node)\n            // ==========================================\n            int sz = curr_sol.route.size();\n            int u = rng.next_int(sz); // Node to move\n            int v = rng.next_int(sz); // Target: insert after v (if v=-1, start)\n            // To simplify, let's say we pick index `ins_idx` in the route *after removal*.\n            // Range 0 to sz-1.\n            \n            if (u == v) continue;\n            \n            // Logic: remove u, insert at v (relative to original indices is tricky).\n            // Let's form candidate vector to check validity/cost simply,\n            // relying on vector speed for small N=100.\n            \n            vector<int> next_route = curr_sol.route;\n            int val = next_route[u];\n            next_route.erase(next_route.begin() + u);\n            \n            // Insert position logic: \n            // We picked random v in range [0, sz-1].\n            // We interpret v as the index to insert *at* in the reduced vector.\n            int ins_idx = v; \n            if (ins_idx > (int)next_route.size()) ins_idx = next_route.size();\n            \n            // Precedence check\n            int partner = (val < 1000) ? val + 1000 : val - 1000;\n            int p_idx = -1;\n            for(int k=0; k<(int)next_route.size(); ++k) {\n                if (next_route[k] == partner) { p_idx = k; break; }\n            }\n            \n            bool ok = true;\n            if (val < 1000) { // Moving Pickup\n                // Must be before Delivery (p_idx)\n                if (ins_idx > p_idx) ok = false;\n            } else { // Moving Delivery\n                // Must be after Pickup (p_idx)\n                if (ins_idx <= p_idx) ok = false;\n            }\n            \n            if (ok) {\n                next_route.insert(next_route.begin() + ins_idx, val);\n                int new_dist = calc_route_dist(next_route);\n                int delta = new_dist - curr_sol.total_dist;\n                \n                if (delta <= 0 || rng.next_double() < exp(-delta / temp)) {\n                    curr_sol.route = next_route;\n                    curr_sol.total_dist = new_dist;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n        }\n    }\n\n    // Output Formatting\n    // 1. Output m and selected orders\n    vector<int> selected_ids;\n    set<int> seen;\n    for(int val : best_sol.route) {\n        int ord = (val < 1000) ? val : val - 1000;\n        if(seen.find(ord) == seen.end()) {\n            selected_ids.push_back(ord + 1); // 1-based index for output\n            seen.insert(ord);\n        }\n    }\n    \n    cout << selected_ids.size();\n    for(int id : selected_ids) cout << \" \" << id;\n    cout << \"\\n\";\n    \n    // 2. Output route coordinates\n    cout << best_sol.route.size() + 2 << \" \" << OFFICE_X << \" \" << OFFICE_Y;\n    for(int val : best_sol.route) {\n        Node n = get_node(val);\n        cout << \" \" << n.x << \" \" << n.y;\n    }\n    cout << \" \" << OFFICE_X << \" \" << OFFICE_Y << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\n// --- Constants ---\nconst int DEFAULT_N = 400;\nconst int DEFAULT_M = 1995;\n\n// --- Data Structures ---\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n    int id;\n};\n\n// Structure for simulation edges (connecting components)\nstruct SimEdge {\n    int u_c, v_c; // Component leaders\n    int d_val;    // Minimum distance\n    int w_val;    // Randomized weight\n};\n\n// Self-contained Disjoint Set Union (DSU)\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int i) {\n        if (parent[i] == i) return i;\n        return parent[i] = find(parent[i]); // Path compression\n    }\n    bool unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n            return true;\n        }\n        return false;\n    }\n    bool same(int i, int j) {\n        return find(i) == find(j);\n    }\n};\n\n// --- Globals ---\nint N, M;\nvector<Point> points;\nvector<Edge> all_edges;\nmt19937 rng(12345); // Fixed seed for reproducibility\nconst double TIME_LIMIT = 1.85; // 2.0s limit with safety margin\nauto start_time = chrono::high_resolution_clock::now();\n\n// --- Helper Functions ---\n\n// Calculate rounded Euclidean distance\nint calc_dist(int i, int j) {\n    long long dx = points[i].x - points[j].x;\n    long long dy = points[i].y - points[j].y;\n    return (int)round(sqrt(dx*dx + dy*dy));\n}\n\n// BFS to find the maximum edge weight on the path between start and target in the MST\nint get_path_max(int start, int target, int n_nodes, const vector<vector<pair<int, int>>>& adj) {\n    vector<int> q;\n    q.reserve(n_nodes);\n    vector<int> dist(n_nodes, -1); \n    vector<bool> visited(n_nodes, false);\n    \n    q.push_back(start);\n    visited[start] = true;\n    dist[start] = 0;\n    \n    int head = 0;\n    while(head < (int)q.size()){\n        int u = q[head++];\n        if (u == target) return dist[u];\n        \n        for(auto& edge : adj[u]){\n            int v = edge.first;\n            int w = edge.second;\n            if(!visited[v]){\n                visited[v] = true;\n                dist[v] = max(dist[u], w);\n                q.push_back(v);\n            }\n        }\n    }\n    return 1000000000; // Return large value if unconnected\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    // cin.tie(NULL); // Interactive problem, we will flush manually using endl\n\n    // --- Robust Input Reading ---\n    // The problem statement format is ambiguous regarding N and M.\n    // We read the first two integers and decide based on their values.\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n    \n    // Coordinates are <= 800. M is 1995. \n    // If the second number is > 800, it must be M (implies format is N M).\n    if (b > 800) {\n        N = a;\n        M = b;\n        points.resize(N);\n        for(int i=0; i<N; ++i) cin >> points[i].x >> points[i].y;\n    } else {\n        // Format is x0 y0, implying N and M are fixed\n        N = DEFAULT_N;\n        M = DEFAULT_M;\n        points.resize(N);\n        points[0].x = a;\n        points[0].y = b;\n        for(int i=1; i<N; ++i) cin >> points[i].x >> points[i].y;\n    }\n\n    all_edges.resize(M);\n    for(int i=0; i<M; ++i) {\n        cin >> all_edges[i].u >> all_edges[i].v;\n        all_edges[i].d = calc_dist(all_edges[i].u, all_edges[i].v);\n        all_edges[i].id = i;\n    }\n\n    // --- Initialization ---\n    DSU main_dsu(N); // Tracks confirmed connections\n    int components = N;\n\n    // Pre-allocate buffers for simulation\n    vector<SimEdge> valid_edges;\n    valid_edges.reserve(M);\n    vector<SimEdge> sim_candidates;\n    sim_candidates.reserve(M);\n    \n    vector<vector<int>> bridge_adj(N);\n    vector<vector<pair<int, int>>> mst_adj(N);\n    DSU sim_dsu(N);\n\n    // --- Main Interactive Loop ---\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i; // Read current edge length\n\n        int u = all_edges[i].u;\n        int v = all_edges[i].v;\n        \n        // 1. Cycle Check: If u and v are already connected, reject immediately.\n        if (main_dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        // Identify all future edges that connect *different* components in the current state\n        valid_edges.clear();\n        for (int j = i + 1; j < M; ++j) {\n            int root_u = main_dsu.find(all_edges[j].u);\n            int root_v = main_dsu.find(all_edges[j].v);\n            if (root_u != root_v) {\n                valid_edges.push_back({root_u, root_v, all_edges[j].d, 0});\n            }\n        }\n\n        int root_u = main_dsu.find(u);\n        int root_v = main_dsu.find(v);\n\n        // 2. Bridge Check: Verify if rejecting this edge makes connectivity impossible later\n        for(int k=0; k<N; ++k) bridge_adj[k].clear();\n        for(const auto& e : valid_edges) {\n            bridge_adj[e.u_c].push_back(e.v_c);\n            bridge_adj[e.v_c].push_back(e.u_c);\n        }\n        \n        // BFS to check if root_u and root_v are connected via future edges\n        vector<int> q; q.push_back(root_u);\n        vector<bool> vis(N, false); vis[root_u] = true;\n        bool bridge_connected = false;\n        int head = 0;\n        while(head < (int)q.size()){\n            int curr = q[head++];\n            if(curr == root_v){\n                bridge_connected = true;\n                break;\n            }\n            for(int nxt : bridge_adj[curr]){\n                if(!vis[nxt]){\n                    vis[nxt] = true;\n                    q.push_back(nxt);\n                }\n            }\n        }\n\n        // If not connected via future edges, this edge is critical (Bridge). Accept it.\n        if (!bridge_connected) {\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            components--;\n            continue;\n        }\n\n        // 3. Monte Carlo Simulation\n        // Filter candidates: Sort by min distance (d) and keep the best K edges.\n        // This speeds up the MST calculation significantly.\n        sort(valid_edges.begin(), valid_edges.end(), [](const SimEdge& a, const SimEdge& b){\n            return a.d_val < b.d_val;\n        });\n\n        // We need enough edges to form a tree (components-1), plus some buffer for randomness.\n        int keep_count = min((int)valid_edges.size(), max(2 * components, 50));\n        sim_candidates.clear();\n        for(int k=0; k<keep_count; ++k) sim_candidates.push_back(valid_edges[k]);\n\n        long long sum_path_max = 0;\n        int sims = 0;\n        \n        // Time Budgeting: Allocate remaining time proportionally to remaining steps\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        double rem = TIME_LIMIT - elapsed.count();\n        double step_budget = rem / (M - i + 10); \n        \n        auto step_start = chrono::high_resolution_clock::now();\n\n        while(true) {\n            sims++;\n            \n            // Assign random weights for future edges: l ~ Uniform[d, 3d]\n            for(auto& e : sim_candidates) {\n                unsigned int r = rng();\n                e.w_val = e.d_val + (r % (2 * e.d_val + 1));\n            }\n            \n            // Sort by random weight for Kruskal's\n            sort(sim_candidates.begin(), sim_candidates.end(), [](const SimEdge& a, const SimEdge& b){\n                return a.w_val < b.w_val;\n            });\n\n            // Build MST on the component graph\n            // Reset simulation DSU\n            for(int k=0; k<N; ++k) sim_dsu.parent[k] = k;\n            for(int k=0; k<N; ++k) mst_adj[k].clear();\n\n            for(const auto& e : sim_candidates) {\n                if (sim_dsu.unite(e.u_c, e.v_c)) {\n                    mst_adj[e.u_c].push_back({e.v_c, e.w_val});\n                    mst_adj[e.v_c].push_back({e.u_c, e.w_val});\n                }\n            }\n            \n            // Find the max weight on the path between current components U and V in this MST\n            int path_max = get_path_max(root_u, root_v, N, mst_adj);\n            \n            if (path_max > 1000000) path_max = 1000000; // Cap large values\n            sum_path_max += path_max;\n\n            // Check time budget periodically\n            if ((sims & 31) == 0) { \n                auto curr = chrono::high_resolution_clock::now();\n                chrono::duration<double> d = curr - step_start;\n                if (d.count() > step_budget) break;\n            }\n        }\n        \n        // Decision: Compare current length with expected max edge on the alternative path\n        double threshold = (sims > 0) ? (double)sum_path_max / sims : 1e9;\n        \n        if (l_i < threshold) {\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            components--;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"/**\n * AtCoder Heuristic Contest 008\n * Solution: Robust Honeycomb Trap with Strict Conflict Resolution\n * \n * Strategy:\n * 1. Layout: We overlay a skeleton of \"rooms\" (approx 5x5 size) on the 30x30 grid.\n *    - Walls are planned at specific rows/cols.\n *    - Gates are planned at the centers of these wall segments.\n * 2. Dynamic Logic:\n *    - We detect \"Dirty\" components (containing pets) and \"Clean\" components.\n *    - We assign priorities: \n *      a. ESCAPE: Humans in dirty rooms must leave.\n *      b. TRAP: Close gates connecting dirty rooms to clean rooms.\n *      c. BUILD: Construct the skeleton.\n * 3. Safety & Conflict Resolution:\n *    - Strict checks to ensure no two humans move to the same square.\n *    - Strict checks to ensure no human moves into a wall being built in the same turn.\n *    - A conservative reservation system ensures that high-priority movers do not displace \n *      low-priority waiters (preventing the \"moving to occupied square\" error).\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --- Constants & Utils ---\nconst int N_ROWS = 30;\nconst int N_COLS = 30;\nconst int MAX_TURNS = 300;\n\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'}; \n\nstruct Pet {\n    int id;\n    int r, c; \n    int type;\n};\n\nstruct Human {\n    int id;\n    int r, c;\n};\n\nstruct State {\n    vector<Pet> pets;\n    vector<Human> humans;\n    bool walls[N_ROWS][N_COLS];\n};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_ROWS && c >= 0 && c < N_COLS;\n}\n\n// --- Strategic Plan ---\nbool plan_skeleton[N_ROWS][N_COLS];\nbool plan_gate[N_ROWS][N_COLS]; // True if this wall part is a gate (initially open)\n\nvoid init_plan() {\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c) {\n            plan_skeleton[r][c] = false;\n            plan_gate[r][c] = false;\n        }\n\n    // Create a grid of walls. \n    // Lines at indices: 5, 11, 17, 23. \n    // This creates 5x5 and 4x5 sized regions.\n    vector<int> lines = {5, 11, 17, 23};\n    \n    for (int r : lines) {\n        for (int c = 0; c < N_COLS; ++c) plan_skeleton[r][c] = true;\n    }\n    for (int c : lines) {\n        for (int r = 0; r < N_ROWS; ++r) plan_skeleton[r][c] = true;\n    }\n    \n    // Define Gates at midpoints of wall segments\n    // Segments: 0-4, 6-10, 12-16, 18-22, 24-29\n    // Mids: 2, 8, 14, 20, 27\n    vector<int> mids = {2, 8, 14, 20, 27};\n    \n    for(int r : lines) {\n        for(int m : mids) plan_gate[r][m] = true;\n    }\n    for(int c : lines) {\n        for(int m : mids) plan_gate[m][c] = true;\n    }\n    \n    // Intersections are always solid walls\n    for(int r : lines) {\n        for(int c : lines) plan_gate[r][c] = false;\n    }\n}\n\n// --- Analysis Helpers ---\n\nstruct Component {\n    int id;\n    bool has_pet = false;\n    vector<pair<int,int>> cells;\n};\n\nvoid get_components(const State& st, vector<vector<int>>& id_map, vector<Component>& comps) {\n    id_map.assign(N_ROWS, vector<int>(N_COLS, -1));\n    comps.clear();\n    \n    for(int r=0; r<N_ROWS; ++r){\n        for(int c=0; c<N_COLS; ++c){\n            if(!st.walls[r][c] && id_map[r][c] == -1){\n                int cid = comps.size();\n                Component comp;\n                comp.id = cid;\n                \n                queue<pair<int,int>> q;\n                q.push({r,c});\n                id_map[r][c] = cid;\n                \n                while(!q.empty()){\n                    auto [cr, cc] = q.front();\n                    q.pop();\n                    comp.cells.push_back({cr, cc});\n                    \n                    for(int i=0; i<4; ++i){\n                        int nr = cr + DR[i];\n                        int nc = cc + DC[i];\n                        if(is_valid(nr, nc) && !st.walls[nr][nc] && id_map[nr][nc] == -1){\n                            id_map[nr][nc] = cid;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                comps.push_back(comp);\n            }\n        }\n    }\n    \n    for(const auto& p : st.pets) {\n        if(id_map[p.r][p.c] != -1) comps[id_map[p.r][p.c]].has_pet = true;\n    }\n}\n\n// BFS pathfinding with strict reservation checks\n// Returns direction index (0-3) or -1\nint bfs_move(int sr, int sc, const vector<pair<int,int>>& targets, \n             const State& st, \n             const vector<vector<bool>>& reserved_next_pos, \n             const vector<vector<bool>>& reserved_new_wall,\n             const vector<bool>& processed_agents) {\n    \n    if(targets.empty()) return -1;\n\n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    \n    vector<vector<int>> dist(N_ROWS, vector<int>(N_COLS, 1e9));\n    vector<vector<pair<int,int>>> parent(N_ROWS, vector<pair<int,int>>(N_COLS, {-1,-1}));\n    \n    dist[sr][sc] = 0;\n    bool found = false;\n    int er = -1, ec = -1;\n    \n    // Optimization: Check targets quickly\n    static int target_mark[N_ROWS][N_COLS];\n    static int mark_counter = 0;\n    mark_counter++;\n    for(auto& t : targets) target_mark[t.first][t.second] = mark_counter;\n    \n    while(!q.empty()){\n        auto [cr, cc] = q.front();\n        q.pop();\n        \n        if(target_mark[cr][cc] == mark_counter){\n            found = true;\n            er = cr; ec = cc;\n            break;\n        }\n        \n        for(int i=0; i<4; ++i){\n            int nr = cr + DR[i];\n            int nc = cc + DC[i];\n            \n            if(!is_valid(nr, nc)) continue;\n            if(st.walls[nr][nc]) continue;\n            \n            // Check dynamic obstacles only for the immediate next step (t+1)\n            if(dist[cr][cc] == 0) {\n                // Cannot move into a new wall\n                if(reserved_new_wall[nr][nc]) continue;\n                // Cannot move into a spot reserved by a processed agent\n                if(reserved_next_pos[nr][nc]) continue;\n                \n                // Conservative Check: Cannot move into a spot occupied by an unprocessed agent\n                // (Because that agent might stay)\n                bool collision = false;\n                for(const auto& h : st.humans){\n                    if(!processed_agents[h.id] && h.r == nr && h.c == nc) collision = true;\n                }\n                if(collision) continue;\n            }\n            \n            if(dist[nr][nc] > dist[cr][cc] + 1){\n                dist[nr][nc] = dist[cr][cc] + 1;\n                parent[nr][nc] = {cr, cc};\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if(!found) return -1;\n    if(er == sr && ec == sc) return -1;\n    \n    // Backtrack\n    int cur_r = er, cur_c = ec;\n    while(parent[cur_r][cur_c].first != sr || parent[cur_r][cur_c].second != sc){\n        auto p = parent[cur_r][cur_c];\n        cur_r = p.first;\n        cur_c = p.second;\n    }\n    \n    for(int i=0; i<4; ++i){\n        if(sr + DR[i] == cur_r && sc + DC[i] == cur_c) return i;\n    }\n    return -1;\n}\n\n// --- Main Logic ---\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_plan();\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    \n    State state;\n    state.pets.resize(N);\n    for(int i=0; i<N; ++i){\n        state.pets[i].id = i;\n        cin >> state.pets[i].r >> state.pets[i].c >> state.pets[i].type;\n        state.pets[i].r--; state.pets[i].c--; \n    }\n    \n    int M;\n    cin >> M;\n    state.humans.resize(M);\n    for(int i=0; i<M; ++i){\n        state.humans[i].id = i;\n        cin >> state.humans[i].r >> state.humans[i].c;\n        state.humans[i].r--; state.humans[i].c--;\n    }\n    \n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c)\n            state.walls[r][c] = false;\n            \n    for(int turn=0; turn<MAX_TURNS; ++turn){\n        // 1. Component Analysis\n        vector<vector<int>> comp_map;\n        vector<Component> comps;\n        get_components(state, comp_map, comps);\n        \n        // Identify humans in danger\n        vector<bool> in_danger(M, false);\n        for(int i=0; i<M; ++i){\n            int cid = comp_map[state.humans[i].r][state.humans[i].c];\n            if(cid != -1 && comps[cid].has_pet) in_danger[i] = true;\n        }\n        \n        // 2. Generate Build Tasks\n        struct Task {\n            int r, c; // Wall location\n            int priority;\n        };\n        vector<Task> tasks;\n        \n        for(int r=0; r<N_ROWS; ++r){\n            for(int c=0; c<N_COLS; ++c){\n                if(state.walls[r][c]) continue;\n                if(!plan_skeleton[r][c]) continue;\n                \n                int prio = 0;\n                bool is_gate = plan_gate[r][c];\n                \n                // Check connectivity of this potential wall\n                set<int> adj_comps;\n                for(int k=0; k<4; ++k){\n                    int nr = r + DR[k];\n                    int nc = c + DC[k];\n                    if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                        if(comp_map[nr][nc] != -1) adj_comps.insert(comp_map[nr][nc]);\n                    }\n                }\n                \n                bool connects_dirty = false;\n                bool connects_clean = false;\n                for(int cid : adj_comps){\n                    if(comps[cid].has_pet) connects_dirty = true;\n                    else connects_clean = true;\n                }\n                \n                if(!is_gate) {\n                    prio = 50; \n                    if(connects_dirty) prio += 200; \n                } else {\n                    // Gate logic\n                    if(connects_dirty && connects_clean) prio = 1000; // MUST CLOSE\n                    else if(connects_dirty) prio = 500; // Contain dirty\n                    else prio = 10; // Clean area, keep low priority\n                }\n                \n                if(prio > 0) tasks.push_back({r, c, prio});\n            }\n        }\n        \n        // 3. Assign Agents to Plans\n        struct AgentPlan {\n            int h_idx;\n            int type; // 0: Wait, 1: Build, 2: Escape/Move\n            int target_r, target_c; \n            double score;\n        };\n        vector<AgentPlan> agents;\n        \n        auto get_dist = [&](int r1, int c1, int r2, int c2) {\n            return abs(r1 - r2) + abs(c1 - c2);\n        };\n        \n        for(int i=0; i<M; ++i){\n            AgentPlan p;\n            p.h_idx = i;\n            p.type = 0; \n            p.score = -1e9;\n            \n            if(in_danger[i]){\n                p.type = 2; \n                p.score = 100000; \n                p.target_r = -1; // Generic \"Safe Place\"\n            } else {\n                // Find best build task\n                for(const auto& t : tasks){\n                    // Verify safety (adjacent to pet rule)\n                    bool pet_adj = false;\n                    for(const auto& pt : state.pets) if(get_dist(t.r, t.c, pt.r, pt.c) <= 1) pet_adj = true;\n                    if(pet_adj) continue;\n                    \n                    // Verify no human stands on the wall site (current pos)\n                    bool human_on_site = false;\n                    for(const auto& h : state.humans) if(h.r == t.r && h.c == t.c) human_on_site = true;\n                    if(human_on_site) continue;\n                    \n                    int d = 1e9;\n                    for(int k=0; k<4; ++k){\n                        int nr = t.r + DR[k];\n                        int nc = t.c + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                            d = min(d, get_dist(state.humans[i].r, state.humans[i].c, nr, nc));\n                        }\n                    }\n                    \n                    if(d < 1e9){\n                        double s = t.priority * 100.0 - d;\n                        if(s > p.score){\n                            p.score = s;\n                            p.target_r = t.r;\n                            p.target_c = t.c;\n                            p.type = 1; // Build\n                        }\n                    }\n                }\n            }\n            agents.push_back(p);\n        }\n        \n        // Sort by score descending\n        sort(agents.begin(), agents.end(), [](const AgentPlan& a, const AgentPlan& b){\n            return a.score > b.score;\n        });\n        \n        // 4. Execute Plans with strict conflict checks\n        vector<string> res_actions(M, \".\");\n        vector<vector<bool>> reserved_next(N_ROWS, vector<bool>(N_COLS, false));\n        vector<vector<bool>> reserved_wall(N_ROWS, vector<bool>(N_COLS, false));\n        vector<bool> processed(M, false);\n        \n        // Note: reserved_next tracks FINALIZED positions.\n        // processed[id] tracks if human `id` has moved.\n        // Unprocessed humans are treated as obstacles at their current pos.\n        \n        for(const auto& ag : agents){\n            int i = ag.h_idx;\n            processed[i] = true; // Mark as processed\n            \n            int r = state.humans[i].r;\n            int c = state.humans[i].c;\n            bool done = false;\n            \n            // -- Type 2: Escape --\n            if(ag.type == 2){\n                vector<pair<int,int>> clean_targets;\n                for(const auto& comp : comps){\n                    if(!comp.has_pet) {\n                        for(auto cell : comp.cells) clean_targets.push_back(cell);\n                    }\n                }\n                \n                int dir = bfs_move(r, c, clean_targets, state, reserved_next, reserved_wall, processed);\n                if(dir != -1){\n                    int nr = r + DR[dir];\n                    int nc = c + DC[dir];\n                    res_actions[i] = string(1, MOVE_CHARS[dir]);\n                    reserved_next[nr][nc] = true;\n                    done = true;\n                }\n            }\n            // -- Type 1: Build --\n            else if(ag.type == 1){\n                int tr = ag.target_r;\n                int tc = ag.target_c;\n                \n                // Can build?\n                if(get_dist(r, c, tr, tc) == 1){\n                    bool ok = true;\n                    if(state.walls[tr][tc] || reserved_wall[tr][tc]) ok = false;\n                    // Pet adjacency check\n                    for(const auto& pt : state.pets) if(get_dist(tr, tc, pt.r, pt.c) <= 1) ok = false;\n                    // Human occupancy (processed)\n                    if(reserved_next[tr][tc]) ok = false;\n                    // Human occupancy (unprocessed)\n                    for(const auto& h : state.humans) if(!processed[h.id] && h.r == tr && h.c == tc) ok = false;\n                    \n                    if(ok){\n                        int b_dir = -1;\n                        for(int k=0; k<4; ++k) if(r+DR[k]==tr && c+DC[k]==tc) b_dir = k;\n                        \n                        res_actions[i] = string(1, BLOCK_CHARS[b_dir]);\n                        reserved_wall[tr][tc] = true;\n                        reserved_next[r][c] = true; // Stay\n                        done = true;\n                    }\n                }\n                \n                // Move to build spot\n                if(!done){\n                    vector<pair<int,int>> spots;\n                    for(int k=0; k<4; ++k){\n                        int nr = tr + DR[k];\n                        int nc = tc + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc]){\n                            spots.push_back({nr, nc});\n                        }\n                    }\n                    int dir = bfs_move(r, c, spots, state, reserved_next, reserved_wall, processed);\n                    if(dir != -1){\n                        int nr = r + DR[dir];\n                        int nc = c + DC[dir];\n                        res_actions[i] = string(1, MOVE_CHARS[dir]);\n                        reserved_next[nr][nc] = true;\n                        done = true;\n                    }\n                }\n            }\n            \n            // -- Default: Stay --\n            if(!done){\n                // Try to stay\n                if(!reserved_next[r][c]){\n                    // Double check nobody claimed it (should be covered by reserved_next)\n                    // Check new wall\n                    if(!reserved_wall[r][c]) {\n                        res_actions[i] = \".\";\n                        reserved_next[r][c] = true;\n                    } else {\n                        // Emergency: Someone built a wall on us (should be prevented by build checks, but just in case)\n                        // Try to move any adjacent free\n                        for(int k=0; k<4; ++k){\n                            int nr = r+DR[k];\n                            int nc = c+DC[k];\n                            if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc] && !reserved_next[nr][nc]){\n                                // And check unprocessed\n                                bool coll = false;\n                                for(const auto& h : state.humans) if(!processed[h.id] && h.r==nr && h.c==nc) coll = true;\n                                if(!coll){\n                                    res_actions[i] = string(1, MOVE_CHARS[k]);\n                                    reserved_next[nr][nc] = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output\n        string out_s = \"\";\n        for(const auto& s : res_actions) out_s += s;\n        cout << out_s << endl;\n        \n        // Update State\n        for(int i=0; i<M; ++i){\n            char c = res_actions[i][0];\n            if(c >= 'A' && c <= 'Z'){ \n                for(int k=0; k<4; ++k){\n                    if(MOVE_CHARS[k] == c){\n                        state.humans[i].r += DR[k];\n                        state.humans[i].c += DC[k];\n                    }\n                }\n            } else if(c >= 'a' && c <= 'z'){\n                 for(int k=0; k<4; ++k){\n                    if(BLOCK_CHARS[k] == c){\n                        state.walls[state.humans[i].r + DR[k]][state.humans[i].c + DC[k]] = true;\n                    }\n                }\n            }\n        }\n        \n        if(turn < MAX_TURNS){\n            string p_s;\n            for(int i=0; i<N; ++i){\n                cin >> p_s;\n                for(char c : p_s){\n                     for(int k=0; k<4; ++k){\n                        if(MOVE_CHARS[k] == c){\n                            state.pets[i].r += DR[k];\n                            state.pets[i].c += DC[k];\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_STEPS = 200;\nconst double EPS = 1e-12; \nconst int INITIAL_BEAM_WIDTH = 1500; \nconst double TIME_LIMIT = 1.90; // Margin for safety\n\n// Globals\nint Si, Sj, Ti, Tj;\ndouble P;\nint H[N][N-1]; \nint V[N-1][N]; \nint flat_dist[N*N];\nint next_pos_cache[N*N][4]; \n\n// Directions: U, D, L, R\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dchar[4] = {'U', 'D', 'L', 'R'};\n\nstruct Particle {\n    int u;\n    double p;\n};\n\nstruct State {\n    vector<Particle> dist; \n    double score; \n    double heuristic;\n    string path;\n};\n\nstruct Candidate {\n    double heuristic;\n    int parent_idx;\n    int move_k;\n};\n\n// Timing\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_elapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Precompute shortest path distances\nvoid bfs_distances() {\n    for(int i=0; i<N*N; ++i) flat_dist[i] = 100000;\n    queue<pair<int,int>> q;\n    flat_dist[Ti*N + Tj] = 0;\n    q.push({Ti, Tj});\n    \n    while(!q.empty()){\n        auto [r, c] = q.front();\n        q.pop();\n        int cur_d = flat_dist[r*N+c];\n        \n        if (r > 0 && V[r-1][c] == 0) {\n            int neighbor = (r-1)*N + c;\n            if (flat_dist[neighbor] > cur_d + 1) {\n                flat_dist[neighbor] = cur_d + 1;\n                q.push({r-1, c});\n            }\n        }\n        if (r < N-1 && V[r][c] == 0) {\n            int neighbor = (r+1)*N + c;\n            if (flat_dist[neighbor] > cur_d + 1) {\n                flat_dist[neighbor] = cur_d + 1;\n                q.push({r+1, c});\n            }\n        }\n        if (c > 0 && H[r][c-1] == 0) {\n            int neighbor = r*N + (c-1);\n            if (flat_dist[neighbor] > cur_d + 1) {\n                flat_dist[neighbor] = cur_d + 1;\n                q.push({r, c-1});\n            }\n        }\n        if (c < N-1 && H[r][c] == 0) {\n            int neighbor = r*N + (c+1);\n            if (flat_dist[neighbor] > cur_d + 1) {\n                flat_dist[neighbor] = cur_d + 1;\n                q.push({r, c+1});\n            }\n        }\n    }\n}\n\n// Precompute move outcomes\nvoid precompute_moves() {\n    for(int r=0; r<N; ++r){\n        for(int c=0; c<N; ++c){\n            int u = r*N + c;\n            for(int k=0; k<4; ++k){\n                bool blocked = false;\n                if(k == 0){ if(r == 0 || V[r-1][c] == 1) blocked = true; }\n                else if(k == 1){ if(r == N-1 || V[r][c] == 1) blocked = true; }\n                else if(k == 2){ if(c == 0 || H[r][c-1] == 1) blocked = true; }\n                else if(k == 3){ if(c == N-1 || H[r][c] == 1) blocked = true; }\n                \n                if(blocked) next_pos_cache[u][k] = u;\n                else next_pos_cache[u][k] = (r + dr[k])*N + (c + dc[k]);\n            }\n        }\n    }\n}\n\n// Static buffers to reduce allocation in hot loop\ndouble temp_probs[N*N];\nint touched_list[N*N]; \nint touched_cnt = 0;\n\nint main(){\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    if (!(cin >> Si >> Sj >> Ti >> Tj >> P)) return 0;\n\n    for(int i=0; i<N; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N-1; ++j) H[i][j] = s[j] - '0';\n    }\n    for(int i=0; i<N-1; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) V[i][j] = s[j] - '0';\n    }\n    \n    bfs_distances();\n    precompute_moves();\n    \n    // Init temp buffers\n    for(int i=0; i<N*N; ++i) temp_probs[i] = 0.0;\n\n    double inv_prob_move = 1.0 / (1.0 - P);\n    int target_u = Ti*N + Tj;\n\n    State initial;\n    initial.path = \"\";\n    initial.score = 0.0;\n    \n    if(Si == Ti && Sj == Tj) {\n        cout << \"\" << endl;\n        return 0;\n    }\n    \n    initial.dist.push_back({Si*N + Sj, 1.0});\n    initial.heuristic = 401.0 - (flat_dist[Si*N + Sj] * inv_prob_move);\n\n    vector<State> beam;\n    beam.reserve(INITIAL_BEAM_WIDTH);\n    beam.push_back(initial);\n    \n    int current_beam_width = INITIAL_BEAM_WIDTH;\n    vector<Candidate> candidates;\n    candidates.reserve(INITIAL_BEAM_WIDTH * 4);\n\n    for(int t=0; t<MAX_STEPS; ++t){\n        // Check time periodically\n        if((t & 0xF) == 0) { \n            double elapsed = get_elapsed();\n            if(elapsed > TIME_LIMIT) break;\n            // Adjust beam width if time is tight\n            if (elapsed > 1.5) current_beam_width = max(100, min(current_beam_width, 200));\n            else if (elapsed > 1.0) current_beam_width = max(500, min(current_beam_width, 800));\n        }\n\n        candidates.clear();\n        \n        // Step 1: Evaluate all possible next moves without building full states\n        for(int i=0; i < (int)beam.size(); ++i){\n            const auto& st = beam[i];\n            if(st.dist.empty()) {\n                // Finished state\n                candidates.push_back({st.heuristic, i, -1});\n                continue;\n            }\n\n            for(int k=0; k<4; ++k){\n                touched_cnt = 0;\n                \n                // 1. Compute temporary distribution to get heuristic\n                for(const auto& p : st.dist){\n                    int u = p.u;\n                    double val = p.p;\n                    \n                    // Stay\n                    if(temp_probs[u] == 0.0) touched_list[touched_cnt++] = u;\n                    temp_probs[u] += val * P;\n                    \n                    // Move\n                    int v = next_pos_cache[u][k];\n                    if(temp_probs[v] == 0.0) touched_list[touched_cnt++] = v;\n                    temp_probs[v] += val * (1.0 - P);\n                }\n                \n                // 2. Calculate Score components\n                double new_score = st.score;\n                double mass_rem = 0;\n                double w_dist = 0;\n                \n                for(int j=0; j<touched_cnt; ++j){\n                    int idx = touched_list[j];\n                    double prob = temp_probs[idx];\n                    temp_probs[idx] = 0.0; // Clear for next iteration\n                    \n                    if(idx == target_u){\n                        new_score += prob * (401.0 - (t + 1));\n                    } else {\n                        mass_rem += prob;\n                        w_dist += prob * flat_dist[idx];\n                    }\n                }\n                \n                // 3. Heuristic = Current Score + Expected Future Score\n                double heur = new_score + mass_rem * (401.0 - (t + 1)) - w_dist * inv_prob_move;\n                candidates.push_back({heur, i, k});\n            }\n        }\n\n        // Step 2: Select Top K Candidates\n        int K = min((int)candidates.size(), current_beam_width);\n        if((int)candidates.size() > K){\n            nth_element(candidates.begin(), candidates.begin() + K, candidates.end(),\n                [](const Candidate& a, const Candidate& b){\n                    return a.heuristic > b.heuristic;\n                });\n        }\n        \n        // Step 3: Construct States only for the selected candidates\n        vector<State> next_beam;\n        next_beam.reserve(K);\n        \n        for(int k=0; k<K; ++k){\n            const auto& cand = candidates[k];\n            const auto& parent = beam[cand.parent_idx];\n            \n            if(cand.move_k == -1){\n                next_beam.push_back(parent);\n                continue;\n            }\n            \n            State nst;\n            nst.heuristic = cand.heuristic;\n            nst.path = parent.path + dchar[cand.move_k];\n            \n            // Re-run distribution update to populate state\n            touched_cnt = 0;\n            for(const auto& p : parent.dist){\n                int u = p.u;\n                double val = p.p;\n                \n                if(temp_probs[u] == 0.0) touched_list[touched_cnt++] = u;\n                temp_probs[u] += val * P;\n                \n                int v = next_pos_cache[u][cand.move_k];\n                if(temp_probs[v] == 0.0) touched_list[touched_cnt++] = v;\n                temp_probs[v] += val * (1.0 - P);\n            }\n            \n            nst.score = parent.score;\n            nst.dist.reserve(touched_cnt);\n            \n            for(int j=0; j<touched_cnt; ++j){\n                int idx = touched_list[j];\n                double prob = temp_probs[idx];\n                temp_probs[idx] = 0.0; // Clear\n                \n                if(prob < EPS) continue;\n                \n                if(idx == target_u){\n                    nst.score += prob * (401.0 - (t + 1));\n                } else {\n                    nst.dist.push_back({idx, prob});\n                }\n            }\n            \n            next_beam.push_back(std::move(nst));\n        }\n        \n        beam = std::move(next_beam);\n        \n        // Early exit if all probability mass reached target\n        bool active = false;\n        for(const auto& s : beam) if(!s.dist.empty()) { active = true; break; }\n        if(!active) break;\n    }\n    \n    // Find best result in final beam\n    double best_score = -1.0;\n    string best_s = \"\";\n    for(const auto& st : beam){\n        if(st.score > best_score){\n            best_score = st.score;\n            best_s = st.path;\n        }\n    }\n    \n    cout << best_s << endl;\n    \n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Directions: 0: Left, 1: Up, 2: Right, 3: Down\nconst int di[] = {0, -1, 0, 1};\nconst int dj[] = {-1, 0, 1, 0};\n\n// Map (type, entry_dir) -> exit_dir\n// -1 if no connection\nint to[8][4];\n\nvoid init_tables() {\n    // Initialize with -1\n    for(int t=0; t<8; ++t) for(int d=0; d<4; ++d) to[t][d] = -1;\n\n    // 0: Left(0)-Up(1)\n    to[0][0] = 1; to[0][1] = 0;\n    // 1: Left(0)-Down(3)\n    to[1][0] = 3; to[1][3] = 0;\n    // 2: Right(2)-Down(3)\n    to[2][2] = 3; to[2][3] = 2;\n    // 3: Right(2)-Up(1)\n    to[3][2] = 1; to[3][1] = 2;\n    \n    // 4: Left(0)-Up(1) & Right(2)-Down(3)\n    to[4][0] = 1; to[4][1] = 0;\n    to[4][2] = 3; to[4][3] = 2;\n    \n    // 5: Left(0)-Down(3) & Right(2)-Up(1)\n    to[5][0] = 3; to[5][3] = 0;\n    to[5][2] = 1; to[5][1] = 2;\n    \n    // 6: Up(1)-Down(3) (Vertical)\n    to[6][1] = 3; to[6][3] = 1;\n    \n    // 7: Left(0)-Right(2) (Horizontal)\n    to[7][0] = 2; to[7][2] = 0;\n}\n\n// Calculate the effective tile type after r counter-clockwise rotations\nint get_rotated_type(int t, int r) {\n    for (int k = 0; k < r; ++k) {\n        if (t >= 0 && t <= 3) {\n            t = (t + 1) % 4;\n        } else if (t == 4) {\n            t = 5;\n        } else if (t == 5) {\n            t = 4;\n        } else if (t == 6) {\n            t = 7;\n        } else if (t == 7) {\n            t = 6;\n        }\n    }\n    return t;\n}\n\nstruct State {\n    int rots[30][30];\n    int types[30][30]; // Cached actual types for performance\n};\n\nint initial_types[30][30];\nState current_state;\nState best_state;\nlong long best_score_real = -1;\n\n// Random number generator\nmt19937 rng(12345);\n\n// Visited array for loop detection\n// Dimensions: [row][col][entry_direction]\n// We use a generation counter to avoid memset\nint visited[30][30][4];\nint gen = 0;\n\nlong long evaluate(const State& st, vector<int>& loop_lengths) {\n    gen++;\n    // In case of overflow (extremely unlikely), reset\n    if (gen <= 0) {\n        memset(visited, 0, sizeof(visited));\n        gen = 1;\n    }\n\n    loop_lengths.clear();\n    vector<int> path_lengths; \n\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            int t = st.types[i][j];\n            for (int d = 0; d < 4; ++d) {\n                // Only process if valid entry and not visited\n                if (visited[i][j][d] == gen) continue;\n                if (to[t][d] == -1) continue;\n\n                // Start tracing\n                int curr_i = i;\n                int curr_j = j;\n                int curr_d = d; // Entry direction\n                int len = 0;\n                bool is_loop = false;\n                \n                int start_i = i;\n                int start_j = j;\n                int start_d = d;\n\n                while (true) {\n                    visited[curr_i][curr_j][curr_d] = gen;\n                    \n                    // Determine exit direction from current tile\n                    int out_d = to[st.types[curr_i][curr_j]][curr_d];\n                    \n                    // Mark the reverse direction on this tile as visited too\n                    // effectively marking the track segment\n                    visited[curr_i][curr_j][out_d] = gen; \n\n                    len++;\n                    \n                    // Move to neighbor\n                    int ni = curr_i + di[out_d];\n                    int nj = curr_j + dj[out_d];\n                    \n                    // Check bounds\n                    if (ni < 0 || ni >= 30 || nj < 0 || nj >= 30) {\n                        is_loop = false;\n                        break;\n                    }\n                    \n                    // Determine entry direction into neighbor\n                    // Entering neighbor (ni, nj) from direction opposite to out_d\n                    int next_entry_d = (out_d + 2) % 4;\n                    \n                    // Check if neighbor connects back\n                    if (to[st.types[ni][nj]][next_entry_d] == -1) {\n                        is_loop = false;\n                        break;\n                    }\n\n                    // Check if we hit a visited state\n                    if (visited[ni][nj][next_entry_d] == gen) {\n                        // If we returned to start, it's a loop\n                        if (ni == start_i && nj == start_j && next_entry_d == start_d) {\n                            is_loop = true;\n                        } else {\n                            // We hit the current path somewhere else, or a previously visited component.\n                            // Due to graph degree <= 2, hitting !start means we merged into a previous component.\n                            // Previous components are fully explored, so this is a path ending in a merge.\n                            is_loop = false;\n                        }\n                        break;\n                    }\n                    \n                    curr_i = ni;\n                    curr_j = nj;\n                    curr_d = next_entry_d;\n                }\n                \n                if (is_loop) {\n                    loop_lengths.push_back(len);\n                } else {\n                    path_lengths.push_back(len);\n                }\n            }\n        }\n    }\n    \n    sort(loop_lengths.rbegin(), loop_lengths.rend());\n    \n    long long score = 0;\n    \n    // Primary objective: Maximize product of two longest loops\n    // We use a large multiplier to ensure any valid solution (2 loops) \n    // is strictly better than any invalid solution.\n    if (loop_lengths.size() >= 2) {\n        long long prod = (long long)loop_lengths[0] * loop_lengths[1];\n        score = prod * 1000000LL;\n    }\n    \n    // Secondary objective: Maximize loop lengths (sum of squares)\n    for (int l : loop_lengths) {\n        score += l * l;\n    }\n    \n    // Tertiary objective: Maximize path lengths (encourage connectivity)\n    for (int p : path_lengths) {\n        score += (p * p) / 10; \n    }\n\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_tables();\n    \n    // Input\n    for (int i = 0; i < 30; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < 30; ++j) {\n            initial_types[i][j] = s[j] - '0';\n        }\n    }\n    \n    // Random initialization\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            current_state.rots[i][j] = rng() % 4;\n            current_state.types[i][j] = get_rotated_type(initial_types[i][j], current_state.rots[i][j]);\n        }\n    }\n    \n    vector<int> loops;\n    best_score_real = -1;\n    \n    auto start_time = chrono::steady_clock::now();\n    // Reserve a small buffer from 2.0s\n    double time_limit = 1.95;\n    \n    long long current_score_aug = evaluate(current_state, loops);\n    best_state = current_state;\n    if (loops.size() >= 2) best_score_real = (long long)loops[0] * loops[1];\n    else best_score_real = 0;\n    \n    // Simulated Annealing parameters\n    double t0 = 50000.0;\n    double t1 = 1.0;\n    double temp = t0;\n    int iter = 0;\n    \n    while (true) {\n        iter++;\n        \n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n            \n            // Exponential cooling\n            double progress = elapsed / time_limit;\n            temp = t0 * pow(t1 / t0, progress);\n        }\n        \n        // Mutation: Rotate one tile\n        int r = rng() % 30;\n        int c = rng() % 30;\n        int old_rot = current_state.rots[r][c];\n        int old_type = current_state.types[r][c];\n        \n        // Pick a random different rotation\n        int new_rot = (old_rot + 1 + (rng() % 3)) % 4;\n        current_state.rots[r][c] = new_rot;\n        current_state.types[r][c] = get_rotated_type(initial_types[r][c], new_rot);\n        \n        long long new_score_aug = evaluate(current_state, loops);\n        \n        double delta = new_score_aug - current_score_aug;\n        \n        // Metropolis criterion\n        if (delta >= 0 || (temp > 1e-9 && exp(delta / temp) > std::uniform_real_distribution<>(0.0, 1.0)(rng))) {\n            current_score_aug = new_score_aug;\n            \n            // Track best valid solution found\n            long long real_score = 0;\n            if (loops.size() >= 2) {\n                real_score = (long long)loops[0] * loops[1];\n            }\n            \n            if (real_score > best_score_real) {\n                best_score_real = real_score;\n                best_state = current_state;\n            }\n        } else {\n            // Revert change\n            current_state.rots[r][c] = old_rot;\n            current_state.types[r][c] = old_type;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < 30; ++i) {\n        for (int j = 0; j < 30; ++j) {\n            cout << best_state.rots[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <map>\n#include <iomanip>\n#include <cstring>\n\nusing namespace std;\n\n// Constants\nconst int UP = 2;\nconst int DOWN = 8;\nconst int LEFT = 1;\nconst int RIGHT = 4;\nconst int DIR[4] = {UP, DOWN, LEFT, RIGHT};\nconst int DR[4] = {-1, 1, 0, 0}; \nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\nint N, T;\nvector<vector<int>> initial_board;\nvector<vector<int>> target_board;\n\n// Time\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Utils\nbool has_dir(int tile, int dir) { return (tile & dir) != 0; }\nint reverse_dir(int dir) {\n    if (dir == UP) return DOWN;\n    if (dir == DOWN) return UP;\n    if (dir == LEFT) return RIGHT;\n    if (dir == RIGHT) return LEFT;\n    return 0;\n}\n\nmt19937 rng(1337);\n\n// Fast Evaluation\nint vis_token[10][10];\nint current_token = 0;\n\nstruct BoardScore {\n    int connections;\n    int mismatches;\n    int max_component;\n    int total_score;\n    vector<pair<int,int>> bad_pos;\n};\n\nBoardScore evaluate(const vector<vector<int>>& board) {\n    int mismatches = 0;\n    int connections = 0;\n    int boundary_penalty = 0;\n    int max_comp = 0;\n    vector<pair<int,int>> bad_pos;\n\n    current_token++;\n    \n    // Component size\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 0) continue; \n            if (vis_token[r][c] == current_token) continue;\n\n            int comp_size = 0;\n            // Static queue for BFS\n            static pair<int,int> q[100];\n            int head = 0, tail = 0;\n            \n            q[tail++] = {r, c};\n            vis_token[r][c] = current_token;\n            comp_size++;\n\n            while(head < tail) {\n                auto [cr, cc] = q[head++];\n                int tile = board[cr][cc];\n\n                for (int d = 0; d < 4; ++d) {\n                    if (has_dir(tile, DIR[d])) {\n                        int nr = cr + DR[d];\n                        int nc = cc + DC[d];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                            int neighbor = board[nr][nc];\n                            if (neighbor != 0 && has_dir(neighbor, reverse_dir(DIR[d]))) {\n                                if (vis_token[nr][nc] != current_token) {\n                                    vis_token[nr][nc] = current_token;\n                                    q[tail++] = {nr, nc};\n                                    comp_size++;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if (comp_size > max_comp) max_comp = comp_size;\n        }\n    }\n\n    // Local connections and defects\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int tile = board[r][c];\n            if (tile == 0) continue;\n            bool is_bad = false;\n            \n            if (has_dir(tile, UP)) {\n                if (r == 0) { boundary_penalty++; is_bad = true; }\n                else {\n                    int n = board[r-1][c];\n                    if (n == 0) { boundary_penalty++; is_bad = true; }\n                    else if (!has_dir(n, DOWN)) { mismatches++; is_bad = true; }\n                    else connections++; \n                }\n            }\n            if (has_dir(tile, DOWN)) {\n                if (r == N-1) { boundary_penalty++; is_bad = true; }\n                else {\n                    int n = board[r+1][c];\n                    if (n == 0) { boundary_penalty++; is_bad = true; }\n                    else if (!has_dir(n, UP)) { mismatches++; is_bad = true; }\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, LEFT)) {\n                if (c == 0) { boundary_penalty++; is_bad = true; }\n                else {\n                    int n = board[r][c-1];\n                    if (n == 0) { boundary_penalty++; is_bad = true; }\n                    else if (!has_dir(n, RIGHT)) { mismatches++; is_bad = true; }\n                    else connections++;\n                }\n            }\n            if (has_dir(tile, RIGHT)) {\n                if (c == N-1) { boundary_penalty++; is_bad = true; }\n                else {\n                    int n = board[r][c+1];\n                    if (n == 0) { boundary_penalty++; is_bad = true; }\n                    else if (!has_dir(n, LEFT)) { mismatches++; is_bad = true; }\n                    else connections++;\n                }\n            }\n            if(is_bad) bad_pos.push_back({r, c});\n        }\n    }\n\n    // Score calculation: High reward for max component, but also significant reward for local connections to guide search\n    int score = connections * 20 - mismatches * 20 - boundary_penalty * 20 + max_comp * 1000;\n    return {connections, mismatches + boundary_penalty, max_comp, score, bad_pos};\n}\n\nvoid find_target_configuration() {\n    vector<int> tiles;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tiles.push_back(initial_board[r][c]);\n    \n    // Ensure 0 is at N-1, N-1\n    auto it = find(tiles.begin(), tiles.end(), 0);\n    if(it != tiles.end()) iter_swap(it, tiles.end() - 1);\n\n    target_board.assign(N, vector<int>(N));\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) target_board[r][c] = tiles[r*N + c];\n    \n    BoardScore current_eval = evaluate(target_board);\n    int current_score = current_eval.total_score;\n    \n    vector<vector<int>> best_board = target_board;\n    int best_score = current_score;\n\n    double start_temp = 1500.0;\n    double end_temp = 0.1;\n    double time_limit = 2.75; \n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            if (get_time() > time_limit) break;\n        }\n\n        double t = get_time();\n        double progress = t / time_limit;\n        double temp = start_temp * pow(end_temp / start_temp, progress);\n\n        int r1, c1, r2, c2;\n        \n        // Heuristic: Swap mismatched tiles\n        if (uniform_real_distribution<>(0,1)(rng) < 0.5 && !current_eval.bad_pos.empty()) {\n            int idx = rng() % current_eval.bad_pos.size();\n            r1 = current_eval.bad_pos[idx].first;\n            c1 = current_eval.bad_pos[idx].second;\n        } else {\n            r1 = rng() % N;\n            c1 = rng() % N;\n        }\n\n        if (r1 == N-1 && c1 == N-1) {\n             r1 = rng() % N; c1 = rng() % N;\n             if(r1==N-1 && c1==N-1) { r1=0; c1=0; }\n        }\n        \n        r2 = rng() % N;\n        c2 = rng() % N;\n        if (r2 == N-1 && c2 == N-1) {\n            do { r2 = rng() % N; c2 = rng() % N; } while(r2==N-1 && c2==N-1);\n        }\n        \n        if (r1 == r2 && c1 == c2) continue;\n        if (target_board[r1][c1] == target_board[r2][c2]) continue; \n\n        swap(target_board[r1][c1], target_board[r2][c2]);\n        \n        BoardScore next_eval = evaluate(target_board);\n        int next_score = next_eval.total_score;\n        \n        if (next_score >= current_score) {\n            current_score = next_score;\n            current_eval = next_eval;\n            if (next_score > best_score) {\n                best_score = next_score;\n                best_board = target_board;\n            }\n        } else {\n            double prob = exp((next_score - current_score) / temp);\n            if (uniform_real_distribution<>(0,1)(rng) < prob) {\n                current_score = next_score;\n                current_eval = next_eval;\n            } else {\n                swap(target_board[r1][c1], target_board[r2][c2]); // Revert\n            }\n        }\n    }\n    target_board = best_board;\n}\n\nstring moves_str = \"\";\npair<int, int> empty_pos;\n\nvoid apply_move(char c) {\n    int dr = 0, dc = 0;\n    if (c == 'U') dr = -1; if (c == 'D') dr = 1;\n    if (c == 'L') dc = -1; if (c == 'R') dc = 1;\n    int nr = empty_pos.first + dr;\n    int nc = empty_pos.second + dc;\n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    moves_str += c;\n    swap(initial_board[empty_pos.first][empty_pos.second], initial_board[nr][nc]);\n    empty_pos = {nr, nc};\n}\n\nint bfs_gen[10][10];\nint cur_bfs_gen = 0;\npair<int,int> bfs_parent[10][10];\nchar bfs_move[10][10];\n\nbool bfs_empty(int tr, int tc, const vector<vector<bool>>& locked) {\n    if (empty_pos.first == tr && empty_pos.second == tc) return true;\n    cur_bfs_gen++;\n    \n    static pair<int,int> q[100];\n    int head = 0, tail = 0;\n    \n    q[tail++] = empty_pos;\n    bfs_gen[empty_pos.first][empty_pos.second] = cur_bfs_gen;\n    \n    bool found = false;\n    while(head < tail) {\n        auto [r, c] = q[head++];\n        if (r == tr && c == tc) { found = true; break; }\n        \n        for (int i=0; i<4; ++i) {\n            int nr = r + DR[i];\n            int nc = c + DC[i];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !locked[nr][nc]) {\n                if (bfs_gen[nr][nc] != cur_bfs_gen) {\n                    bfs_gen[nr][nc] = cur_bfs_gen;\n                    bfs_parent[nr][nc] = {r, c};\n                    bfs_move[nr][nc] = DIR_CHAR[i];\n                    q[tail++] = {nr, nc};\n                }\n            }\n        }\n    }\n    \n    if (!found) return false;\n    string path = \"\";\n    pair<int,int> curr = {tr, tc};\n    while (curr != empty_pos) {\n        path += bfs_move[curr.first][curr.second];\n        curr = bfs_parent[curr.first][curr.second];\n    }\n    reverse(path.begin(), path.end());\n    for(char c : path) apply_move(c);\n    return true;\n}\n\nint get_inv_count(const vector<int>& arr) {\n    int inv_count = 0;\n    for (int i = 0; i < arr.size(); i++) {\n        if (arr[i] == -1) continue;\n        for (int j = i + 1; j < arr.size(); j++) {\n            if (arr[j] == -1) continue;\n            if (arr[i] > arr[j]) inv_count++;\n        }\n    }\n    return inv_count;\n}\n\nvoid solve_puzzle() {\n    vector<vector<int>> tile_ids(N, vector<int>(N));\n    int id_counter = 0;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tile_ids[r][c] = id_counter++;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c] == 0) empty_pos = {r,c};\n\n    vector<int> target_assignment(N*N, -1);\n    vector<bool> id_used(N*N, false);\n\n    // Greedy Assignment\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int type = target_board[r][c];\n            int best_id = -1;\n            int min_dist = 10000;\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                int id = tile_ids[i][j];\n                if (!id_used[id] && initial_board[i][j] == type) {\n                    int dist = abs(r - i) + abs(c - j);\n                    if (dist < min_dist) { min_dist = dist; best_id = id; }\n                }\n            }\n            target_assignment[r*N + c] = best_id;\n            id_used[best_id] = true;\n        }\n    }\n\n    int empty_id = -1;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c]==0) empty_id = tile_ids[r][c];\n    \n    int target_empty_pos = -1;\n    for(int i=0; i<N*N; ++i) if(target_assignment[i] == empty_id) target_empty_pos = i;\n    int tr_empty = target_empty_pos / N;\n    int tc_empty = target_empty_pos % N;\n\n    vector<int> s_current;\n    for(int r=0;r<N;++r) for(int c=0;c<N;++c) if(tile_ids[r][c] != empty_id) s_current.push_back(tile_ids[r][c]);\n    \n    vector<int> s_target;\n    for(int i=0; i<N*N; ++i) if(target_assignment[i] != empty_id) s_target.push_back(target_assignment[i]);\n    \n    int inv_curr = get_inv_count(s_current);\n    int p_curr = (inv_curr + empty_pos.first + empty_pos.second) % 2;\n    int inv_tgt = get_inv_count(s_target);\n    int p_tgt = (inv_tgt + tr_empty + tc_empty) % 2;\n\n    if (p_curr != p_tgt) {\n        bool swapped = false;\n        for(int i=0; i<N*N && !swapped; ++i) {\n            for(int j=i+1; j<N*N && !swapped; ++j) {\n                int id1 = target_assignment[i];\n                int id2 = target_assignment[j];\n                if (id1 == empty_id || id2 == empty_id) continue;\n                int t1 = -1, t2 = -2;\n                for(int r=0;r<N;++r) for(int c=0;c<N;++c) if(tile_ids[r][c]==id1) t1=initial_board[r][c];\n                for(int r=0;r<N;++r) for(int c=0;c<N;++c) if(tile_ids[r][c]==id2) t2=initial_board[r][c];\n                if (t1 == t2) {\n                    swap(target_assignment[i], target_assignment[j]);\n                    swapped = true;\n                }\n            }\n        }\n        if (!swapped) {\n             for(int i=0; i<N*N && !swapped; ++i) {\n                for(int j=i+1; j<N*N && !swapped; ++j) {\n                     int id1 = target_assignment[i];\n                     int id2 = target_assignment[j];\n                     if (id1 != empty_id && id2 != empty_id) {\n                         swap(target_assignment[i], target_assignment[j]);\n                         swapped = true;\n                     }\n                }\n             }\n        }\n    }\n\n    vector<vector<int>> target_ids_map(N, vector<int>(N));\n    for(int i=0; i<N*N; ++i) target_ids_map[i/N][i%N] = target_assignment[i];\n    vector<vector<bool>> locked(N, vector<bool>(N, false));\n    \n    auto get_pos = [&](int id) {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n        return make_pair(-1,-1);\n    };\n\n    auto move_piece = [&](int id, int tr, int tc, int avoid_id = -1) {\n        pair<int,int> curr = get_pos(id);\n        while(curr.first != tr || curr.second != tc) {\n             int dr = 0, dc = 0;\n             if (curr.first < tr) dr = 1; else if (curr.first > tr) dr = -1;\n             else if (curr.second < tc) dc = 1; else if (curr.second > tc) dc = -1;\n             int nr = curr.first + dr; int nc = curr.second + dc;\n             pair<int,int> avoid_pos = {-1,-1};\n             if(avoid_id != -1) { avoid_pos = get_pos(avoid_id); locked[avoid_pos.first][avoid_pos.second] = true; }\n             locked[curr.first][curr.second] = true;\n             bool ok = bfs_empty(nr, nc, locked);\n             locked[curr.first][curr.second] = false;\n             if(avoid_id != -1) locked[avoid_pos.first][avoid_pos.second] = false;\n             if(!ok) return false;\n             char m = ' ';\n             if (curr.first == nr + 1) m = 'D'; else if (curr.first == nr - 1) m = 'U';\n             else if (curr.second == nc + 1) m = 'R'; else if (curr.second == nc - 1) m = 'L';\n             apply_move(m);\n             swap(tile_ids[curr.first][curr.second], tile_ids[nr][nc]);\n             curr = {nr, nc};\n        }\n        return true;\n    };\n\n    // Solve rows 0 to N-3\n    for (int r = 0; r <= N - 3; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (c < N - 2) {\n                int id = target_ids_map[r][c];\n                move_piece(id, r, c);\n                locked[r][c] = true;\n            } else {\n                int t1_id = target_ids_map[r][N-2];\n                int t2_id = target_ids_map[r][N-1];\n                move_piece(t2_id, r+1, N-1, t1_id);\n                pair<int,int> p = get_pos(t2_id); locked[p.first][p.second] = true;\n                move_piece(t1_id, r, N-1);\n                locked[p.first][p.second] = false;\n                pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n                p = get_pos(t2_id); locked[p.first][p.second] = true;\n                bfs_empty(r, N-2, locked);\n                apply_move('R'); swap(tile_ids[r][N-2], tile_ids[r][N-1]);\n                apply_move('D'); swap(tile_ids[r][N-1], tile_ids[r+1][N-1]);\n                locked[p1.first][p1.second] = false; locked[p.first][p.second] = false;\n                locked[r][N-2] = true; locked[r][N-1] = true;\n                break;\n            }\n        }\n    }\n    // Solve columns\n    for(int c=0; c <= N-3; ++c) {\n        int t1_id = target_ids_map[N-2][c];\n        int t2_id = target_ids_map[N-1][c];\n        move_piece(t2_id, N-1, c+1, t1_id);\n        pair<int,int> p = get_pos(t2_id); locked[p.first][p.second] = true;\n        move_piece(t1_id, N-1, c);\n        locked[p.first][p.second] = false;\n        pair<int,int> p1 = get_pos(t1_id); locked[p1.first][p1.second] = true;\n        p = get_pos(t2_id); locked[p.first][p.second] = true;\n        bfs_empty(N-2, c, locked);\n        apply_move('D'); swap(tile_ids[N-2][c], tile_ids[N-1][c]);\n        apply_move('R'); swap(tile_ids[N-1][c], tile_ids[N-1][c+1]);\n        locked[p1.first][p1.second] = false; locked[p.first][p.second] = false;\n        locked[N-2][c] = true; locked[N-1][c] = true;\n    }\n\n    // 2x3 BFS\n    locked[N-2][N-3] = false; locked[N-1][N-3] = false; \n    vector<pair<int,int>> pos_map = {{N-2, N-3}, {N-2, N-2}, {N-2, N-1}, {N-1, N-3}, {N-1, N-2}, {N-1, N-1}};\n    vector<int> target_state(6);\n    for(int i=0; i<6; ++i) target_state[i] = target_ids_map[pos_map[i].first][pos_map[i].second];\n\n    map<vector<int>, char> move_map;\n    map<vector<int>, vector<int>> parent_map;\n    queue<vector<int>> q;\n    \n    vector<int> start_s(6);\n    for(int i=0; i<6; ++i) start_s[i] = tile_ids[pos_map[i].first][pos_map[i].second];\n    \n    q.push(start_s);\n    move_map[start_s] = 0;\n    \n    bool solved = false;\n    vector<int> final_s;\n    int steps = 0;\n    \n    while(!q.empty()) {\n        vector<int> curr = q.front();\n        q.pop();\n        if (curr == target_state) { solved = true; final_s = curr; break; }\n        if(++steps > 100000) break;\n        \n        int z = -1;\n        for(int i=0; i<6; ++i) if(curr[i] == empty_id) z = i;\n        int r = pos_map[z].first;\n        int c = pos_map[z].second;\n        \n        for(int d=0; d<4; ++d) {\n            int nr = r + DR[d];\n            int nc = c + DC[d];\n            int nz = -1;\n            for(int k=0; k<6; ++k) if(pos_map[k].first == nr && pos_map[k].second == nc) nz = k;\n            if (nz != -1) {\n                vector<int> next_s = curr;\n                swap(next_s[z], next_s[nz]);\n                if (move_map.find(next_s) == move_map.end()) {\n                    move_map[next_s] = DIR_CHAR[d];\n                    parent_map[next_s] = curr;\n                    q.push(next_s);\n                }\n            }\n        }\n    }\n    if (solved) {\n        string path = \"\";\n        vector<int> curr = final_s;\n        while (curr != start_s) {\n            path += move_map[curr];\n            curr = parent_map[curr];\n        }\n        reverse(path.begin(), path.end());\n        for(char c : path) apply_move(c);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if(!(cin >> N >> T)) return 0;\n    initial_board.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) {\n            char c = s[j];\n            if (c >= '0' && c <= '9') initial_board[i][j] = c - '0';\n            else initial_board[i][j] = c - 'a' + 10;\n        }\n    }\n    find_target_configuration();\n    solve_puzzle();\n    cout << moves_str << endl;\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n#include <numeric>\n\nusing namespace std;\n\n// Constants\nconst double PI = std::acos(-1.0);\nconst int MAX_K = 105;\nconst int MAX_N = 6000;\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\n// Global inputs\nint N;\nint K_limit;\nint A[11];\nvector<Point> points;\n\n// Random engine\nmt19937 rng(42);\n\n// Buffers for fast evaluation\n// Using short to optimize cache usage (fits in L1/L2 cache better)\nunsigned short counts_grid[MAX_K][MAX_K];\nunsigned short Lx[MAX_N];\nunsigned short Ly[MAX_N];\n\n// Timer\nclass Timer {\n    chrono::high_resolution_clock::time_point start;\npublic:\n    Timer() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(now - start).count();\n    }\n};\n\n// Data structures for a specific angle pair configuration\nstruct AngleConfig {\n    double theta1, theta2; // degrees\n    vector<double> uniq_1, uniq_2;\n    vector<unsigned short> rank_1, rank_2; \n    \n    // Best solution found for this config\n    vector<int> best_c1, best_c2;\n    long long best_score = -1;\n};\n\n// Helper: Unique coordinates with tolerance\nvector<double> get_unique_coords(const vector<double>& coords) {\n    if (coords.empty()) return {};\n    vector<double> sorted = coords;\n    sort(sorted.begin(), sorted.end());\n    vector<double> uniq;\n    uniq.push_back(sorted[0]);\n    for (size_t i = 1; i < sorted.size(); ++i) {\n        if (sorted[i] - uniq.back() > 1e-3) {\n            uniq.push_back(sorted[i]);\n        }\n    }\n    return uniq;\n}\n\n// Solver class\nclass Solver {\npublic:\n    // Evaluation function\n    // Optimized to use precomputed rank arrays and short integers\n    long long eval(const AngleConfig& config, const vector<int>& c1, const vector<int>& c2) {\n        int n1 = (int)c1.size() + 1;\n        int n2 = (int)c2.size() + 1;\n        int u1s = (int)config.uniq_1.size();\n        int u2s = (int)config.uniq_2.size();\n\n        // Fill Lx lookup table\n        {\n            int current_bin = 0;\n            int cut_idx = 0;\n            int num_cuts = c1.size();\n            for(int r=0; r<u1s; ++r) {\n                if(cut_idx < num_cuts && r == c1[cut_idx]) {\n                    current_bin++;\n                    cut_idx++;\n                }\n                Lx[r] = (unsigned short)current_bin;\n            }\n        }\n        // Fill Ly lookup table\n        {\n            int current_bin = 0;\n            int cut_idx = 0;\n            int num_cuts = c2.size();\n            for(int r=0; r<u2s; ++r) {\n                if(cut_idx < num_cuts && r == c2[cut_idx]) {\n                    current_bin++;\n                    cut_idx++;\n                }\n                Ly[r] = (unsigned short)current_bin;\n            }\n        }\n\n        // Clear grid - only the used portion\n        for(int i=0; i<n1; ++i) {\n             memset(counts_grid[i], 0, n2 * sizeof(unsigned short));\n        }\n\n        // Count points in bins\n        const unsigned short* r1_ptr = config.rank_1.data();\n        const unsigned short* r2_ptr = config.rank_2.data();\n        for(int i=0; i<N; ++i) {\n            counts_grid[Lx[r1_ptr[i]]][Ly[r2_ptr[i]]]++;\n        }\n\n        // Calculate Score\n        int piece_b[11] = {0};\n        for(int i=0; i<n1; ++i) {\n            for(int j=0; j<n2; ++j) {\n                int c = counts_grid[i][j];\n                if(c <= 10 && c >= 1) piece_b[c]++;\n            }\n        }\n\n        long long num = 0;\n        for(int d=1; d<=10; ++d) {\n            num += min(A[d], piece_b[d]);\n        }\n        return num;\n    }\n\n    // SA function: runs for specific duration or max_iters\n    // max_iters > 0: runs for fixed iterations (screening)\n    // max_iters < 0: runs for max_duration (refinement/final)\n    void run_sa(AngleConfig& config, double max_duration, int max_iters, bool warm_start) {\n        Timer t;\n        vector<int> c1, c2;\n        int u1s = (int)config.uniq_1.size();\n        int u2s = (int)config.uniq_2.size();\n\n        // Initialization strategy: Spread cuts based on quantiles (roughly equal points per strip)\n        auto gen_quantile_cuts = [&](int n, int max_v) {\n             vector<int> res;\n             if (max_v <= 1) return res;\n             if (n > max_v - 1) n = max_v - 1;\n             for (int i = 1; i <= n; ++i) {\n                 int idx = (int)(1.0 * i * max_v / (n + 1));\n                 if (idx < 1) idx = 1;\n                 if (idx >= max_v) idx = max_v - 1;\n                 res.push_back(idx);\n             }\n             sort(res.begin(), res.end());\n             res.erase(unique(res.begin(), res.end()), res.end());\n             return res;\n        };\n\n        if (warm_start && config.best_score != -1) {\n            c1 = config.best_c1;\n            c2 = config.best_c2;\n        } else {\n            int k1 = K_limit / 2;\n            int k2 = K_limit - k1;\n            c1 = gen_quantile_cuts(k1, u1s);\n            c2 = gen_quantile_cuts(k2, u2s);\n        }\n\n        long long current_score = eval(config, c1, c2);\n        if (current_score > config.best_score) {\n            config.best_score = current_score;\n            config.best_c1 = c1;\n            config.best_c2 = c2;\n        }\n\n        double start_temp = 2.0; \n        if (warm_start) start_temp = 0.5;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            // Check termination conditions\n            if (max_iters > 0 && iter >= max_iters) break;\n            if (max_iters < 0 && (iter & 63) == 0) {\n                if (t.elapsed() > max_duration) break;\n            }\n\n            double progress = 0;\n            if (max_iters > 0) progress = (double)iter / max_iters;\n            else progress = t.elapsed() / max_duration;\n            if (progress > 1.0) progress = 1.0;\n\n            double temp = start_temp * (1.0 - progress);\n            if(temp < 1e-9) temp = 1e-9;\n\n            // Proposal: Mutate current solution\n            vector<int> nc1 = c1;\n            vector<int> nc2 = c2;\n            \n            int op_dim = rng() % 2; \n            vector<int>* cuts = (op_dim == 0) ? &nc1 : &nc2;\n            int max_val = (op_dim == 0) ? u1s : u2s;\n            int other_size = (op_dim == 0) ? c2.size() : c1.size();\n            \n            if (max_val <= 1) continue;\n\n            int type = rng() % 3; \n\n            if (type == 0 && !cuts->empty()) { // Shift a cut\n                int idx = rng() % cuts->size();\n                int old_v = (*cuts)[idx];\n                int shift = (rng() % 7) - 3; \n                int val = old_v + shift;\n                \n                if (val < 1) val = 1;\n                if (val >= max_val) val = max_val - 1;\n                \n                // Check collision\n                bool exists = false;\n                for(int v : *cuts) if(v == val && v != old_v) { exists = true; break; }\n                \n                if(!exists) {\n                    (*cuts)[idx] = val;\n                    sort(cuts->begin(), cuts->end());\n                } else { continue; }\n            } else if (type == 1) { // Add a cut\n                if (cuts->size() + other_size < K_limit) {\n                    int val = (rng() % (max_val - 1)) + 1;\n                    bool exists = false;\n                    for(int v : *cuts) if(v == val) { exists = true; break; }\n                    if(!exists) {\n                        cuts->push_back(val);\n                        sort(cuts->begin(), cuts->end());\n                    } else { continue; }\n                } else { continue; }\n            } else if (type == 2 && !cuts->empty()) { // Delete a cut\n                int idx = rng() % cuts->size();\n                cuts->erase(cuts->begin() + idx);\n            } else { continue; }\n\n            long long new_score = eval(config, nc1, nc2);\n            long long diff = new_score - current_score;\n\n            if (diff >= 0 || exp(diff / temp) > (double(rng())/mt19937::max())) {\n                c1 = nc1;\n                c2 = nc2;\n                current_score = new_score;\n                if (current_score > config.best_score) {\n                    config.best_score = current_score;\n                    config.best_c1 = c1;\n                    config.best_c2 = c2;\n                }\n            }\n        }\n    }\n};\n\n// Helper to generate config from angles\nAngleConfig make_config(double t1, double t2) {\n    AngleConfig cfg;\n    cfg.theta1 = t1;\n    cfg.theta2 = t2;\n    \n    vector<double> raw_vals(N);\n    \n    double rad1 = t1 * PI / 180.0;\n    double c1 = cos(rad1), s1 = sin(rad1);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c1 + points[j].y * s1;\n    \n    cfg.uniq_1 = get_unique_coords(raw_vals);\n    cfg.rank_1.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_1.begin(), cfg.uniq_1.end(), raw_vals[j] - 1e-4);\n        cfg.rank_1[j] = (unsigned short)distance(cfg.uniq_1.begin(), it);\n    }\n    \n    double rad2 = t2 * PI / 180.0;\n    double c2 = cos(rad2), s2 = sin(rad2);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c2 + points[j].y * s2;\n    \n    cfg.uniq_2 = get_unique_coords(raw_vals);\n    cfg.rank_2.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_2.begin(), cfg.uniq_2.end(), raw_vals[j] - 1e-4);\n        cfg.rank_2[j] = (unsigned short)distance(cfg.uniq_2.begin(), it);\n    }\n    \n    return cfg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> K_limit)) return 0;\n    for(int i=1; i<=10; ++i) cin >> A[i];\n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y;\n    }\n\n    Timer total_timer;\n    Solver solver;\n    \n    // ---------------------------------------------------\n    // Phase 1: Screening (High diversity, low precision)\n    // ---------------------------------------------------\n    vector<AngleConfig> configs;\n    configs.reserve(200);\n    \n    // Orthogonal pairs: 0 to 90 degrees, step 1 degree\n    for(int i=0; i<90; i += 1) { \n        configs.push_back(make_config(i, i + 90.0));\n    }\n    // Random pairs for non-orthogonal possibilities\n    for(int i=0; i<40; ++i) {\n        double t1 = uniform_real_distribution<double>(0, 180)(rng);\n        double t2 = uniform_real_distribution<double>(0, 180)(rng);\n        double diff = abs(t1 - t2);\n        while(diff > 180) diff -= 180;\n        if(abs(diff) < 10 || abs(diff) > 170) continue;\n        configs.push_back(make_config(t1, t2));\n    }\n    \n    // Very fast check: 250 iterations per config\n    for(auto& cfg : configs) {\n        solver.run_sa(cfg, 0, 250, false); \n    }\n    \n    // Sort by score\n    vector<int> indices(configs.size());\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b){\n        return configs[a].best_score > configs[b].best_score;\n    });\n    \n    // ---------------------------------------------------\n    // Phase 2: Refinement (Focus on promising areas)\n    // ---------------------------------------------------\n    int keep_top = 5;\n    vector<AngleConfig> refined_configs;\n    \n    for(int k=0; k<keep_top && k<(int)indices.size(); ++k) {\n        const auto& base = configs[indices[k]];\n        refined_configs.push_back(base); // Keep original\n        \n        // Generate neighbors: perturb angles slightly to fine-tune grid orientation\n        double deltas[] = {-0.5, 0.5};\n        for(double d1 : deltas) {\n             refined_configs.push_back(make_config(base.theta1 + d1, base.theta2));\n             refined_configs.push_back(make_config(base.theta1, base.theta2 + d1));\n             refined_configs.push_back(make_config(base.theta1 + d1, base.theta2 + d1));\n        }\n    }\n    \n    // Run moderate SA on refined set\n    // Time per config approx 0.025s (Total ~0.8s for ~30-40 configs)\n    for(auto& cfg : refined_configs) {\n        solver.run_sa(cfg, 0.025, -1, false); \n    }\n    \n    // ---------------------------------------------------\n    // Phase 3: Final Optimization (Deep search on best)\n    // ---------------------------------------------------\n    int best_idx = 0;\n    for(size_t i=1; i<refined_configs.size(); ++i) {\n        if(refined_configs[i].best_score > refined_configs[best_idx].best_score) {\n            best_idx = i;\n        }\n    }\n    \n    // Use remaining time for the champion\n    double remaining = 2.8 - total_timer.elapsed();\n    if(remaining < 0.1) remaining = 0.1;\n    \n    solver.run_sa(refined_configs[best_idx], remaining, -1, true);\n    \n    // Output\n    const auto& S = refined_configs[best_idx];\n    cout << S.best_c1.size() + S.best_c2.size() << endl;\n    \n    auto print_line = [&](double ang, double val) {\n        double rad = ang * PI / 180.0;\n        double A = cos(rad);\n        double B = sin(rad);\n        // Equation: A*x + B*y = val\n        double C = val;\n        double Mx = C * A;\n        double My = C * B;\n        double Dx = -B;\n        double Dy = A;\n        long long scale = 400000000LL;\n        long long x1 = round(Mx - scale * Dx);\n        long long y1 = round(My - scale * Dy);\n        long long x2 = round(Mx + scale * Dx);\n        long long y2 = round(My + scale * Dy);\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    };\n    \n    for(int idx : S.best_c1) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_1.size())\n            val = (S.uniq_1[idx-1] + S.uniq_1[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_1[0] - 10.0;\n        else val = S.uniq_1.back() + 10.0;\n        print_line(S.theta1, val);\n    }\n    for(int idx : S.best_c2) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_2.size())\n            val = (S.uniq_2[idx-1] + S.uniq_2[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_2[0] - 10.0;\n        else val = S.uniq_2.back() + 10.0;\n        print_line(S.theta2, val);\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double TIME_LIMIT = 4.8;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n};\n\nint N, M;\nint C; \nlong long weights[65][65];\n\nusing Mask = unsigned long long;\n\ninline void set_bit(Mask& m, int i) {\n    m |= (1ULL << i);\n}\n\n// Check if bits in range [l, r) are all 0\n// Range is inclusive of l, exclusive of r.\ninline bool check_range_empty(Mask m, int l, int r) {\n    if (l >= r) return true;\n    if (l >= 64) return true; \n    unsigned long long mask_r = (r >= 64) ? (~0ULL) : ((1ULL << r) - 1);\n    unsigned long long mask_l = (1ULL << l) - 1;\n    Mask mask = mask_r ^ mask_l;\n    return (m & mask) == 0;\n}\n\nstruct Move {\n    Point p1, p2, p3, p4;\n};\n\nstruct State {\n    Mask row_dots[62];\n    Mask col_dots[62];\n    Mask d1_dots[130]; \n    Mask d2_dots[130]; \n\n    Mask h_edges[62]; \n    Mask v_edges[62];\n    Mask d1_edges[130];\n    Mask d2_edges[130];\n\n    long long current_score_w;\n    vector<Move> history;\n\n    State() {\n        for(int i=0; i<62; ++i) row_dots[i] = col_dots[i] = h_edges[i] = v_edges[i] = 0;\n        for(int i=0; i<130; ++i) d1_dots[i] = d2_dots[i] = d1_edges[i] = d2_edges[i] = 0;\n        current_score_w = 0;\n    }\n\n    bool has_dot(int x, int y) const {\n        return (row_dots[y] >> x) & 1;\n    }\n\n    void add_dot(int x, int y) {\n        set_bit(row_dots[y], x);\n        set_bit(col_dots[x], y);\n        set_bit(d1_dots[x + y], x);\n        set_bit(d2_dots[x - y + N], x);\n        current_score_w += weights[x][y];\n    }\n    \n    void add_edges(Point p1, Point p2, Point p3, Point p4) {\n        auto mark = [&](Point a, Point b) {\n            if (a.y == b.y) { \n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                for (int x = l; x < r; ++x) set_bit(h_edges[y], x);\n            } else if (a.x == b.x) { \n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                for (int y = l; y < r; ++y) set_bit(v_edges[x], y);\n            } else {\n                if ((a.x + a.y) == (b.x + b.y)) { \n                    int k = a.x + a.y;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d1_edges[k], x);\n                } else { \n                    int k = a.x - a.y + N;\n                    int l = min(a.x, b.x);\n                    int r = max(a.x, b.x);\n                    for (int x = l; x < r; ++x) set_bit(d2_edges[k], x);\n                }\n            }\n        };\n        mark(p1, p2);\n        mark(p2, p3);\n        mark(p3, p4);\n        mark(p4, p1);\n    }\n};\n\nconst int pairs90[8][2] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0}, \n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\nstruct Solver {\n    vector<State> beam;\n    vector<Point> initial_dots;\n\n    Point find_neighbor(const State& s, Point p, int dir) {\n        int x = p.x, y = p.y;\n        if (dir == 0) { // R\n            Mask m = s.row_dots[y];\n            m &= (~0ULL << (x + 1)); \n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, y};\n        } else if (dir == 2) { // L\n            Mask m = s.row_dots[y];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, y};\n        } else if (dir == 1) { // U\n            Mask m = s.col_dots[x];\n            m &= (~0ULL << (y + 1));\n            if (m == 0) return {-1, -1};\n            int ny = __builtin_ctzll(m);\n            return {x, ny};\n        } else if (dir == 3) { // D\n            Mask m = s.col_dots[x];\n            m &= ((1ULL << y) - 1);\n            if (m == 0) return {-1, -1};\n            int ny = 63 - __builtin_clzll(m);\n            return {x, ny};\n        } else if (dir == 4) { // NE (d2 const, x inc)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 6) { // SW (d2 const, x dec)\n            int k = x - y + N;\n            Mask m = s.d2_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, nx - k + N};\n        } else if (dir == 5) { // NW (d1 const, x dec)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= ((1ULL << x) - 1);\n            if (m == 0) return {-1, -1};\n            int nx = 63 - __builtin_clzll(m);\n            return {nx, k - nx};\n        } else if (dir == 7) { // SE (d1 const, x inc)\n            int k = x + y;\n            Mask m = s.d1_dots[k];\n            m &= (~0ULL << (x + 1));\n            if (m == 0) return {-1, -1};\n            int nx = __builtin_ctzll(m);\n            return {nx, k - nx};\n        }\n        return {-1, -1};\n    }\n\n    bool check_edges_free(const State& s, Point p1, Point p2, Point p3, Point p4) {\n        auto check = [&](Point a, Point b) {\n            if (a.y == b.y) {\n                int y = a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.h_edges[y], l, r);\n            } else if (a.x == b.x) {\n                int x = a.x;\n                int l = min(a.y, b.y);\n                int r = max(a.y, b.y);\n                return check_range_empty(s.v_edges[x], l, r);\n            } else if ((a.x + a.y) == (b.x + b.y)) {\n                int k = a.x + a.y;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d1_edges[k], l, r);\n            } else {\n                int k = a.x - a.y + N;\n                int l = min(a.x, b.x);\n                int r = max(a.x, b.x);\n                return check_range_empty(s.d2_edges[k], l, r);\n            }\n        };\n        return check(p1, p2) && check(p2, p3) && check(p3, p4) && check(p4, p1);\n    }\n    \n    bool check_perimeter_dots(const State& s, Point p1, Point p2) {\n         if (p1.y == p2.y) {\n             int y = p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.row_dots[y], l, r);\n         } else if (p1.x == p2.x) {\n             int x = p1.x;\n             int l = min(p1.y, p2.y) + 1;\n             int r = max(p1.y, p2.y);\n             return check_range_empty(s.col_dots[x], l, r);\n         } else if ((p1.x + p1.y) == (p2.x + p2.y)) {\n             int k = p1.x + p1.y;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d1_dots[k], l, r);\n         } else {\n             int k = p1.x - p1.y + N;\n             int l = min(p1.x, p2.x) + 1;\n             int r = max(p1.x, p2.x);\n             return check_range_empty(s.d2_dots[k], l, r);\n         }\n    }\n\n    void solve() {\n        auto start_time = chrono::high_resolution_clock::now();\n        \n        State s0;\n        for (auto p : initial_dots) {\n            s0.add_dot(p.x, p.y);\n        }\n        beam.push_back(s0);\n        \n        // Beam width adjustment based on N\n        int BEAM_WIDTH = 80;\n        if (N > 45) BEAM_WIDTH = 50;\n        if (N > 55) BEAM_WIDTH = 30; \n\n        struct NextStateInfo {\n            int parent_idx;\n            Move move;\n            long long new_score;\n            double heuristic; \n        };\n        vector<NextStateInfo> candidates;\n        candidates.reserve(BEAM_WIDTH * 50);\n\n        int turn = 0;\n        static vector<Point> dots;\n\n        while (true) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            candidates.clear();\n            bool any_move = false;\n\n            for (int i = 0; i < beam.size(); ++i) {\n                const State& s = beam[i];\n                \n                dots.clear();\n                for(int y=0; y<N; ++y) {\n                    Mask m = s.row_dots[y];\n                    while(m) {\n                        int x = __builtin_ctzll(m);\n                        dots.push_back({x, y});\n                        m &= (m - 1);\n                    }\n                }\n\n                for (const auto& p3 : dots) {\n                    for (int pair_idx = 0; pair_idx < 8; ++pair_idx) {\n                        int d_idx1 = pairs90[pair_idx][0];\n                        int d_idx2 = pairs90[pair_idx][1];\n\n                        Point p2 = find_neighbor(s, p3, d_idx1);\n                        if (p2.x == -1) continue;\n                        Point p4 = find_neighbor(s, p3, d_idx2);\n                        if (p4.x == -1) continue;\n\n                        Point p1 = {p2.x + p4.x - p3.x, p2.y + p4.y - p3.y};\n                        \n                        if (p1.x < 0 || p1.x >= N || p1.y < 0 || p1.y >= N) continue;\n                        if (s.has_dot(p1.x, p1.y)) continue;\n\n                        if (!check_perimeter_dots(s, p1, p2)) continue;\n                        if (!check_perimeter_dots(s, p1, p4)) continue;\n                        if (!check_edges_free(s, p1, p2, p3, p4)) continue;\n\n                        long long gain = weights[p1.x][p1.y];\n                        long long new_total = s.current_score_w + gain;\n                        \n                        // Heuristic is simple greedy gain\n                        candidates.push_back({i, {p1, p2, p3, p4}, new_total, (double)gain});\n                        any_move = true;\n                    }\n                }\n            }\n\n            if (!any_move) break;\n\n            if (candidates.size() > BEAM_WIDTH) {\n                 nth_element(candidates.begin(), candidates.begin() + BEAM_WIDTH, candidates.end(),\n                    [](const NextStateInfo& a, const NextStateInfo& b) {\n                        return a.heuristic > b.heuristic;\n                    });\n                 candidates.resize(BEAM_WIDTH);\n            }\n            \n            sort(candidates.begin(), candidates.end(), \n                 [](const NextStateInfo& a, const NextStateInfo& b) {\n                     return a.heuristic > b.heuristic;\n                 });\n\n            vector<State> next_beam;\n            next_beam.reserve(candidates.size());\n            \n            for (const auto& cand : candidates) {\n                State ns = beam[cand.parent_idx];\n                ns.add_dot(cand.move.p1.x, cand.move.p1.y);\n                ns.add_edges(cand.move.p1, cand.move.p2, cand.move.p3, cand.move.p4);\n                ns.history.push_back(cand.move);\n                next_beam.push_back(ns);\n            }\n\n            beam = move(next_beam);\n            turn++;\n        }\n\n        if (beam.empty()) return;\n        auto best_it = max_element(beam.begin(), beam.end(), [](const State& a, const State& b){\n            return a.current_score_w < b.current_score_w;\n        });\n        \n        const auto& history = best_it->history;\n        cout << history.size() << \"\\n\";\n        for (const auto& m : history) {\n            cout << m.p1.x << \" \" << m.p1.y << \" \" \n                 << m.p2.x << \" \" << m.p2.y << \" \" \n                 << m.p3.x << \" \" << m.p3.y << \" \" \n                 << m.p4.x << \" \" << m.p4.y << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if (!(cin >> N >> M)) return 0;\n\n    C = (N - 1) / 2;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            weights[x][y] = 1LL * (x - C) * (x - C) + 1LL * (y - C) * (y - C) + 1;\n        }\n    }\n\n    Solver solver;\n    solver.initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> solver.initial_dots[i].x >> solver.initial_dots[i].y;\n    }\n\n    solver.solve();\n\n    return 0;\n}","ahc015":"/**\n * Improved Solution for AtCoder Heuristic Contest (AHC015) - Halloween Candy\n * \n * Strategy & Improvements:\n * 1. State Representation & LUT Optimization:\n *    - The 10x10 grid is small enough to be represented using bit-packed integers.\n *    - Each row (10 cells, 2 bits per cell) fits into a 32-bit integer.\n *    - Movement (Tilting) and Scoring (Adjacency) logic is precomputed into Look-Up Tables (LUTs).\n *    - This reduces the complexity of 'tilt' and 'eval' operations from O(N) loops to O(1) table lookups (plus a fast transpose for vertical ops).\n * \n * 2. Monte Carlo Tree Search (MCTS) / Simulation:\n *    - Due to the faster state operations, we can perform significantly more simulations (playouts) within the 2s time limit.\n *    - The playout strategy is \"Greedy with Lookahead\": at each step of the simulation, we choose the move that maximizes immediate same-flavor adjacency.\n *    - We simulate until the end of the game (t=100) and evaluate using the exact scoring function (Sum of Squares of Component Sizes) using DSU.\n * \n * 3. Time Management:\n *    - Time is allocated dynamically per step based on remaining time and remaining steps.\n *    - As the game progresses and the simulation depth decreases, the number of iterations naturally increases, improving precision for critical late-game moves.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// --- Constants ---\nconstexpr int N = 10;\nconstexpr int MAX_T = 100;\nconstexpr int NUM_DIRS = 4;\nconstexpr char DIR_CHARS[] = {'F', 'B', 'L', 'R'}; // 0:F(Up), 1:B(Down), 2:L, 3:R\n\n// 2 bits per cell * 10 cells = 20 bits. Size = 2^20 approx 1MB.\nconstexpr int LUT_SIZE = 1 << (2 * N);\n\n// --- Global Look-Up Tables ---\nuint32_t lut_move_L[LUT_SIZE];\nuint32_t lut_move_R[LUT_SIZE];\nuint8_t lut_adj_score[LUT_SIZE]; // Max score for a row is 9, fits in uint8\n\n// --- Global Data ---\nint flavors[MAX_T]; // Pre-read flavors\n\n// --- Random Number Generator ---\nstruct XorShift128 {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    \n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    \n    inline int next_int(int n) {\n        if (n <= 0) return 0;\n        return next() % n;\n    }\n} rng;\n\n// --- Initialization ---\nvoid init_lut() {\n    // Iterate all possible row configurations (20 bits)\n    for (int i = 0; i < LUT_SIZE; ++i) {\n        int cells[N];\n        int temp = i;\n        // Decode bits to cells\n        for (int k = 0; k < N; ++k) {\n            cells[k] = temp & 3;\n            temp >>= 2;\n        }\n        \n        // 1. Precompute Move Left\n        // Pack non-zero cells to the beginning (index 0)\n        int p = 0;\n        int new_cells_L[N] = {0};\n        for (int k = 0; k < N; ++k) {\n            if (cells[k] != 0) {\n                new_cells_L[p++] = cells[k];\n            }\n        }\n        uint32_t res_L = 0;\n        for (int k = 0; k < N; ++k) {\n            res_L |= (uint32_t(new_cells_L[k]) << (2 * k));\n        }\n        lut_move_L[i] = res_L;\n        \n        // 2. Precompute Move Right\n        // Pack non-zero cells to the end (index N-1)\n        p = N - 1;\n        int new_cells_R[N] = {0};\n        for (int k = N - 1; k >= 0; --k) {\n            if (cells[k] != 0) {\n                new_cells_R[p--] = cells[k];\n            }\n        }\n        uint32_t res_R = 0;\n        for (int k = 0; k < N; ++k) {\n            res_R |= (uint32_t(new_cells_R[k]) << (2 * k));\n        }\n        lut_move_R[i] = res_R;\n        \n        // 3. Precompute Adjacency Score\n        // Count adjacent pairs of same flavor\n        int score = 0;\n        for (int k = 0; k < N - 1; ++k) {\n            if (cells[k] != 0 && cells[k] == cells[k+1]) {\n                score++;\n            }\n        }\n        lut_adj_score[i] = score;\n    }\n}\n\n// --- State Structure ---\nstruct State {\n    // rows[r] stores the configuration of row r.\n    // Bits 0-1 correspond to column 0, bits 2-3 to column 1, etc.\n    uint32_t rows[N]; \n\n    void init() {\n        memset(rows, 0, sizeof(rows));\n    }\n    \n    // Place a candy of flavor f at (r, c)\n    // Assumes cell is empty (0)\n    inline void place(int r, int c, int f) {\n        rows[r] |= (uint32_t(f) << (2 * c));\n    }\n    \n    // Transpose the grid: rows -> cols\n    // Used to apply row-based operations (L/R/Score) to columns (U/D)\n    inline void transpose(uint32_t* dst) const {\n        memset(dst, 0, sizeof(uint32_t) * N);\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            if (val == 0) continue; // Optimization for empty rows\n            for (int c = 0; c < N; ++c) {\n                uint32_t f = (val >> (2 * c)) & 3;\n                if (f) {\n                    // Element at (r, c) moves to dest col c at position r\n                    dst[c] |= (f << (2 * r));\n                }\n            }\n        }\n    }\n    \n    // Reconstruct rows from columns (inverse transpose)\n    inline void from_cols(const uint32_t* cols) {\n        memset(rows, 0, sizeof(rows));\n        for (int c = 0; c < N; ++c) {\n            uint32_t val = cols[c];\n            if (val == 0) continue;\n            for (int r = 0; r < N; ++r) {\n                uint32_t f = (val >> (2 * r)) & 3;\n                if (f) {\n                    rows[r] |= (f << (2 * c));\n                }\n            }\n        }\n    }\n\n    // Tilt the board in direction dir\n    // 0:F(Up), 1:B(Down), 2:L, 3:R\n    void tilt(int dir) {\n        if (dir == 2) { // Left\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_L[rows[i]];\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_R[rows[i]];\n        } else {\n            // Vertical moves require transpose\n            uint32_t cols[N];\n            transpose(cols);\n            if (dir == 0) { // Forward/Up -> Like Left on columns\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_L[cols[i]];\n            } else { // Backward/Down -> Like Right on columns\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_R[cols[i]];\n            }\n            from_cols(cols);\n        }\n    }\n    \n    // Fast evaluation: count adjacent same-flavor pairs\n    int eval_adj() const {\n        int score = 0;\n        // Horizontal score from rows\n        for (int i = 0; i < N; ++i) score += lut_adj_score[rows[i]];\n        \n        // Vertical score needs transpose\n        uint32_t cols[N];\n        transpose(cols);\n        for (int i = 0; i < N; ++i) score += lut_adj_score[cols[i]];\n        \n        return score;\n    }\n    \n    // Find the k-th empty cell (1-based index)\n    // Priority: Top-to-Bottom, Left-to-Right\n    pair<int,int> get_kth_empty(int k) const {\n        int cnt = 0;\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            // Optimization: if row is full (no zeros), skip? \n            // Checking if full is complex due to 2-bit packing, simple loop is fine for N=10.\n            for (int c = 0; c < N; ++c) {\n                if (((val >> (2 * c)) & 3) == 0) {\n                    cnt++;\n                    if (cnt == k) return {r, c};\n                }\n            }\n        }\n        return {-1, -1};\n    }\n    \n    // Full Score Calculation: Sum of squares of connected component sizes.\n    // Uses Disjoint Set Union (DSU).\n    long long eval_full() const {\n        static int parent[N*N];\n        static int sz[N*N];\n        static int board_flat[N*N];\n        \n        // Flatten board for easier indexing\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            for (int c = 0; c < N; ++c) {\n                board_flat[r*N + c] = (val >> (2*c)) & 3;\n            }\n        }\n        \n        // Init DSU\n        for (int i = 0; i < N*N; ++i) {\n            parent[i] = i;\n            sz[i] = 1;\n        }\n        \n        auto find_set = [&](int i) {\n            int root = i;\n            while (root != parent[root]) root = parent[root];\n            // Path compression\n            int curr = i;\n            while (curr != root) {\n                int next = parent[curr];\n                parent[curr] = root;\n                curr = next;\n            }\n            return root;\n        };\n        \n        auto unite_sets = [&](int i, int j) {\n            int root_i = find_set(i);\n            int root_j = find_set(j);\n            if (root_i != root_j) {\n                parent[root_j] = root_i;\n                sz[root_i] += sz[root_j];\n            }\n        };\n        \n        // Horizontal connections\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N - 1; ++c) {\n                int idx = r*N + c;\n                int f = board_flat[idx];\n                if (f != 0 && f == board_flat[idx+1]) {\n                    unite_sets(idx, idx+1);\n                }\n            }\n        }\n        \n        // Vertical connections\n        for (int r = 0; r < N - 1; ++r) {\n            for (int c = 0; c < N; ++c) {\n                int idx = r*N + c;\n                int f = board_flat[idx];\n                if (f != 0 && f == board_flat[idx+N]) {\n                    unite_sets(idx, idx+N);\n                }\n            }\n        }\n        \n        long long total_sq = 0;\n        // Use a simple array to track visited roots to avoid recounting\n        // (re-using parent array logic is complex, just use a bool flag array)\n        bool counted[N*N] = {false};\n        \n        for (int i = 0; i < N*N; ++i) {\n            if (board_flat[i] != 0) {\n                int root = find_set(i);\n                if (!counted[root]) {\n                    total_sq += (long long)sz[root] * sz[root];\n                    counted[root] = true;\n                }\n            }\n        }\n        return total_sq;\n    }\n};\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_lut();\n    \n    // Read flavors\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n    \n    State current_state;\n    current_state.init();\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    // Total time limit set slightly below 2.0s to be safe\n    double total_time_limit = 1.95;\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // 1. Place the candy\n        pair<int,int> pos = current_state.get_kth_empty(p);\n        current_state.place(pos.first, pos.second, flavors[t]);\n        \n        int best_dir = 0;\n        \n        // Time management\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_time;\n        double remaining_time = total_time_limit - elapsed.count();\n        double time_per_move = remaining_time / (100 - t);\n        \n        // Ensure a minimum budget to avoid skipping\n        if (time_per_move < 0.001) time_per_move = 0.001;\n        \n        // Last move: just maximize final score (no randomness left)\n        if (t == 99) {\n            long long max_score = -1;\n            for (int d = 0; d < 4; ++d) {\n                State next = current_state;\n                next.tilt(d);\n                long long s = next.eval_full();\n                if (s > max_score) {\n                    max_score = s;\n                    best_dir = d;\n                }\n            }\n        } else {\n            // Monte Carlo Simulation\n            long long sum_scores[4] = {0};\n            int counts[4] = {0};\n            \n            auto move_start_time = chrono::high_resolution_clock::now();\n            int iter = 0;\n            \n            // Loop until time budget for this move is exhausted\n            while (true) {\n                // Check time every 64 iterations to minimize overhead\n                if ((iter & 63) == 0) {\n                    auto curr = chrono::high_resolution_clock::now();\n                    if ((curr - move_start_time).count() * 1e-9 > time_per_move) break;\n                }\n                iter++;\n                \n                int first_move = (iter - 1) % 4;\n                \n                // Playout\n                State sim_state = current_state;\n                sim_state.tilt(first_move);\n                \n                // Simulate rest of the game\n                for (int k = t + 1; k < 100; ++k) {\n                    int empty_cnt = 100 - k;\n                    if (empty_cnt <= 0) break;\n                    \n                    // Random placement\n                    int rnd_p = rng.next_int(empty_cnt) + 1;\n                    pair<int,int> rnd_pos = sim_state.get_kth_empty(rnd_p);\n                    sim_state.place(rnd_pos.first, rnd_pos.second, flavors[k]);\n                    \n                    // Greedy Policy: Choose move that maximizes immediate adjacency\n                    int best_adj = -1;\n                    int cands[4];\n                    int cand_cnt = 0;\n                    \n                    for (int d = 0; d < 4; ++d) {\n                        State temp = sim_state;\n                        temp.tilt(d);\n                        int adj = temp.eval_adj();\n                        if (adj > best_adj) {\n                            best_adj = adj;\n                            cand_cnt = 0;\n                            cands[cand_cnt++] = d;\n                        } else if (adj == best_adj) {\n                            cands[cand_cnt++] = d;\n                        }\n                    }\n                    \n                    // Pick random among best candidates\n                    int chosen = cands[rng.next_int(cand_cnt)];\n                    sim_state.tilt(chosen);\n                }\n                \n                sum_scores[first_move] += sim_state.eval_full();\n                counts[first_move]++;\n            }\n            \n            // Select best average score\n            double best_avg = -1.0;\n            for (int d = 0; d < 4; ++d) {\n                if (counts[d] > 0) {\n                    double avg = (double)sum_scores[d] / counts[d];\n                    if (avg > best_avg) {\n                        best_avg = avg;\n                        best_dir = d;\n                    }\n                }\n            }\n        }\n        \n        // Output and update\n        cout << DIR_CHARS[best_dir] << endl;\n        current_state.tilt(best_dir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nmt19937 rng(12345);\n\n// Helper for random numbers\nint rand_int(int l, int r) {\n    if (l > r) return l;\n    return uniform_int_distribution<int>(l, r)(rng);\n}\n\ndouble rand_double() {\n    return uniform_real_distribution<double>(0.0, 1.0)(rng);\n}\n\n// Type for Sorted Degree Sequence\ntypedef vector<int> SDS;\n\n// Compute Sorted Degree Sequence from adjacency matrix\nSDS get_sds(const vector<string>& adj, int N) {\n    SDS degs(N, 0);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (i != j && adj[i][j] == '1') {\n                degs[i]++;\n            }\n        }\n    }\n    sort(degs.begin(), degs.end());\n    return degs;\n}\n\n// Generate a random graph using Randomized Stochastic Block Model\n// This creates graphs with diverse degree structures\nvector<string> generate_sbm_graph(int N) {\n    // Random number of blocks from 1 to 10\n    int K = rand_int(1, 10);\n    \n    // Random vertex assignment\n    vector<int> assign(N);\n    for(int i=0; i<N; ++i) assign[i] = rand_int(0, K-1);\n    \n    // Random block interaction probabilities\n    // We bias probabilities towards 0 or 1 to create stronger signals\n    vector<vector<double>> probs(K, vector<double>(K));\n    for(int i=0; i<K; ++i) {\n        for(int j=i; j<K; ++j) {\n            double p = rand_double();\n            // Polarize p to increase variance\n            if (rand_double() < 0.6) {\n                p = (p < 0.5) ? 0.05 : 0.95; \n            }\n            probs[i][j] = probs[j][i] = p;\n        }\n    }\n    \n    // Generate adjacency matrix\n    vector<string> adj(N, string(N, '0'));\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if (rand_double() < probs[assign[i]][assign[j]]) {\n                adj[i][j] = adj[j][i] = '1';\n            }\n        }\n    }\n    return adj;\n}\n\n// Calculate squared Euclidean distance between two SDS vectors\ndouble calc_sq_dist(const SDS& a, const SDS& b) {\n    double d = 0;\n    for(size_t i=0; i<a.size(); ++i) {\n        double diff = a[i] - b[i];\n        d += diff * diff;\n    }\n    return d;\n}\n\nstruct Candidate {\n    vector<string> adj;\n    SDS sds;\n};\n\nvoid solve() {\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return;\n\n    // Strategy 1: Low Epsilon -> Compact encoding\n    // If noise is negligible, minimize N using simple edge count encoding\n    if (eps < 0.0001) { \n         for(int n=4; n<=100; ++n) {\n            if (n*(n-1)/2 + 1 >= M) {\n                cout << n << endl;\n                for(int i=0; i<M; ++i) {\n                    string s(n*(n-1)/2, '0');\n                    for(int k=0; k<i; ++k) s[k] = '1';\n                    cout << s << endl;\n                }\n                cout << flush;\n                for(int q=0; q<100; ++q) {\n                    string s; cin >> s;\n                    int cnt=0; for(char c:s) if(c=='1') cnt++;\n                    cout << min(cnt, M-1) << endl << flush;\n                }\n                return;\n            }\n        }\n    }\n    \n    // Strategy 2: General Case -> Robust SDS Encoding\n    // For significant noise, we prioritize E=0 by using N=100.\n    // For mild noise, we can reduce N slightly to improve score.\n    int N = 100;\n    if (eps <= 0.15) {\n        // Heuristic reduction of N for lower noise levels\n        // Needs to be large enough to support M distinct degree profiles\n        N = max(12, (int)(sqrt(M)*2.5)); \n        if (N > 100) N = 100;\n    }\n\n    // Generate a pool of candidate graphs\n    vector<Candidate> pool;\n    // We can generate fewer candidates if N is small to save time, \n    // but for N=100 we want good diversity.\n    int pool_size = 2500; \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    while((int)pool.size() < pool_size) {\n        Candidate c;\n        c.adj = generate_sbm_graph(N);\n        c.sds = get_sds(c.adj, N);\n        pool.push_back(c);\n        \n        // Time safety check (2.0 sec limit for generation)\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 2000) break;\n    }\n    \n    // Fallback if generation was too slow\n    if ((int)pool.size() < M) {\n        while((int)pool.size() < M) {\n             Candidate c;\n             c.adj = vector<string>(N, string(N, '0'));\n             c.sds = vector<int>(N, 0);\n             pool.push_back(c);\n        }\n    }\n\n    // Greedy Selection: Select M graphs that maximize Minimum Distance (MaxMin)\n    vector<int> selected_indices;\n    vector<double> min_dists(pool.size(), 1e18);\n    \n    // Pick the first one (highest variance usually implies more information, or just random)\n    // Let's pick one with high variance in degrees? Or just random index 0.\n    selected_indices.push_back(0);\n    \n    // Initialize distances\n    for(size_t i=0; i<pool.size(); ++i) {\n        min_dists[i] = calc_sq_dist(pool[i].sds, pool[0].sds);\n    }\n    \n    while((int)selected_indices.size() < M) {\n        int best_idx = -1;\n        double max_val = -1.0;\n        \n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] > max_val) {\n                max_val = min_dists[i];\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) break;\n        \n        selected_indices.push_back(best_idx);\n        min_dists[best_idx] = -1.0; // Mark as used\n        \n        // Update distances\n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] >= 0) {\n                double d = calc_sq_dist(pool[i].sds, pool[best_idx].sds);\n                if (d < min_dists[i]) min_dists[i] = d;\n            }\n        }\n    }\n    \n    // Output N and Graphs\n    cout << N << endl;\n    \n    // Prepare expected feature vectors for decoding\n    vector<vector<double>> code_expected_sds(M);\n    \n    for(int k=0; k<M; ++k) {\n        int idx = selected_indices[k];\n        const auto& cand = pool[idx];\n        \n        string s_out;\n        s_out.reserve(N*(N-1)/2);\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                s_out += cand.adj[i][j];\n            }\n        }\n        cout << s_out << endl;\n        \n        // Calculate Expected SDS under noise\n        // E[deg_new] = deg_old * (1 - epsilon) + (N - 1 - deg_old) * epsilon\n        //            = deg_old * (1 - 2*epsilon) + (N - 1) * epsilon\n        // We assume the sorted order is largely preserved or effectively approximated by transforming the sorted vector.\n        vector<double> exp_sds(N);\n        for(int i=0; i<N; ++i) {\n            exp_sds[i] = cand.sds[i] * (1.0 - 2.0 * eps) + (N - 1) * eps;\n        }\n        code_expected_sds[k] = exp_sds;\n    }\n    cout << flush;\n    \n    // Process Queries\n    for(int q=0; q<100; ++q) {\n        string s; cin >> s;\n        \n        // Compute observed SDS\n        SDS obs_sds(N, 0);\n        int p = 0;\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                if(s[p] == '1') {\n                    obs_sds[i]++;\n                    obs_sds[j]++;\n                }\n                p++;\n            }\n        }\n        sort(obs_sds.begin(), obs_sds.end());\n        \n        // Find nearest codeword in Euclidean space\n        int best_m = 0;\n        double min_dist = 1e18;\n        \n        for(int m=0; m<M; ++m) {\n            double d = 0;\n            const auto& target = code_expected_sds[m];\n            for(int i=0; i<N; ++i) {\n                double diff = obs_sds[i] - target[i];\n                d += diff * diff;\n            }\n            \n            if (d < min_dist) {\n                min_dist = d;\n                best_m = m;\n            }\n        }\n        cout << best_m << endl << flush;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants\nconst long long INF_DIST = 1e18;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Point {\n    int x, y;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<Point> coords;\nvector<vector<pair<int, int>>> adj; // u -> {v, edge_index}\n\n// Precomputed data\nvector<vector<int16_t>> edge_hop_dist; // MxM matrix storing hop distances between edges\nvector<double> edge_importance; // size M, stores approximate betweenness centrality\n\n// Solution state\nvector<int> assignment; // edge_id -> day (1-based)\nvector<vector<int>> day_edges; // day (1-based) -> list of edge_ids\n\n// Random number generator\nmt19937 rng(12345);\n\n// Time management\nauto start_time = chrono::steady_clock::now();\ndouble get_time() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Union Find for connectivity checks\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n + 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) parent[rootX] = rootY;\n    }\n};\n\n// Preprocessing: Hop distances between all pairs of nodes and then edges\nvoid compute_hop_distances() {\n    // node_hop_dist[u][v]: min hops between node u and node v\n    vector<vector<int16_t>> node_dist(N + 1, vector<int16_t>(N + 1, 0));\n\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        vector<int> d(N + 1, -1);\n        queue<int> q;\n        \n        d[start_node] = 0;\n        q.push(start_node);\n        \n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            for (auto& edge : adj[u]) {\n                int v = edge.first;\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        for(int i=1; i<=N; ++i) node_dist[start_node][i] = (int16_t)d[i];\n    }\n\n    // Compute edge_hop_dist[i][j]: min hops between any endpoint of edge i and any endpoint of edge j\n    edge_hop_dist.assign(M, vector<int16_t>(M));\n    for (int i = 0; i < M; ++i) {\n        for (int j = i; j < M; ++j) {\n            if (i == j) {\n                edge_hop_dist[i][j] = 0;\n            } else {\n                int u1 = edges[i].u;\n                int v1 = edges[i].v;\n                int u2 = edges[j].u;\n                int v2 = edges[j].v;\n                \n                int d1 = node_dist[u1][u2];\n                int d2 = node_dist[u1][v2];\n                int d3 = node_dist[v1][u2];\n                int d4 = node_dist[v1][v2];\n                \n                int min_d = min({d1, d2, d3, d4});\n                edge_hop_dist[i][j] = min_d;\n                edge_hop_dist[j][i] = min_d;\n            }\n        }\n    }\n}\n\n// Preprocessing: Importance (Betweenness Centrality approximation)\nvoid compute_importance() {\n    edge_importance.assign(M, 0.0);\n    \n    // Run Dijkstra from each node to count how often an edge is part of a Shortest Path Tree\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, INF_DIST);\n        vector<int> parent_edge(N + 1, -1);\n        \n        dist[start_node] = 0;\n        pq.push({0, start_node});\n        \n        while (!pq.empty()) {\n            long long d = pq.top().first;\n            int u = pq.top().second;\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            \n            for (auto& e : adj[u]) {\n                int v = e.first;\n                int idx = e.second;\n                int w = edges[idx].w;\n                \n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        // Backtrack to increment counts\n        for (int i = 1; i <= N; ++i) {\n            if (i == start_node) continue;\n            int curr = i;\n            while (curr != start_node && parent_edge[curr] != -1) {\n                int e_idx = parent_edge[curr];\n                edge_importance[e_idx] += 1.0;\n                \n                int u = edges[e_idx].u;\n                int v = edges[e_idx].v;\n                // Determine which node is closer to start_node\n                if (dist[u] < dist[v]) curr = u;\n                else curr = v;\n            }\n        }\n    }\n    \n    // Normalize\n    double max_imp = 0;\n    for (double v : edge_importance) max_imp = max(max_imp, v);\n    if (max_imp > 0) {\n        for (auto& v : edge_importance) v /= max_imp;\n    }\n}\n\n// Initial Solution Generation\nvoid initial_solution() {\n    assignment.assign(M, 0);\n    day_edges.assign(D + 1, vector<int>());\n    \n    // Use BFS on the dual-like structure or just BFS on edges starting from center\n    // to ensure nearby edges get consecutive indices.\n    vector<bool> visited(M, false);\n    queue<int> q;\n    \n    // Find node closest to center (500, 500)\n    int center_node = 1;\n    int min_dist = 1e9;\n    if (!coords.empty()) {\n        for(int i=1; i<=N; ++i) {\n            int d = (coords[i-1].x - 500)*(coords[i-1].x - 500) + (coords[i-1].y - 500)*(coords[i-1].y - 500);\n            if (d < min_dist) {\n                min_dist = d;\n                center_node = i;\n            }\n        }\n    }\n    \n    // Push edges of center node\n    for(auto& p : adj[center_node]) {\n        q.push(p.second);\n        visited[p.second] = true;\n    }\n    if(q.empty()) { q.push(0); visited[0] = true; }\n\n    vector<int> ordered_edges;\n    ordered_edges.reserve(M);\n    \n    while(ordered_edges.size() < M) {\n        if (q.empty()) {\n            for(int i=0; i<M; ++i) if(!visited[i]) { q.push(i); visited[i]=true; break; }\n        }\n        \n        while(!q.empty()){\n            int e_idx = q.front();\n            q.pop();\n            ordered_edges.push_back(e_idx);\n            \n            int u = edges[e_idx].u;\n            int v = edges[e_idx].v;\n            \n            for(auto& p : adj[u]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n            for(auto& p : adj[v]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n        }\n    }\n    \n    // Assign days in a round-robin fashion to spatially separate edges on the same day\n    vector<int> counts(D + 1, 0);\n    int current_day = 1;\n    for(int e_idx : ordered_edges) {\n        // Ensure we don't exceed K\n        while(counts[current_day] >= K) {\n            current_day = (current_day % D) + 1;\n        }\n        assignment[e_idx] = current_day;\n        day_edges[current_day].push_back(e_idx);\n        counts[current_day]++;\n        current_day = (current_day % D) + 1;\n    }\n}\n\n// Cost Function for SA\n// Calculate contribution of a pair of removed edges (i, j)\ninline double pair_cost(int i, int j) {\n    double dist = edge_hop_dist[i][j];\n    // Penalty is high if distance is small.\n    // Penalty is scaled by importance: removing two important edges nearby is very bad.\n    double imp_factor = 1.0 + 10.0 * edge_importance[i] * edge_importance[j]; \n    return imp_factor / ((dist + 1.0) * (dist + 1.0));\n}\n\n// Calculate total dispersion cost for a day\ndouble calculate_day_cost(int d) {\n    double cost = 0;\n    const auto& es = day_edges[d];\n    for (size_t i = 0; i < es.size(); ++i) {\n        for (size_t j = i + 1; j < es.size(); ++j) {\n            cost += pair_cost(es[i], es[j]);\n        }\n    }\n    return cost;\n}\n\n// Check if graph remains connected when edges of day 'd' are removed\nbool check_connectivity(int d) {\n    DSU dsu(N);\n    int components = N;\n    for(int i=0; i<M; ++i) {\n        if (assignment[i] != d) {\n            if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                dsu.unite(edges[i].u, edges[i].v);\n                components--;\n            }\n        }\n    }\n    return components == 1;\n}\n\n// Try to fix connectivity issues greedily\nbool fix_connectivity() {\n    bool changed = false;\n    for (int d = 1; d <= D; ++d) {\n        if (!check_connectivity(d)) {\n            // Identify components\n            DSU dsu(N);\n            for(int i=0; i<M; ++i) {\n                if (assignment[i] != d) {\n                    dsu.unite(edges[i].u, edges[i].v);\n                }\n            }\n            \n            // Find an edge currently scheduled for day 'd' that connects two different components\n            // If we move this edge to another day, it will be present on day 'd', fixing connectivity.\n            int best_edge = -1;\n            \n            for (int e_idx : day_edges[d]) {\n                if (dsu.find(edges[e_idx].u) != dsu.find(edges[e_idx].v)) {\n                    best_edge = e_idx;\n                    break; // Found a bridging edge\n                }\n            }\n            \n            if (best_edge != -1) {\n                // Move best_edge to a day with capacity < K\n                for (int target = 1; target <= D; ++target) {\n                    if (target != d && day_edges[target].size() < K) {\n                        // Perform move\n                        vector<int>& vec_d = day_edges[d];\n                        vec_d.erase(remove(vec_d.begin(), vec_d.end(), best_edge), vec_d.end());\n                        \n                        day_edges[target].push_back(best_edge);\n                        assignment[best_edge] = target;\n                        changed = true;\n                        break; \n                    }\n                }\n            }\n        }\n    }\n    return changed;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> D >> K)) return 0;\n    \n    adj.resize(N + 1);\n    edges.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        edges.push_back({u, v, w, i});\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n    \n    coords.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n\n    // 1. Preprocessing\n    compute_hop_distances();\n    compute_importance();\n    \n    // 2. Initial Assignment\n    initial_solution();\n\n    // Calculate initial costs\n    vector<double> day_costs(D + 1);\n    double total_cost = 0;\n    for (int d = 1; d <= D; ++d) {\n        day_costs[d] = calculate_day_cost(d);\n        total_cost += day_costs[d];\n    }\n\n    // 3. Simulated Annealing\n    double time_limit = 5.6; \n    double t0 = 5.0;\n    double t1 = 0.0001;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) { \n            if (get_time() > time_limit) break;\n        }\n        \n        double temp = t0 + (t1 - t0) * (get_time() / time_limit);\n        \n        // Swap Move: Pick two different days and swap an edge\n        int d1 = uniform_int_distribution<int>(1, D)(rng);\n        int d2 = uniform_int_distribution<int>(1, D)(rng);\n        if (d1 == d2) continue;\n        \n        if (day_edges[d1].empty() || day_edges[d2].empty()) continue;\n\n        int idx1 = uniform_int_distribution<int>(0, day_edges[d1].size() - 1)(rng);\n        int idx2 = uniform_int_distribution<int>(0, day_edges[d2].size() - 1)(rng);\n        \n        int e1 = day_edges[d1][idx1];\n        int e2 = day_edges[d2][idx2];\n        \n        // Calculate cost delta incrementally\n        double d1_old = day_costs[d1];\n        double d2_old = day_costs[d2];\n        \n        // Remove e1 from d1, add e2 to d1\n        double cost_e1_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e1_in_d1 += pair_cost(e1, other);\n        }\n        double cost_e2_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e2_in_d1 += pair_cost(e2, other);\n        }\n        \n        // Remove e2 from d2, add e1 to d2\n        double cost_e2_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e2_in_d2 += pair_cost(e2, other);\n        }\n        double cost_e1_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e1_in_d2 += pair_cost(e1, other);\n        }\n        \n        double d1_new = d1_old - cost_e1_in_d1 + cost_e2_in_d1;\n        double d2_new = d2_old - cost_e2_in_d2 + cost_e1_in_d2;\n        \n        double delta = (d1_new + d2_new) - (d1_old + d2_old);\n        \n        if (delta < 0 || bernoulli_distribution(exp(-delta / temp))(rng)) {\n            // Accept swap\n            day_edges[d1][idx1] = e2;\n            day_edges[d2][idx2] = e1;\n            assignment[e1] = d2;\n            assignment[e2] = d1;\n            day_costs[d1] = d1_new;\n            day_costs[d2] = d2_new;\n            total_cost += delta;\n        }\n    }\n    \n    // 4. Ensure Connectivity\n    // Keep trying to fix until valid or time is up (allow slight over time if needed, but keep safe)\n    while (get_time() < 5.9) {\n        if (!fix_connectivity()) break; \n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        cout << assignment[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cstring>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global Constants and Time\nconst int MAX_D = 14;\nint D;\nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Data Structures\nstruct Point {\n    int x, y, z;\n    auto operator<=>(const Point&) const = default;\n    Point operator+(const Point& other) const { return {x + other.x, y + other.y, z + other.z}; }\n    Point operator-(const Point& other) const { return {x - other.x, y - other.y, z - other.z}; }\n};\n\nstruct Rotation {\n    int p[3];\n    int s[3];\n};\nvector<Rotation> rotations;\n\nvoid init_rotations() {\n    int perms[6][3] = {{0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}};\n    for (int i = 0; i < 6; ++i) {\n        for (int mask = 0; mask < 8; ++mask) {\n            Rotation r;\n            for (int j = 0; j < 3; ++j) {\n                r.p[j] = perms[i][j];\n                r.s[j] = (mask & (1 << j)) ? -1 : 1;\n            }\n            int mat[3][3] = {0};\n            for(int j=0; j<3; ++j) mat[j][r.p[j]] = r.s[j];\n            int det = mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1])\n                    - mat[0][1]*(mat[1][0]*mat[2][2] - mat[1][2]*mat[2][0])\n                    + mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]);\n            if (det == 1) rotations.push_back(r);\n        }\n    }\n}\n\nPoint apply_rot(const Point& pt, int rot_idx) {\n    const Rotation& r = rotations[rot_idx];\n    int coords[3] = {pt.x, pt.y, pt.z};\n    return {\n        coords[r.p[0]] * r.s[0],\n        coords[r.p[1]] * r.s[1],\n        coords[r.p[2]] * r.s[2]\n    };\n}\n\n// Inputs\nvector<string> f1_in, r1_in, f2_in, r2_in;\n\n// Helpers\nbool is_set(const vector<string>& s, int r, int c) { return s[r][c] == '1'; }\n\n// Get all valid positions\nvector<Point> get_maximal_voxels(const vector<string>& f, const vector<string>& r_s) {\n    vector<Point> v;\n    for(int x=0; x<D; ++x)\n        for(int y=0; y<D; ++y)\n            for(int z=0; z<D; ++z)\n                if(is_set(f, z, x) && is_set(r_s, z, y))\n                    v.push_back({x,y,z});\n    return v;\n}\n\nstruct Solution {\n    vector<int> grid1;\n    vector<int> grid2;\n    int num_blocks;\n    double score;\n};\n\n// Solver State\nstruct SolverState {\n    vector<Point> M1, M2;\n    vector<bool> used1, used2;\n    vector<int> cover_f1, cover_r1, cover_f2, cover_r2; // counts of coverage\n    vector<int> grid1, grid2;\n    int block_counter;\n    \n    SolverState() : grid1(D*D*D, 0), grid2(D*D*D, 0), block_counter(1) {}\n\n    void init(const vector<Point>& m1, const vector<Point>& m2) {\n        M1 = m1; M2 = m2;\n        used1.assign(M1.size(), false);\n        used2.assign(M2.size(), false);\n        cover_f1.assign(D*D, 0); cover_r1.assign(D*D, 0);\n        cover_f2.assign(D*D, 0); cover_r2.assign(D*D, 0);\n    }\n\n    void add_block(const vector<Point>& shape, int rot, Point shift, const vector<int>& indices1, const vector<int>& indices2) {\n        int id = block_counter++;\n        for(int idx : indices1) {\n            used1[idx] = true;\n            Point p = M1[idx];\n            grid1[p.x*D*D + p.y*D + p.z] = id;\n            cover_f1[p.z*D + p.x]++;\n            cover_r1[p.z*D + p.y]++;\n        }\n        for(int idx : indices2) {\n            used2[idx] = true;\n            Point p = M2[idx];\n            grid2[p.x*D*D + p.y*D + p.z] = id;\n            cover_f2[p.z*D + p.x]++;\n            cover_r2[p.z*D + p.y]++;\n        }\n    }\n};\n\n// Compute weights dynamically\nvoid update_weights(SolverState& state, vector<double>& w1, vector<double>& w2, mt19937& rng) {\n    // Counts of available voxels for each pixel\n    vector<int> cnt_f1(D*D, 0), cnt_r1(D*D, 0);\n    vector<int> cnt_f2(D*D, 0), cnt_r2(D*D, 0);\n\n    int n1 = state.M1.size();\n    int n2 = state.M2.size();\n\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        Point p = state.M1[i];\n        cnt_f1[p.z*D + p.x]++;\n        cnt_r1[p.z*D + p.y]++;\n    }\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        Point p = state.M2[i];\n        cnt_f2[p.z*D + p.x]++;\n        cnt_r2[p.z*D + p.y]++;\n    }\n\n    auto calc_w = [&](const Point& p, const vector<int>& cnt_f, const vector<int>& cnt_r, \n                      const vector<int>& cov_f, const vector<int>& cov_r) {\n        double w = 1.0; // base volume weight\n        int zx = p.z*D + p.x;\n        int zy = p.z*D + p.y;\n        \n        // If pixel not covered yet, high value. Inversely proportional to availability.\n        if (cov_f[zx] == 0) w += 50.0 / (cnt_f[zx] + 1e-5);\n        if (cov_r[zy] == 0) w += 50.0 / (cnt_r[zy] + 1e-5);\n        \n        return w;\n    };\n\n    w1.assign(n1, 0);\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        w1[i] = calc_w(state.M1[i], cnt_f1, cnt_r1, state.cover_f1, state.cover_r1);\n        w1[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n\n    w2.assign(n2, 0);\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        w2[i] = calc_w(state.M2[i], cnt_f2, cnt_r2, state.cover_f2, state.cover_r2);\n        w2[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n}\n\n// Voting grid\ndouble votes[30*30*30];\nint vote_dim = 0;\nint vote_dim_sq = 0;\nint vote_offset = 0;\n\nvoid reset_votes() {\n    vote_offset = D;\n    vote_dim = 2 * D + 1;\n    vote_dim_sq = vote_dim * vote_dim;\n    fill(votes, votes + vote_dim*vote_dim*vote_dim, 0.0);\n}\n\nstruct MatchResult {\n    vector<Point> shape;\n    vector<int> indices1;\n    vector<int> indices2;\n    double total_weight;\n    int rotation;\n    Point shift;\n};\n\nMatchResult find_best_block(SolverState& state, const vector<double>& w1, const vector<double>& w2) {\n    MatchResult best_res;\n    best_res.total_weight = -1.0;\n\n    // Collect available indices\n    vector<int> c1, c2;\n    for(size_t i=0; i<state.M1.size(); ++i) if(!state.used1[i]) c1.push_back(i);\n    for(size_t i=0; i<state.M2.size(); ++i) if(!state.used2[i]) c2.push_back(i);\n\n    if (c1.empty() || c2.empty()) return best_res;\n\n    // Subsample for voting to speed up\n    vector<int> vote_c1 = c1;\n    vector<int> vote_c2 = c2;\n    \n    // Heuristic: Vote only with highest weight voxels to find promising alignments\n    // This avoids O(N^2) in the voting loop\n    int limit = 300;\n    if (vote_c1.size() > limit) {\n        partial_sort(vote_c1.begin(), vote_c1.begin()+limit, vote_c1.end(), [&](int a, int b){ return w1[a] > w1[b]; });\n        vote_c1.resize(limit);\n    }\n    if (vote_c2.size() > limit) {\n        partial_sort(vote_c2.begin(), vote_c2.begin()+limit, vote_c2.end(), [&](int a, int b){ return w2[a] > w2[b]; });\n        vote_c2.resize(limit);\n    }\n\n    // Iterate Rotations\n    for(int rot=0; rot<24; ++rot) {\n        reset_votes();\n        \n        // Precompute rotated V2 subset\n        vector<Point> v2_rot(vote_c2.size());\n        for(size_t i=0; i<vote_c2.size(); ++i) v2_rot[i] = apply_rot(state.M2[vote_c2[i]], rot);\n\n        // Voting\n        for(size_t i=0; i<vote_c1.size(); ++i) {\n            Point p1 = state.M1[vote_c1[i]];\n            double val1 = w1[vote_c1[i]];\n            for(size_t j=0; j<vote_c2.size(); ++j) {\n                Point d = p1 - v2_rot[j];\n                if(abs(d.x) < D && abs(d.y) < D && abs(d.z) < D) {\n                    int idx = (d.x + vote_offset) * vote_dim_sq + (d.y + vote_offset) * vote_dim + (d.z + vote_offset);\n                    votes[idx] += val1 + w2[vote_c2[j]];\n                }\n            }\n        }\n\n        // Find top candidate shifts\n        priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n        for(int i=0; i<vote_dim*vote_dim*vote_dim; ++i) {\n            if(votes[i] > 1e-3) {\n                pq.push({votes[i], i});\n                if(pq.size() > 5) pq.pop();\n            }\n        }\n\n        vector<int> candidates;\n        while(!pq.empty()) {\n            candidates.push_back(pq.top().second);\n            pq.pop();\n        }\n\n        // Evaluate candidates with full sets\n        for(int cand_idx : candidates) {\n            int dz = cand_idx % vote_dim;\n            int dy = (cand_idx / vote_dim) % vote_dim;\n            int dx = (cand_idx / vote_dim_sq);\n            Point shift = {dx - vote_offset, dy - vote_offset, dz - vote_offset};\n\n            // Build map of V2 points (rotated and shifted) -> original index\n            map<Point, int> v2_map;\n            for(int idx : c2) {\n                Point p = apply_rot(state.M2[idx], rot) + shift;\n                if (p.x >= 0 && p.x < D && p.y >= 0 && p.y < D && p.z >= 0 && p.z < D) {\n                    v2_map[p] = idx;\n                }\n            }\n\n            // Intersection nodes\n            struct Node {\n                Point p;\n                int idx1;\n                int idx2;\n                double w;\n            };\n            vector<Node> intersection;\n            for(int idx1 : c1) {\n                Point p = state.M1[idx1];\n                if (v2_map.count(p)) {\n                    int idx2 = v2_map[p];\n                    intersection.push_back({p, idx1, idx2, w1[idx1] + w2[idx2]});\n                }\n            }\n\n            if (intersection.empty()) continue;\n\n            // Find largest weighted connected component\n            set<Point> int_pts;\n            for(const auto& node : intersection) int_pts.insert(node.p);\n            set<Point> visited;\n            map<Point, int> p_to_node;\n            for(size_t k=0; k<intersection.size(); ++k) p_to_node[intersection[k].p] = k;\n\n            for(const auto& node : intersection) {\n                if (visited.count(node.p)) continue;\n\n                vector<Point> comp_shape;\n                vector<int> comp_idx1, comp_idx2;\n                double comp_w = 0;\n                \n                queue<Point> q;\n                q.push(node.p);\n                visited.insert(node.p);\n                \n                while(!q.empty()){\n                    Point u = q.front(); q.pop();\n                    int u_node_idx = p_to_node[u];\n                    comp_shape.push_back(u);\n                    comp_idx1.push_back(intersection[u_node_idx].idx1);\n                    comp_idx2.push_back(intersection[u_node_idx].idx2);\n                    comp_w += intersection[u_node_idx].w;\n\n                    Point neighbors[6] = {\n                        {u.x+1, u.y, u.z}, {u.x-1, u.y, u.z},\n                        {u.x, u.y+1, u.z}, {u.x, u.y-1, u.z},\n                        {u.x, u.y, u.z+1}, {u.x, u.y, u.z-1}\n                    };\n\n                    for(const auto& v : neighbors) {\n                        if(int_pts.count(v) && !visited.count(v)) {\n                            visited.insert(v);\n                            q.push(v);\n                        }\n                    }\n                }\n\n                if (comp_w > best_res.total_weight) {\n                    best_res.total_weight = comp_w;\n                    best_res.shape = comp_shape;\n                    best_res.indices1 = comp_idx1;\n                    best_res.indices2 = comp_idx2;\n                    best_res.rotation = rot;\n                    best_res.shift = shift;\n                }\n            }\n        }\n    }\n    return best_res;\n}\n\nvoid fill_residuals(SolverState& state, const vector<string>& f, const vector<string>& r_s, bool is_second) {\n    vector<pair<int,int>> needed_f, needed_r;\n    const vector<int>& cov_f = (is_second ? state.cover_f2 : state.cover_f1);\n    const vector<int>& cov_r = (is_second ? state.cover_r2 : state.cover_r1);\n\n    for(int z=0; z<D; ++z) {\n        for(int x=0; x<D; ++x) \n            if(is_set(f, z, x) && cov_f[z*D+x] == 0) needed_f.push_back({x, z});\n        for(int y=0; y<D; ++y) \n            if(is_set(r_s, z, y) && cov_r[z*D+y] == 0) needed_r.push_back({y, z});\n    }\n\n    vector<Point> candidates;\n    const vector<Point>& M = (is_second ? state.M2 : state.M1);\n    const vector<bool>& used = (is_second ? state.used2 : state.used1);\n    \n    for(size_t i=0; i<M.size(); ++i) if(!used[i]) candidates.push_back(M[i]);\n\n    vector<bool> done_f(needed_f.size(), false);\n    vector<bool> done_r(needed_r.size(), false);\n    int rem_f = needed_f.size();\n    int rem_r = needed_r.size();\n\n    while(rem_f > 0 || rem_r > 0) {\n        int best_idx = -1;\n        int best_cnt = -1;\n        \n        int step = (candidates.size() > 500) ? 2 : 1;\n        for(size_t i=0; i<candidates.size(); i+=step) {\n            if(candidates[i].x == -1) continue;\n            int cnt = 0;\n            const Point& p = candidates[i];\n            for(size_t k=0; k<needed_f.size(); ++k) \n                if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) cnt++;\n            for(size_t k=0; k<needed_r.size(); ++k) \n                if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) cnt++;\n            \n            if(cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = i;\n            }\n        }\n\n        if(best_idx == -1 || best_cnt == 0) break;\n\n        Point p = candidates[best_idx];\n        candidates[best_idx].x = -1; \n        \n        int id = state.block_counter++;\n        if (is_second) state.grid2[p.x*D*D + p.y*D + p.z] = id;\n        else state.grid1[p.x*D*D + p.y*D + p.z] = id;\n\n        for(size_t k=0; k<needed_f.size(); ++k) \n            if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) { done_f[k]=true; rem_f--; }\n        for(size_t k=0; k<needed_r.size(); ++k) \n            if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) { done_r[k]=true; rem_r--; }\n    }\n}\n\ndouble calc_score(const SolverState& state) {\n    map<int, int> vol;\n    set<int> s1, s2;\n    \n    for(int x : state.grid1) if(x) { vol[x]++; s1.insert(x); }\n    for(int x : state.grid2) if(x) { vol[x]++; s2.insert(x); }\n    \n    double score = 0;\n    for(int id : s1) {\n        if(s2.count(id)) score += 1.0 / vol[id];\n        else score += vol[id];\n    }\n    for(int id : s2) {\n        if(!s1.count(id)) score += vol[id];\n    }\n    return round(1e9 * score);\n}\n\nvoid run_solve() {\n    cin >> D;\n    f1_in.resize(D); r1_in.resize(D);\n    f2_in.resize(D); r2_in.resize(D);\n    for(int i=0; i<D; ++i) cin >> f1_in[i];\n    for(int i=0; i<D; ++i) cin >> r1_in[i];\n    for(int i=0; i<D; ++i) cin >> f2_in[i];\n    for(int i=0; i<D; ++i) cin >> r2_in[i];\n\n    init_rotations();\n    vector<Point> M1 = get_maximal_voxels(f1_in, r1_in);\n    vector<Point> M2 = get_maximal_voxels(f2_in, r2_in);\n    \n    Solution best_sol;\n    best_sol.score = 1e18;\n\n    mt19937 rng(42);\n\n    while (get_time() < 5.8) {\n        SolverState state;\n        state.init(M1, M2);\n        \n        int consecutive_fails = 0;\n        while(consecutive_fails < 5) {\n            vector<double> w1, w2;\n            update_weights(state, w1, w2, rng);\n            \n            MatchResult res = find_best_block(state, w1, w2);\n            \n            // If the best block is empty or has very low value (meaning it probably contributes nothing to silhouettes)\n            if(res.shape.empty() || res.total_weight < 0.5) { \n                break;\n            }\n            \n            // Heuristic: if the block is just 1x1 and contributes only to volume (weight approx 2.0)\n            // and doesn't help cover new silhouette (which would add ~50 weight), \n            // it might be better to stop greedy matching and let residuals handle it,\n            // UNLESS we still have large unmatched chunks. \n            // But 1x1 common (cost 1) is better than 1x1 residual (cost 1) if we need it for both.\n            // If we need it for only one, 1x1 common is cost 1 (0 unmatched, 1 inv).\n            // 1x1 residual is cost 1 (1 unmatched).\n            // So common is never strictly worse.\n            \n            state.add_block(res.shape, res.rotation, res.shift, res.indices1, res.indices2);\n            \n            // Check if block was \"trivial\" (small volume, low weight)\n            if (res.total_weight < 20.0 && res.shape.size() < 2) {\n                 consecutive_fails++;\n            } else {\n                 consecutive_fails = 0;\n            }\n        }\n        \n        fill_residuals(state, f1_in, r1_in, false);\n        fill_residuals(state, f2_in, r2_in, true);\n        \n        double s = calc_score(state);\n        if (s < best_sol.score) {\n            best_sol.score = s;\n            best_sol.grid1 = state.grid1;\n            best_sol.grid2 = state.grid2;\n            best_sol.num_blocks = state.block_counter - 1;\n        }\n    }\n\n    cout << best_sol.num_blocks << endl;\n    for(int i=0; i<(int)best_sol.grid1.size(); ++i) cout << best_sol.grid1[i] << (i==best_sol.grid1.size()-1?\"\":\" \");\n    cout << endl;\n    for(int i=0; i<(int)best_sol.grid2.size(); ++i) cout << best_sol.grid2[i] << (i==best_sol.grid2.size()-1?\"\":\" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    run_solve();\n    return 0;\n}","ahc020":"/**\n * Problem: AHC020 - Broadcasting\n * Approach: Simulated Annealing on Resident Assignments with Dynamic Steiner Tree Cost.\n * \n * Fixes from previous iteration:\n * - Strictly enforce 0 <= P_i <= 5000. Moves that require P > 5000 are rejected.\n * - Pre-filter nearby stations to only include those within range 5000.\n * - In \"Clear Station\" move, ensure residents are only reassigned to reachable terminals.\n * \n * Algorithm Overview:\n * 1. Precompute all-pairs shortest paths between stations (for fast Steiner approximation).\n * 2. State: Assignment of each resident to a valid station.\n *    - Terminals = Station 0 + any station with >= 1 resident.\n * 3. Cost = Sum(P^2) + MST(Terminals on Metric Closure).\n * 4. SA Moves:\n *    - Shift: Move resident to a nearby valid station.\n *    - Clear: Empty a station and redistribute residents to other terminals (if valid).\n * 5. Post-processing: Reconstruct tree edges and prune non-terminal leaves.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 105;\nconst int MAX_K = 5005;\nconst int MAX_M = 305;\nconst long long INF = 1e18;\nconst int MAX_P = 5000; // Constraint\n\n// Structures\nstruct Point { int x, y; };\nstruct Edge { int u, v, w, id; };\n\n// Global Inputs\nint N, M, K;\nPoint stations[MAX_N];\nEdge edges[MAX_M];\nPoint residents[MAX_K];\n\n// Precomputed Data\nlong long adj_dist[MAX_N][MAX_N];      // Shortest path distance between stations\nint next_node[MAX_N][MAX_N];           // For path reconstruction\nint edge_index[MAX_N][MAX_N];          // Edge ID connecting two nodes\nint dist_res_stat[MAX_K][MAX_N];       // Required P for resident k at station i\nvector<int> nearby_stations[MAX_K];    // Valid stations (P <= 5000) sorted by distance\n\n// Random number generator\nmt19937 rng(12345);\n\n// Helper Functions\nlong long distSq(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint get_P(long long sq_dist) {\n    if (sq_dist == 0) return 0;\n    return (int)ceil(sqrt((double)sq_dist));\n}\n\n// Floyd-Warshall for metric closure\nvoid precompute_paths() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            adj_dist[i][j] = (i == j ? 0 : INF);\n            next_node[i][j] = -1;\n            edge_index[i][j] = -1;\n        }\n    }\n    for(int i=0; i<M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int w = edges[i].w;\n        if(w < adj_dist[u][v]) {\n            adj_dist[u][v] = adj_dist[v][u] = w;\n            next_node[u][v] = v;\n            next_node[v][u] = u;\n            edge_index[u][v] = edge_index[v][u] = i;\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(adj_dist[i][k] != INF && adj_dist[k][j] != INF) {\n                    if(adj_dist[i][k] + adj_dist[k][j] < adj_dist[i][j]) {\n                        adj_dist[i][j] = adj_dist[i][k] + adj_dist[k][j];\n                        next_node[i][j] = next_node[i][k];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate MST cost on the complete graph of terminals (Metric Closure)\nlong long calc_mst_cost(const vector<int>& terminals) {\n    if (terminals.empty()) return 0;\n    int T = terminals.size();\n    if (T == 1 && terminals[0] == 0) return 0; \n    \n    static long long min_d[MAX_N];\n    static bool visited[MAX_N];\n    \n    for(int i=0; i<T; ++i) {\n        min_d[i] = INF;\n        visited[i] = false;\n    }\n    \n    min_d[0] = 0;\n    long long total_mst = 0;\n    \n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_d[j] < best) {\n                best = min_d[j];\n                u = j;\n            }\n        }\n        \n        if (u == -1) break;\n        visited[u] = true;\n        total_mst += best;\n        \n        int u_idx = terminals[u];\n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[u_idx][terminals[v]];\n                if(d < min_d[v]) min_d[v] = d;\n            }\n        }\n    }\n    return total_mst;\n}\n\n// Reconstruct edges from the MST on terminals\nvector<int> get_steiner_edges(const vector<int>& terminals) {\n    vector<int> result_edges;\n    if (terminals.size() <= 1) return result_edges;\n\n    int T = terminals.size();\n    vector<long long> min_d(T, INF);\n    vector<int> parent(T, -1);\n    vector<bool> visited(T, false);\n    min_d[0] = 0;\n    \n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_d[j] < best) {\n                best = min_d[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        \n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[terminals[u]][terminals[v]];\n                if(d < min_d[v]) {\n                    min_d[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    \n    bitset<MAX_M> used;\n    for(int i=1; i<T; ++i) {\n        if(parent[i] == -1) continue;\n        int u = terminals[i];\n        int v = terminals[parent[i]];\n        int curr = u;\n        while(curr != v) {\n            int nxt = next_node[curr][v];\n            int idx = edge_index[curr][nxt];\n            if(idx != -1) used[idx] = 1;\n            curr = nxt;\n        }\n    }\n    for(int i=0; i<M; ++i) if(used[i]) result_edges.push_back(i);\n    return result_edges;\n}\n\nstruct State {\n    vector<int> assignment;\n    vector<multiset<int>> station_radii; \n    vector<int> active_counts;\n    vector<int> terminals;\n    long long power_cost;\n    long long network_cost;\n    long long total_cost;\n    \n    void update_terminals() {\n        terminals.clear();\n        terminals.push_back(0); \n        for(int i=1; i<N; ++i) {\n            if(active_counts[i] > 0) terminals.push_back(i);\n        }\n    }\n    \n    void recalc_network_cost() {\n        update_terminals();\n        network_cost = calc_mst_cost(terminals);\n        total_cost = power_cost + network_cost;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K)) return 0;\n    for(int i=0; i<N; ++i) cin >> stations[i].x >> stations[i].y;\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    }\n    for(int i=0; i<K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    precompute_paths();\n\n    // Init distances with check\n    for(int k=0; k<K; ++k) {\n        vector<pair<int, int>> dists;\n        for(int i=0; i<N; ++i) {\n            long long sq = distSq(residents[k].x, residents[k].y, stations[i].x, stations[i].y);\n            int P = get_P(sq);\n            if (P <= MAX_P) {\n                dist_res_stat[k][i] = P;\n                dists.push_back({P, i});\n            } else {\n                dist_res_stat[k][i] = MAX_P + 1; // Mark invalid\n            }\n        }\n        sort(dists.begin(), dists.end());\n        for(auto& p : dists) nearby_stations[k].push_back(p.second);\n    }\n\n    State cur;\n    cur.assignment.resize(K);\n    cur.station_radii.resize(N);\n    cur.active_counts.assign(N, 0);\n    cur.power_cost = 0;\n\n    // Initial state: nearest valid station\n    for(int k=0; k<K; ++k) {\n        int u = nearby_stations[k][0]; \n        cur.assignment[k] = u;\n        cur.station_radii[u].insert(dist_res_stat[k][u]);\n        cur.active_counts[u]++;\n    }\n\n    for(int i=0; i<N; ++i) {\n        if(!cur.station_radii[i].empty()) {\n            long long r = *cur.station_radii[i].rbegin();\n            cur.power_cost += r * r;\n        }\n    }\n    cur.recalc_network_cost();\n    \n    State best = cur;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double start_temp = 500000.0;\n    double end_temp = 100.0;\n\n    long long iter = 0;\n    while(true) {\n        iter++;\n        if((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if(elapsed > time_limit) break;\n        }\n        double progress = chrono::duration_cast<chrono::duration<double>>(chrono::steady_clock::now() - start_time).count() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n\n        // Move Selection\n        int move_type = (rng() % 100 < 96) ? 0 : 1;\n\n        if (move_type == 0) { // === SHIFT RESIDENT ===\n            int k = rng() % K;\n            int u = cur.assignment[k]; \n            \n            // Select new station from filtered list\n            int idx = 0;\n            int list_sz = nearby_stations[k].size();\n            if (rng() % 2 == 0) idx = rng() % min(list_sz, 5); \n            else idx = rng() % min(list_sz, 20);\n            \n            int v = nearby_stations[k][idx];\n            if (u == v) continue;\n            \n            int r_k_v = dist_res_stat[k][v];\n            // Constraint check (though redundant if filtering is correct, strictly safe)\n            if (r_k_v > MAX_P) continue; \n\n            long long old_Pu_sq = 0, new_Pu_sq = 0;\n            if(!cur.station_radii[u].empty()) old_Pu_sq = (long long)(*cur.station_radii[u].rbegin()) * (*cur.station_radii[u].rbegin());\n            \n            int r_k_u = dist_res_stat[k][u];\n            bool u_becomes_empty = (cur.active_counts[u] == 1);\n            \n            if (!u_becomes_empty) {\n                int max_u = *cur.station_radii[u].rbegin();\n                if (r_k_u == max_u && cur.station_radii[u].count(max_u) == 1) {\n                    if (cur.station_radii[u].size() > 1) {\n                         auto it_last = prev(cur.station_radii[u].end());\n                         new_Pu_sq = (long long)(*prev(it_last)) * (*prev(it_last));\n                    }\n                } else {\n                    new_Pu_sq = old_Pu_sq;\n                }\n            }\n\n            long long old_Pv_sq = 0, new_Pv_sq = 0;\n            if(!cur.station_radii[v].empty()) old_Pv_sq = (long long)(*cur.station_radii[v].rbegin()) * (*cur.station_radii[v].rbegin());\n            \n            bool v_becomes_active = (cur.active_counts[v] == 0);\n            if (!v_becomes_active) {\n                int max_v = *cur.station_radii[v].rbegin();\n                new_Pv_sq = (long long)max(max_v, r_k_v) * max(max_v, r_k_v);\n            } else {\n                new_Pv_sq = (long long)r_k_v * r_k_v;\n            }\n\n            long long power_delta = (new_Pu_sq - old_Pu_sq) + (new_Pv_sq - old_Pv_sq);\n            long long network_delta = 0;\n            \n            bool terminals_changed = (u_becomes_empty || v_becomes_active);\n            \n            if (terminals_changed) {\n                vector<int> next_terminals = cur.terminals;\n                if (u_becomes_empty) {\n                    for(auto it = next_terminals.begin(); it != next_terminals.end(); ++it) {\n                        if (*it == u) { next_terminals.erase(it); break; }\n                    }\n                }\n                if (v_becomes_active && v != 0) { \n                    next_terminals.push_back(v);\n                }\n                network_delta = calc_mst_cost(next_terminals) - cur.network_cost;\n            }\n\n            long long total_delta = power_delta + network_delta;\n\n            if (total_delta <= 0 || generate_canonical<double, 10>(rng) < exp(-total_delta / temp)) {\n                cur.assignment[k] = v;\n                \n                auto it = cur.station_radii[u].find(r_k_u);\n                cur.station_radii[u].erase(it);\n                cur.active_counts[u]--;\n                \n                cur.station_radii[v].insert(r_k_v);\n                cur.active_counts[v]++;\n                \n                cur.power_cost += power_delta;\n                cur.network_cost += network_delta;\n                cur.total_cost += total_delta;\n                \n                if(terminals_changed) cur.update_terminals();\n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n\n        } else { // === CLEAR STATION ===\n            if (cur.terminals.size() <= 1) continue;\n            \n            int idx = rng() % (cur.terminals.size());\n            int u = cur.terminals[idx];\n            if (u == 0) {\n                if (cur.terminals.size() > 1) {\n                    idx = (idx + 1) % cur.terminals.size();\n                    u = cur.terminals[idx];\n                }\n                if (u == 0) continue;\n            }\n\n            vector<int> residents_in_u;\n            for(int k=0; k<K; ++k) if(cur.assignment[k] == u) residents_in_u.push_back(k);\n            if (residents_in_u.empty()) continue; \n\n            long long current_Pu_sq = 0;\n            if(!cur.station_radii[u].empty()) current_Pu_sq = (long long)(*cur.station_radii[u].rbegin()) * (*cur.station_radii[u].rbegin());\n            \n            long long power_delta = -current_Pu_sq;\n            \n            vector<int> targets = cur.terminals;\n            for(auto it = targets.begin(); it != targets.end(); ++it) {\n                if(*it == u) { targets.erase(it); break; }\n            }\n            \n            struct MoveReq { int k; int v; int r; };\n            vector<MoveReq> moves;\n            bool possible = true;\n\n            for (int k : residents_in_u) {\n                int best_v = -1;\n                int min_r = MAX_P + 1;\n                \n                for (int v : targets) {\n                    int r = dist_res_stat[k][v];\n                    if (r > MAX_P) continue; // Check Constraint\n                    if (r < min_r) {\n                        min_r = r;\n                        best_v = v;\n                    }\n                }\n                if (best_v == -1) { possible=false; break; } \n                moves.push_back({k, best_v, min_r});\n            }\n            \n            if (!possible) continue;\n\n            map<int, int> new_max_r;\n            long long added_power_cost = 0;\n            for (const auto& mv : moves) {\n                int v = mv.v;\n                int r = mv.r;\n                if (new_max_r.find(v) == new_max_r.end()) {\n                    if (cur.station_radii[v].empty()) new_max_r[v] = 0;\n                    else new_max_r[v] = *cur.station_radii[v].rbegin();\n                }\n                new_max_r[v] = max(new_max_r[v], r);\n            }\n            \n            for (auto const& [v, r_new] : new_max_r) {\n                int r_old = 0;\n                if (!cur.station_radii[v].empty()) r_old = *cur.station_radii[v].rbegin();\n                added_power_cost += ((long long)r_new * r_new - (long long)r_old * r_old);\n            }\n            \n            power_delta += added_power_cost;\n            long long new_net_cost = calc_mst_cost(targets);\n            long long net_delta = new_net_cost - cur.network_cost;\n            long long total_delta = power_delta + net_delta;\n            \n            if (total_delta <= 0 || generate_canonical<double, 10>(rng) < exp(-total_delta / temp)) {\n                cur.station_radii[u].clear();\n                cur.active_counts[u] = 0;\n                \n                for (const auto& mv : moves) {\n                    int k = mv.k;\n                    int v = mv.v;\n                    cur.assignment[k] = v;\n                    cur.station_radii[v].insert(mv.r);\n                    cur.active_counts[v]++;\n                }\n                \n                cur.power_cost += power_delta;\n                cur.network_cost = new_net_cost;\n                cur.total_cost += total_delta;\n                cur.update_terminals();\n                \n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n        }\n    }\n    \n    // Final Output Generation\n    vector<int> terminals;\n    terminals.push_back(0);\n    vector<int> P_out(N, 0);\n    for(int i=0; i<N; ++i) {\n        if(best.active_counts[i] > 0) {\n             if (i != 0) terminals.push_back(i);\n             P_out[i] = *best.station_radii[i].rbegin();\n        }\n    }\n    \n    // Reconstruct tree\n    vector<int> tree_edges_idx = get_steiner_edges(terminals);\n    vector<vector<pair<int,int>>> adj(N);\n    vector<int> degree(N, 0);\n    vector<bool> edge_active(M, false);\n    \n    for(int idx : tree_edges_idx) {\n        edge_active[idx] = true;\n        adj[edges[idx].u].push_back({edges[idx].v, idx});\n        adj[edges[idx].v].push_back({edges[idx].u, idx});\n        degree[edges[idx].u]++;\n        degree[edges[idx].v]++;\n    }\n    \n    // Prune leaves\n    vector<bool> is_terminal(N, false);\n    for(int t : terminals) is_terminal[t] = true;\n    \n    queue<int> q;\n    for(int i=0; i<N; ++i) {\n        if(degree[i] == 1 && !is_terminal[i]) q.push(i);\n    }\n    \n    while(!q.empty()) {\n        int u = q.front(); q.pop();\n        for(auto& p : adj[u]) {\n            int v = p.first;\n            int id = p.second;\n            if(edge_active[id]) {\n                edge_active[id] = false;\n                degree[u]--;\n                degree[v]--;\n                if(degree[v] == 1 && !is_terminal[v]) q.push(v);\n            }\n        }\n    }\n    \n    for(int i=0; i<N; ++i) cout << P_out[i] << (i == N-1 ? \"\" : \" \");\n    cout << \"\\n\";\n    for(int i=0; i<M; ++i) cout << (edge_active[i] ? 1 : 0) << (i == M-1 ? \"\" : \" \");\n    cout << \"\\n\";\n\n    return 0;\n}","ahc021":"/* \n   Solution for AtCoder Heuristic Problem\n   Approach: Greedy Heap-Adjustment with Parametrized Heuristics and Random Search\n*/\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 30;\nconst int MAX_OPS = 10000;\n\n// Structures\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nstruct Weights {\n    double w_val_p; // Parent Value\n    double w_val_c; // Child Value\n    double w_row;   // Row index\n    double w_diff;  // Difference (Parent - Child)\n    double w_rand;  // Random Noise\n};\n\n// Global helpers\nmt19937 rng(12345);\nvector<pair<int,int>> violations;\nvector<vector<bool>> in_violation;\n\n// Check violation condition\ninline bool is_violation(const vector<vector<int>>& b, int x, int y) {\n    if (x >= N - 1) return false;\n    // A node is a violation if it is larger than ANY of its children\n    return (b[x][y] > b[x+1][y] || b[x][y] > b[x+1][y+1]);\n}\n\n// Main Solver\nvector<Move> solve(const vector<vector<int>>& initial_board, const Weights& w, size_t limit_k) {\n    // Local copy of board\n    vector<vector<int>> b = initial_board;\n    \n    vector<Move> ops;\n    ops.reserve(limit_k + 100);\n\n    // Reset violation tracking\n    violations.clear();\n    violations.reserve(500);\n    // Reset in_violation grid\n    for(int i=0; i<N; ++i) {\n        fill(in_violation[i].begin(), in_violation[i].end(), false);\n    }\n\n    // Helper to add violation\n    auto add = [&](int x, int y) {\n        if (x < 0 || x >= N - 1 || y < 0 || y > x) return;\n        if (!in_violation[x][y] && is_violation(b, x, y)) {\n            in_violation[x][y] = true;\n            violations.push_back({x, y});\n        }\n    };\n\n    // Helper to remove violation at index\n    auto remove_at = [&](int idx) {\n        pair<int,int> p = violations[idx];\n        in_violation[p.first][p.second] = false;\n        violations[idx] = violations.back();\n        violations.pop_back();\n        return p;\n    };\n\n    // Initial Scan\n    for(int x = 0; x < N - 1; ++x) {\n        for(int y = 0; y <= x; ++y) {\n            add(x, y);\n        }\n    }\n\n    while (!violations.empty()) {\n        // Pruning: if we reached the limit, this path is not better than best found so far\n        if (ops.size() >= limit_k) {\n            return ops; // Return current to indicate failure/no-improvement\n        }\n\n        int best_idx = 0;\n        double best_score = -1e18;\n\n        // We scan all violations to find the best one according to weights\n        int sz = violations.size();\n        for (int i = 0; i < sz; ++i) {\n            int x = violations[i].first;\n            int y = violations[i].second;\n            \n            int p_val = b[x][y];\n            int l = b[x+1][y];\n            int r = b[x+1][y+1];\n            int c_val = (l < r) ? l : r; // Min child\n\n            double score = 0;\n            if (w.w_val_p != 0) score += w.w_val_p * p_val;\n            if (w.w_val_c != 0) score += w.w_val_c * c_val;\n            if (w.w_row != 0)   score += w.w_row * x;\n            if (w.w_diff != 0)  score += w.w_diff * (p_val - c_val);\n            \n            // Random tie-breaking / noise\n            if (w.w_rand != 0) {\n                // Fast noise\n                score += w.w_rand * (rng() % 1024 / 1024.0);\n            }\n\n            if (score > best_score) {\n                best_score = score;\n                best_idx = i;\n            }\n        }\n\n        // Retrieve and remove best\n        pair<int,int> u = remove_at(best_idx);\n        int x = u.first;\n        int y = u.second;\n\n        // Double check violation (neighbors might have changed)\n        if (!is_violation(b, x, y)) continue;\n\n        // Perform Swap\n        int l = b[x+1][y];\n        int r = b[x+1][y+1];\n        int swap_x = x + 1;\n        int swap_y = (l < r) ? y : y + 1;\n\n        swap(b[x][y], b[swap_x][swap_y]);\n        ops.push_back({x, y, swap_x, swap_y});\n\n        // Update violations in affected area\n        // 1. The original position (now holds smaller value)\n        add(x, y);\n        // 2. Parents of original position\n        if (x > 0) {\n            if (y < x) add(x-1, y);   // Top-Right Parent\n            if (y > 0) add(x-1, y-1); // Top-Left Parent\n        }\n        // 3. The new position (now holds larger value)\n        add(swap_x, swap_y);\n        // 4. The other parent of the new position\n        if (swap_y == y) {\n            // Swapped with Left Child -> Other parent is (x, y-1)\n            if (y > 0) add(x, y-1);\n        } else {\n            // Swapped with Right Child -> Other parent is (x, y+1)\n            add(x, y+1);\n        }\n    }\n\n    return ops;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Init globals\n    in_violation.resize(N);\n    for(int i=0; i<N; ++i) in_violation[i].resize(N, false);\n\n    // Input\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    vector<Move> best_ops;\n    size_t min_k = MAX_OPS + 1;\n\n    auto update = [&](const vector<Move>& ops) {\n        // Only accept if strictly better and within limits\n        // Note: If ops.size() == limit_k, it means we didn't improve or hit pruning.\n        if (!ops.empty() && ops.size() < min_k) {\n            min_k = ops.size();\n            best_ops = ops;\n        }\n    };\n\n    // 1. Deterministic Heuristics\n    // Max Parent Value: Prioritize moving large values down\n    update(solve(a, {1.0, 0, 0, 0, 0}, min_k));\n    // Max Diff: Prioritize swaps that give max local gain\n    update(solve(a, {0, 0, 0, 1.0, 0}, min_k));\n    // Bottom-Up (Max Row): Prioritize fixing deep violations\n    update(solve(a, {0, 0, 1.0, 0, 0}, min_k));\n    // Top-Down (Min Row): Prioritize fixing shallow violations\n    update(solve(a, {0, 0, -1.0, 0, 0}, min_k));\n    // Min Child: Prioritize moving small values up (bubble up)\n    update(solve(a, {0, -1.0, 0, 0, 0}, min_k));\n\n    // 2. Randomized Parametrized Search\n    uniform_real_distribution<double> dist_w(-1.0, 1.0);\n    \n    int iterations = 0;\n    while (true) {\n        iterations++;\n        // Check time every 32 iterations\n        if ((iterations & 31) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            if (chrono::duration<double>(now - start_time).count() > 1.90) break;\n        }\n\n        Weights w;\n        w.w_val_p = dist_w(rng);\n        w.w_val_c = dist_w(rng);\n        w.w_row   = dist_w(rng) * 10.0; // Increase weight of Row to match Value magnitude\n        w.w_diff  = dist_w(rng);\n        w.w_rand  = dist_w(rng) * 200.0; // Significant noise to explore\n        \n        update(solve(a, w, min_k));\n    }\n\n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.x1 << \" \" << op.y1 << \" \" << op.x2 << \" \" << op.y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <bitset>\n#include <map>\n#include <unordered_map>\n\nusing namespace std;\n\n// Configuration\nconst int D = 9;\nconst int TOTAL_CELLS = D * D;\n\n// Heuristic Weights\nconst double W_DIST = 20.0;\nconst double W_FREE = 3.0;  // Increased to prioritize future flexibility\nconst double W_LEAF = 4.0;  // Slightly reduced\n\nint N;\nint grid_fixed[D][D]; // 0: empty, 1: obstacle\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\n// Global buffers to minimize allocation overhead\nint dist_map[D][D];\nint visited_token[D][D];\nint bfs_token = 0;\nPoint q_buff[TOTAL_CELLS];\n\nint dr[] = {0, 0, 1, -1};\nint dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// BFS: Counts reachable empty cells (excluding entrance).\n// grid_val: 0=empty, 1=obstacle, 2=container.\nint bfs_dist(const int grid[D][D]) {\n    bfs_token++;\n    int head = 0, tail = 0;\n    \n    q_buff[tail++] = {0, 4};\n    visited_token[0][4] = bfs_token;\n    dist_map[0][4] = 0;\n    \n    int count = 0;\n    while(head < tail){\n        Point p = q_buff[head++];\n        int d = dist_map[p.r][p.c];\n        \n        for(int i=0; i<4; ++i){\n            int nr = p.r + dr[i];\n            int nc = p.c + dc[i];\n            \n            if(is_valid(nr, nc) && grid[nr][nc] == 0 && visited_token[nr][nc] != bfs_token){\n                visited_token[nr][nc] = bfs_token;\n                dist_map[nr][nc] = d + 1;\n                q_buff[tail++] = {nr, nc};\n                if(nr != 0 || nc != 4) count++;\n            }\n        }\n    }\n    return count;\n}\n\nint grid_current[D][D]; \n\n// Check connectivity: returns true if placing at (r,c) leaves expected_count reachable empty cells\nbool check_connectivity(int r, int c, int expected_count) {\n    grid_current[r][c] = 2; \n    int cnt = bfs_dist(grid_current);\n    grid_current[r][c] = 0; \n    return cnt == expected_count;\n}\n\n// --- Retrieval Phase ---\n\nstruct BeamNode {\n    vector<int> removed_ids; \n    bitset<81> removed_mask; \n    long long inversions;    \n    \n    // We do not use this operator for sorting by cost, but for deduplication logic if needed.\n};\n\nvoid solve_retrieval(int K, const vector<int>& pos_to_id) {\n    vector<int> initial_positions;\n    for(int i=0; i<TOTAL_CELLS; ++i) {\n        if(pos_to_id[i] != -1) initial_positions.push_back(i);\n    }\n    \n    vector<BeamNode> beam;\n    beam.reserve(600);\n    beam.push_back({{}, 0, 0});\n    \n    int BEAM_WIDTH = 600; \n    \n    for(int step = 0; step < K; ++step) {\n        vector<BeamNode> next_candidates;\n        next_candidates.reserve(beam.size() * 5); \n        \n        for(const auto& node : beam) {\n            // Find reachable containers\n            bfs_token++;\n            int head = 0, tail = 0;\n            q_buff[tail++] = {0, 4};\n            visited_token[0][4] = bfs_token;\n            \n            vector<int> reachable_ids;\n            \n            while(head < tail) {\n                Point p = q_buff[head++];\n                \n                for(int i=0; i<4; ++i){\n                    int nr = p.r + dr[i];\n                    int nc = p.c + dc[i];\n                    if(!is_valid(nr, nc)) continue;\n                    if(grid_fixed[nr][nc] == 1) continue; \n                    if(visited_token[nr][nc] == bfs_token) continue;\n                    \n                    int idx = nr * D + nc;\n                    int id = pos_to_id[idx];\n                    bool is_removed = (id != -1 && node.removed_mask[idx]);\n                    bool has_container = (id != -1 && !is_removed);\n                    \n                    visited_token[nr][nc] = bfs_token;\n                    \n                    if(has_container) {\n                        reachable_ids.push_back(id);\n                    } else {\n                        q_buff[tail++] = {nr, nc};\n                    }\n                }\n            }\n            \n            // Pre-calc remaining for cost calculation\n            vector<int> remaining;\n            remaining.reserve(K - step);\n            for(int pos : initial_positions) {\n                if(!node.removed_mask[pos]) {\n                    remaining.push_back(pos_to_id[pos]);\n                }\n            }\n            \n            for(int cand_id : reachable_ids) {\n                int cost_inc = 0;\n                // Count how many remaining IDs are smaller than candidate\n                for(int rem : remaining) {\n                    if(rem != cand_id && rem < cand_id) {\n                        cost_inc++;\n                    }\n                }\n                \n                BeamNode next_node = node;\n                next_node.inversions += cost_inc;\n                next_node.removed_ids.push_back(cand_id);\n                \n                int pos = -1;\n                for(int p : initial_positions) {\n                    if(pos_to_id[p] == cand_id) { pos = p; break; }\n                }\n                next_node.removed_mask[pos] = 1;\n                \n                next_candidates.push_back(next_node);\n            }\n        }\n        \n        if(next_candidates.empty()) break;\n        \n        // Deduplication: Sort by Mask then Inversions\n        sort(next_candidates.begin(), next_candidates.end(), \n             [](const BeamNode& a, const BeamNode& b) {\n                 for(int i=0; i<81; ++i) {\n                     bool bitA = a.removed_mask[i];\n                     bool bitB = b.removed_mask[i];\n                     if(bitA != bitB) return int(bitA) < int(bitB);\n                 }\n                 return a.inversions < b.inversions;\n             });\n        \n        vector<BeamNode> unique_next;\n        unique_next.reserve(BEAM_WIDTH);\n        \n        if(!next_candidates.empty()) {\n            unique_next.push_back(next_candidates[0]);\n            for(size_t i=1; i<next_candidates.size(); ++i) {\n                bool same_mask = (next_candidates[i].removed_mask == unique_next.back().removed_mask);\n                if(same_mask) {\n                    // Skip duplicates (since we sorted by inversions, the first one is best)\n                    continue;\n                } else {\n                    unique_next.push_back(next_candidates[i]);\n                }\n            }\n        }\n        \n        // Selection: Keep top K by inversions\n        if(unique_next.size() > BEAM_WIDTH) {\n             nth_element(unique_next.begin(), unique_next.begin() + BEAM_WIDTH, unique_next.end(), \n                [](const BeamNode& a, const BeamNode& b){\n                    return a.inversions < b.inversions;\n                });\n            unique_next.resize(BEAM_WIDTH);\n        }\n        beam = unique_next;\n    }\n    \n    const auto& best = *min_element(beam.begin(), beam.end(), [](const BeamNode& a, const BeamNode& b){\n        return a.inversions < b.inversions;\n    });\n    \n    vector<Point> id_to_p(K);\n    for(int r=0; r<D; ++r){\n        for(int c=0; c<D; ++c){\n            int id = pos_to_id[r*D + c];\n            if(id != -1) id_to_p[id] = {r, c};\n        }\n    }\n    \n    for(int id : best.removed_ids) {\n        cout << id_to_p[id].r << \" \" << id_to_p[id].c << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int d_in;\n    if (!(cin >> d_in)) return 0;\n    cin >> N;\n    \n    for(int r=0; r<D; ++r) for(int c=0; c<D; ++c) {\n        grid_fixed[r][c] = 0;\n        grid_current[r][c] = 0;\n    }\n    \n    for(int i=0; i<N; ++i){\n        int r, c;\n        cin >> r >> c;\n        grid_fixed[r][c] = 1;\n        grid_current[r][c] = 1;\n    }\n    \n    for(int r=0; r<D; ++r) for(int c=0; c<D; ++c) visited_token[r][c] = 0;\n    \n    int K = D*D - 1 - N;\n    vector<bool> id_seen(D*D, false);\n    vector<int> pos_to_id(TOTAL_CELLS, -1);\n    \n    // Working vectors\n    vector<Point> reachable_cells; \n    reachable_cells.reserve(TOTAL_CELLS);\n    vector<int> all_dists;\n    all_dists.reserve(TOTAL_CELLS);\n    vector<Point> candidates;\n    candidates.reserve(TOTAL_CELLS);\n    vector<Point> next_cells;\n    next_cells.reserve(TOTAL_CELLS);\n    \n    int saved_dists[D][D];\n\n    for(int step=0; step<K; ++step){\n        int t;\n        cin >> t;\n        \n        // Calculate Rank Percentile\n        int rem_count = 0;\n        int rank_t = 0;\n        for(int i=0; i<K; ++i){\n            if(!id_seen[i] || i == t) {\n                rem_count++;\n                if(i < t) rank_t++;\n            }\n        }\n        id_seen[t] = true;\n        double P = (rem_count > 1) ? (double)rank_t / (rem_count - 1) : 0.5;\n        \n        // Current Reachability\n        int reachable_current = bfs_dist(grid_current);\n        \n        // Collect Reachable Cells & Dists safely\n        reachable_cells.clear();\n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_current[r][c] == 0 && (r!=0 || c!=4)){\n                    if(visited_token[r][c] == bfs_token) { \n                        reachable_cells.push_back({r, c});\n                        saved_dists[r][c] = dist_map[r][c];\n                    }\n                }\n            }\n        }\n        \n        // Determine Target Distance\n        all_dists.clear();\n        for(auto p : reachable_cells) all_dists.push_back(saved_dists[p.r][p.c]);\n        sort(all_dists.begin(), all_dists.end());\n        \n        double target_dist = 0;\n        if(!all_dists.empty()){\n            int idx = (int)round(P * (all_dists.size() - 1));\n            target_dist = all_dists[idx];\n        }\n        \n        // Filter Candidates (must not break connectivity)\n        candidates.clear();\n        for(auto p : reachable_cells) {\n            if(check_connectivity(p.r, p.c, reachable_current - 1)) {\n                candidates.push_back(p);\n            }\n        }\n        \n        // Heuristic Scoring\n        double best_score = -1e18;\n        Point best_p = candidates[0];\n        \n        for(auto p : candidates){\n            double dist = saved_dists[p.r][p.c];\n            double match_err = (dist - target_dist) * (dist - target_dist);\n            \n            // Lookahead: Calculate Future Freedom (c_prime)\n            grid_current[p.r][p.c] = 2;\n            int next_reachable = bfs_dist(grid_current); // Uses globals\n            \n            next_cells.clear();\n            for(int r=0; r<D; ++r){\n                for(int c=0; c<D; ++c){\n                    if(grid_current[r][c] == 0 && (r!=0 || c!=4) && visited_token[r][c] == bfs_token) {\n                        next_cells.push_back({r, c});\n                    }\n                }\n            }\n            \n            int c_prime = 0;\n            for(auto np : next_cells) {\n                // Check if placing at np in the next step is valid\n                if(check_connectivity(np.r, np.c, next_reachable - 1)) {\n                    c_prime++;\n                }\n            }\n            \n            grid_current[p.r][p.c] = 0; // Restore\n            \n            // Prefer dead-ends / leaves\n            int empty_neighbors = 0;\n            for(int k=0; k<4; ++k){\n                int nr = p.r + dr[k];\n                int nc = p.c + dc[k];\n                if(is_valid(nr, nc) && grid_current[nr][nc] == 0 && (nr!=0 || nc!=4)) {\n                    empty_neighbors++;\n                }\n            }\n            \n            // Weighted Score\n            double score = -W_DIST * match_err + W_FREE * c_prime - W_LEAF * empty_neighbors;\n            \n            if(score > best_score){\n                best_score = score;\n                best_p = p;\n            }\n        }\n        \n        cout << best_p.r << \" \" << best_p.c << endl;\n        grid_current[best_p.r][best_p.c] = 2;\n        pos_to_id[best_p.r * D + best_p.c] = t;\n    }\n    \n    solve_retrieval(K, pos_to_id);\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n#include <map>\n\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\nconst int TIME_LIMIT_MS = 1950;\n\nint grid[N][N];\nint best_grid[N][N];\nint current_score = 0;\nint best_score = 0;\n\n// Adjacency\n// adj_count[u][v] stores the number of boundary segments between color u and v.\nint adj_count[M + 1][M + 1];\nbool is_required[M + 1][M + 1];\n\n// BFS State\nint visited[N][N];\nint visited_token = 0;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Fast Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n} rng;\n\n// Global Connectivity Check (BFS)\n// Returns true if removing (rem_r, rem_c) of 'color' leaves the 'color' component connected.\nbool check_global_connectivity(int rem_r, int rem_c, int color) {\n    visited_token++;\n    int neighbors_r[4], neighbors_c[4];\n    int k = 0;\n    bool touches_boundary = false;\n\n    for (int i = 0; i < 4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) {\n                neighbors_r[k] = nr;\n                neighbors_c[k] = nc;\n                k++;\n            }\n        } else if (color == 0) {\n            touches_boundary = true;\n        }\n    }\n    \n    if (k == 0) return true; \n\n    // If color != 0, all neighbors must be in one component.\n    // If color == 0, all neighbors must be able to reach the boundary (or be connected to it via outside).\n    \n    if (color != 0) {\n        int q_r[N * N], q_c[N * N];\n        int head = 0, tail = 0;\n        \n        q_r[tail] = neighbors_r[0];\n        q_c[tail] = neighbors_c[0];\n        tail++;\n        visited[neighbors_r[0]][neighbors_c[0]] = visited_token;\n        \n        int found_neighbors = 1;\n\n        while(head < tail) {\n            int r = q_r[head++];\n            int c = q_c[head-1]; // Bug fix: was referencing head\n            \n            for(int i=0; i<4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                \n                if (!is_valid(nr, nc)) continue;\n                if (nr == rem_r && nc == rem_c) continue;\n                \n                if (grid[nr][nc] == color && visited[nr][nc] != visited_token) {\n                    visited[nr][nc] = visited_token;\n                    q_r[tail] = nr;\n                    q_c[tail] = nc;\n                    tail++;\n                    \n                    // Check if we found a neighbor\n                    // Optimization: Manhattan dist to rem_r, rem_c is 1\n                    if (abs(nr - rem_r) + abs(nc - rem_c) == 1) {\n                        found_neighbors++;\n                    }\n                }\n            }\n        }\n        return found_neighbors == k;\n    } else {\n        // For color 0, check if each neighbor component touches boundary\n        // We use visited array to track processed neighbors\n        for(int j=0; j<k; ++j) {\n            if (visited[neighbors_r[j]][neighbors_c[j]] == visited_token) continue;\n            \n            // Start BFS for this component\n            int q_r[N * N], q_c[N * N];\n            int head = 0, tail = 0;\n            q_r[tail] = neighbors_r[j];\n            q_c[tail] = neighbors_c[j];\n            tail++;\n            visited[neighbors_r[j]][neighbors_c[j]] = visited_token;\n            \n            bool reached_boundary = false;\n            if (neighbors_r[j] == 0 || neighbors_r[j] == N-1 || neighbors_c[j] == 0 || neighbors_c[j] == N-1)\n                reached_boundary = true;\n                \n            while(head < tail) {\n                int r = q_r[head++];\n                int c = q_c[head-1];\n                \n                for(int i=0; i<4; ++i) {\n                    int nr = r + dr[i];\n                    int nc = c + dc[i];\n                    \n                    if (!is_valid(nr, nc)) {\n                        reached_boundary = true;\n                        continue;\n                    }\n                    if (nr == rem_r && nc == rem_c) continue;\n                    \n                    if (grid[nr][nc] == 0 && visited[nr][nc] != visited_token) {\n                        visited[nr][nc] = visited_token;\n                        q_r[tail] = nr;\n                        q_c[tail] = nc;\n                        tail++;\n                        if (!reached_boundary) {\n                            if (nr == 0 || nr == N-1 || nc == 0 || nc == N-1) reached_boundary = true;\n                        }\n                    }\n                }\n            }\n            \n            if (!reached_boundary && !touches_boundary) return false;\n        }\n        return true;\n    }\n}\n\n// Local Connectivity Check (3x3 window)\n// Returns true if neighbors are connected within the 3x3 area excluding center\nbool check_local(int r, int c, int color) {\n    int n_idx[4], k = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) n_idx[k++] = i;\n        } else if (color == 0) {\n            n_idx[k++] = i;\n        }\n    }\n    if (k <= 1) return true;\n    \n    // Union-Find\n    int parent[4];\n    for(int i=0; i<k; ++i) parent[i] = i;\n    auto find = [&](int i) { while(i != parent[i]) i = parent[i]; return i; };\n    \n    int dir_map[4]; \n    // -1 init\n    dir_map[0]=dir_map[1]=dir_map[2]=dir_map[3]=-1;\n    for(int i=0; i<k; ++i) dir_map[n_idx[i]] = i;\n    \n    // Diagonals check\n    int pairs[4][2] = {{0,2}, {0,3}, {1,2}, {1,3}}; // (Up,Left), (Up,Right), (Down,Left), (Down,Right)\n    int d_off[4][2] = {{-1,-1}, {-1,1}, {1,-1}, {1,1}};\n    \n    for(int i=0; i<4; ++i) {\n        int idx1 = dir_map[pairs[i][0]];\n        int idx2 = dir_map[pairs[i][1]];\n        if(idx1 != -1 && idx2 != -1) {\n            int nr = r + d_off[i][0];\n            int nc = c + d_off[i][1];\n            bool conn = false;\n            if(is_valid(nr, nc)) {\n                if(grid[nr][nc] == color) conn = true;\n            } else if(color == 0) conn = true;\n            \n            if(conn) {\n                int r1 = find(idx1), r2 = find(idx2);\n                if(r1 != r2) parent[r1] = r2;\n            }\n        }\n    }\n    int root = find(0);\n    for(int i=1; i<k; ++i) if(find(i) != root) return false;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int n_in, m_in;\n    if (!(cin >> n_in >> m_in)) return 0;\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> grid[i][j];\n            best_grid[i][j] = grid[i][j];\n            // Initial grid has no 0s inside as per constraints, so score 0\n        }\n    }\n    // Calculate initial adjacencies\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = grid[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int nr = i + dr[k];\n                int nc = j + dc[k];\n                int v = 0; \n                if (is_valid(nr, nc)) v = grid[nr][nc];\n                \n                if (u != v) {\n                    adj_count[u][v]++; // Increments for both u->v and v->u during full scan\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i <= M; ++i) {\n        for (int j = 0; j <= M; ++j) {\n            if (adj_count[i][j] > 0) is_required[i][j] = true;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    double start_temp = 2.5;\n    double end_temp = 0.1;\n\n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0xFFF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        int r = rng.next_int(N);\n        int c = rng.next_int(N);\n        int current_color = grid[r][c];\n        \n        // Pick a target color from neighbors (eroding or shifting)\n        int k = rng.next_int(4);\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n        int target_color = 0;\n        if (is_valid(nr, nc)) target_color = grid[nr][nc];\n        \n        if (current_color == target_color) continue;\n\n        int score_diff = 0;\n        if (current_color == 0) score_diff--;\n        if (target_color == 0) score_diff++;\n\n        // SA Logic\n        if (score_diff < 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            double temp = start_temp + (end_temp - start_temp) * (elapsed / TIME_LIMIT_MS);\n            if (rng.next_double() > exp(score_diff / temp)) continue;\n        }\n\n        // 1. Adjacency Constraints\n        // Calculate aggregate changes to adjacency counts\n        map<pair<int,int>, int> changes; \n        \n        for(int i=0; i<4; ++i) {\n            int nnr = r + dr[i];\n            int nnc = c + dc[i];\n            int n_col = 0;\n            if (is_valid(nnr, nnc)) n_col = grid[nnr][nnc];\n            \n            // Removing current_color\n            if (n_col != current_color) {\n                int u = current_color, v = n_col;\n                if (u > v) swap(u, v);\n                changes[{u, v}]--;\n            }\n            // Adding target_color\n            if (n_col != target_color) {\n                int u = target_color, v = n_col;\n                if (u > v) swap(u, v);\n                changes[{u, v}]++;\n            }\n        }\n        \n        bool adj_ok = true;\n        for (auto const& [key, val] : changes) {\n            if (val == 0) continue;\n            int u = key.first;\n            int v = key.second;\n            int new_count = adj_count[u][v] + val;\n            \n            if (is_required[u][v]) {\n                // Must maintain at least one edge\n                if (new_count <= 0) { adj_ok = false; break; }\n            } else {\n                // Must not create new edge\n                if (new_count > 0) { adj_ok = false; break; }\n            }\n        }\n        if (!adj_ok) continue;\n\n        // 2. Connectivity of Old Color\n        if (!check_local(r, c, current_color)) {\n            if (!check_global_connectivity(r, c, current_color)) continue;\n        }\n        \n        // 3. Connectivity of New Color\n        // Safe by construction (extending from neighbor), unless specific split cases for color 0.\n        // But adding a 0 adjacent to existing 0 is always safe for 0's connectivity.\n        // Adding non-0 adjacent to existing non-0 is safe.\n        \n        // Apply Move\n        for (auto const& [key, val] : changes) {\n            int u = key.first;\n            int v = key.second;\n            adj_count[u][v] += val;\n            adj_count[v][u] += val;\n        }\n        \n        grid[r][c] = target_color;\n        current_score += score_diff;\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) copy(begin(grid[i]), end(grid[i]), begin(best_grid[i]));\n        }\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    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\nvector<vector<int>> memo; // Memoization for item comparisons\n\n// Perform a query: Output L size, R size, then elements of L and R\nvoid ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    query_count++;\n}\n\n// Read the judge's response\nint get_response() {\n    string res;\n    cin >> res;\n    if (res == \"<\") return 1;\n    if (res == \">\") return -1;\n    if (res == \"=\") return 2;\n    return 0; \n}\n\n// Pad remaining queries with dummy operations to meet the exact Q requirement\nvoid pad_queries() {\n    while (query_count < Q) {\n        // Compare item 0 and item 1. They are always valid indices (N >= 30).\n        // This consumes a query without changing state.\n        ask({0}, {1});\n        get_response(); \n    }\n}\n\n// Compare items a and b using the balance scale.\n// Returns 1 if a < b, -1 if a > b, 0 if a == b.\n// Uses memoization to avoid redundant queries.\nint compare_items(int a, int b) {\n    if (a == b) return 0;\n    if (memo[a][b] != 0) return (memo[a][b] == 2 ? 0 : memo[a][b]);\n\n    ask({a}, {b});\n    int res = get_response();\n    \n    if (res == 1) {\n        memo[a][b] = 1;\n        memo[b][a] = -1;\n        return 1;\n    } else if (res == -1) {\n        memo[a][b] = -1;\n        memo[b][a] = 1;\n        return -1;\n    } else {\n        memo[a][b] = 2;\n        memo[b][a] = 2;\n        return 0;\n    }\n}\n\n// Compute expected values of order statistics for the Exponential Distribution\nvector<double> compute_expected_weights(int n) {\n    vector<double> w(n);\n    double current = 0;\n    for (int i = 0; i < n; ++i) {\n        current += 1.0 / (n - i);\n        w[i] = current;\n    }\n    return w;\n}\n\n// Isotonic Regression (Pool Adjacent Violators Algorithm)\n// Fits data to be monotonically non-decreasing minimizing MSE.\nvector<double> isotonic_regression(const vector<double>& y) {\n    vector<pair<double, double>> stack; \n    for (double val : y) {\n        double current_val = val;\n        double current_w = 1.0;\n        while (!stack.empty() && stack.back().first >= current_val) {\n            double prev_val = stack.back().first;\n            double prev_w = stack.back().second;\n            stack.pop_back();\n            current_val = (prev_val * prev_w + current_val * current_w) / (prev_w + current_w);\n            current_w += prev_w;\n        }\n        stack.push_back({current_val, current_w});\n    }\n    vector<double> res;\n    for (auto p : stack) {\n        for (int i = 0; i < (int)p.second; ++i) res.push_back(p.first);\n    }\n    return res;\n}\n\nint main() {\n    // IO setup\n    ios_base::sync_with_stdio(false);\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    memo.assign(N, vector<int>(N, 0));\n    srand(123); \n\n    // Determine budget for initial sorting.\n    // We reserve queries for the refinement phase (sorting sets + adjusting).\n    // Sorting D sets takes approx D * log2(D) queries. We want a few rounds.\n    // Maximize sort budget but ensure we can do at least some refinement.\n    int refinement_budget = max(Q / 4, min(Q / 2, D * D * 2));\n    int sort_budget = Q - refinement_budget;\n    if (sort_budget < 0) sort_budget = 0;\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // 1. Sort items (partially if budget is tight)\n    // We use stable_sort. If we hit the query limit, we stop comparing, \n    // effectively leaving the remaining items in their original relative order.\n    try {\n        stable_sort(p.begin(), p.end(), [&](int a, int b) {\n            if (query_count >= sort_budget) return false; \n            int res = compare_items(a, b);\n            return res == 1; // a < b\n        });\n    } catch(...) {}\n\n    // 2. Assign Expected Weights based on rank\n    vector<double> exp_w_sorted = compute_expected_weights(N);\n    vector<double> item_w(N);\n    // The item at p[i] is the i-th smallest found.\n    for (int i = 0; i < N; ++i) {\n        item_w[p[i]] = exp_w_sorted[i];\n    }\n\n    // 3. Greedy Partitioning (Largest Items First)\n    // This heuristic generally works well for minimizing variance.\n    vector<int> p_desc = p;\n    reverse(p_desc.begin(), p_desc.end());\n\n    vector<vector<int>> sets(D);\n    vector<double> set_sums(D, 0.0);\n\n    for (int idx : p_desc) {\n        int best_s = -1;\n        double min_sum = 1e18;\n        for (int s = 0; s < D; ++s) {\n            if (set_sums[s] < min_sum) {\n                min_sum = set_sums[s];\n                best_s = s;\n            }\n        }\n        sets[best_s].push_back(idx);\n        set_sums[best_s] += item_w[idx];\n    }\n\n    // 4. Local Search (In Silico)\n    // Optimize the partition using the estimated weights before spending more queries.\n    int ls_iter = 0;\n    while (ls_iter < 20000) {\n        ls_iter++;\n        int s1 = rand() % D;\n        int s2 = rand() % D;\n        if (s1 == s2) continue;\n        if (sets[s1].empty()) continue;\n\n        int type = (sets[s2].empty() ? 0 : rand() % 2);\n        int idx1 = rand() % sets[s1].size();\n        int u = sets[s1][idx1];\n\n        if (type == 0) { // Move u from s1 to s2\n            double new_s1 = set_sums[s1] - item_w[u];\n            double new_s2 = set_sums[s2] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n            \n            if (new_sq < old_sq) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        } else { // Swap u (from s1) with v (from s2)\n            int idx2 = rand() % sets[s2].size();\n            int v = sets[s2][idx2];\n            \n            double new_s1 = set_sums[s1] - item_w[u] + item_w[v];\n            double new_s2 = set_sums[s2] - item_w[v] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n\n            if (new_sq < old_sq) {\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        }\n    }\n\n    // 5. Refinement Phase with Physical Queries\n    // We sort the sets by weight using the scale, then update our belief (estimates)\n    // using Isotonic Regression, and finally try to balance the extremes.\n    while (true) {\n        // Check if we have enough queries to perform a set sort.\n        int needed = D * log2(D) + 2;\n        if (query_count + needed > Q) break;\n\n        // 5.1 Sort sets physically\n        vector<int> set_indices(D);\n        iota(set_indices.begin(), set_indices.end(), 0);\n        \n        bool possible = true;\n        stable_sort(set_indices.begin(), set_indices.end(), [&](int a, int b){\n            if (query_count >= Q) { possible = false; return false; }\n            ask(sets[a], sets[b]);\n            int res = get_response();\n            return res == 1; // a < b\n        });\n        if (!possible) break;\n\n        // 5.2 Correct estimates\n        // We extract the current estimates in the physical sorted order\n        vector<double> sorted_estimates;\n        for (int idx : set_indices) sorted_estimates.push_back(set_sums[idx]);\n        \n        // Apply PAVA to enforce monotonicity\n        vector<double> pav_res = isotonic_regression(sorted_estimates);\n        \n        // Slightly perturb to enforce strict inequality where PAVA flattens,\n        // to encourage movement.\n        for (int i = 1; i < D; ++i) {\n            if (pav_res[i] <= pav_res[i-1] + 1e-9) {\n                pav_res[i] = pav_res[i-1] + 1e-5;\n            }\n        }\n        // Update set_sums\n        for (int i = 0; i < D; ++i) set_sums[set_indices[i]] = pav_res[i];\n\n        // 5.3 Balance Heaviest and Lightest\n        int light_idx = set_indices[0];\n        int heavy_idx = set_indices.back();\n\n        double diff = set_sums[heavy_idx] - set_sums[light_idx];\n        if (diff < 1e-5) break; // Already balanced within estimate precision\n\n        double target = diff / 2.0; // Amount to transfer from Heavy to Light\n        int best_type = -1;\n        int best_u_idx = -1, best_v_idx = -1;\n        double min_err = 1e18;\n\n        // Try Move\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            int u = sets[heavy_idx][i];\n            double err = abs(item_w[u] - target);\n            if (err < min_err) {\n                min_err = err;\n                best_type = 0;\n                best_u_idx = i;\n            }\n        }\n        // Try Swap\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            for (int j = 0; j < (int)sets[light_idx].size(); ++j) {\n                int u = sets[heavy_idx][i];\n                int v = sets[light_idx][j];\n                double delta = item_w[u] - item_w[v];\n                if (delta <= 0) continue; // Must move mass from heavy to light\n                double err = abs(delta - target);\n                if (err < min_err) {\n                    min_err = err;\n                    best_type = 1;\n                    best_u_idx = i;\n                    best_v_idx = j;\n                }\n            }\n        }\n\n        // Apply best operation\n        if (best_type == 0) {\n            int u = sets[heavy_idx][best_u_idx];\n            sets[heavy_idx].erase(sets[heavy_idx].begin() + best_u_idx);\n            sets[light_idx].push_back(u);\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[light_idx] += item_w[u];\n        } else if (best_type == 1) {\n            int u = sets[heavy_idx][best_u_idx];\n            int v = sets[light_idx][best_v_idx];\n            swap(sets[heavy_idx][best_u_idx], sets[light_idx][best_v_idx]);\n            set_sums[heavy_idx] -= item_w[u] - item_w[v];\n            set_sums[light_idx] += item_w[u] - item_w[v];\n        } else {\n            break; // Cannot find a move/swap that matches target\n        }\n    }\n\n    // Ensure exactly Q queries are performed\n    pad_queries();\n\n    // Output final assignment\n    vector<int> ans(N);\n    for (int i = 0; i < D; ++i) {\n        for (int x : sets[i]) ans[x] = i;\n    }\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"/**\n * Heuristic solution for \"Stack of Boxes\" problem.\n * \n * Strategy:\n * The problem asks us to retrieve boxes 1 to N in order. This implies a strong constraint on\n * the order of access.\n * We adopt a greedy simulation strategy. We iterate through the targets 1 to N.\n * If the current target is buried, we must move the boxes covering it to other stacks.\n * \n * Key decision point: When moving covering boxes, where should we put them?\n * And how many should we move at once?\n * \n * Algorithm Steps:\n * 1. Identify the current target 'v'.\n * 2. If 'v' is not at the top of its stack 'src', we need to clear boxes above it.\n * 3. Identify the longest \"sorted suffix\" at the top of 'src'. \n *    A sorted suffix is a sequence of boxes at the top that are in decreasing order (e.g., 10, 8, 5).\n *    Moving unsorted chunks (e.g., 5, 10) is generally inefficient because it maintains disorder.\n *    By only moving sorted chunks (or parts of them), we naturally decompose unsorted stacks into sorted ones.\n * 4. Evaluate all valid moves:\n *    - A \"move\" is defined by a split point in the sorted suffix (defining a chunk) \n *      and a destination stack.\n *    - We calculate a Cost for each move:\n *      Cost = Energy + Penalties\n * \n * Cost Function Components:\n * - Energy: (Chunk Size + 1). Direct cost minimization.\n * - Bad Link Penalty: Placing a box 'B' on top of 'T' where B > T.\n *   This is bad because 'T' is smaller and will be needed before 'B'. 'B' blocks 'T'.\n *   The penalty is proportional to \"Urgency\": how close 'T' is to the current global target.\n *   If 'T' is needed very soon, the penalty is massive.\n * - Gap Penalty: Placing 'B' on 'T' where B < T (Good link).\n *   We prefer T - B to be small (tight packing) to save \"number space\" for other boxes.\n * - Empty Stack Penalty: Using an empty stack is penalized, especially for small values.\n *   We want to reserve empty stacks for base of new piles or emergency maneuvering.\n * \n * The parameters are tuned to balance immediate energy costs against the future cost of fixing bad states.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Tuned heuristic constants\nconst double WEIGHT_ENERGY = 1.0;\nconst double PENALTY_BAD_LINK_BASE = 100.0;       // Base penalty for inverting order\nconst double PENALTY_BAD_LINK_URGENCY_FACTOR = 2000.0; // High penalty if blocked box is needed soon\nconst double PENALTY_GAP_FACTOR = 0.5;            // Penalty for gaps in sorted stacks\nconst double PENALTY_EMPTY_BASE = 50.0;           // High cost to consume an empty stack\nconst double PENALTY_EMPTY_VAL_FACTOR = 0.2;      // Prefer high values on empty stacks\n\nstruct Move {\n    int v;\n    int i;\n};\n\nint N, M;\nvector<vector<int>> stacks;\nvector<Move> result;\nint op_count = 0;\nconst int MAX_OPS = 5000;\n\n// Find the stack index and position of a box v\npair<int, int> find_box(int v) {\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<(int)stacks[i].size(); ++j) {\n            if(stacks[i][j] == v) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Execute the chosen move\nvoid execute_move(int src, int k, int dst) {\n    // The box at stacks[src][k] is the bottom of the chunk being moved.\n    int v = stacks[src][k];\n    \n    vector<int> chunk;\n    for(int i = k; i < (int)stacks[src].size(); ++i) {\n        chunk.push_back(stacks[src][i]);\n    }\n    \n    stacks[src].resize(k);\n    \n    for(int x : chunk) {\n        stacks[dst].push_back(x);\n    }\n    \n    result.push_back({v, dst + 1});\n    op_count++;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    stacks.resize(M);\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<N/M; ++j) {\n            int val;\n            cin >> val;\n            stacks[i].push_back(val);\n        }\n    }\n\n    // Process boxes 1 to N in order\n    for (int target = 1; target <= N; ++target) {\n        if (op_count >= MAX_OPS) break;\n\n        while (true) {\n            pair<int, int> loc = find_box(target);\n            if (loc.first == -1) break; // Should not happen\n            \n            int src = loc.first;\n            int idx = loc.second;\n            \n            // If target is at the top, we can carry it out (Operation 2)\n            if (idx == (int)stacks[src].size() - 1) {\n                result.push_back({target, 0});\n                stacks[src].pop_back();\n                op_count++;\n                break; \n            }\n            \n            // Target is buried. We need to move boxes above it.\n            // We identify the longest sequence at the top that is already sorted (decreasing upwards).\n            // We only consider moving sub-chunks of this sorted sequence.\n            int top_idx = (int)stacks[src].size() - 1;\n            int start_sorted = top_idx;\n            \n            // Extend sorted range downwards as long as order is valid (bottom > top)\n            while(start_sorted > idx + 1) {\n                if (stacks[src][start_sorted - 1] > stacks[src][start_sorted]) {\n                    start_sorted--;\n                } else {\n                    break;\n                }\n            }\n            \n            double best_cost = 1e18;\n            int best_k = -1;\n            int best_dst = -1;\n            \n            // Evaluate all possible chunks [k...top] from the sorted suffix\n            for (int k = start_sorted; k <= top_idx; ++k) {\n                int chunk_bottom_val = stacks[src][k];\n                int chunk_sz = top_idx - k + 1;\n                double energy = (double)(chunk_sz + 1);\n                \n                // Try all possible destination stacks\n                for (int dst = 0; dst < M; ++dst) {\n                    if (dst == src) continue;\n                    \n                    double cost = energy * WEIGHT_ENERGY;\n                    bool dst_empty = stacks[dst].empty();\n                    int dst_top_val = dst_empty ? -1 : stacks[dst].back();\n                    \n                    if (dst_empty) {\n                        // Penalty for using an empty stack\n                        // Reduces if we place a large value (good base)\n                        cost += PENALTY_EMPTY_BASE + PENALTY_EMPTY_VAL_FACTOR * (double)(N - chunk_bottom_val);\n                    } else {\n                        if (chunk_bottom_val < dst_top_val) {\n                            // Good Link: Placing smaller on larger (e.g., 10 on 20)\n                            // We penalize large gaps to keep stacks compact\n                            int gap = dst_top_val - chunk_bottom_val;\n                            cost += (double)gap * PENALTY_GAP_FACTOR;\n                        } else {\n                            // Bad Link: Placing larger on smaller (e.g., 20 on 10)\n                            // The smaller box (dst_top_val) is now blocked.\n                            // Penalize based on how soon we need dst_top_val.\n                            int dist = dst_top_val - target;\n                            if (dist < 1) dist = 1; // Safety check\n                            \n                            double urgency = 1.0 / (double)dist;\n                            double penalty = PENALTY_BAD_LINK_BASE + PENALTY_BAD_LINK_URGENCY_FACTOR * urgency;\n                            \n                            // Additional penalty for heavy chunks (harder to undo)\n                            penalty *= (1.0 + 0.2 * chunk_sz);\n                            \n                            cost += penalty;\n                        }\n                    }\n                    \n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_k = k;\n                        best_dst = dst;\n                    }\n                }\n            }\n            \n            // Fallback logic (rarely needed)\n            if (best_k == -1) {\n                best_k = top_idx;\n                best_dst = (src + 1) % M;\n                if (best_dst == src) best_dst = (src + 2) % M;\n            }\n            \n            execute_move(src, best_k, best_dst);\n            if (op_count >= MAX_OPS) break;\n        }\n    }\n    \n    // Output the sequence of operations\n    for(const auto &m : result) {\n        cout << m.v << \" \" << m.i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Timer class to manage execution time\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    Timer() { reset(); }\n    void reset() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto end = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end - start).count() / 1000.0;\n    }\n};\n\nint N;\nvector<string> h_walls, v_walls;\nvector<int> D_vals; // Flattened dirtiness values\nvector<int> dist_mat_flat; // Flattened All-Pairs Shortest Paths matrix\n\n// Directions: Up, Down, Left, Right\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dc_char[] = {'U', 'D', 'L', 'R'};\nconst int INF = 1e9;\n\n// Check if a move is blocked by a wall\nbool can_move(int r, int c, int dir) {\n    if (dir == 0) return r > 0 && h_walls[r-1][c] == '0';\n    if (dir == 1) return r < N-1 && h_walls[r][c] == '0';\n    if (dir == 2) return c > 0 && v_walls[r][c-1] == '0';\n    if (dir == 3) return c < N-1 && v_walls[r][c] == '0';\n    return false;\n}\n\n// Compute APSP using BFS since edge weights are 1\nvoid compute_apsp() {\n    int num_nodes = N * N;\n    dist_mat_flat.assign(num_nodes * num_nodes, INF);\n    \n    // Static vectors to reuse memory\n    static vector<int> q_vec;\n    static vector<int> d_local; \n    if (q_vec.capacity() < num_nodes) { \n        q_vec.resize(num_nodes); \n        d_local.resize(num_nodes); \n    }\n    \n    for (int u = 0; u < num_nodes; ++u) {\n        // BFS from u\n        fill(d_local.begin(), d_local.end(), INF);\n        int head = 0, tail = 0;\n        q_vec[tail++] = u;\n        d_local[u] = 0;\n        dist_mat_flat[u * num_nodes + u] = 0;\n        \n        while(head < tail){\n            int curr = q_vec[head++];\n            int d_c = d_local[curr];\n            dist_mat_flat[u * num_nodes + curr] = d_c;\n            \n            int cr = curr / N;\n            int cc = curr % N;\n            \n            for(int k=0; k<4; ++k){\n                if(can_move(cr, cc, k)){\n                    int nr = cr + dr[k];\n                    int nc = cc + dc[k];\n                    int v = nr * N + nc;\n                    if(d_local[v] == INF){\n                        d_local[v] = d_c + 1;\n                        q_vec[tail++] = v;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate the average dirtiness score for the given cycle\nlong long calculate_score_cycle(const string& path) {\n    if (path.empty()) return 2e18;\n    long long L = path.length();\n    \n    int num_nodes = N * N;\n    vector<vector<int>> visits(num_nodes);\n    \n    // Simulation starts at (0,0). We assume (0,0) is cleaned at t=0.\n    int r = 0, c = 0;\n    visits[0].push_back(0);\n    \n    for(int t=1; t<=L; ++t){\n        char m = path[t-1];\n        if(m=='U') r--;\n        else if(m=='D') r++;\n        else if(m=='L') c--;\n        else if(m=='R') c++;\n        visits[r*N + c].push_back(t);\n    }\n    \n    double total_sum = 0;\n    for(int u=0; u<num_nodes; ++u){\n        // If a node is not visited, the cost is infinite (conceptually)\n        // But our construction guarantees visitation.\n        if(visits[u].empty()) return 2e18; \n        \n        long long s_sq = 0;\n        // Sum of (interval * (interval - 1))\n        for(size_t i=0; i<visits[u].size()-1; ++i){\n            long long diff = visits[u][i+1] - visits[u][i];\n            s_sq += diff * (diff - 1);\n        }\n        // Wrap-around interval: distance from last visit back to first visit (+L)\n        long long diff = (visits[u][0] + L) - visits[u].back();\n        s_sq += diff * (diff - 1);\n        \n        total_sum += (double)D_vals[u] * s_sq;\n    }\n    \n    // The formula for average dirtiness simplifies to: sum(d * sum(intervals^2)) / 2L\n    return (long long)round(total_sum / (2.0 * L));\n}\n\nint main() {\n    // Initialize IO and timer\n    Timer timer;\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input reading\n    if(!(cin >> N)) return 0;\n    h_walls.resize(N-1);\n    for(int i=0; i<N-1; ++i) cin >> h_walls[i];\n    v_walls.resize(N);\n    for(int i=0; i<N; ++i) cin >> v_walls[i];\n    \n    int num_nodes = N*N;\n    D_vals.resize(num_nodes);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> D_vals[i*N + j];\n        }\n    }\n\n    // Preprocessing\n    compute_apsp();\n\n    // Parameter exploration strategy\n    // params represent the exponent 'k' in the gravity formula 1 / dist^k\n    // Small k: global attraction (visit far away dirty nodes)\n    // Large k: local attraction (clean nearby dirty nodes first)\n    vector<double> params = {2.5, 1.5, 3.5, 1.0, 4.0, 0.5, 5.0, 2.0};\n    \n    long long best_score = -1;\n    string best_path = \"\";\n    \n    mt19937 rng(123);\n    \n    // Limit path length to save time. 25,000 is sufficient for N<=40.\n    const int MAX_PATH_LEN = 25000; \n    \n    int p_idx = 0;\n    \n    // Loop until time is close to limit\n    while(timer.elapsed() < 1.85) {\n        // Select parameter\n        double k_pow;\n        if (p_idx < params.size()) k_pow = params[p_idx++];\n        else {\n            uniform_real_distribution<double> dist_p(0.5, 5.0);\n            k_pow = dist_p(rng);\n        }\n\n        // Precompute lookup table for power function to avoid calls in loop\n        vector<double> pow_lookup(2 * num_nodes + 5);\n        for(int d=0; d<pow_lookup.size(); ++d) pow_lookup[d] = 1.0 / pow(d + 1, k_pow);\n\n        // Precompute Weight matrix W based on APSP\n        // W[u][v] = weight of node u viewed from v (symmetric)\n        // Stored flat, effectively row-major\n        vector<double> W(num_nodes * num_nodes);\n        for(int i=0; i<num_nodes * num_nodes; ++i) {\n            if(dist_mat_flat[i] == INF) W[i] = 0;\n            else W[i] = pow_lookup[dist_mat_flat[i]];\n        }\n        \n        // Incremental score tracking\n        // static_score[v]: potential dirtiness gain rate from v's perspective\n        // dynamic_score[v]: penalty reduction based on recent visits\n        vector<double> static_score(num_nodes, 0.0);\n        vector<double> dynamic_score(num_nodes, 0.0);\n        vector<int> last_visit(num_nodes, -MAX_PATH_LEN); \n        \n        // Initialize static scores\n        for(int v=0; v<num_nodes; ++v) {\n            double s = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                s += D_vals[u] * w_row[u];\n            }\n            static_score[v] = s;\n        }\n        \n        // Initialize state\n        int curr = 0;\n        last_visit[0] = 0; // (0,0) visited at t=0\n        \n        // Initialize dynamic scores (urgency)\n        for(int v=0; v<num_nodes; ++v) {\n            double d = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                d += (double)D_vals[u] * last_visit[u] * w_row[u];\n            }\n            dynamic_score[v] = d;\n        }\n        \n        string path;\n        path.reserve(MAX_PATH_LEN + 5);\n        \n        // Greedy Construction Step\n        for(int t=1; t<=MAX_PATH_LEN; ++t) {\n            // Frequent time check to prevent TLE\n            if((t & 1023) == 0) {\n                if(timer.elapsed() > 1.95) break;\n            }\n\n            int best_next = -1;\n            \n            // Check return condition: if we can't extend much further without violating return ability\n            int dist_to_home = dist_mat_flat[curr * num_nodes + 0];\n            bool must_return = (t + dist_to_home >= MAX_PATH_LEN);\n            \n            if(must_return) {\n                // Move towards (0,0) via shortest path\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        // Distance strictly decreases in BFS tree towards root\n                        if(dist_mat_flat[next_node * num_nodes + 0] < dist_to_home) {\n                            best_next = next_node;\n                            break; \n                        }\n                    }\n                }\n                if(best_next == -1) break; // Should not happen\n            } else {\n                // Greedy choice: Maximize (t * static - dynamic)\n                double max_s = -1e18;\n                \n                // Inspect valid neighbors\n                // dr/dc arrays are small, loop unrolling is implicit\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        \n                        // Heuristic score\n                        double s = (double)t * static_score[next_node] - dynamic_score[next_node];\n                        \n                        if(s > max_s) {\n                            max_s = s;\n                            best_next = next_node;\n                        }\n                    }\n                }\n            }\n            \n            if(best_next == -1) break;\n            \n            // Record Move\n            if(best_next == curr - N) path += 'U';\n            else if(best_next == curr + N) path += 'D';\n            else if(best_next == curr - 1) path += 'L';\n            else path += 'R';\n            \n            // Update State\n            // Only update dynamic scores based on the change in `last_visit` of `best_next`\n            long long old_last = last_visit[best_next];\n            double update_factor = (double)D_vals[best_next] * (t - old_last);\n            \n            // Optimized Update: Access W memory sequentially\n            const double* w_vec = &W[best_next * num_nodes];\n            for(int v=0; v<num_nodes; ++v) {\n                dynamic_score[v] += update_factor * w_vec[v];\n            }\n            \n            last_visit[best_next] = t;\n            curr = best_next;\n            \n            // Check if we successfully closed the cycle\n            if(curr == 0 && must_return) {\n                break;\n            }\n        }\n        \n        // Evaluate result\n        if(curr == 0 && !path.empty()) {\n            long long sc = calculate_score_cycle(path);\n            if(best_score == -1 || sc < best_score) {\n                best_score = sc;\n                best_path = path;\n            }\n        }\n    }\n\n    cout << best_path << endl;\n\n    return 0;\n}","ahc028":"/**\n * Solution for AtCoder Heuristic Contest 028\n * \n * Improvements from feedback:\n * 1. Refined the heuristic optimization loop:\n *    - Introduced GRASP (Greedy Randomized Adaptive Search Procedure) for diverse initialization.\n *    - Incorporated \"Block Swap\" move to allow exchanging disjoint subsegments.\n *    - Implemented a hybrid evaluation strategy where the approximate cost (ATSP) drives the SA,\n *      but the Exact Cost (DP) is periodically computed to update the global best solution.\n * 2. The Approximate Cost (ATSP distance matrix) serves as a lower bound, while the Exact Cost\n *    accounts for the specific optimal path on the keyboard grid. Minimizing the approximation\n *    correlates well with minimizing the exact cost, but periodic verification ensures we don't miss\n *    configurations that are better in reality than in the heuristic view.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <iomanip>\n\nusing namespace std;\n\n// -------------------- Constants & Globals --------------------\nint N, M;\nint start_r, start_c;\nvector<string> A;\nvector<string> T;\n// Positions of each character 'A'-'Z' on the grid\nvector<pair<int, int>> char_positions[26];\n\n// overlaps[i][j] = length of suffix of T[i] matching prefix of T[j]\nint overlaps[205][205];\n\n// ATSP Distance Matrix (Lower Bound Heuristic)\n// dist_matrix[i][j] = min cost to type the non-overlapping extension of T[j] \n// immediately after T[i], minimizing over all possible physical endpoints of T[i].\nint dist_matrix[205][205];\n\n// Start distances (Cost to type T[i] from the initial finger position)\nint start_dist[205];\n\n// Global best tracking\nvector<int> global_best_p;\nint global_min_exact_cost = INT_MAX;\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// -------------------- Helper Functions --------------------\n\ninline int c2i(char c) {\n    return c - 'A';\n}\n\ninline int dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Precompute overlap between two strings (Max length suffix of s1 matching prefix of s2)\nint calc_overlap(const string& s1, const string& s2) {\n    for (int len = 4; len >= 1; --len) {\n        bool match = true;\n        for (int k = 0; k < len; ++k) {\n            if (s1[5 - len + k] != s2[k]) {\n                match = false;\n                break;\n            }\n        }\n        if (match) return len;\n    }\n    return 0;\n}\n\n// DP to calculate min cost to type string 's' starting from any position in start_coords.\n// This effectively finds the shortest path through the grid for the string characters.\nint calc_segment_cost(const vector<pair<int,int>>& start_coords, const string& s) {\n    if (s.empty()) return 0;\n    int L = s.size();\n    \n    // Static vectors to reuse memory\n    static vector<int> dp_prev;\n    static vector<int> dp_curr;\n    \n    int c0 = c2i(s[0]);\n    const auto& pos0 = char_positions[c0];\n    dp_prev.assign(pos0.size(), 1000000);\n    \n    // Initialize costs for the first character of s from start_coords\n    for (size_t j = 0; j < pos0.size(); ++j) {\n        int r = pos0[j].first;\n        int c = pos0[j].second;\n        for (const auto& start_pos : start_coords) {\n            int d = dist(start_pos.first, start_pos.second, r, c) + 1; \n            if (d < dp_prev[j]) dp_prev[j] = d;\n        }\n    }\n    \n    // Iterate through the rest of the string\n    for (int i = 1; i < L; ++i) {\n        int curr_char = c2i(s[i]);\n        const auto& curr_pos = char_positions[curr_char];\n        const auto& prev_pos = char_positions[c2i(s[i-1])];\n        \n        dp_curr.assign(curr_pos.size(), 1000000);\n        \n        for (size_t j = 0; j < curr_pos.size(); ++j) {\n            int r = curr_pos[j].first;\n            int c = curr_pos[j].second;\n            for (size_t k = 0; k < prev_pos.size(); ++k) {\n                if (dp_prev[k] >= 1000000) continue;\n                int d = dist(prev_pos[k].first, prev_pos[k].second, r, c) + 1;\n                if (dp_prev[k] + d < dp_curr[j]) {\n                    dp_curr[j] = dp_prev[k] + d;\n                }\n            }\n        }\n        dp_prev = dp_curr;\n    }\n    \n    int ans = 1000000;\n    for (int v : dp_prev) if (v < ans) ans = v;\n    return ans;\n}\n\n// Reconstructs the exact cost for a given permutation p.\n// mode 0: just return the minimum cost.\n// mode 1: output the sequence of coordinates to cout.\nint solve_exact(const vector<int>& p, int mode) {\n    // Construct the full sequence of characters indices\n    vector<int> S;\n    S.reserve(1200);\n    \n    for (char c : T[p[0]]) S.push_back(c2i(c));\n    for (size_t i = 1; i < p.size(); ++i) {\n        int u = p[i-1];\n        int v = p[i];\n        int ov = overlaps[u][v];\n        for (size_t k = ov; k < 5; ++k) {\n            S.push_back(c2i(T[v][k]));\n        }\n    }\n    \n    int L = S.size();\n    vector<vector<int>> dp(L);\n    vector<vector<int>> parent; \n    if (mode == 1) parent.resize(L);\n    \n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp[0].resize(pos0.size());\n    if (mode == 1) parent[0].resize(pos0.size(), -1);\n    \n    // Init DP from start position\n    for (size_t j = 0; j < pos0.size(); ++j) {\n        dp[0][j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    // Run Viterbi-like DP\n    for (int i = 1; i < L; ++i) {\n        int curr_c = S[i];\n        int prev_c = S[i-1];\n        const auto& curr_pos = char_positions[curr_c];\n        const auto& prev_pos = char_positions[prev_c];\n        \n        dp[i].resize(curr_pos.size());\n        if (mode == 1) parent[i].resize(curr_pos.size());\n        \n        for (size_t j = 0; j < curr_pos.size(); ++j) {\n            int r = curr_pos[j].first;\n            int c = curr_pos[j].second;\n            int min_val = 1e9;\n            int best_p = -1;\n            \n            for (size_t k = 0; k < prev_pos.size(); ++k) {\n                int d = dist(prev_pos[k].first, prev_pos[k].second, r, c);\n                int total = dp[i-1][k] + d + 1;\n                if (total < min_val) {\n                    min_val = total;\n                    best_p = k;\n                }\n            }\n            dp[i][j] = min_val;\n            if (mode == 1) parent[i][j] = best_p;\n        }\n    }\n    \n    int min_total = 1e9;\n    int curr_idx = -1;\n    for (size_t j = 0; j < dp[L-1].size(); ++j) {\n        if (dp[L-1][j] < min_total) {\n            min_total = dp[L-1][j];\n            curr_idx = j;\n        }\n    }\n    \n    if (mode == 1) {\n        // Backtrack to print path\n        vector<pair<int,int>> path;\n        for (int i = L - 1; i >= 0; --i) {\n            path.push_back(char_positions[S[i]][curr_idx]);\n            curr_idx = parent[i][curr_idx];\n        }\n        reverse(path.begin(), path.end());\n        for (auto& pt : path) {\n            cout << pt.first << \" \" << pt.second << \"\\n\";\n        }\n    }\n    \n    return min_total;\n}\n\n// Update global best if the current candidate p is better in terms of exact cost\nvoid check_candidate(const vector<int>& p) {\n    int cost = solve_exact(p, 0);\n    if (cost < global_min_exact_cost) {\n        global_min_exact_cost = cost;\n        global_best_p = p;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    if (!(cin >> N >> M)) return 0;\n    cin >> start_r >> start_c;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    T.resize(M);\n    for (int i = 0; i < M; ++i) cin >> T[i];\n    \n    // Preprocess Map\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char_positions[c2i(A[i][j])].push_back({i, j});\n        }\n    }\n    \n    // Precompute Overlaps\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i == j) overlaps[i][j] = 0;\n            else overlaps[i][j] = calc_overlap(T[i], T[j]);\n        }\n    }\n    \n    // Precompute Start Distances\n    vector<pair<int,int>> s_pos;\n    s_pos.push_back({start_r, start_c});\n    for (int i = 0; i < M; ++i) {\n        start_dist[i] = calc_segment_cost(s_pos, T[i]);\n    }\n    \n    // Precompute ATSP Distance Matrix\n    // This uses the optimized heuristic: Min cost to type extension of j from ANY valid end of i.\n    for (int i = 0; i < M; ++i) {\n        int last_char_idx = c2i(T[i].back());\n        const auto& end_positions = char_positions[last_char_idx];\n        for (int j = 0; j < M; ++j) {\n            if (i == j) {\n                dist_matrix[i][j] = 1e9;\n                continue;\n            }\n            string ext = T[j].substr(overlaps[i][j]);\n            dist_matrix[i][j] = calc_segment_cost(end_positions, ext);\n        }\n    }\n    \n    // --- Initialization: GRASP (Randomized Greedy) ---\n    // Generate multiple greedy solutions and pick the best (by approximate metric)\n    // Also check them against exact metric.\n    int best_approx_cost = 1e9;\n    vector<int> current_p;\n    \n    for (int iter = 0; iter < 150; ++iter) {\n        vector<int> p;\n        p.reserve(M);\n        vector<bool> used(M, false);\n        \n        int start_node = rng() % M;\n        \n        p.push_back(start_node);\n        used[start_node] = true;\n        int cost = start_dist[start_node];\n        int curr = start_node;\n        \n        for (int i = 1; i < M; ++i) {\n            vector<pair<int,int>> candidates;\n            candidates.reserve(M);\n            for (int j = 0; j < M; ++j) {\n                if (!used[j]) {\n                    candidates.push_back({dist_matrix[curr][j], j});\n                }\n            }\n            \n            // Randomized selection from top candidates\n            sort(candidates.begin(), candidates.end());\n            int range = min((int)candidates.size(), 4);\n            int choice = rng() % range;\n            \n            int next_node = candidates[choice].second;\n            int d = candidates[choice].first;\n            \n            p.push_back(next_node);\n            used[next_node] = true;\n            cost += d;\n            curr = next_node;\n        }\n        \n        if (cost < best_approx_cost) {\n            best_approx_cost = cost;\n            current_p = p;\n        }\n        \n        check_candidate(p);\n    }\n    \n    // --- Simulated Annealing ---\n    vector<int> p = current_p;\n    int current_cost = best_approx_cost;\n    \n    double T0 = 10.0;\n    double T1 = 0.1;\n    double TL = 1.95;\n    \n    static double temp = T0;\n    int iters = 0;\n    \n    while (true) {\n        iters++;\n        if ((iters & 1023) == 0) {\n            double el = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (el > TL) break;\n            temp = T0 + (T1 - T0) * (el / TL);\n            \n            // Periodically check exact cost for current configuration\n            check_candidate(p);\n        }\n        \n        int type = rng() % 100;\n        \n        if (type < 30) {\n            // --- SWAP Move ---\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i == j) continue;\n            if (i > j) swap(i, j);\n            \n            int u = p[i]; int v = p[j];\n            int prev_i = (i > 0) ? p[i-1] : -1;\n            int next_i = p[i+1]; \n            int prev_j = p[j-1];\n            int next_j = (j < M-1) ? p[j+1] : -1;\n\n            int delta = 0;\n            if (j == i + 1) {\n                // Adjacent\n                if (prev_i != -1) delta += dist_matrix[prev_i][v] - dist_matrix[prev_i][u];\n                else delta += start_dist[v] - start_dist[u];\n                \n                delta += dist_matrix[v][u] - dist_matrix[u][v];\n                \n                if (next_j != -1) delta += dist_matrix[u][next_j] - dist_matrix[v][next_j];\n            } else {\n                // Disjoint\n                if (prev_i != -1) delta += dist_matrix[prev_i][v] - dist_matrix[prev_i][u];\n                else delta += start_dist[v] - start_dist[u];\n                \n                delta += dist_matrix[v][next_i] - dist_matrix[u][next_i];\n                delta += dist_matrix[prev_j][u] - dist_matrix[prev_j][v];\n                \n                if (next_j != -1) delta += dist_matrix[u][next_j] - dist_matrix[v][next_j];\n            }\n            \n            if (delta <= 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                swap(p[i], p[j]);\n                current_cost += delta;\n            }\n\n        } else if (type < 70) {\n            // --- BLOCK INSERT Move ---\n            // Moves a block p[i...i+len-1] to a new position\n            int len = (rng() % 4) + 1;\n            if (M < len + 1) len = 1;\n            int i = rng() % (M - len + 1);\n            int j_reduced = rng() % (M - len + 1);\n            int pos_in_original = j_reduced;\n            if (pos_in_original > i) pos_in_original += len;\n            \n            if (pos_in_original >= i && pos_in_original <= i + len) continue;\n            \n            int block_start = p[i];\n            int block_end = p[i+len-1];\n            int prev_block = (i > 0) ? p[i-1] : -1;\n            int next_block = (i + len < M) ? p[i+len] : -1;\n            \n            int u_idx = pos_in_original - 1;\n            int v_idx = pos_in_original;\n            int u = (u_idx >= 0) ? p[u_idx] : -1;\n            int v = (v_idx < M) ? p[v_idx] : -1;\n            \n            int delta = 0;\n            // Remove current edges\n            if (prev_block != -1) delta -= dist_matrix[prev_block][block_start];\n            else delta -= start_dist[block_start];\n            if (next_block != -1) delta -= dist_matrix[block_end][next_block];\n            \n            // Add edge closing gap\n            if (prev_block != -1 && next_block != -1) delta += dist_matrix[prev_block][next_block];\n            else if (prev_block == -1 && next_block != -1) delta += start_dist[next_block];\n            \n            // Break edge at target\n            if (u != -1 && v != -1) delta -= dist_matrix[u][v];\n            else if (u == -1 && v != -1) delta -= start_dist[v];\n            \n            // Add edges for inserted block\n            if (u != -1) delta += dist_matrix[u][block_start];\n            else delta += start_dist[block_start];\n            if (v != -1) delta += dist_matrix[block_end][v];\n            \n            if (delta <= 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                vector<int> block;\n                block.reserve(len);\n                for(int k=0; k<len; ++k) block.push_back(p[i+k]);\n                p.erase(p.begin() + i, p.begin() + i + len);\n                int ins = (pos_in_original > i) ? (pos_in_original - len) : pos_in_original;\n                p.insert(p.begin() + ins, block.begin(), block.end());\n                current_cost += delta;\n            }\n        } else {\n            // --- BLOCK SWAP Move ---\n            // Swaps two disjoint blocks\n            int len1 = (rng() % 3) + 1;\n            int i1 = rng() % (M - len1 + 1);\n            int len2 = (rng() % 3) + 1;\n            int i2 = rng() % (M - len2 + 1);\n            \n            // Check overlap\n            if (max(i1, i2) <= min(i1+len1-1, i2+len2-1)) continue; \n            if (i1 > i2) { swap(i1, i2); swap(len1, len2); } \n            \n            int prev1 = (i1 > 0) ? p[i1-1] : -1;\n            int start1 = p[i1];\n            int end1 = p[i1+len1-1];\n            int next1 = p[i1+len1];\n            \n            int prev2 = p[i2-1];\n            int start2 = p[i2];\n            int end2 = p[i2+len2-1];\n            int next2 = (i2 + len2 < M) ? p[i2+len2] : -1;\n            \n            int delta = 0;\n            \n            if (i2 == i1 + len1) {\n                // Adjacent blocks: [B1][B2] -> [B2][B1]\n                if (prev1 != -1) delta += dist_matrix[prev1][start2] - dist_matrix[prev1][start1];\n                else delta += start_dist[start2] - start_dist[start1];\n                \n                delta += dist_matrix[end2][start1] - dist_matrix[end1][start2];\n                \n                if (next2 != -1) delta += dist_matrix[end1][next2] - dist_matrix[end2][next2];\n            } else {\n                // Disjoint\n                // Remove B1 connections\n                if (prev1 != -1) delta -= dist_matrix[prev1][start1]; else delta -= start_dist[start1];\n                delta -= dist_matrix[end1][next1];\n                \n                // Remove B2 connections\n                delta -= dist_matrix[prev2][start2];\n                if (next2 != -1) delta -= dist_matrix[end2][next2];\n                \n                // Add B2 at pos1\n                if (prev1 != -1) delta += dist_matrix[prev1][start2]; else delta += start_dist[start2];\n                delta += dist_matrix[end2][next1];\n                \n                // Add B1 at pos2\n                delta += dist_matrix[prev2][start1];\n                if (next2 != -1) delta += dist_matrix[end1][next2];\n            }\n            \n            if (delta <= 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                vector<int> b1(p.begin() + i1, p.begin() + i1 + len1);\n                vector<int> b2(p.begin() + i2, p.begin() + i2 + len2);\n                \n                p.erase(p.begin() + i2, p.begin() + i2 + len2);\n                p.insert(p.begin() + i2, b1.begin(), b1.end());\n                \n                p.erase(p.begin() + i1, p.begin() + i1 + len1);\n                p.insert(p.begin() + i1, b2.begin(), b2.end());\n                \n                current_cost += delta;\n            }\n        }\n    }\n    \n    // Final output\n    solve_exact(global_best_p, 1);\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <cassert>\n#include <map>\n\nusing namespace std;\n\n// ---------------------- Utils ----------------------\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool is_time_over() {\n        return elapsed() > limit;\n    }\n};\n\nmt19937 rng(12345);\n\n// ---------------------- Globals ----------------------\n\nint N, M;\ndouble EPS;\n\nstruct Point { int r, c; };\n\nstruct Polyomino {\n    vector<Point> shape;\n};\nvector<Polyomino> fields;\n\nstruct Operation {\n    int type; // 0: drill, 1: divine\n    int r, c; // for drill\n    vector<Point> set_points; // for divine\n    int result_drill;\n    int result_divine;\n    \n    // Precomputed parameters for energy calc\n    double divine_mean_base; // k*eps\n    double divine_mean_coeff; // 1 - 2*eps\n    double divine_var_inv; // 1 / (2*sigma^2)\n};\nvector<Operation> history;\nvector<vector<vector<int>>> cell_to_ops;\n\nstruct ValidPos {\n    int r, c; // top-left\n    vector<Point> cells;\n};\nvector<vector<ValidPos>> possible_positions; // [field_id][pos_id]\nvector<vector<int>> active_indices; // [field_id] -> list of valid pos_ids\n\nvector<vector<int>> grid_known; // -1: unknown, >=0: exact value\n\n// ---------------------- Functions ----------------------\n\nvoid precompute_positions() {\n    possible_positions.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = 0, max_c = 0;\n        for (auto& p : fields[k].shape) {\n            max_r = max(max_r, p.r);\n            max_c = max(max_c, p.c);\n        }\n        for (int r = 0; r < N - max_r; ++r) {\n            for (int c = 0; c < N - max_c; ++c) {\n                ValidPos vp;\n                vp.r = r;\n                vp.c = c;\n                for (auto& p : fields[k].shape) {\n                    vp.cells.push_back({p.r + r, p.c + c});\n                }\n                possible_positions[k].push_back(vp);\n            }\n        }\n    }\n}\n\nvoid add_history(Operation op) {\n    int idx = history.size();\n    \n    if (op.type == 1) {\n        int k_sz = op.set_points.size();\n        double var = k_sz * EPS * (1.0 - EPS);\n        op.divine_mean_base = k_sz * EPS;\n        op.divine_mean_coeff = 1.0 - 2.0 * EPS;\n        op.divine_var_inv = 0.5 / max(1e-9, var);\n    } \n    \n    history.push_back(op);\n    \n    // Update lookup\n    if (op.type == 0) {\n        cell_to_ops[op.r][op.c].push_back(idx);\n        grid_known[op.r][op.c] = op.result_drill;\n    } else {\n        for (auto& p : op.set_points) {\n            cell_to_ops[p.r][p.c].push_back(idx);\n        }\n    }\n}\n\n// Prune valid positions based on known 0s\nvoid prune_positions() {\n    active_indices.assign(M, {});\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < (int)possible_positions[k].size(); ++i) {\n            bool ok = true;\n            const auto& cells = possible_positions[k][i].cells;\n            for (const auto& p : cells) {\n                if (grid_known[p.r][p.c] == 0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                active_indices[k].push_back(i);\n            }\n        }\n    }\n}\n\n// SA State\nstruct State {\n    vector<int> config; // [field_id] -> pos_index\n    vector<vector<int>> counts;\n    vector<int> op_preds; // [op_idx] -> predicted value\n    double energy;\n};\n\ndouble get_op_energy(int op_idx, int pred_val) {\n    const auto& op = history[op_idx];\n    if (op.type == 0) { // Drill\n        // Hard constraint violation penalty\n        return 100000.0 * abs(pred_val - op.result_drill);\n    } else { // Divine\n        double mean = op.divine_mean_base + pred_val * op.divine_mean_coeff;\n        double diff = op.result_divine - mean;\n        return diff * diff * op.divine_var_inv;\n    }\n}\n\nvector<vector<int>> run_sa(int num_solutions, double duration) {\n    vector<vector<int>> solutions;\n    Timer t(duration);\n    \n    for (int k = 0; k < M; ++k) {\n        if (active_indices[k].empty()) return {}; \n    }\n\n    while (solutions.size() < (size_t)num_solutions && !t.is_time_over()) {\n        State S;\n        S.config.resize(M);\n        S.counts.assign(N, vector<int>(N, 0));\n        S.op_preds.assign(history.size(), 0);\n        S.energy = 0;\n\n        // Random Init\n        for (int k = 0; k < M; ++k) {\n            int idx = active_indices[k][rng() % active_indices[k].size()];\n            S.config[k] = idx;\n            for (const auto& p : possible_positions[k][idx].cells) {\n                S.counts[p.r][p.c]++;\n                for (int op_idx : cell_to_ops[p.r][p.c]) {\n                    S.op_preds[op_idx]++;\n                }\n            }\n        }\n\n        for (int i = 0; i < (int)history.size(); ++i) {\n            S.energy += get_op_energy(i, S.op_preds[i]);\n        }\n        \n        State best_S = S;\n\n        double Temp = 5.0;\n        double decay = 0.92;\n        int iter = 0;\n        int max_iter = 1500;\n        \n        static vector<int> changed_ops;\n        changed_ops.reserve(history.size());\n\n        while (iter < max_iter) { \n            iter++;\n            int k = rng() % M;\n            if (active_indices[k].size() <= 1) continue;\n\n            int old_idx = S.config[k];\n            int new_idx = active_indices[k][rng() % active_indices[k].size()];\n            if (old_idx == new_idx) continue;\n\n            const auto& old_cells = possible_positions[k][old_idx].cells;\n            const auto& new_cells = possible_positions[k][new_idx].cells;\n\n            changed_ops.clear();\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            sort(changed_ops.begin(), changed_ops.end());\n            changed_ops.erase(unique(changed_ops.begin(), changed_ops.end()), changed_ops.end());\n\n            double delta = 0;\n            for (int op_idx : changed_ops) delta -= get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n            }\n\n            for (int op_idx : changed_ops) delta += get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            if (delta < 0 || exp(-delta / Temp) > (double)rng() / 4294967296.0) {\n                S.energy += delta;\n                S.config[k] = new_idx;\n                for (const auto& p : old_cells) S.counts[p.r][p.c]--;\n                for (const auto& p : new_cells) S.counts[p.r][p.c]++;\n                \n                if (S.energy < best_S.energy) {\n                    best_S = S;\n                }\n            } else {\n                for (const auto& p : new_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n                }\n                for (const auto& p : old_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n                }\n            }\n            Temp *= decay;\n            if (Temp < 0.05) break;\n        }\n        solutions.push_back(best_S.config);\n    }\n    return solutions;\n}\n\nint main() {\n    cin.tie(nullptr);\n    ios_base::sync_with_stdio(false);\n\n    if (!(cin >> N >> M >> EPS)) return 0;\n\n    fields.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int d; cin >> d;\n        fields[i].shape.resize(d);\n        for (int j = 0; j < d; ++j) {\n            cin >> fields[i].shape[j].r >> fields[i].shape[j].c;\n        }\n    }\n\n    precompute_positions();\n    grid_known.assign(N, vector<int>(N, -1));\n    cell_to_ops.assign(N, vector<vector<int>>(N));\n\n    // 1. Initial Scan: Sparse blocks to save cost\n    int block_size = 3;\n    if (EPS <= 0.15) block_size = 4; \n    if (N < 12) block_size = 2; \n\n    for(int r=0; r<N; r+=block_size) {\n        for(int c=0; c<N; c+=block_size) {\n            vector<Point> pts;\n            for(int rr=r; rr<min(N, r+block_size); ++rr) {\n                for(int cc=c; cc<min(N, c+block_size); ++cc) {\n                    pts.push_back({rr, cc});\n                }\n            }\n            if(pts.size() >= 2) {\n                cout << \"q \" << pts.size();\n                for(auto& p : pts) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                int res; cin >> res;\n                add_history({1, 0, 0, pts, 0, res});\n            }\n        }\n    }\n\n    Timer global_timer(2.8);\n    int max_ops = 2 * N * N;\n\n    while (!global_timer.is_time_over() && (int)history.size() < max_ops) {\n        prune_positions();\n\n        // Run SA\n        vector<vector<int>> solutions = run_sa(25, 0.08);\n\n        vector<vector<int>> pos_counts(N, vector<int>(N, 0));\n        int sol_cnt = solutions.size();\n        \n        if (sol_cnt > 0) {\n            for(const auto& cfg : solutions) {\n                for(int k=0; k<M; ++k) {\n                    int idx = cfg[k];\n                    for(auto& p : possible_positions[k][idx].cells) {\n                        pos_counts[p.r][p.c]++;\n                    }\n                }\n            }\n        }\n\n        vector<Point> answer_candidates;\n        bool confident = true;\n        if (sol_cnt == 0) confident = false;\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                bool cell_oil = false;\n                if (grid_known[r][c] != -1) {\n                    if (grid_known[r][c] > 0) cell_oil = true;\n                } else {\n                    if (sol_cnt > 0) {\n                        if (pos_counts[r][c] == sol_cnt) cell_oil = true;\n                        else if (pos_counts[r][c] == 0) cell_oil = false;\n                        else confident = false;\n                    } else {\n                        confident = false;\n                    }\n                }\n                if (cell_oil) answer_candidates.push_back({r, c});\n            }\n        }\n        \n        if (confident && sol_cnt > 0) {\n            bool consistent = true;\n            for (auto& p : answer_candidates) {\n                if (grid_known[p.r][p.c] == 0) consistent = false;\n            }\n            if (consistent) {\n                cout << \"a \" << answer_candidates.size();\n                for(auto& p : answer_candidates) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                int res; cin >> res;\n                if (res == 1) return 0;\n            }\n        }\n        \n        int best_r = -1, best_c = -1;\n        \n        if (sol_cnt > 0) {\n            int max_ent = -1;\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    if (grid_known[r][c] != -1) continue;\n                    int yes = pos_counts[r][c];\n                    int no = sol_cnt - yes;\n                    int score = min(yes, no);\n                    \n                    if (score > max_ent) {\n                        max_ent = score;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n        }\n        \n        if (best_r == -1) {\n             vector<Point> unknowns;\n             for(int r=0; r<N; ++r)\n                 for(int c=0; c<N; ++c)\n                     if(grid_known[r][c] == -1) unknowns.push_back({r, c});\n             \n             if (unknowns.empty()) break; \n             \n             vector<Point> adj_candidates;\n             for(auto& u : unknowns) {\n                 bool adj = false;\n                 int dr[] = {0,0,1,-1};\n                 int dc[] = {1,-1,0,0};\n                 for(int i=0; i<4; ++i) {\n                     int nr=u.r+dr[i], nc=u.c+dc[i];\n                     if(nr>=0 && nr<N && nc>=0 && nc<N && grid_known[nr][nc]>0) adj=true;\n                 }\n                 if(adj) adj_candidates.push_back(u);\n             }\n             \n             if (!adj_candidates.empty()) {\n                 int idx = rng() % adj_candidates.size();\n                 best_r = adj_candidates[idx].r;\n                 best_c = adj_candidates[idx].c;\n             } else {\n                 int idx = rng() % unknowns.size();\n                 best_r = unknowns[idx].r;\n                 best_c = unknowns[idx].c;\n             }\n        }\n        \n        cout << \"q 1 \" << best_r << \" \" << best_c << endl;\n        int val; cin >> val;\n        add_history({0, best_r, best_c, {}, val, 0});\n    }\n    \n    vector<Point> final_ans;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            if(grid_known[r][c] > 0) final_ans.push_back({r, c});\n        }\n    }\n    cout << \"a \" << final_ans.size();\n    for(auto& p : final_ans) cout << \" \" << p.r << \" \" << p.c;\n    cout << endl;\n    int res; cin >> res;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global Inputs\nint W_GRID;\nint D, N;\nvector<vector<int>> A;\n\n// Constants\nconst int SHORTAGE_PENALTY = 100;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct ColumnResult {\n    long long cost;\n    vector<vector<int>> cuts;\n};\n\n// Time management\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\n// Solves the 1D layout problem for a single column.\n// Prioritizes avoiding shortage (high cost), then stability (low cost).\nColumnResult solve_column(const vector<int>& items, int width) {\n    if (items.empty()) return {0, vector<vector<int>>(D)};\n    if (width <= 0) return {1000000000000LL, {}}; // Safety\n\n    int m = items.size();\n    vector<vector<int>> cuts(D, vector<int>(m));\n    long long total_cost = 0;\n    \n    vector<int> prev_cuts(m, 0); \n    \n    // Reused vectors\n    vector<int> needs(m);\n    vector<int> R(m);\n    vector<int> curr_cuts(m);\n\n    for (int d = 0; d < D; ++d) {\n        // 1. Calculate strictly required height for each item (ceil division)\n        for(int i=0; i<m; ++i) {\n            needs[i] = (A[d][items[i]] + width - 1) / width;\n        }\n\n        // 2. Calculate Upper Bounds (R)\n        // R[i] is the maximum position for cut i that allows all subsequent items to fit\n        int acc_space = W_GRID;\n        R[m-1] = W_GRID;\n        for(int i=m-2; i>=0; --i) {\n            acc_space -= needs[i+1];\n            if (acc_space < 0) acc_space = 0;\n            R[i] = acc_space;\n        }\n\n        curr_cuts[m-1] = W_GRID;\n        int current_y = 0;\n        \n        // 3. Determine cuts\n        for(int i=0; i<m-1; ++i) {\n            int min_pos = current_y + needs[i];\n            int max_pos = R[i];\n            \n            int chosen = min_pos;\n            \n            if (min_pos <= max_pos) {\n                // Valid range exists. Try to minimize movement.\n                if (d > 0) {\n                    int p = prev_cuts[i];\n                    if (p >= min_pos && p <= max_pos) chosen = p; // Perfect stability\n                    else if (p < min_pos) chosen = min_pos;       // Must move down\n                    else chosen = max_pos;                        // Must move up\n                }\n            } else {\n                // Shortage unavoidable. Prioritize current item to maintain top structure.\n                chosen = min_pos;\n            }\n            \n            if (chosen > W_GRID) chosen = W_GRID;\n            curr_cuts[i] = chosen;\n            current_y = chosen;\n        }\n        \n        // 4. Calculate Cost\n        long long d_cost = 0;\n        int prev_y = 0;\n        for(int i=0; i<m; ++i) {\n            int h = curr_cuts[i] - prev_y;\n            long long area = (long long)h * width;\n            long long req = A[d][items[i]];\n            if (area < req) {\n                d_cost += (req - area) * SHORTAGE_PENALTY;\n            }\n            prev_y = curr_cuts[i];\n        }\n        \n        if (d > 0) {\n            for(int i=0; i<m-1; ++i) {\n                if (curr_cuts[i] != prev_cuts[i]) {\n                    // 1 unit move of a horizontal separator costs 2 * width \n                    // (remove old line, add new line)\n                    d_cost += (width << 1); \n                }\n            }\n        }\n        \n        total_cost += d_cost;\n        cuts[d] = curr_cuts;\n        prev_cuts = curr_cuts;\n    }\n    return {total_cost, cuts};\n}\n\nstruct Solution {\n    vector<int> partition_cuts; // Indices in 0..N where columns split\n    vector<int> widths;\n    long long score;\n    vector<vector<int>> part_groups;\n};\n\n// Evaluates a partition configuration\nSolution evaluate(const vector<int>& cuts, int K) {\n    vector<vector<int>> part(K);\n    for(int c=0; c<K; ++c) {\n        part[c].reserve(cuts[c+1]-cuts[c]);\n        for(int i=cuts[c]; i<cuts[c+1]; ++i) part[c].push_back(i);\n    }\n\n    // Determine optimal column widths based on Proportional Peak Demand\n    vector<long long> max_demands(K, 0);\n    long long total_demand = 0;\n    \n    for(int c=0; c<K; ++c) {\n        for(int d=0; d<D; ++d) {\n            long long daily_sum = 0;\n            for(int idx : part[c]) daily_sum += A[d][idx];\n            if (daily_sum > max_demands[c]) max_demands[c] = daily_sum;\n        }\n        total_demand += max_demands[c];\n    }\n\n    vector<int> widths(K);\n    if (total_demand == 0) total_demand = 1;\n    \n    // Distribute W_GRID using Largest Remainder Method to handle rounding\n    long long current_sum = 0;\n    vector<pair<long long, int>> remainders(K);\n    \n    for(int c=0; c<K; ++c) {\n        long long val = (long long)W_GRID * max_demands[c];\n        widths[c] = (int)(val / total_demand);\n        remainders[c] = { val % total_demand, c };\n        if (widths[c] < 1) widths[c] = 1;\n        current_sum += widths[c];\n    }\n    \n    // Adjust sum to exactly W_GRID\n    if (current_sum < W_GRID) {\n        sort(remainders.rbegin(), remainders.rend());\n        for(int i=0; i < W_GRID - current_sum; ++i) {\n            widths[remainders[i].second]++;\n        }\n    } else if (current_sum > W_GRID) {\n        int diff = current_sum - W_GRID;\n        for(int c=0; c<K && diff>0; ++c) {\n            if (widths[c] > 1) { widths[c]--; diff--; }\n        }\n        if (diff > 0) widths[K-1] -= diff;\n    }\n\n    long long total_score = 0;\n    for(int c=0; c<K; ++c) {\n        total_score += solve_column(part[c], widths[c]).cost;\n    }\n    \n    return {cuts, widths, total_score, part};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> W_GRID >> D >> N)) return 0;\n    A.resize(D, vector<int>(N));\n    for(int d=0; d<D; ++d) for(int k=0; k<N; ++k) cin >> A[d][k];\n\n    long long start_time = get_time_ms();\n    mt19937 rng(42);\n\n    Solution best_sol;\n    best_sol.score = -1;\n\n    // Iterate through possible number of columns\n    int max_k = min(N, 14); \n    \n    for(int K=1; K<=max_k; ++K) {\n        // Initial uniform partition\n        vector<int> cuts(K+1);\n        cuts[0] = 0; cuts[K] = N;\n        for(int i=1; i<K; ++i) cuts[i] = (N * i) / K;\n\n        Solution current_sol = evaluate(cuts, K);\n        if (best_sol.score == -1 || current_sol.score < best_sol.score) best_sol = current_sol;\n        \n        if (K == 1) continue;\n\n        // Steepest Descent Hill Climbing with Random Kicks\n        int no_improv = 0;\n        while(true) {\n            if (get_time_ms() - start_time > 2850) break;\n            if (no_improv > 15) break; // Move to next K if stuck\n            \n            bool improved = false;\n            vector<int> best_local_cuts = current_sol.partition_cuts;\n            long long best_local_score = current_sol.score;\n\n            // Evaluate all single-step moves for all boundaries\n            for(int i=1; i<K; ++i) {\n                // Move Left\n                if (current_sol.partition_cuts[i] > current_sol.partition_cuts[i-1] + 1) {\n                    vector<int> next_cuts = current_sol.partition_cuts;\n                    next_cuts[i]--;\n                    Solution next_s = evaluate(next_cuts, K);\n                    if (next_s.score < best_local_score) {\n                        best_local_score = next_s.score;\n                        best_local_cuts = next_cuts;\n                        improved = true;\n                    }\n                }\n                // Move Right\n                if (current_sol.partition_cuts[i] < current_sol.partition_cuts[i+1] - 1) {\n                    vector<int> next_cuts = current_sol.partition_cuts;\n                    next_cuts[i]++;\n                    Solution next_s = evaluate(next_cuts, K);\n                    if (next_s.score < best_local_score) {\n                        best_local_score = next_s.score;\n                        best_local_cuts = next_cuts;\n                        improved = true;\n                    }\n                }\n            }\n            \n            if (improved) {\n                current_sol = evaluate(best_local_cuts, K);\n                if (current_sol.score < best_sol.score) best_sol = current_sol;\n                no_improv = 0;\n            } else {\n                no_improv++;\n                // Random Kick: Move a random boundary significantly\n                int idx = uniform_int_distribution<int>(1, K-1)(rng);\n                int shift = uniform_int_distribution<int>(-2, 2)(rng);\n                if (shift == 0) shift = (uniform_int_distribution<int>(0,1)(rng) ? 1 : -1);\n                \n                vector<int> next_cuts = current_sol.partition_cuts;\n                next_cuts[idx] += shift;\n                \n                // Validate limits\n                if (next_cuts[idx] > next_cuts[idx-1] && next_cuts[idx] < next_cuts[idx+1]) {\n                    current_sol = evaluate(next_cuts, K);\n                }\n            }\n        }\n    }\n\n    // Output generation\n    vector<vector<Rect>> final_rects(D, vector<Rect>(N));\n    int current_x = 0;\n    for(int c=0; c<best_sol.part_groups.size(); ++c) {\n        int w = best_sol.widths[c];\n        ColumnResult res = solve_column(best_sol.part_groups[c], w);\n        for(int d=0; d<D; ++d) {\n            int prev_y = 0;\n            for(int i=0; i<best_sol.part_groups[c].size(); ++i) {\n                int idx = best_sol.part_groups[c][i];\n                int y = res.cuts[d][i];\n                final_rects[d][idx] = {prev_y, current_x, y, current_x + w};\n                prev_y = y;\n            }\n        }\n        current_x += w;\n    }\n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            cout << final_rects[d][k].r0 << \" \" << final_rects[d][k].c0 << \" \" \n                 << final_rects[d][k].r1 << \" \" << final_rects[d][k].c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n\nusing namespace std;\n\n// Problem Constraints\nconstexpr int N = 9;\nconstexpr long long MOD = 998244353;\n\n// Fast RNG using Xorshift128\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Global Variables\nint M, K;\nlong long initial_board[81];\nlong long stamps[20][9]; // Flattened 3x3 stamps\nint move_indices[49][9]; // Affected board indices for each top-left position\n\nstruct MoveDef {\n    int m;       // Stamp ID\n    int pos_idx; // Position ID (0..48)\n    int p, q;    // Coordinates\n};\nvector<MoveDef> all_moves;\n\n// State Variables\nint current_ops[81]; // Stores index in all_moves, or -1 for empty\nlong long board[81];\nlong long current_score;\n\n// Best Solution Tracking\nint best_ops[81];\nlong long best_score = -1;\n\n// Undo System for efficient rollback\nstruct Undo {\n    int idx;\n    long long val;\n};\nUndo undo_log[20]; // Buffer for changes (max 18 per step)\nint undo_ptr = 0;\n\n// Apply or remove a stamp operation. \n// If adding=true, adds stamp values. If adding=false, subtracts stamp values.\n// Records old values to undo_log.\ninline void apply_change(int move_id, bool adding) {\n    if (move_id == -1) return;\n    const auto& mv = all_moves[move_id];\n    int m = mv.m;\n    int pos = mv.pos_idx;\n    \n    // Unroll loop manually or let compiler optimize. 9 iterations is small.\n    for (int i = 0; i < 9; ++i) {\n        int idx = move_indices[pos][i];\n        long long old_val = board[idx];\n        long long s_val = stamps[m][i];\n        \n        // Record for undo\n        undo_log[undo_ptr++] = {idx, old_val};\n        \n        // Update Score (remove old value contribution)\n        current_score -= old_val;\n        \n        // Calculate new value\n        long long new_val;\n        if (adding) {\n            new_val = old_val + s_val;\n            if (new_val >= MOD) new_val -= MOD;\n        } else {\n            new_val = old_val - s_val;\n            if (new_val < 0) new_val += MOD;\n        }\n        \n        // Apply update\n        board[idx] = new_val;\n        current_score += new_val;\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Input\n    int n_in;\n    if (!(cin >> n_in >> M >> K)) return 0;\n    \n    for (int i = 0; i < 81; ++i) cin >> initial_board[i];\n    \n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < 9; ++i) cin >> stamps[m][i];\n    }\n    \n    // Precompute moves and affected indices\n    // Positions are 0 <= p, q <= N-3 (=6). 7x7 = 49 positions.\n    int pos_cnt = 0;\n    for (int p = 0; p <= N - 3; ++p) {\n        for (int q = 0; q <= N - 3; ++q) {\n            for (int i = 0; i < 3; ++i) {\n                for (int j = 0; j < 3; ++j) {\n                    move_indices[pos_cnt][i * 3 + j] = (p + i) * N + (q + j);\n                }\n            }\n            for (int m = 0; m < M; ++m) {\n                all_moves.push_back({m, pos_cnt, p, q});\n            }\n            pos_cnt++;\n        }\n    }\n    int num_valid_moves = all_moves.size();\n    \n    // Initialize state\n    for (int i = 0; i < 81; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < 81; ++i) current_score += board[i];\n    for (int i = 0; i < K; ++i) current_ops[i] = -1;\n    \n    best_score = current_score;\n    for (int i = 0; i < K; ++i) best_ops[i] = -1;\n    \n    // Greedy Initialization\n    // Sequentially fill slots if it improves the score\n    for (int k = 0; k < K; ++k) {\n        long long best_local_score = current_score;\n        int best_move = -1;\n        \n        // Try all possible moves for this slot\n        for (int mv = 0; mv < num_valid_moves; ++mv) {\n            undo_ptr = 0;\n            long long prev_score = current_score;\n            \n            apply_change(mv, true);\n            \n            if (current_score > best_local_score) {\n                best_local_score = current_score;\n                best_move = mv;\n            }\n            \n            // Revert\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n            current_score = prev_score;\n        }\n        \n        // If we found a beneficial move, apply it permanently\n        if (best_move != -1) {\n            current_ops[k] = best_move;\n            undo_ptr = 0;\n            apply_change(best_move, true);\n        }\n    }\n    \n    // Update global best after greedy\n    if (current_score > best_score) {\n        best_score = current_score;\n        for(int i=0; i<K; ++i) best_ops[i] = current_ops[i];\n    }\n    \n    // Simulated Annealing\n    auto start_clock = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double t0 = 2e8;     // Initial temperature\n    double t1 = 1.0;     // Final temperature\n    \n    long long iter = 0;\n    double current_temp = t0;\n    \n    while (true) {\n        // Check time every 1024 iterations\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_clock).count();\n            if (elapsed > time_limit) break;\n            double progress = elapsed / time_limit;\n            current_temp = t0 * pow(t1 / t0, progress);\n        }\n        iter++;\n        \n        // Pick a random slot and a random new move (or empty)\n        int slot = rng.next_int(K);\n        int old_move = current_ops[slot];\n        // Generate new move in range [-1, num_valid_moves-1]\n        int new_move = rng.next_int(num_valid_moves + 1) - 1;\n        \n        if (old_move == new_move) continue;\n        \n        long long prev_score = current_score;\n        undo_ptr = 0;\n        \n        // Apply transition: Remove old move, Add new move\n        apply_change(old_move, false); // Remove old\n        apply_change(new_move, true);  // Add new\n        \n        long long delta = current_score - prev_score;\n        bool accept = false;\n        \n        if (delta >= 0) {\n            accept = true;\n        } else {\n            if (rng.next_double() < exp(delta / current_temp)) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_ops[slot] = new_move;\n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int i = 0; i < K; ++i) best_ops[i] = current_ops[i];\n            }\n        } else {\n            // Revert changes using log (in reverse order)\n            while (undo_ptr > 0) {\n                undo_ptr--;\n                int idx = undo_log[undo_ptr].idx;\n                current_score -= board[idx];\n                board[idx] = undo_log[undo_ptr].val;\n                current_score += board[idx];\n            }\n        }\n    }\n    \n    // Output results\n    vector<MoveDef> result_moves;\n    for (int i = 0; i < K; ++i) {\n        if (best_ops[i] != -1) {\n            result_moves.push_back(all_moves[best_ops[i]]);\n        }\n    }\n    \n    cout << result_moves.size() << \"\\n\";\n    for (const auto& mv : result_moves) {\n        cout << mv.m << \" \" << mv.p << \" \" << mv.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <deque>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Crane {\n    int id;\n    Coord pos;\n    bool holding;\n    int container_id; // -1 if none\n    bool dead;\n};\n\nstruct State {\n    int grid[N][N]; // -1 if empty, else container ID\n    deque<int> queues[N];\n    Crane cranes[N];\n    int containers_dispatched;\n    vector<string> history;\n    \n    State() {\n        for(int i=0; i<N; ++i)\n            for(int j=0; j<N; ++j)\n                grid[i][j] = -1;\n        containers_dispatched = 0;\n        history.resize(N);\n    }\n};\n\nint dist(Coord a, Coord b) {\n    return std::abs(a.r - b.r) + std::abs(a.c - b.c);\n}\n\nint main() {\n    // Optimize I/O operations\n    std::ios_base::sync_with_stdio(false);\n    std::cin.tie(NULL);\n\n    // Input\n    int n_in;\n    if (!(cin >> n_in)) return 0;\n    // N is fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Initialize State\n    State st;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            st.queues[i].push_back(A[i][j]);\n        }\n        st.cranes[i] = {i, {i, 0}, false, -1, false};\n    }\n\n    // Track next needed container for each row\n    // Dispatch gate i needs containers 5*i, 5*i+1, ... in order\n    vector<int> next_needed(N);\n    for(int i=0; i<N; ++i) next_needed[i] = i * N;\n\n    // Main simulation loop\n    for (int turn = 1; turn <= MAX_TURNS; ++turn) {\n        if (st.containers_dispatched == N*N) break;\n\n        // 1. Refill Receiving Gates (Step 1 of turn)\n        for(int i=0; i<N; ++i) {\n            if (!st.queues[i].empty()) {\n                bool empty_sq = (st.grid[i][0] == -1);\n                bool crane_holding = false;\n                // Check if any crane is holding a container at this gate (blocks refill)\n                for(int k=0; k<N; ++k) {\n                    if (!st.cranes[k].dead && st.cranes[k].pos.r == i && st.cranes[k].pos.c == 0 && st.cranes[k].holding) {\n                        crane_holding = true;\n                        break;\n                    }\n                }\n                if (empty_sq && !crane_holding) {\n                    st.grid[i][0] = st.queues[i].front();\n                    st.queues[i].pop_front();\n                }\n            }\n        }\n\n        // 2. Crane Actions (Step 2 of turn)\n        for(int i=0; i<N; ++i) {\n            char act = '.';\n            if (i > 0) {\n                // Small cranes bomb themselves on turn 1 to clear the way\n                if (turn == 1) {\n                    act = 'B';\n                    st.cranes[i].dead = true;\n                } else {\n                    act = '.';\n                }\n            } else {\n                // Large Crane (0) Logic\n                Crane& c = st.cranes[0];\n                \n                auto is_needed = [&](int id) {\n                    if (id == -1) return false;\n                    int row = id / N;\n                    // Only the exact next one is \"needed\" to enforce order\n                    if (next_needed[row] == id) return true;\n                    return false;\n                };\n                \n                char my_act = '.';\n                \n                if (c.holding) {\n                    int held = c.container_id;\n                    if (is_needed(held)) {\n                        // DELIVER: Move to dispatch gate\n                        int row = held / N;\n                        Coord dest = {row, N-1};\n                        \n                        if (c.pos == dest) {\n                            // Drop if square is empty (it will be dispatched in step 3)\n                            if (st.grid[dest.r][dest.c] == -1) {\n                                my_act = 'Q';\n                            } else {\n                                my_act = '.'; // Wait for space\n                            }\n                        } else {\n                            // Move towards destination\n                            if (c.pos.r < dest.r) my_act = 'D';\n                            else if (c.pos.r > dest.r) my_act = 'U';\n                            else if (c.pos.c < dest.c) my_act = 'R';\n                            else if (c.pos.c > dest.c) my_act = 'L';\n                        }\n                    } else {\n                        // STORE: Move garbage to buffer\n                        // Prefer columns 1, 2, 3. Column 0 is last resort.\n                        int best_dist = 999;\n                        Coord best_spot = {-1, -1};\n                        \n                        for(int c_idx : {1, 2, 3, 0}) { \n                             for(int r_idx=0; r_idx<N; ++r_idx) {\n                                 // Skip Dispatch column 4\n                                 if (st.grid[r_idx][c_idx] == -1) {\n                                     int d = dist(c.pos, {r_idx, c_idx});\n                                     if (d < best_dist) {\n                                         best_dist = d;\n                                         best_spot = {r_idx, c_idx};\n                                     }\n                                 }\n                             }\n                        }\n                        \n                        if (best_spot.r != -1) {\n                            if (c.pos == best_spot) {\n                                my_act = 'Q';\n                            } else {\n                                if (c.pos.r < best_spot.r) my_act = 'D';\n                                else if (c.pos.r > best_spot.r) my_act = 'U';\n                                else if (c.pos.c < best_spot.c) my_act = 'R';\n                                else if (c.pos.c > best_spot.c) my_act = 'L';\n                            }\n                        } else {\n                             my_act = '.'; // Stuck (should not happen with N=5)\n                        }\n                    }\n                } else {\n                    // PICK: Find something to pick\n                    int best_dist = 999;\n                    Coord target = {-1, -1};\n                    \n                    // Priority 1: Look for exposed needed items on the grid\n                    for(int r=0; r<N; ++r) {\n                        for(int c_idx=0; c_idx<N; ++c_idx) {\n                            int id = st.grid[r][c_idx];\n                            if (is_needed(id)) {\n                                // Ignore if already at correct dispatch gate (will be auto-dispatched)\n                                int needed_row = id / N;\n                                if (r == needed_row && c_idx == N-1) continue; \n                                \n                                int d = dist(c.pos, {r, c_idx});\n                                if (d < best_dist) {\n                                    best_dist = d;\n                                    target = {r, c_idx};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (target.r != -1) {\n                        // Go pick the visible needed item\n                        if (c.pos == target) {\n                            my_act = 'P';\n                        } else {\n                             if (c.pos.r < target.r) my_act = 'D';\n                             else if (c.pos.r > target.r) my_act = 'U';\n                             else if (c.pos.c < target.c) my_act = 'R';\n                             else if (c.pos.c > target.c) my_act = 'L';\n                        }\n                    } else {\n                        // Priority 2: Dig for buried needed items in queues\n                        int best_depth = 999;\n                        int target_q = -1;\n                        \n                        for(int q=0; q<N; ++q) {\n                            for(int k=0; k<(int)st.queues[q].size(); ++k) {\n                                if (is_needed(st.queues[q][k])) {\n                                    if (k < best_depth) {\n                                        best_depth = k;\n                                        target_q = q;\n                                    }\n                                    break; \n                                }\n                            }\n                        }\n                        \n                        if (target_q != -1) {\n                            // Go to the queue to clear the blocker\n                            Coord t = {target_q, 0};\n                            if (c.pos == t) {\n                                if (st.grid[t.r][t.c] != -1) my_act = 'P';\n                                else my_act = '.'; // Wait for refill\n                            } else {\n                                 if (c.pos.r < t.r) my_act = 'D';\n                                 else if (c.pos.r > t.r) my_act = 'U';\n                                 else if (c.pos.c < t.c) my_act = 'R';\n                                 else if (c.pos.c > t.c) my_act = 'L';\n                            }\n                        } else {\n                            my_act = '.';\n                        }\n                    }\n                }\n                \n                act = my_act;\n                \n                // Update Crane 0 state based on action\n                if (act == 'U') st.cranes[0].pos.r--;\n                else if (act == 'D') st.cranes[0].pos.r++;\n                else if (act == 'L') st.cranes[0].pos.c--;\n                else if (act == 'R') st.cranes[0].pos.c++;\n                else if (act == 'P') {\n                    st.cranes[0].holding = true;\n                    st.cranes[0].container_id = st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c];\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = -1;\n                }\n                else if (act == 'Q') {\n                    st.cranes[0].holding = false;\n                    st.grid[st.cranes[0].pos.r][st.cranes[0].pos.c] = st.cranes[0].container_id;\n                    st.cranes[0].container_id = -1;\n                }\n            }\n            st.history[i] += act;\n        }\n        \n        // 3. Dispatch (Step 3 of turn)\n        for(int i=0; i<N; ++i) {\n            int cid = st.grid[i][N-1];\n            if (cid != -1) {\n                // Item at dispatch gate is removed from grid\n                st.grid[i][N-1] = -1;\n                st.containers_dispatched++;\n                \n                // Update needed index if correct one was dispatched\n                int row = cid / N;\n                if (row == i && cid == next_needed[i]) {\n                    next_needed[i]++;\n                }\n            }\n        }\n    }\n\n    // Output results\n    for(int i=0; i<N; ++i) {\n        cout << st.history[i] << endl;\n    }\n\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/mincostflow>\n#include <chrono>\n#include <random>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Directions: 0:U, 1:D, 2:L, 3:R\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint N = 20;\nlong long grid_h[20][20];\n\n// Job represents a single unit of transport derived from flow\nstruct Job {\n    int id;\n    int start_node;\n    int end_node;\n    long long amount;\n};\n\nstruct Result {\n    long long cost;\n    vector<string> ops;\n};\n\n// Configuration for a single randomized iteration\nstruct SearchParams {\n    double mcf_noise_factor; // Magnitude of random noise in edge costs\n    \n    // Heuristic coefficients\n    double dist_weight;      // Weight for movement cost\n    double drop_base;        // Constant bonus for dropping\n    double drop_mult;        // Bonus per unit dropped\n    double pick_base;        // Constant bonus/penalty for picking\n    double pick_mult;        // Bonus/penalty per unit picked\n};\n\n// Global random engine\nmt19937 rng(12345);\n\n// Manhattan distance\ninline int dist(int u, int v) {\n    int r1 = u / N, c1 = u % N;\n    int r2 = v / N, c2 = v % N;\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Helper for flow decomposition\nstruct EdgeInfo {\n    int to;\n    long long flow;\n};\n\nResult solve_iteration(const SearchParams& p) {\n    // 1. Construct Min-Cost Flow Graph with Noisy Costs\n    mcf_graph<int, long long> g(N * N + 2);\n    int S = N * N;\n    int T = N * N + 1;\n    long long BASE_COST = 1000; \n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = i * N + j;\n            // Source/Sink connections\n            if (grid_h[i][j] > 0) {\n                g.add_edge(S, u, grid_h[i][j], 0);\n            } else if (grid_h[i][j] < 0) {\n                g.add_edge(u, T, -grid_h[i][j], 0);\n            }\n            \n            // Grid connections\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int v = ni * N + nj;\n                    long long noise = 0;\n                    if (p.mcf_noise_factor > 1e-9) {\n                        noise = uniform_int_distribution<long long>(0, (long long)(p.mcf_noise_factor * 100))(rng);\n                    }\n                    g.add_edge(u, v, 1e9, BASE_COST + noise);\n                }\n            }\n        }\n    }\n\n    g.flow(S, T);\n    \n    // 2. Decompose Flow into Jobs\n    auto edges = g.edges();\n    vector<vector<EdgeInfo>> flow_adj(N*N+2);\n    for(const auto& e : edges) {\n        if(e.flow > 0) {\n             // Filter relevant edges for path reconstruction\n             if (e.from == S || e.to == T || (e.from < N*N && e.to < N*N)) {\n                 flow_adj[e.from].push_back({e.to, e.flow});\n             }\n        }\n    }\n\n    vector<Job> jobs;\n    int job_counter = 0;\n    \n    while(true) {\n        queue<int> q;\n        q.push(S);\n        vector<int> parent(N*N+2, -1);\n        vector<int> edge_index(N*N+2, -1);\n        parent[S] = S;\n        \n        bool found = false;\n        while(!q.empty()){\n            int u = q.front(); q.pop();\n            if(u == T) { found = true; break; }\n            \n            // Randomize traversal order for diverse path decomposition\n            if (!flow_adj[u].empty()) {\n                for (int i = flow_adj[u].size() - 1; i > 0; i--) {\n                    int j = uniform_int_distribution<int>(0, i)(rng);\n                    swap(flow_adj[u][i], flow_adj[u][j]);\n                }\n                for(int i=0; i<(int)flow_adj[u].size(); ++i) {\n                    if(flow_adj[u][i].flow > 0 && parent[flow_adj[u][i].to] == -1) {\n                        parent[flow_adj[u][i].to] = u;\n                        edge_index[flow_adj[u][i].to] = i;\n                        q.push(flow_adj[u][i].to);\n                    }\n                }\n            }\n        }\n        \n        if(!found) break;\n        \n        // Extract path and capacity\n        long long path_cap = 1e18;\n        int curr = T;\n        while(curr != S) {\n            int pr = parent[curr];\n            int idx = edge_index[curr];\n            path_cap = min(path_cap, flow_adj[pr][idx].flow);\n            curr = pr;\n        }\n        \n        int u_start = -1, u_end = -1;\n        curr = T;\n        while(curr != S) {\n            int pr = parent[curr];\n            int idx = edge_index[curr];\n            flow_adj[pr][idx].flow -= path_cap;\n            if(curr == T) u_end = pr;\n            if(pr == S) u_start = curr;\n            curr = pr;\n        }\n        jobs.push_back({job_counter++, u_start, u_end, path_cap});\n    }\n    \n    // 3. Greedy Simulation\n    int truck_r = 0, truck_c = 0;\n    long long truck_load = 0;\n    vector<string> ops;\n    long long total_cost = 0;\n    \n    vector<bool> is_picked(jobs.size(), false);\n    vector<bool> is_done(jobs.size(), false);\n    int completed_count = 0;\n    int step_limit = 200000; // Safety break\n    \n    while(completed_count < jobs.size() && ops.size() < step_limit) {\n        int u = truck_r * N + truck_c;\n        \n        // Opportunistic Unload\n        for(auto &j : jobs) {\n            if(is_picked[j.id] && !is_done[j.id] && j.end_node == u) {\n                ops.push_back(\"-\" + to_string(j.amount));\n                total_cost += j.amount;\n                truck_load -= j.amount;\n                is_done[j.id] = true;\n                completed_count++;\n            }\n        }\n        \n        // Opportunistic Load\n        for(auto &j : jobs) {\n            if(!is_picked[j.id] && j.start_node == u) {\n                ops.push_back(\"+\" + to_string(j.amount));\n                total_cost += j.amount;\n                truck_load += j.amount;\n                is_picked[j.id] = true;\n            }\n        }\n        \n        if(completed_count == jobs.size()) break;\n        \n        // Select Next Target based on Score\n        int best_target = -1;\n        double best_score = 1e18;\n        \n        for(const auto &j : jobs) {\n            if(is_done[j.id]) continue;\n            \n            int target = -1;\n            bool is_drop = false;\n            \n            if(is_picked[j.id]) {\n                target = j.end_node;\n                is_drop = true;\n            } else {\n                target = j.start_node;\n                is_drop = false;\n            }\n            \n            int d = dist(u, target);\n            \n            // Cost component: Moving there\n            double move_cost = d * (100.0 + truck_load);\n            double score = p.dist_weight * move_cost;\n            \n            // Heuristic incentives\n            if(is_drop) {\n                score += p.drop_base;\n                score += p.drop_mult * j.amount;\n            } else {\n                score += p.pick_base;\n                score += p.pick_mult * j.amount;\n            }\n            \n            if(score < best_score) {\n                best_score = score;\n                best_target = target;\n            }\n        }\n        \n        // Move one step\n        if(best_target != -1) {\n            int tr = best_target / N;\n            int tc = best_target % N;\n            \n            vector<int> dirs;\n            if(tr < truck_r) dirs.push_back(0);\n            if(tr > truck_r) dirs.push_back(1);\n            if(tc < truck_c) dirs.push_back(2);\n            if(tc > truck_c) dirs.push_back(3);\n            \n            if(!dirs.empty()) {\n                // Randomize valid moves to avoid bias\n                int dir = dirs[uniform_int_distribution<int>(0, dirs.size()-1)(rng)];\n                ops.push_back(string(1, dir_char[dir]));\n                total_cost += (100 + truck_load);\n                truck_r += dr[dir];\n                truck_c += dc[dir];\n            }\n        } else {\n            break;\n        }\n    }\n    \n    return {total_cost, ops};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (cin >> N) {}\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> grid_h[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95; // Maximize usage of 2.0s\n    \n    long long best_cost = -1;\n    vector<string> best_ops;\n    \n    // Loop until time limit\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> diff = now - start_time;\n        if(diff.count() > time_limit) break;\n        \n        // Generate random parameters for this iteration\n        SearchParams p;\n        p.mcf_noise_factor = uniform_real_distribution<double>(0.0, 15.0)(rng);\n        p.dist_weight = 1.0;\n        \n        // Drop incentives: usually negative (reduces score -> preferred)\n        p.drop_base = uniform_real_distribution<double>(-600.0, 0.0)(rng);\n        p.drop_mult = uniform_real_distribution<double>(-25.0, -5.0)(rng);\n        \n        // Pickup incentives: mix of positive (penalty) and negative (bonus)\n        // Penalty encourages deferring heavy loads. Bonus encourages clustering.\n        p.pick_base = uniform_real_distribution<double>(-200.0, 200.0)(rng);\n        p.pick_mult = uniform_real_distribution<double>(-5.0, 15.0)(rng);\n        \n        Result res = solve_iteration(p);\n        \n        if(best_cost == -1 || res.cost < best_cost) {\n            best_cost = res.cost;\n            best_ops = res.ops;\n        }\n    }\n    \n    for (const auto& s : best_ops) cout << s << \"\\n\";\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// --- Global Constants & Parameters ---\nint N, M, T;\nint SEED_COUNT;     // 2*N*(N-1)\nint GRID_SIZE;      // N*N\n\n// Selection parameters\n// K_MIN: Priority to strictly keep at least this many carriers of the max gene.\n// K_TARGET: Soft target to keep this many carriers for redundancy.\nconst int K_MIN = 1; \nconst int K_TARGET = 5;\n\n// Scoring weights for selection\nconst long long BONUS_NOT_COVERED = 1e12; // Critical importance\nconst long long BONUS_LOW_COVERAGE = 1e7; // High importance\n\n// Random Engine\nmt19937 rng(12345);\n\n// --- Structures ---\nstruct Seed {\n    int id;\n    vector<int> x;\n    int total_val;\n};\n\n// --- Timing Helper ---\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool check() {\n        return elapsed() < limit;\n    }\n};\n\n// --- Grid & Adjacency ---\nvector<vector<int>> adj;\nvector<int> degrees;\n\nvoid init_grid() {\n    GRID_SIZE = N * N;\n    adj.assign(GRID_SIZE, vector<int>());\n    degrees.assign(GRID_SIZE, 0);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // Neighbor Down\n            if (r + 1 < N) {\n                int v = (r + 1) * N + c;\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            // Neighbor Right\n            if (c + 1 < N) {\n                int v = r * N + (c + 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n        }\n    }\n    for(int i=0; i<GRID_SIZE; ++i) degrees[i] = adj[i].size();\n}\n\n// --- Logic ---\n\n// Calculate Potential of a pair (u, v)\n// maximizing sum of maximums corresponds to maximizing the theoretical best offspring.\ninline int calc_potential(const Seed& a, const Seed& b) {\n    int score = 0;\n    for (int k = 0; k < M; ++k) {\n        score += (a.x[k] > b.x[k]) ? a.x[k] : b.x[k];\n    }\n    return score;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> T)) return 0;\n    SEED_COUNT = 2 * N * (N - 1);\n    init_grid();\n\n    vector<Seed> seeds(SEED_COUNT);\n\n    // Reading Initial Input\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        seeds[i].id = i;\n        seeds[i].x.resize(M);\n        seeds[i].total_val = 0;\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i].x[j];\n            seeds[i].total_val += seeds[i].x[j];\n        }\n    }\n\n    // Pre-allocate vectors to avoid reallocation in loop\n    vector<int> global_max(M);\n    vector<Seed> selected_seeds;\n    selected_seeds.reserve(GRID_SIZE);\n    vector<bool> used(SEED_COUNT);\n    vector<int> current_counts(M);\n    \n    // Sort grid nodes by degree for heuristic initialization\n    vector<pair<int, int>> node_degrees(GRID_SIZE);\n    for(int i=0; i<GRID_SIZE; ++i) node_degrees[i] = { degrees[i], i };\n    sort(node_degrees.rbegin(), node_degrees.rend());\n\n    for (int t = 0; t < T; ++t) {\n        // 1. Identify global maximums for current generation\n        fill(global_max.begin(), global_max.end(), -1);\n        for(const auto& s : seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] > global_max[j]) global_max[j] = s.x[j];\n            }\n        }\n\n        // 2. Iterative Greedy Selection\n        selected_seeds.clear();\n        fill(used.begin(), used.end(), false);\n        fill(current_counts.begin(), current_counts.end(), 0);\n\n        // We select exactly GRID_SIZE (36) seeds\n        for(int step = 0; step < GRID_SIZE; ++step) {\n            int best_idx = -1;\n            long long best_score = -1;\n\n            for(int k = 0; k < SEED_COUNT; ++k) {\n                if(used[k]) continue;\n\n                long long score = seeds[k].total_val; \n\n                // Dynamic Bonus calculation\n                for(int j = 0; j < M; ++j) {\n                    if(seeds[k].x[j] == global_max[j]) {\n                        if(current_counts[j] < K_MIN) {\n                            score += BONUS_NOT_COVERED;\n                        } else if(current_counts[j] < K_TARGET) {\n                            score += BONUS_LOW_COVERAGE;\n                        }\n                    }\n                }\n\n                if(score > best_score) {\n                    best_score = score;\n                    best_idx = k;\n                }\n            }\n\n            // Commit best seed\n            used[best_idx] = true;\n            selected_seeds.push_back(seeds[best_idx]);\n            for(int j = 0; j < M; ++j) {\n                if(seeds[best_idx].x[j] == global_max[j]) {\n                    current_counts[j]++;\n                }\n            }\n        }\n\n        // 3. Placement Initialization\n        // Map best seeds (by total_val) to nodes with highest degrees.\n        vector<int> p(GRID_SIZE);\n        iota(p.begin(), p.end(), 0);\n        sort(p.begin(), p.end(), [&](int a, int b){\n            return selected_seeds[a].total_val > selected_seeds[b].total_val;\n        });\n\n        vector<int> layout(GRID_SIZE);\n        for(int i=0; i<GRID_SIZE; ++i) {\n            layout[node_degrees[i].second] = p[i];\n        }\n\n        // 4. Precompute Edge Potentials\n        // potentials[i][j] is the potential if selected_seed[i] and selected_seed[j] are adjacent\n        vector<vector<int>> potentials(GRID_SIZE, vector<int>(GRID_SIZE));\n        for(int i=0; i<GRID_SIZE; ++i) {\n            for(int j=i+1; j<GRID_SIZE; ++j) {\n                potentials[i][j] = potentials[j][i] = calc_potential(selected_seeds[i], selected_seeds[j]);\n            }\n        }\n\n        // Calculate initial score of layout\n        long long current_score = 0;\n        for (int u = 0; u < GRID_SIZE; ++u) {\n            for (int v : adj[u]) {\n                if (u < v) {\n                    current_score += potentials[layout[u]][layout[v]];\n                }\n            }\n        }\n\n        long long best_score = current_score;\n        vector<int> best_layout = layout;\n\n        // 5. Simulated Annealing\n        // Time allowed per turn ~ 0.18s (Total 2.0s for T=10)\n        Timer timer(0.18);\n        \n        double t0 = 200.0;\n        double t1 = 0.01;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            // Check timer every 128 iterations\n            if ((iter & 127) == 0) {\n                if (!timer.check()) break;\n            }\n\n            double time_ratio = timer.elapsed() / 0.18;\n            double temp = t0 * pow(t1/t0, time_ratio);\n\n            // Pick two distinct cells to swap\n            int c1 = rng() % GRID_SIZE;\n            int c2 = rng() % GRID_SIZE;\n            while (c1 == c2) {\n                c2 = rng() % GRID_SIZE;\n            }\n\n            int s1 = layout[c1];\n            int s2 = layout[c2];\n\n            // Calculate score change (delta)\n            long long delta = 0;\n            \n            // Subtract edges of c1 with old seed s1, add with new seed s2\n            for (int u : adj[c1]) {\n                if (u != c2) {\n                    delta -= potentials[s1][layout[u]];\n                    delta += potentials[s2][layout[u]];\n                }\n            }\n            // Subtract edges of c2 with old seed s2, add with new seed s1\n            for (int u : adj[c2]) {\n                if (u != c1) {\n                    delta -= potentials[s2][layout[u]];\n                    delta += potentials[s1][layout[u]];\n                }\n            }\n            // Edge between c1 and c2 (if exists) remains s1-s2 vs s2-s1, potential is symmetric.\n\n            if (delta >= 0 || bernoulli_distribution(exp(delta / temp))(rng)) {\n                swap(layout[c1], layout[c2]);\n                current_score += delta;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_layout = layout;\n                }\n            }\n        }\n\n        // 6. Output Result\n        vector<vector<int>> output_grid(N, vector<int>(N));\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                int cell = r*N + c;\n                int seed_idx = best_layout[cell];\n                output_grid[r][c] = selected_seeds[seed_idx].id;\n            }\n        }\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cout << output_grid[r][c] << (c == N-1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        // 7. Read New Seeds\n        for(int i=0; i<SEED_COUNT; ++i) {\n            seeds[i].id = i; \n            seeds[i].total_val = 0;\n            for(int j=0; j<M; ++j) {\n                cin >> seeds[i].x[j];\n                seeds[i].total_val += seeds[i].x[j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <map>\n#include <tuple>\n\nusing namespace std;\n\n// --------------------------------------------------------\n// Constants & Globals\n// --------------------------------------------------------\nconst int MAX_N = 35;\nconst int DR[] = {0, 1, 0, -1};\nconst int DC[] = {1, 0, -1, 0};\nconst char MOVE_CHARS[] = {'R', 'D', 'L', 'U'};\n\nint N, M, V;\nint s_grid[MAX_N][MAX_N];\nint t_grid[MAX_N][MAX_N];\n// To track if a location becomes a target after an item is removed\nint t_original[MAX_N][MAX_N]; \n\nint root_r, root_c;\nint turns = 0;\nint delivered_count = 0;\n\nstruct Leaf {\n    int id;\n    int len;\n    int dir; // 0:R, 1:D, 2:L, 3:U\n    bool holding;\n};\nvector<Leaf> leaves;\n\nstruct Task {\n    int leaf_idx;\n    int r, c; // Target coordinates\n    int type; // 0: Pick, 1: Drop\n    bool valid;\n};\n\n// Currently locked primary task\nTask current_task = {-1, -1, -1, -1, false};\n\n// --------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------\n\n// Calculate the coordinate of a leaf's tip given root pos and leaf config\ninline pair<int, int> get_leaf_pos(int rr, int rc, int len, int dir) {\n    return {rr + DR[dir] * len, rc + DC[dir] * len};\n}\n\n// Calculate rotation difference (0, 1, 2, 3)\n// 1=Right(90), 3=Left(90), 2=180\ninline int get_rot_diff(int current, int target) {\n    return (target - current + 4) % 4;\n}\n\n// Get the rotation command char for a single step to minimize turns\nchar get_rot_cmd(int diff) {\n    if (diff == 0) return '.';\n    if (diff == 1) return 'R';\n    if (diff == 3) return 'L';\n    if (diff == 2) return 'R'; // 180 degrees -> start with R\n    return '.';\n}\n\n// Calculate cost in turns to achieve rotation\ninline int get_rot_cost(int diff) {\n    if (diff == 0) return 0;\n    if (diff == 1 || diff == 3) return 1;\n    return 2; // 180 degrees takes 2 turns\n}\n\n// --------------------------------------------------------\n// Main\n// --------------------------------------------------------\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> V)) return 0;\n    \n    vector<string> s_in(N), t_in(N);\n    for(int i=0; i<N; ++i) cin >> s_in[i];\n    for(int i=0; i<N; ++i) cin >> t_in[i];\n\n    // Initialize Grids\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            bool is_s = (s_in[i][j] == '1');\n            bool is_t = (t_in[i][j] == '1');\n            t_original[i][j] = is_t ? 1 : 0;\n            \n            if (is_s && is_t) {\n                delivered_count++;\n                s_grid[i][j] = 0;\n                t_grid[i][j] = 0;\n            } else {\n                s_grid[i][j] = is_s ? 1 : 0;\n                t_grid[i][j] = is_t ? 1 : 0;\n            }\n        }\n    }\n    \n    // 1. Arm Design\n    // Strategy: Star graph with cyclic lengths 1..~N/2.\n    // This creates a diverse set of tools to reach targets at various distances.\n    cout << V << endl;\n    int max_len = max(1, (N + 1) / 2); \n    for(int i=1; i<V; ++i) {\n        int len = (i - 1) % max_len + 1; \n        cout << \"0 \" << len << endl;\n    }\n    \n    // Initial position: Center\n    root_r = N/2; \n    root_c = N/2;\n    cout << root_r << \" \" << root_c << endl;\n\n    // Initialize Leaf State\n    leaves.resize(V-1);\n    for(int i=0; i<V-1; ++i) {\n        leaves[i].id = i;\n        leaves[i].len = (i) % max_len + 1;\n        leaves[i].dir = 0;\n        leaves[i].holding = false;\n    }\n\n    // Main Simulation Loop\n    while (delivered_count < M && turns < 100000) {\n        \n        // -------------------------------------------------\n        // Step 1: Identification of Targets\n        // -------------------------------------------------\n        vector<pair<int,int>> active_picks;\n        vector<pair<int,int>> active_drops;\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                if (s_grid[r][c]) active_picks.push_back({r, c});\n                if (t_grid[r][c]) active_drops.push_back({r, c});\n            }\n        }\n\n        if (active_picks.empty() && active_drops.empty()) break;\n\n        // -------------------------------------------------\n        // Step 2: Task Selection (Hysteresis & Heuristics)\n        // -------------------------------------------------\n        \n        // Validate current locked task\n        bool maintain_lock = false;\n        if (current_task.valid) {\n            if (current_task.type == 0 && s_grid[current_task.r][current_task.c] == 0) current_task.valid = false;\n            else if (current_task.type == 1 && t_grid[current_task.r][current_task.c] == 0) current_task.valid = false;\n            else if (current_task.type == 0 && leaves[current_task.leaf_idx].holding) current_task.valid = false; \n            else if (current_task.type == 1 && !leaves[current_task.leaf_idx].holding) current_task.valid = false;\n            \n            if (current_task.valid) maintain_lock = true;\n        }\n\n        double best_cost = 1e9;\n        int best_root_r = -1, best_root_c = -1;\n        int best_leaf_idx = -1;\n        int best_leaf_dir = -1;\n        int best_type = -1;\n        int best_tr = -1, best_tc = -1;\n\n        // Heuristic function\n        auto evaluate_task = [&](int l_idx, int tr, int tc, bool holding) -> tuple<double, int, int, int> {\n             double min_c = 1e9;\n             int best_d = -1, br = -1, bc = -1;\n\n             for(int d=0; d<4; ++d) {\n                 int rr = tr - DR[d] * leaves[l_idx].len;\n                 int rc = tc - DC[d] * leaves[l_idx].len;\n                 if(rr<0 || rr>=N || rc<0 || rc>=N) continue;\n                 \n                 // Turns to move root\n                 int mv = abs(rr - root_r) + abs(rc - root_c);\n                 // Turns to rotate leaf\n                 int rot = get_rot_cost(get_rot_diff(leaves[l_idx].dir, d));\n                 \n                 // Since they happen simultaneously, max is the limiting factor\n                 double c = max(mv, rot);\n                 \n                 // Bias adjustments\n                 if(holding) c -= 0.6; // Slight preference to Drop to free up capacity\n                 \n                 // Hysteresis: Stick to locked task unless significant gain\n                 if(maintain_lock && l_idx == current_task.leaf_idx && tr == current_task.r && tc == current_task.c) {\n                     c -= 2.0; \n                 }\n\n                 if(c < min_c) {\n                     min_c = c;\n                     best_d = d;\n                     br = rr;\n                     bc = rc;\n                 }\n             }\n             return {min_c, best_d, br, bc};\n        };\n\n        // Search for best task\n        for(int i=0; i<V-1; ++i) {\n            const auto& targets = leaves[i].holding ? active_drops : active_picks;\n            // Optimization: If targets are many, maybe check nearest ones? \n            // For N=30, iterating all is ~450 * 15 = 6750 ops, very fast.\n            for(const auto& t : targets) {\n                auto [c, d, rr, rc] = evaluate_task(i, t.first, t.second, leaves[i].holding);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_leaf_idx = i;\n                    best_leaf_dir = d;\n                    best_root_r = rr;\n                    best_root_c = rc;\n                    best_type = leaves[i].holding ? 1 : 0;\n                    best_tr = t.first;\n                    best_tc = t.second;\n                }\n            }\n        }\n\n        current_task = {best_leaf_idx, best_tr, best_tc, best_type, true};\n\n        // -------------------------------------------------\n        // Step 3: Determine Root Move\n        // -------------------------------------------------\n        int move_dir = -1;\n        int next_rr = root_r, next_rc = root_c;\n        \n        if (best_root_r != -1) {\n            if (best_root_r > root_r) move_dir = 1;\n            else if (best_root_r < root_r) move_dir = 3;\n            else if (best_root_c > root_c) move_dir = 0;\n            else if (best_root_c < root_c) move_dir = 2;\n            \n            if (move_dir != -1) {\n                next_rr += DR[move_dir];\n                next_rc += DC[move_dir];\n            }\n        }\n\n        // -------------------------------------------------\n        // Step 4: Determine Leaf Actions (Simultaneous)\n        // -------------------------------------------------\n        vector<char> rot_cmds(V-1, '.');\n        vector<char> act_cmds(V, '.');\n        vector<bool> leaf_busy(V-1, false);\n        vector<pair<int,int>> action_locs;\n\n        // Order leaves for opportunistic checks (Drop > Pick)\n        vector<int> leaf_order(V-1);\n        for(int i=0; i<V-1; ++i) leaf_order[i] = i;\n        sort(leaf_order.begin(), leaf_order.end(), [&](int a, int b){\n            return leaves[a].holding > leaves[b].holding;\n        });\n\n        // A. Opportunistic Actions at next_root\n        for(int i : leaf_order) {\n            int best_opp_dir = -1;\n            int best_opp_type = -1;\n            \n            for(int d=0; d<4; ++d) {\n                int diff = get_rot_diff(leaves[i].dir, d);\n                if (diff == 2) continue; // Too far to rotate in 1 turn\n\n                auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, d);\n                if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n\n                // Collision check\n                bool conflict = false;\n                for(auto& loc : action_locs) if(loc.first == tr && loc.second == tc) conflict = true;\n                if (conflict) continue;\n\n                if (leaves[i].holding) {\n                    if (t_grid[tr][tc]) {\n                        best_opp_dir = d;\n                        best_opp_type = 1;\n                        break; // Drop\n                    }\n                } else {\n                    if (s_grid[tr][tc]) {\n                        best_opp_dir = d;\n                        best_opp_type = 0;\n                        break; // Pick\n                    }\n                }\n            }\n\n            if (best_opp_dir != -1) {\n                leaf_busy[i] = true;\n                rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, best_opp_dir));\n                act_cmds[i+1] = 'P';\n                action_locs.push_back(get_leaf_pos(next_rr, next_rc, leaves[i].len, best_opp_dir));\n            }\n        }\n\n        // B. Rotate Primary Leaf (if not busy)\n        if (best_leaf_idx != -1 && !leaf_busy[best_leaf_idx]) {\n            rot_cmds[best_leaf_idx] = get_rot_cmd(get_rot_diff(leaves[best_leaf_idx].dir, best_leaf_dir));\n        }\n\n        // C. Pre-rotate Idle Leaves (Lookahead)\n        // Align idle leaves towards useful targets relative to the *destination* root position.\n        // This prepares them to be useful as soon as the arm arrives.\n        int target_root_r = (best_root_r == -1) ? next_rr : best_root_r;\n        int target_root_c = (best_root_c == -1) ? next_rc : best_root_c;\n\n        for(int i=0; i<V-1; ++i) {\n            if (leaf_busy[i] || i == best_leaf_idx) continue;\n\n            const auto& targets = leaves[i].holding ? active_drops : active_picks;\n            int min_dist = 1e9;\n            int pre_rot_dir = -1;\n\n            // Find nearest target relative to target_root_r/c\n            for(const auto& t : targets) {\n                for(int d=0; d<4; ++d) {\n                    // Leaf tip position if leaf is at dir d relative to target_root\n                    int lr = target_root_r + DR[d] * leaves[i].len;\n                    int lc = target_root_c + DC[d] * leaves[i].len;\n                    \n                    int d_man = abs(lr - t.first) + abs(lc - t.second);\n                    if (d_man < min_dist) {\n                        min_dist = d_man;\n                        pre_rot_dir = d;\n                    }\n                }\n                if (min_dist == 0) break;\n            }\n\n            if (pre_rot_dir != -1) {\n                rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, pre_rot_dir));\n            }\n        }\n\n        // -------------------------------------------------\n        // Step 5: Execute & Update State\n        // -------------------------------------------------\n        cout << (move_dir == -1 ? '.' : MOVE_CHARS[move_dir]);\n        for(char c : rot_cmds) cout << c;\n        for(int k=0; k<V; ++k) cout << act_cmds[k];\n        cout << \"\\n\";\n\n        // Update Root\n        root_r = next_rr;\n        root_c = next_rc;\n        \n        // Update Leaf Directions\n        for(int i=0; i<V-1; ++i) {\n            if (rot_cmds[i] == 'R') leaves[i].dir = (leaves[i].dir + 1) % 4;\n            else if (rot_cmds[i] == 'L') leaves[i].dir = (leaves[i].dir + 3) % 4;\n        }\n\n        // Apply Actions (Grid Updates)\n        for(int i=0; i<V-1; ++i) {\n            if (act_cmds[i+1] == 'P') {\n                // Calculate actual tip pos based on new root/dir\n                auto [tr, tc] = get_leaf_pos(root_r, root_c, leaves[i].len, leaves[i].dir);\n                \n                if (leaves[i].holding) {\n                    // Drop\n                    if (tr >= 0 && tr < N && tc >= 0 && tc < N && t_grid[tr][tc]) {\n                        t_grid[tr][tc] = 0;\n                        delivered_count++;\n                        leaves[i].holding = false;\n                    }\n                } else {\n                    // Pick\n                    if (tr >= 0 && tr < N && tc >= 0 && tc < N && s_grid[tr][tc]) {\n                        s_grid[tr][tc] = 0;\n                        // If the picked spot is also a target location, mark it as needing a drop\n                        if (t_original[tr][tc]) t_grid[tr][tc] = 1; \n                        leaves[i].holding = true;\n                    }\n                }\n            }\n        }\n\n        turns++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <set>\n#include <queue>\n#include <chrono>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst long long MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\nconst double TIME_LIMIT = 1.95; \n\nstruct Point {\n    int x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\n// Global timing\nlong long start_time;\nlong long get_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(\n        std::chrono::steady_clock::now().time_since_epoch()).count();\n}\n\ntypedef vector<Point> Polygon;\n\n// Geometry Utils: Check if point is inside polygon (Ray Casting)\nbool is_inside(const Polygon& poly, const Point& p) {\n    bool inside = false;\n    size_t n = poly.size();\n    for (size_t i = 0; i < n; ++i) {\n        const Point& p1 = poly[i];\n        const Point& p2 = poly[(i + 1) % n];\n        \n        // Check if point lies exactly on a segment\n        if (p1.x == p2.x) { // Vertical segment\n            if (p1.x == p.x && p.y >= min(p1.y, p2.y) && p.y <= max(p1.y, p2.y)) return true;\n        } else { // Horizontal segment\n            if (p1.y == p.y && p.x >= min(p1.x, p2.x) && p.x <= max(p1.x, p2.x)) return true;\n        }\n\n        // Ray casting for interior check\n        if ((p1.y > p.y) != (p2.y > p.y)) {\n            double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x;\n            if (p.x < intersect_x) inside = !inside;\n        }\n    }\n    return inside;\n}\n\n// Calculate exact score: Mackerels - Sardines\nint raw_score(const Polygon& poly) {\n    if (poly.empty()) return 0;\n    int m = 0, s = 0;\n    int min_x = MAX_COORD, max_x = 0, min_y = MAX_COORD, max_y = 0;\n    for (const auto& p : poly) {\n        min_x = min(min_x, p.x);\n        max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y);\n        max_y = max(max_y, p.y);\n    }\n    \n    for (const auto& p : mackerels) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) m++;\n    }\n    for (const auto& p : sardines) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) s++;\n    }\n    return m - s;\n}\n\nlong long perimeter(const Polygon& poly) {\n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        perim += abs(poly[i].x - poly[(i + 1) % poly.size()].x) + abs(poly[i].y - poly[(i + 1) % poly.size()].y);\n    }\n    return perim;\n}\n\nstruct GridSolver {\n    int cell_size;\n    int offset_x, offset_y;\n    int GX, GY;\n    vector<vector<int>> grid_score;\n    vector<vector<bool>> active;\n    \n    GridSolver(int cs, int ox, int oy) : cell_size(cs), offset_x(ox), offset_y(oy) {\n        // Determine grid dimensions to cover the range\n        GX = (MAX_COORD + offset_x) / cell_size + 2; \n        GY = (MAX_COORD + offset_y) / cell_size + 2;\n        grid_score.assign(GX, vector<int>(GY, 0));\n        active.assign(GX, vector<bool>(GY, false));\n    }\n    \n    void build() {\n        for (const auto& p : mackerels) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]++;\n        }\n        for (const auto& p : sardines) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]--;\n        }\n        \n        // Mark cells with positive score as active, keeping within bounds\n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                long long xL = (long long)x * cell_size - offset_x;\n                long long xR = (long long)(x + 1) * cell_size - offset_x;\n                long long yL = (long long)y * cell_size - offset_y;\n                long long yR = (long long)(y + 1) * cell_size - offset_y;\n                \n                // Only activate if the cell is strictly inside the coordinate space slightly\n                // or at least overlaps significantly. The problem requires coords 0-100000.\n                // We ensure our vertices are clamped later, but selecting cells completely outside is useless.\n                if (xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                     if (grid_score[x][y] > 0) active[x][y] = true;\n                }\n            }\n        }\n    }\n    \n    // Fix \"checkerboard\" patterns that cause self-intersecting boundaries\n    void repair_topology() {\n        bool changed = true;\n        int loops = 0;\n        while(changed && loops < 5) { // Limit loops for safety\n            changed = false;\n            loops++;\n            for(int x=0; x<GX-1; ++x) {\n                for(int y=0; y<GY-1; ++y) {\n                    bool tl = active[x][y+1];     // Top-Left\n                    bool tr = active[x+1][y+1];   // Top-Right\n                    bool bl = active[x][y];       // Bottom-Left\n                    bool br = active[x+1][y];     // Bottom-Right\n                    \n                    // Case: Bottom-Left and Top-Right active, others inactive\n                    if (bl && tr && !tl && !br) {\n                        // Fill one gap. Prefer the one with better score.\n                        if (grid_score[x][y+1] >= grid_score[x+1][y]) active[x][y+1] = true;\n                        else active[x+1][y] = true;\n                        changed = true;\n                    }\n                    // Case: Top-Left and Bottom-Right active, others inactive\n                    else if (tl && br && !tr && !bl) {\n                        if (grid_score[x+1][y+1] >= grid_score[x][y]) active[x+1][y+1] = true;\n                        else active[x][y] = true;\n                        changed = true;\n                    }\n                }\n            }\n        }\n    }\n\n    Polygon solve() {\n        repair_topology();\n        \n        vector<vector<bool>> visited(GX, vector<bool>(GY, false));\n        Polygon best_poly;\n        int best_est_score = -1e9;\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (active[x][y] && !visited[x][y]) {\n                    // BFS to find connected component\n                    vector<pair<int,int>> comp;\n                    queue<pair<int,int>> q;\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    int current_est_score = 0;\n                    \n                    while(!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        comp.push_back({cx, cy});\n                        current_est_score += grid_score[cx][cy];\n                        \n                        int dx[] = {1, -1, 0, 0};\n                        int dy[] = {0, 0, 1, -1};\n                        for(int k=0; k<4; ++k) {\n                            int nx = cx + dx[k];\n                            int ny = cy + dy[k];\n                            if (nx>=0 && nx<GX && ny>=0 && ny<GY && active[nx][ny] && !visited[nx][ny]) {\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    \n                    if (comp.empty()) continue;\n                    // Heuristic: Skip components with non-positive total score if we have better\n                    if (current_est_score <= 0 && current_est_score < best_est_score) continue;\n                    \n                    // Trace Boundary\n                    set<pair<int,int>> cell_set(comp.begin(), comp.end());\n                    Polygon p = trace(cell_set);\n                    \n                    // Check Constraints\n                    if (p.size() >= 4 && p.size() <= MAX_VERTICES && perimeter(p) <= MAX_PERIMETER) {\n                        bool ok = true;\n                        for(auto& pt : p) if(pt.x < 0 || pt.x > MAX_COORD || pt.y < 0 || pt.y > MAX_COORD) ok = false;\n                        \n                        if (ok && current_est_score > best_est_score) {\n                            best_est_score = current_est_score;\n                            best_poly = p;\n                        }\n                    }\n                }\n            }\n        }\n        return best_poly;\n    }\n    \n    Polygon trace(const set<pair<int,int>>& cells) {\n        if (cells.empty()) return {};\n        \n        // Find starting cell: lowest y, then lowest x.\n        // This ensures we start at the bottom-left corner of the shape.\n        int sx = GX, sy = GY;\n        for(auto p : cells) {\n            if (p.second < sy || (p.second == sy && p.first < sx)) {\n                sx = p.first;\n                sy = p.second;\n            }\n        }\n        \n        // Start tracing from the bottom-left corner of cell (sx, sy)\n        // Grid vertex (x, y) corresponds to bottom-left of cell (x, y)\n        int vx = sx, vy = sy;\n        int dir = 0; // 0:Right, 1:Up, 2:Left, 3:Down\n        \n        vector<pair<int,int>> path;\n        path.push_back({vx, vy});\n        \n        int start_vx = vx, start_vy = vy;\n        int steps = 0;\n        bool closed = false;\n        \n        auto check = [&](int cx, int cy) { return cells.count({cx, cy}); };\n        \n        do {\n            // Moore-Neighbor / Left-Hand Rule\n            // Determine next direction relative to current 'dir'.\n            // Try: Left -> Straight -> Right -> Back\n            int search_order[] = {(dir + 1) % 4, dir, (dir + 3) % 4, (dir + 2) % 4};\n            int next_dir = -1;\n            \n            for (int nd : search_order) {\n                // Identify cells on Left and Right of the edge in direction 'nd'\n                // Relative to vertex (vx, vy):\n                // nd=0 (Right): Left=Cell(vx,vy), Right=Cell(vx, vy-1)\n                // nd=1 (Up)   : Left=Cell(vx-1,vy), Right=Cell(vx, vy) -- Wait, check coordinate system\n                // Let's define clearly:\n                // Vertex (x,y) is surrounded by:\n                // Q1(Top-Right): Cell(x,y)\n                // Q2(Top-Left): Cell(x-1,y)\n                // Q3(Bottom-Left): Cell(x-1,y-1)\n                // Q4(Bottom-Right): Cell(x,y-1)\n                \n                pair<int,int> l, r;\n                if (nd == 0) { l = {vx, vy}; r = {vx, vy-1}; }      // Moving East\n                else if (nd == 1) { l = {vx-1, vy}; r = {vx, vy}; } // Moving North\n                else if (nd == 2) { l = {vx-1, vy-1}; r = {vx-1, vy}; } // Moving West\n                else { l = {vx, vy-1}; r = {vx-1, vy-1}; }          // Moving South\n                \n                // We trace the boundary where Left is IN (active) and Right is OUT (inactive)\n                if (check(l.first, l.second) && !check(r.first, r.second)) {\n                    next_dir = nd;\n                    break;\n                }\n            }\n            \n            if (next_dir == -1) return {}; // Should not happen\n            \n            dir = next_dir;\n            if (dir == 0) vx++;\n            else if (dir == 1) vy++;\n            else if (dir == 2) vx--;\n            else vy--;\n            \n            path.push_back({vx, vy});\n            steps++;\n            if (steps > 20000) return {}; // Safety limit\n            \n            if (vx == start_vx && vy == start_vy) closed = true;\n        } while (!closed);\n        \n        // Simplify Path (remove collinear vertices)\n        if (path.size() <= 1) return {};\n        path.pop_back(); // Remove duplicate start point\n        \n        auto get_pt = [&](pair<int,int> p) {\n            long long X = (long long)p.first * cell_size - offset_x;\n            long long Y = (long long)p.second * cell_size - offset_y;\n            return Point{(int)clamp(X, 0LL, (long long)MAX_COORD), (int)clamp(Y, 0LL, (long long)MAX_COORD)};\n        };\n        \n        vector<Point> simple_poly;\n        if (path.empty()) return {};\n        simple_poly.push_back(get_pt(path[0]));\n        \n        for(size_t i = 1; i < path.size(); ++i) {\n            Point curr = get_pt(path[i]);\n            Point prev = simple_poly.back();\n            \n            if (simple_poly.size() >= 2) {\n                Point pprev = simple_poly[simple_poly.size()-2];\n                // Check if extending the same line (Horizontal or Vertical)\n                bool prev_seg_vert = (prev.x == pprev.x);\n                bool curr_seg_vert = (curr.x == prev.x);\n                bool prev_seg_horz = (prev.y == pprev.y);\n                bool curr_seg_horz = (curr.y == prev.y);\n                \n                if ((prev_seg_vert && curr_seg_vert) || (prev_seg_horz && curr_seg_horz)) {\n                    simple_poly.back() = curr; // Merge\n                } else {\n                    simple_poly.push_back(curr);\n                }\n            } else {\n                simple_poly.push_back(curr);\n            }\n        }\n        \n        // Handle wrap-around simplification\n        if (simple_poly.size() > 2) {\n            Point first = simple_poly[0];\n            Point last = simple_poly.back();\n            Point prev = simple_poly[simple_poly.size()-2];\n            \n            bool last_seg_vert = (last.x == prev.x);\n            bool close_seg_vert = (first.x == last.x);\n            bool last_seg_horz = (last.y == prev.y);\n            bool close_seg_horz = (first.y == last.y);\n            \n            // If last segment and closing segment are collinear\n            if ((last_seg_vert && close_seg_vert) || (last_seg_horz && close_seg_horz)) {\n                simple_poly.pop_back();\n                last = simple_poly.back();\n            }\n            \n            // If new closing segment and first segment are collinear\n            Point second = simple_poly[1];\n            bool first_seg_vert = (second.x == first.x);\n            bool new_close_vert = (first.x == last.x);\n            bool first_seg_horz = (second.y == first.y);\n            bool new_close_horz = (first.y == last.y);\n            \n            if ((first_seg_vert && new_close_vert) || (first_seg_horz && new_close_horz)) {\n                simple_poly.erase(simple_poly.begin());\n            }\n        }\n        \n        return simple_poly;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = get_time_ms();\n    \n    if (!(cin >> N)) return 0;\n    mackerels.resize(N);\n    for(int i=0; i<N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    sardines.resize(N);\n    for(int i=0; i<N; ++i) cin >> sardines[i].x >> sardines[i].y;\n    \n    Polygon best_poly = {{0,0}, {1,0}, {1,1}, {0,1}};\n    int best_score = 0;\n    \n    mt19937 rng(1337);\n    \n    // Grid sizes to try\n    vector<int> grid_sizes = {5000, 4000, 3000, 2500, 2000, 1500, 1000, 800};\n    \n    int iter = 0;\n    while (get_time_ms() - start_time < TIME_LIMIT * 1000) {\n        iter++;\n        int cs;\n        if (iter <= (int)grid_sizes.size()) cs = grid_sizes[iter-1];\n        else cs = 500 + (rng() % 6000);\n        \n        int ox = rng() % cs;\n        int oy = rng() % cs;\n        \n        GridSolver solver(cs, ox, oy);\n        solver.build();\n        Polygon poly = solver.solve();\n        \n        if (poly.size() < 4) continue;\n        \n        int current_score = raw_score(poly);\n        if (current_score > best_score) {\n            best_score = current_score;\n            best_poly = poly;\n        }\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Constants & Globals ---\nconst int MAX_N = 105;\nint N, T, sigma_val;\nint w_prime[MAX_N], h_prime[MAX_N];\ndouble w_est[MAX_N], h_est[MAX_N];\n\nstruct Rect {\n    int x, y, w, h;\n};\n\nstruct Op {\n    short p; \n    short r; \n    short d; \n    short b; \n};\n\n// Fixed-size State structure to avoid dynamic allocation overhead\nstruct State {\n    Rect rects[MAX_N];\n    Op ops[MAX_N];\n    int W, H;\n    long long score;          // Primary objective: W + H\n    long long secondary;      // Secondary objective: W * H (Area)\n    \n    void add(int idx, int r_flag, int d_flag, int b_idx, const Rect& r) {\n        ops[idx] = { (short)idx, (short)r_flag, (short)d_flag, (short)b_idx };\n        rects[idx] = r;\n        W = max(W, r.x + r.w);\n        H = max(H, r.y + r.h);\n        score = (long long)W + H;\n        secondary = (long long)W * H;\n    }\n};\n\nstruct Candidate {\n    int parent_idx;\n    int r, d, b;\n    Rect geometry;\n    long long score;\n    long long secondary;\n};\n\n// --- Helpers ---\n\n// Calculate the position of a new rectangle given a base and direction.\n// Checks collisions against rects[0...idx-1].\npair<int, int> get_pos(int idx, int d, int b, int rw, int rh, const Rect* current_rects) {\n    int x = 0, y = 0;\n    if (d == 0) { // Direction U: Moves \"Upward\" (stops at bottom of others)\n        // X is determined by the base rectangle's right edge\n        if (b != -1) x = current_rects[b].x + current_rects[b].w;\n        \n        // Y is determined by \"gravity\" falling towards 0 (stacking in +y direction relative to blockers)\n        y = 0;\n        for (int j = 0; j < idx; ++j) {\n            // Check x-interval overlap: [x, x+rw) vs [j.x, j.x+j.w)\n            if (x < current_rects[j].x + current_rects[j].w && x + rw > current_rects[j].x) {\n                y = max(y, current_rects[j].y + current_rects[j].h);\n            }\n        }\n    } else { // Direction L: Moves \"Leftward\" (stops at right of others)\n        // Y is determined by the base rectangle's bottom edge\n        if (b != -1) y = current_rects[b].y + current_rects[b].h;\n        \n        // X is determined by \"gravity\" falling towards 0\n        x = 0;\n        for (int j = 0; j < idx; ++j) {\n            // Check y-interval overlap: [y, y+rh) vs [j.y, j.y+j.h)\n            if (y < current_rects[j].y + current_rects[j].h && y + rh > current_rects[j].y) {\n                x = max(x, current_rects[j].x + current_rects[j].w);\n            }\n        }\n    }\n    return {x, y};\n}\n\nState solve_beam(int K) {\n    // Use static buffers to reduce allocation\n    static vector<State> beam;\n    static vector<State> next_beam;\n    static vector<Candidate> candidates;\n    \n    beam.clear();\n    beam.reserve(K);\n    \n    State init_state;\n    init_state.W = 0;\n    init_state.H = 0;\n    init_state.score = 0;\n    init_state.secondary = 0;\n    beam.push_back(init_state);\n    \n    // Reusable buffer for unique coordinate generation\n    static vector<pair<int,int>> coords; \n    coords.reserve(MAX_N);\n\n    for (int i = 0; i < N; ++i) {\n        candidates.clear();\n        \n        // Expand each state in the current beam\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& S = beam[s_idx];\n            \n            // Calculate dimensions for current rect based on rotation\n            int dims[2][2]; // r=0, r=1\n            dims[0][0] = (int)lround(w_est[i]); dims[0][1] = (int)lround(h_est[i]);\n            dims[1][0] = (int)lround(h_est[i]); dims[1][1] = (int)lround(w_est[i]);\n            \n            for(int r=0; r<2; ++r) {\n                if (dims[r][0] < 1) dims[r][0] = 1;\n                if (dims[r][1] < 1) dims[r][1] = 1;\n            }\n            \n            // -- Try Direction U --\n            // Collect potential bases (unique X coordinates)\n            coords.clear();\n            coords.push_back({0, -1});\n            for(int j=0; j<i; ++j) coords.push_back({S.rects[j].x + S.rects[j].w, j});\n            \n            // Filter unique coordinates to prune branching factor\n            sort(coords.begin(), coords.end());\n            int unique_count = unique(coords.begin(), coords.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n                return a.first == b.first;\n            }) - coords.begin();\n            \n            for(int k=0; k<unique_count; ++k) {\n                int base = coords[k].second;\n                for(int r=0; r<2; ++r) {\n                    int rw = dims[r][0];\n                    int rh = dims[r][1];\n                    pair<int,int> pos = get_pos(i, 0, base, rw, rh, S.rects);\n                    \n                    int nW = max(S.W, pos.first + rw);\n                    int nH = max(S.H, pos.second + rh);\n                    long long sc = (long long)nW + nH;\n                    long long sec = (long long)nW * nH;\n                    candidates.push_back({s_idx, r, 0, base, {pos.first, pos.second, rw, rh}, sc, sec});\n                }\n            }\n\n            // -- Try Direction L --\n            // Collect potential bases (unique Y coordinates)\n            coords.clear();\n            coords.push_back({0, -1});\n            for(int j=0; j<i; ++j) coords.push_back({S.rects[j].y + S.rects[j].h, j});\n            \n            sort(coords.begin(), coords.end());\n            unique_count = unique(coords.begin(), coords.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n                return a.first == b.first;\n            }) - coords.begin();\n            \n            for(int k=0; k<unique_count; ++k) {\n                int base = coords[k].second;\n                for(int r=0; r<2; ++r) {\n                    int rw = dims[r][0];\n                    int rh = dims[r][1];\n                    pair<int,int> pos = get_pos(i, 1, base, rw, rh, S.rects);\n                    \n                    int nW = max(S.W, pos.first + rw);\n                    int nH = max(S.H, pos.second + rh);\n                    long long sc = (long long)nW + nH;\n                    long long sec = (long long)nW * nH;\n                    candidates.push_back({s_idx, r, 1, base, {pos.first, pos.second, rw, rh}, sc, sec});\n                }\n            }\n        }\n        \n        // Select top K candidates\n        if ((int)candidates.size() > K) {\n            nth_element(candidates.begin(), candidates.begin() + K, candidates.end(), \n                [](const Candidate& a, const Candidate& b){\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.secondary < b.secondary;\n                });\n            candidates.resize(K);\n        }\n        \n        next_beam.clear();\n        next_beam.reserve(candidates.size());\n        for(const auto& c : candidates) {\n            State ns = beam[c.parent_idx];\n            ns.add(i, c.r, c.d, c.b, c.geometry);\n            next_beam.push_back(ns);\n        }\n        beam = next_beam;\n    }\n    \n    // Return best\n    if(beam.empty()) return init_state;\n    auto best_it = min_element(beam.begin(), beam.end(), [](const State& a, const State& b){\n         if (a.score != b.score) return a.score < b.score;\n         return a.secondary < b.secondary;\n    });\n    return *best_it;\n}\n\nvoid update_estimates(const State& state, int W_obs, int H_obs) {\n    int diff_W = W_obs - state.W;\n    int diff_H = H_obs - state.H;\n    \n    // Rebuild dependency graph to trace critical paths\n    static int px[MAX_N], py[MAX_N];\n    fill(px, px+N, -1);\n    fill(py, py+N, -1);\n    \n    for(int i=0; i<N; ++i) {\n        const auto& op = state.ops[i];\n        const auto& r = state.rects[i];\n        if(op.d == 0) { // U\n            px[i] = op.b;\n            int best_k = -1, max_v = 0;\n            for(int k=0; k<i; ++k) {\n                if(state.rects[k].x < r.x+r.w && state.rects[k].x+state.rects[k].w > r.x) {\n                    int bot = state.rects[k].y + state.rects[k].h;\n                    if(bot > max_v) { max_v = bot; best_k = k; }\n                }\n            }\n            py[i] = best_k;\n        } else { // L\n            py[i] = op.b;\n            int best_k = -1, max_v = 0;\n            for(int k=0; k<i; ++k) {\n                if(state.rects[k].y < r.y+r.h && state.rects[k].y+state.rects[k].h > r.y) {\n                    int right = state.rects[k].x + state.rects[k].w;\n                    if(right > max_v) { max_v = right; best_k = k; }\n                }\n            }\n            px[i] = best_k;\n        }\n    }\n    \n    static bool crit[MAX_N];\n    \n    // Update Width Estimates\n    fill(crit, crit+N, false);\n    int cnt_w = 0;\n    vector<int> q; q.reserve(N);\n    for(int i=0; i<N; ++i) if(state.rects[i].x + state.rects[i].w == state.W) {\n        crit[i] = true; q.push_back(i);\n    }\n    int hd = 0;\n    while(hd < (int)q.size()){\n        int u = q[hd++];\n        int p = px[u];\n        if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n    }\n    for(int i=0; i<N; ++i) if(crit[i]) cnt_w++;\n    \n    if(cnt_w > 0) {\n        double delta = (double)diff_W / cnt_w * 0.4;\n        for(int i=0; i<N; ++i) if(crit[i]) {\n            if(state.ops[i].r == 0) w_est[i] += delta;\n            else h_est[i] += delta;\n        }\n    }\n    \n    // Update Height Estimates\n    fill(crit, crit+N, false);\n    int cnt_h = 0;\n    q.clear();\n    for(int i=0; i<N; ++i) if(state.rects[i].y + state.rects[i].h == state.H) {\n        crit[i] = true; q.push_back(i);\n    }\n    hd = 0;\n    while(hd < (int)q.size()){\n        int u = q[hd++];\n        int p = py[u];\n        if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n    }\n    for(int i=0; i<N; ++i) if(crit[i]) cnt_h++;\n\n    if(cnt_h > 0) {\n        double delta = (double)diff_H / cnt_h * 0.4;\n        for(int i=0; i<N; ++i) if(crit[i]) {\n            if(state.ops[i].r == 0) h_est[i] += delta;\n            else w_est[i] += delta;\n        }\n    }\n    \n    // Clamp values\n    for(int i=0; i<N; ++i) {\n        if(w_est[i] < 1) w_est[i] = 1;\n        if(h_est[i] < 1) h_est[i] = 1;\n        if(w_est[i] > 1e9) w_est[i] = 1e9;\n        if(h_est[i] > 1e9) h_est[i] = 1e9;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma_val)) return 0;\n    for(int i=0; i<N; ++i) {\n        cin >> w_prime[i] >> h_prime[i];\n        w_est[i] = w_prime[i];\n        h_est[i] = h_prime[i];\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Initial Beam Width Calculation\n    // We aim to keep total operations roughly constant ~ 2e8 ops over T turns\n    long long estimated_ops_per_K = (long long)T * N * N * 10; \n    int K = 300000000LL / estimated_ops_per_K;\n    if (K < 1) K = 1;\n    if (K > 80) K = 80;\n    \n    // Strict cap for very large N to ensure 3.0s safety\n    if (N > 80 && K > 5) K = 5;\n    if (N > 90 && K > 3) K = 3;\n    \n    for(int t=0; t<T; ++t) {\n        // Time management: if we are behind schedule, reduce K\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double expected_time = (double)(t) / T * 2.85;\n        \n        if (elapsed > expected_time && K > 1) {\n            K = max(1, K - 1);\n        }\n        \n        State sol = solve_beam(K);\n        \n        cout << N << \"\\n\";\n        for(int i=0; i<N; ++i) {\n            const auto& op = sol.ops[i];\n            char c = (op.d==0?'U':'L');\n            cout << op.p << \" \" << op.r << \" \" << c << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        int W_obs, H_obs;\n        cin >> W_obs >> H_obs;\n        update_estimates(sol, W_obs, H_obs);\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Problem Constants\nconst int MAXN = 1005;\nconst int H_LIMIT = 10;\n\n// Global Variables\nint N, M, H_in;\nint A[MAXN];\nvector<int> adj[MAXN]; // Adjacency list\n\n// State Variables\nint p[MAXN];                // Parent of node i (-1 if root)\nint S[MAXN];                // Sum of A values in the subtree rooted at i\nint d_max[MAXN];            // Height of subtree at i (max distance to a descendant)\nint cnt_h[MAXN][H_LIMIT + 2]; // Frequency of children heights. indices 0..10 are valid.\n\n// Random Number Generator\nmt19937 rng(12345);\n\n// Utility: Get depth of v (0-indexed) by walking up\n// O(H)\nint get_depth(int v) {\n    int d = 0;\n    while (v != -1) {\n        v = p[v];\n        d++;\n    }\n    return d - 1; // Root is depth 0\n}\n\n// Check if u is a descendant of v\n// Optimization: use depths if available, but here we just walk.\n// O(H)\nbool is_descendant(int u, int v) {\n    if (v == -1) return false;\n    if (u == v) return true;\n    while (u != -1) {\n        if (u == v) return true;\n        u = p[u];\n    }\n    return false;\n}\n\n// Update S (beauty sum) upwards\nvoid update_S_up(int u, int diff) {\n    while (u != -1) {\n        S[u] += diff;\n        u = p[u];\n    }\n}\n\n// Update d_max upwards after adding a child with height h_child\nvoid update_d_max_add(int u, int h_child) {\n    int curr = u;\n    int h = h_child;\n    while (curr != -1) {\n        cnt_h[curr][h]++;\n        if (h + 1 > d_max[curr]) {\n            int old_h = d_max[curr];\n            d_max[curr] = h + 1;\n            \n            int next_p = p[curr];\n            if (next_p != -1) {\n                // For the parent, 'curr' changed from old_h to d_max[curr]\n                // We need to remove old_h stats and add new.\n                // Since we are in 'add' logic (height strictly increases), \n                // we decrement old_h count and loop to increment new height.\n                if (cnt_h[next_p][old_h] > 0) cnt_h[next_p][old_h]--; \n                h = d_max[curr];\n                curr = next_p;\n            } else {\n                break;\n            }\n        } else {\n            // Max height didn't change, propagation stops\n            break;\n        }\n    }\n}\n\n// Update d_max upwards after removing a child with height h_child\nvoid update_d_max_remove(int u, int h_child) {\n    int curr = u;\n    int h = h_child;\n    while (curr != -1) {\n        if (cnt_h[curr][h] > 0) cnt_h[curr][h]--;\n        \n        bool shape_changed = false;\n        // If the removed height was defining the max height\n        if (h + 1 == d_max[curr]) {\n            if (cnt_h[curr][h] == 0) {\n                // Find new max\n                int new_max = 0;\n                for (int k = h - 1; k >= 0; --k) {\n                    if (cnt_h[curr][k] > 0) {\n                        new_max = k + 1;\n                        break;\n                    }\n                }\n                d_max[curr] = new_max;\n                shape_changed = true;\n            }\n        }\n        \n        if (shape_changed) {\n            int next_p = p[curr];\n            if (next_p != -1) {\n                // 'curr' height reduced.\n                // We need to add the NEW height to parent, and continue loop to remove OLD height.\n                // Add new height stats:\n                update_d_max_add(next_p, d_max[curr]);\n                \n                // Prepare to remove old height from parent in next iteration\n                h = h + 1; // old d_max was h+1\n                curr = next_p;\n            } else {\n                break;\n            }\n        } else {\n            // Max height didn't change\n            break;\n        }\n    }\n}\n\n// Calculate total score\nlong long calc_score() {\n    long long score = 0;\n    for (int i = 0; i < N; ++i) {\n        int h = 0;\n        int curr = p[i];\n        while(curr != -1) {\n            h++;\n            curr = p[curr];\n        }\n        score += (long long)(h + 1) * A[i];\n    }\n    return score;\n}\n\n// Initialize state\nvoid init_state() {\n    for (int i = 0; i < N; ++i) {\n        p[i] = -1;\n        S[i] = A[i];\n        d_max[i] = 0;\n        for(int k=0; k<=H_LIMIT+1; ++k) cnt_h[i][k] = 0;\n    }\n}\n\nint main() {\n    // Fast IO\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    if (!(cin >> N >> M >> H_in)) return 0;\n    for(int i=0; i<N; ++i) cin >> A[i];\n    for(int i=0; i<M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for(int i=0; i<N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    // Best solution tracking\n    vector<int> best_p(N);\n    long long best_score = -1;\n    \n    // Multiple Greedy Starts\n    // We sort by A, but we can introduce slight noise to order for diversity\n    int num_greedy_tries = 20;\n    \n    for (int t = 0; t < num_greedy_tries; ++t) {\n        init_state();\n        \n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        \n        if (t == 0) {\n            // Deterministic sort\n            sort(order.begin(), order.end(), [&](int a, int b){\n                return A[a] < A[b];\n            });\n        } else {\n            // Noisy sort\n            vector<double> noisy_A(N);\n            for(int i=0; i<N; ++i) noisy_A[i] = A[i] + (rng() % 100) * 0.01;\n            sort(order.begin(), order.end(), [&](int a, int b){\n                return noisy_A[a] < noisy_A[b];\n            });\n        }\n        \n        // Construct\n        for (int v : order) {\n            int best_u = -1;\n            int best_depth = 0; // Depth if root\n            \n            // Current v is root. d_max[v] is 0 (since it has no children yet in this process? \n            // Wait, we are building incrementally. v is a root of a single node tree initially.\n            // No, in init_state everyone is root. \n            // But as we link, trees merge.\n            // When we process v, v might already have children from previous steps \n            // (nodes processed earlier that attached to v).\n            // So d_max[v] is valid.\n            \n            vector<int> candidates = adj[v];\n            shuffle(candidates.begin(), candidates.end(), rng);\n            \n            for (int u : candidates) {\n                if (is_descendant(u, v)) continue;\n                \n                int depth_u = get_depth(u); // 0-based depth of u\n                // If we attach v to u, v's new depth is depth_u + 1.\n                // Check height constraint: new_depth + d_max[v] <= H\n                if (depth_u + 1 + d_max[v] <= H_LIMIT) {\n                    if (depth_u + 1 > best_depth) {\n                        best_depth = depth_u + 1;\n                        best_u = u;\n                    }\n                }\n            }\n            \n            if (best_u != -1) {\n                p[v] = best_u;\n                update_S_up(best_u, S[v]);\n                update_d_max_add(best_u, d_max[v]);\n            }\n        }\n        \n        long long current_score = calc_score();\n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) best_p[i] = p[i];\n        }\n    }\n    \n    // Restore best greedy solution for SA\n    init_state();\n    for(int i=0; i<N; ++i) {\n        p[i] = best_p[i];\n    }\n    // Rebuild S and d_max/cnt_h\n    // Since order matters for d_max update (children before parents), \n    // and p array defines a forest, we can rebuild by processing by depth (deep to shallow) or just naive N passes?\n    // Better: rebuild from scratch using p.\n    // Compute depths\n    vector<int> depths(N);\n    vector<vector<int>> nodes_by_depth(H_LIMIT + 2);\n    for(int i=0; i<N; ++i) {\n        depths[i] = get_depth(i); // p is set\n        if(depths[i] > H_LIMIT) depths[i] = H_LIMIT + 1; // Should not happen\n        nodes_by_depth[depths[i]].push_back(i);\n    }\n    // Process bottom up\n    for (int d = H_LIMIT; d >= 0; --d) {\n        for (int u : nodes_by_depth[d]) {\n            S[u] = A[u];\n            d_max[u] = 0;\n            // Add children stats\n            // This requires knowing children.\n            // We don't have children lists.\n            // Simple way: iterate all nodes, find children of u.\n            // N^2 is fine once.\n            for(int c=0; c<N; ++c) {\n                if (p[c] == u) {\n                    S[u] += S[c];\n                    cnt_h[u][d_max[c]]++;\n                    d_max[u] = max(d_max[u], d_max[c] + 1);\n                }\n            }\n        }\n    }\n    \n    // Simulated Annealing\n    double time_limit = 1.98;\n    double T_start = 150.0;\n    double T_end = 0.1;\n    \n    int iter = 0;\n    \n    while (true) {\n        iter++;\n        if ((iter & 1023) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n        \n        // Pick random node v\n        int v = rng() % N;\n        int old_p = p[v];\n        \n        // Pick new parent u\n        int u = -1;\n        if (!adj[v].empty()) {\n            // Uniform choice from neighbors + {-1}\n            // To favor -1 less, maybe 1/(deg+5)?\n            int idx = rng() % (adj[v].size() + 1);\n            if (idx < (int)adj[v].size()) u = adj[v][idx];\n        }\n        \n        if (u == old_p) continue;\n        \n        // 1. Cycle Check\n        // Optimization: If depth[u] < depth[v], u cannot be descendant (unless u is not in v's tree at all, which is allowed)\n        // Wait, depth logic is valid for rejecting descendants.\n        // Descendant depth > ancestor depth.\n        // So if depth[u] <= depth[v], u is NOT a descendant (safe).\n        // If u == -1, safe.\n        int depth_v = -1; // Compute only if needed\n        int depth_u = -1;\n        \n        if (u != -1) {\n            // Need check\n            // Calculate depth on fly\n            depth_v = get_depth(v); // O(H)\n            depth_u = get_depth(u); // O(H)\n            \n            if (depth_u > depth_v) {\n                if (is_descendant(u, v)) continue;\n            } else if (depth_u == depth_v) {\n                if (u == v) continue; // self loop\n                // Else safe (u not descendant)\n            }\n            // If depth_u < depth_v, u is definitely not descendant.\n        }\n        \n        // 2. Height Constraint\n        // new_depth_v = depth_u + 1\n        // check: depth_u + 1 + d_max[v] <= H\n        int new_depth_v = (u == -1) ? 0 : (depth_u != -1 ? depth_u : get_depth(u)) + 1;\n        if (new_depth_v + d_max[v] > H_LIMIT) continue;\n        \n        // 3. Score Delta\n        // Gain = (new_depth_v - old_depth_v) * S[v]\n        int old_depth_v = (depth_v != -1) ? depth_v : get_depth(v);\n        long long diff = (long long)(new_depth_v - old_depth_v) * S[v];\n        \n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            double progress = elapsed / time_limit;\n            double T = T_start * pow(T_end / T_start, progress);\n            if (generate_canonical<double, 10>(rng) < exp(diff / T)) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            // Execute Move\n            // 1. Remove from old parent\n            if (old_p != -1) {\n                update_S_up(old_p, -S[v]);\n                update_d_max_remove(old_p, d_max[v]);\n            }\n            \n            // 2. Link to new parent\n            p[v] = u;\n            \n            // 3. Add to new parent\n            if (u != -1) {\n                update_S_up(u, S[v]);\n                update_d_max_add(u, d_max[v]);\n            }\n        }\n    }\n    \n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << p[i] << (i == N-1 ? \"\" : \" \");\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <array>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_OPS = 4 * N * N; // 1600\nconst int INF = 1e9;\n\n// Directions: 0: L, 1: R, 2: U, 3: D\nconst char DIR_CHARS[] = {'L', 'R', 'U', 'D'};\n\nstruct Move {\n    char d;\n    int p; // row or column index\n};\n\nstruct State {\n    array<string, N> board;\n    vector<Move> history;\n    int score; // Heuristic score (lower is better)\n    int cost;  // Number of moves so far\n    int removed_oni; // Number of Oni removed\n\n    // For sorting in priority queue or sort function\n    bool operator>(const State& other) const {\n        return score > other.score;\n    }\n};\n\n// Helper to calculate distance to edge for a specific cell and direction\n// Returns -1 if blocked by 'o'\nint get_dist(const array<string, N>& board, int r, int c, int dir) {\n    if (dir == 0) { // L\n        for (int k = 0; k < c; ++k) if (board[r][k] == 'o') return -1;\n        return c + 1;\n    } else if (dir == 1) { // R\n        for (int k = c + 1; k < N; ++k) if (board[r][k] == 'o') return -1;\n        return N - c;\n    } else if (dir == 2) { // U\n        for (int k = 0; k < r; ++k) if (board[k][c] == 'o') return -1;\n        return r + 1;\n    } else { // D\n        for (int k = r + 1; k < N; ++k) if (board[k][c] == 'o') return -1;\n        return N - r;\n    }\n}\n\n// Calculate heuristic score\n// Heuristic = Sum of min_dist for all remaining Oni + Penalties\nint calculate_heuristic(const array<string, N>& board) {\n    int total_dist = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (board[r][c] == 'x') {\n                int min_d = INF;\n                int blocked_cnt = 0;\n                for (int d = 0; d < 4; ++d) {\n                    int dist = get_dist(board, r, c, d);\n                    if (dist != -1) {\n                        if (dist < min_d) min_d = dist;\n                    } else {\n                        blocked_cnt++;\n                    }\n                }\n                if (min_d == INF) {\n                    total_dist += 200; // Heavy penalty if blocked in all directions\n                } else {\n                    total_dist += min_d;\n                }\n                total_dist += blocked_cnt * 2; // Penalty for reduced options\n            }\n        }\n    }\n    return total_dist;\n}\n\n// Apply shift to the board\nvoid apply_shift(array<string, N>& board, int type, int idx) {\n    if (type == 0) { // L\n        for (int j = 0; j < N - 1; ++j) board[idx][j] = board[idx][j+1];\n        board[idx][N-1] = '.';\n    } else if (type == 1) { // R\n        for (int j = N - 1; j > 0; --j) board[idx][j] = board[idx][j-1];\n        board[idx][0] = '.';\n    } else if (type == 2) { // U\n        for (int i = 0; i < N - 1; ++i) board[i][idx] = board[i+1][idx];\n        board[N-1][idx] = '.';\n    } else { // D\n        for (int i = N - 1; i > 0; --i) board[i][idx] = board[i-1][idx];\n        board[0][idx] = '.';\n    }\n}\n\n// Count Oni on the board\nint count_oni(const array<string, N>& board) {\n    int c = 0;\n    for (const auto& row : board) \n        for (char ch : row) if (ch == 'x') c++;\n    return c;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_dummy;\n    if (cin >> n_dummy) {} \n\n    State initial_state;\n    initial_state.cost = 0;\n    for (int i = 0; i < N; ++i) cin >> initial_state.board[i];\n    \n    int initial_total_oni = count_oni(initial_state.board);\n    initial_state.removed_oni = 0; \n    initial_state.score = calculate_heuristic(initial_state.board);\n\n    // Beam search organized by number of removed Oni\n    // beams[k] holds states with k Oni removed\n    vector<vector<State>> beams(2 * N + 1);\n    beams[0].push_back(initial_state);\n\n    int BEAM_WIDTH = 30; \n\n    // Iterate through progress levels\n    for (int k = 0; k < initial_total_oni; ++k) {\n        if (beams[k].empty()) continue;\n        \n        // Sort by score (lower is better) and keep top BEAM_WIDTH\n        sort(beams[k].begin(), beams[k].end(), [](const State& a, const State& b){\n            return a.score < b.score;\n        });\n        if (beams[k].size() > BEAM_WIDTH) {\n            beams[k].resize(BEAM_WIDTH);\n        }\n        \n        for (const auto& state : beams[k]) {\n            // Try all directions and lines\n            for (int dir = 0; dir < 4; ++dir) {\n                for (int line = 0; line < N; ++line) {\n                    // Calculate safe shift limit\n                    int max_safe = 0;\n                    int first_fuku = -1;\n                    \n                    if (dir == 0) { // L\n                        for(int c=0; c<N; ++c) if(state.board[line][c] == 'o') { first_fuku = c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=0; --c) if(state.board[line][c] == 'o') { first_fuku = (N-1)-c; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<N; ++r) if(state.board[r][line] == 'o') { first_fuku = r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    } else { // D\n                        for(int r=N-1; r>=0; --r) if(state.board[r][line] == 'o') { first_fuku = (N-1)-r; break; }\n                        max_safe = (first_fuku == -1) ? N : first_fuku;\n                    }\n                    \n                    if (max_safe == 0) continue;\n                    \n                    // Identify Oni positions that can be removed\n                    vector<int> oni_shifts;\n                    if (dir == 0) { // L\n                        for(int c=0; c<max_safe; ++c) if(state.board[line][c] == 'x') oni_shifts.push_back(c + 1);\n                    } else if (dir == 1) { // R\n                        for(int c=N-1; c>=N-max_safe; --c) if(state.board[line][c] == 'x') oni_shifts.push_back((N-1)-c + 1);\n                    } else if (dir == 2) { // U\n                        for(int r=0; r<max_safe; ++r) if(state.board[r][line] == 'x') oni_shifts.push_back(r + 1);\n                    } else { // D\n                        for(int r=N-1; r>=N-max_safe; --r) if(state.board[r][line] == 'x') oni_shifts.push_back((N-1)-r + 1);\n                    }\n                    \n                    if (oni_shifts.empty()) continue;\n\n                    // Only consider:\n                    // 1. Shift to remove the FIRST Oni (minimal progress)\n                    // 2. Shift to remove the LAST safe Oni (maximal progress in this line)\n                    vector<int> candidates;\n                    candidates.push_back(oni_shifts[0]);\n                    if (oni_shifts.back() != oni_shifts[0]) {\n                        candidates.push_back(oni_shifts.back());\n                    }\n\n                    for (int shift_amt : candidates) {\n                        // Option 1: Eject (Permanent Change)\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            next_state.cost += shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                        \n                        // Option 2: Eject & Restore (Safe fallback)\n                        // Costs 2x but preserves board structure\n                        {\n                            State next_state = state;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, dir, line);\n                                next_state.history.push_back({DIR_CHARS[dir], line});\n                            }\n                            int opp_dir = (dir == 0) ? 1 : (dir == 1) ? 0 : (dir == 2) ? 3 : 2;\n                            for(int s=0; s<shift_amt; ++s) {\n                                apply_shift(next_state.board, opp_dir, line);\n                                next_state.history.push_back({DIR_CHARS[opp_dir], line});\n                            }\n                            next_state.cost += 2 * shift_amt;\n                            if (next_state.cost <= MAX_OPS) {\n                                int remaining = count_oni(next_state.board);\n                                int removed = initial_total_oni - remaining;\n                                next_state.removed_oni = removed;\n                                next_state.score = next_state.cost + calculate_heuristic(next_state.board);\n                                \n                                if (removed > k) {\n                                    beams[removed].push_back(next_state);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Select best solution from states that removed all Oni\n    int final_idx = initial_total_oni;\n    // Fallback to best available if full solution not found\n    while (final_idx >= 0 && beams[final_idx].empty()) {\n        final_idx--;\n    }\n    \n    State* best = nullptr;\n    if (final_idx >= 0) {\n        for (auto& s : beams[final_idx]) {\n            if (!best || s.cost < best->cost) {\n                best = &s;\n            }\n        }\n    }\n    \n    if (best) {\n        for (const auto& mv : best->history) {\n            cout << mv.d << \" \" << mv.p << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <queue>\n\nusing namespace std;\n\n// ==========================================\n// Constants & Globals\n// ==========================================\nconst int N = 100;\nconst int L_TOTAL = 500000;\n\n// Input Data\nint T[N];\n\n// State\nint A[N], B[N]; \nint best_A[N], best_B[N];\n\n// Simulation State\nint sim_counts[N];\nint backup_counts[N]; // For restoring state upon rejection\n\n// Flow Proxy State (Phase 1)\nint current_inflow[N];\nint est_flow_A[N];\nint est_flow_B[N];\n\n// Timing Control\nauto start_time = chrono::high_resolution_clock::now();\ndouble TIME_LIMIT = 1.90; \n\n// Fast RNG\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967295.0;\n    }\n} rng;\n\n// ==========================================\n// Utils\n// ==========================================\n\n// Check reachability from node 0 using the flow proxy model\n// Returns the sum of T[i] for unreachable nodes\nint get_unreached_mass_proxy() {\n    static bool visited[N];\n    memset(visited, 0, sizeof(visited));\n    static int q[N];\n    int head = 0, tail = 0;\n    \n    if (T[0] > 0) {\n        visited[0] = true;\n        q[tail++] = 0;\n    }\n    \n    while(head < tail) {\n        int u = q[head++];\n        // Check A flow\n        if (est_flow_A[u] > 0) {\n            int v = A[u];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n        // Check B flow\n        if (est_flow_B[u] > 0) {\n            int v = B[u];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n    }\n    \n    int mass = 0;\n    for(int i=0; i<N; ++i) {\n        if (!visited[i]) mass += T[i];\n    }\n    return mass;\n}\n\n// Calculate Flow Proxy Error\n// Heuristic: Error = |Inflow - T| + Penalty(Unreached)\nlong long calc_flow_error() {\n    long long err = 0;\n    // Node 0 essentially provides 1 unit of \"external\" flow start.\n    // So expected incoming for node 0 is T[0]-1, others T[i].\n    for(int i=0; i<N; ++i) {\n        int target = T[i];\n        if (i == 0 && target > 0) target--;\n        err += abs(current_inflow[i] - target);\n    }\n    int unreached = get_unreached_mass_proxy();\n    return err + (long long)unreached * 5000; // Heavy penalty ensures connectivity\n}\n\n// Run Simulation for given Length\n// Stores result in sim_counts\n// Returns Sum of Absolute Differences\nlong long run_simulation(int length, const vector<int>& targets) {\n    memset(sim_counts, 0, sizeof(sim_counts));\n    \n    int curr = 0;\n    sim_counts[0]++;\n    \n    const int* a_ptr = A;\n    const int* b_ptr = B;\n    \n    for (int k = 1; k < length; ++k) {\n        int prev = curr;\n        int t = sim_counts[prev];\n        // Logic: t is the number of times prev had been visited (inclusive).\n        // If t is odd -> A, even -> B.\n        if (t & 1) curr = a_ptr[prev];\n        else curr = b_ptr[prev];\n        sim_counts[curr]++;\n    }\n    \n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(sim_counts[i] - targets[i]);\n    }\n    return err;\n}\n\n// ==========================================\n// Main Algorithm\n// ==========================================\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, l_in;\n    if (cin >> n_in >> l_in) {}\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // --- Setup Flow Estimates for Phase 1 ---\n    for(int i=0; i<N; ++i) {\n        est_flow_A[i] = (T[i] + 1) / 2;\n        est_flow_B[i] = T[i] / 2;\n    }\n\n    // --- Initial Construction (Greedy Bin Packing) ---\n    struct Plug { int u; int type; int val; }; \n    vector<Plug> plugs;\n    plugs.reserve(2*N);\n    for(int i=0; i<N; ++i) {\n        if (est_flow_A[i] > 0) plugs.push_back({i, 0, est_flow_A[i]});\n        if (est_flow_B[i] > 0) plugs.push_back({i, 1, est_flow_B[i]});\n    }\n    sort(plugs.begin(), plugs.end(), [](const Plug& a, const Plug& b){\n        return a.val > b.val;\n    });\n\n    // Initialize with default cycle\n    for(int i=0; i<N; ++i) { A[i] = (i+1)%N; B[i] = (i+1)%N; }\n    \n    // Track Capacity for Bin Packing\n    vector<int> cap(N);\n    for(int i=0; i<N; ++i) cap[i] = T[i];\n    if (cap[0] > 0) cap[0]--;\n    \n    fill(current_inflow, current_inflow+N, 0);\n    \n    for(const auto& p : plugs) {\n        int best = -1; \n        int max_rem = -2e9;\n        \n        // Random start to avoid bias\n        int s = rng.next_int(N);\n        for(int k=0; k<N; ++k) {\n            int v = (s + k) % N;\n            int rem = cap[v];\n            if (rem > max_rem) {\n                max_rem = rem;\n                best = v;\n            }\n        }\n        \n        if (p.type == 0) A[p.u] = best;\n        else B[p.u] = best;\n        \n        cap[best] -= p.val;\n        current_inflow[best] += p.val;\n    }\n    \n    // Save initial solution\n    copy(begin(A), end(A), begin(best_A));\n    copy(begin(B), end(B), begin(best_B));\n\n    // --- PHASE 1: Fast Flow Optimization (0.0s - 0.3s) ---\n    // Heuristic: Optimize flow balance and connectivity without simulation.\n    {\n        long long cur_err = calc_flow_error();\n        double temp = 100.0;\n        while(true) {\n            auto now = chrono::high_resolution_clock::now();\n            if (chrono::duration<double>(now - start_time).count() > 0.3) break;\n            \n            // Move: Redirect random edge\n            int u = rng.next_int(N);\n            if (T[u] == 0) continue;\n            \n            int type = (est_flow_B[u] > 0) ? rng.next_int(2) : 0;\n            int val = (type == 0) ? est_flow_A[u] : est_flow_B[u];\n            \n            int old_v = (type == 0) ? A[u] : B[u];\n            int new_v = rng.next_int(N);\n            if (old_v == new_v) continue;\n            \n            // Apply\n            current_inflow[old_v] -= val;\n            current_inflow[new_v] += val;\n            if (type == 0) A[u] = new_v; else B[u] = new_v;\n            \n            long long next_err = calc_flow_error();\n            long long delta = next_err - cur_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_err = next_err;\n            } else {\n                // Revert\n                current_inflow[old_v] += val;\n                current_inflow[new_v] -= val;\n                if (type == 0) A[u] = old_v; else B[u] = old_v;\n            }\n            temp *= 0.995;\n            if (temp < 0.1) temp = 0.1;\n        }\n    }\n    \n    // Sync best\n    copy(begin(A), end(A), begin(best_A));\n    copy(begin(B), end(B), begin(best_B));\n\n    // --- PHASE 2: Scaled Simulation (0.3s - 0.8s) ---\n    // Simulate with L = 100,000 (1/5th). \n    // This runs 5x faster, allowing more iterations to fix macro structure.\n    int L_STAGE1 = 100000;\n    vector<int> T_STAGE1(N);\n    {\n        long long sum = 0;\n        for(int i=0; i<N; ++i) {\n            T_STAGE1[i] = (long long)T[i] * L_STAGE1 / L_TOTAL;\n            sum += T_STAGE1[i];\n        }\n        // Distribute remainder\n        while(sum < L_STAGE1) {\n            int i = rng.next_int(N);\n            if (T[i] > 0) { T_STAGE1[i]++; sum++; }\n        }\n    }\n    \n    // Initial run for Stage 1\n    long long cur_sim_err = run_simulation(L_STAGE1, T_STAGE1);\n    copy(begin(sim_counts), end(sim_counts), begin(backup_counts));\n    \n    // Reset temperature for Phase 2\n    double temp = 50.0;\n    \n    // Auxiliary vectors for directed moves\n    vector<int> surplus, deficit;\n    surplus.reserve(N); deficit.reserve(N);\n    \n    // Lambda for Simulated Annealing Step\n    auto sa_step = [&](int current_L, const vector<int>& current_T, double end_time_limit) {\n        while(true) {\n            auto now = chrono::high_resolution_clock::now();\n            if (chrono::duration<double>(now - start_time).count() > end_time_limit) break;\n            \n            int u = -1, type = -1, new_v = -1, old_v = -1;\n            bool directed = false;\n            \n            // Strategy: Redirect Parent of Surplus -> Deficit\n            if (rng.next_double() < 0.7) {\n                surplus.clear(); deficit.clear();\n                for(int i=0; i<N; ++i) {\n                    if (sim_counts[i] > current_T[i]) surplus.push_back(i);\n                    if (sim_counts[i] < current_T[i]) deficit.push_back(i);\n                }\n                \n                if (!surplus.empty() && !deficit.empty()) {\n                    int target_node = deficit[rng.next_int(deficit.size())]; // The deficit node we want to feed\n                    \n                    // We need to find a node 'u' that currently feeds a surplus node 's',\n                    // and redirect it to 'target_node'.\n                    int s = surplus[rng.next_int(surplus.size())];\n                    \n                    // Heuristic: Check 20 random nodes to see if they point to s.\n                    for(int k=0; k<20; ++k) {\n                        int cand = rng.next_int(N);\n                        if (T[cand] == 0) continue;\n                        \n                        // Check A\n                        if (A[cand] == s) {\n                            u = cand; type = 0; old_v = s; new_v = target_node; directed = true; break;\n                        }\n                        // Check B\n                        if (T[cand] > 1 && B[cand] == s) {\n                            u = cand; type = 1; old_v = s; new_v = target_node; directed = true; break;\n                        }\n                    }\n                }\n            }\n            \n            if (!directed) {\n                // Random move\n                u = rng.next_int(N);\n                if (T[u] == 0) continue;\n                type = (T[u] > 1) ? rng.next_int(2) : 0;\n                old_v = (type == 0) ? A[u] : B[u];\n                new_v = rng.next_int(N);\n            }\n            \n            if (u == -1 || old_v == new_v) continue;\n            \n            // Apply Move\n            if (type == 0) A[u] = new_v; else B[u] = new_v;\n            \n            long long next_err = run_simulation(current_L, current_T);\n            long long delta = next_err - cur_sim_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_sim_err = next_err;\n                copy(begin(sim_counts), end(sim_counts), begin(backup_counts)); // Save valid state\n            } else {\n                // Revert\n                if (type == 0) A[u] = old_v; else B[u] = old_v;\n                // Restore sim counts (CRITICAL for correctness of next surplus/deficit check)\n                copy(begin(backup_counts), end(backup_counts), begin(sim_counts));\n            }\n            \n            temp *= 0.9995;\n            if (temp < 0.5) temp = 0.5;\n        }\n    };\n    \n    // Run Stage 1\n    sa_step(L_STAGE1, T_STAGE1, 0.8);\n    \n    // --- PHASE 3: Full Simulation (0.8s - 1.9s) ---\n    // Apply best found so far to start Stage 2\n    // Note: sim_counts currently holds values for L_STAGE1. \n    // We need to re-run for L_TOTAL to get initial error and counts for this stage.\n    vector<int> T_FULL(N);\n    for(int i=0; i<N; ++i) T_FULL[i] = T[i];\n    \n    cur_sim_err = run_simulation(L_TOTAL, T_FULL);\n    copy(begin(sim_counts), end(sim_counts), begin(backup_counts));\n    \n    long long global_best_err = cur_sim_err;\n    copy(begin(A), end(A), begin(best_A));\n    copy(begin(B), end(B), begin(best_B));\n    \n    temp = 50.0; \n    \n    // Run Stage 2 loop\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > TIME_LIMIT) break;\n        \n        int u = -1, type = -1, new_v = -1, old_v = -1;\n        bool directed = false;\n        \n        // Move Logic (Same as Stage 1 but on full data)\n        if (rng.next_double() < 0.65) { \n            surplus.clear(); deficit.clear();\n            for(int i=0; i<N; ++i) {\n                if (sim_counts[i] > T_FULL[i]) surplus.push_back(i);\n                if (sim_counts[i] < T_FULL[i]) deficit.push_back(i);\n            }\n            if (!surplus.empty() && !deficit.empty()) {\n                int target_node = deficit[rng.next_int(deficit.size())];\n                int s = surplus[rng.next_int(surplus.size())];\n                for(int k=0; k<25; ++k) {\n                    int cand = rng.next_int(N);\n                    if (T[cand] == 0) continue;\n                    if (A[cand] == s) {\n                        u = cand; type = 0; old_v = s; new_v = target_node; directed = true; break;\n                    }\n                    if (T[cand] > 1 && B[cand] == s) {\n                        u = cand; type = 1; old_v = s; new_v = target_node; directed = true; break;\n                    }\n                }\n            }\n        }\n        \n        if (!directed) {\n            u = rng.next_int(N);\n            if (T[u] == 0) continue;\n            type = (T[u] > 1) ? rng.next_int(2) : 0;\n            old_v = (type == 0) ? A[u] : B[u];\n            new_v = rng.next_int(N);\n        }\n        \n        if (u == -1 || old_v == new_v) continue;\n        \n        if (type == 0) A[u] = new_v; else B[u] = new_v;\n        \n        long long next_err = run_simulation(L_TOTAL, T_FULL);\n        long long delta = next_err - cur_sim_err;\n        \n        if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n            cur_sim_err = next_err;\n            copy(begin(sim_counts), end(sim_counts), begin(backup_counts));\n            \n            if (cur_sim_err < global_best_err) {\n                global_best_err = cur_sim_err;\n                copy(begin(A), end(A), begin(best_A));\n                copy(begin(B), end(B), begin(best_B));\n            }\n        } else {\n            if (type == 0) A[u] = old_v; else B[u] = old_v;\n            copy(begin(backup_counts), end(backup_counts), begin(sim_counts));\n        }\n        \n        temp *= 0.9995;\n        if (temp < 0.5) temp = 0.5;\n    }\n\n    // Output\n    for(int i=0; i<N; ++i) {\n        cout << best_A[i] << \" \" << best_B[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <set>\n#include <array>\n\nusing namespace std;\n\n// --------------------------------------------------------------------------\n// Global Variables and Structs\n// --------------------------------------------------------------------------\nint N, M, Q, L, W;\nvector<int> G;\n\nstruct City {\n    int id;\n    int lx, rx, ly, ry;\n    int x, y; \n};\nvector<City> cities;\nvector<int> city_group; // city_id -> group_index\nvector<vector<int>> groups;\n\n// Precomputed KNN\n// Increasing K reduces the chance of disconnected sparse graph, increasing robustness of sparse MST calc.\nconst int K_NN = 40; \nconst int DENSE_THRESHOLD = 40; \n\nstruct Neighbor {\n    int to;\n    long long w_sq;\n};\nvector<vector<Neighbor>> knn_adj; \nvector<vector<int>> knn_simple; // Just IDs for SA guidance\n\n// --------------------------------------------------------------------------\n// Geometry & Utils\n// --------------------------------------------------------------------------\ninline long long dist_sq(int i, int j) {\n    long long dx = cities[i].x - cities[j].x;\n    long long dy = cities[i].y - cities[j].y;\n    return dx * dx + dy * dy;\n}\n\n// Hilbert Curve for spatial sorting\nlong long hilbert(int x, int y, int pow, int rotate) {\n    if (pow == 0) return 0;\n    int hpow = 1 << (pow - 1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rotate) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rotate + rotateDelta[seg]) & 3;\n    long long subSquareSize = 1LL << (2 * pow - 2);\n    long long ans = seg * subSquareSize;\n    long long add = hilbert(nx, ny, pow - 1, nrot);\n    ans += (seg == 1 || seg == 2) ? add : (subSquareSize - 1 - add);\n    return ans;\n}\n\n// --------------------------------------------------------------------------\n// DSU\n// --------------------------------------------------------------------------\nstruct DSU {\n    vector<int> p;\n    DSU(int n) : p(n, -1) {}\n    void reset() { fill(p.begin(), p.end(), -1); }\n    int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (p[x] > p[y]) swap(x, y);\n        p[x] += p[y];\n        p[y] = x;\n        return true;\n    }\n};\n\nDSU dsu_calc(805);\n\n// --------------------------------------------------------------------------\n// Cost Calculation\n// --------------------------------------------------------------------------\n\n// Dense Prim's Algorithm for small groups or fallback\ndouble compute_dense_mst(const vector<int>& grp) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    // Reuse static buffers to avoid allocation\n    static vector<long long> min_dist(805);\n    static vector<bool> visited(805);\n    \n    for(int i=0; i<k; ++i) {\n        min_dist[i] = 4e18; \n        visited[i] = false;\n    }\n    \n    min_dist[0] = 0;\n    double total = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        long long cur_min = 4e18;\n        \n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur_min) {\n                cur_min = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        if(i > 0) total += sqrt(cur_min);\n        \n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                long long d = dist_sq(city_u, grp[v]);\n                if(d < min_dist[v]) min_dist[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\n// Sparse Kruskal's using precomputed KNN\nstruct LocalEdge {\n    int u, v;\n    long long w_sq;\n    bool operator<(const LocalEdge& other) const { return w_sq < other.w_sq; }\n};\n\n// Static buffer to avoid allocation in hot loop\nvector<LocalEdge> edge_buffer;\n\ndouble compute_sparse_mst(const vector<int>& grp, int group_idx) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    edge_buffer.clear();\n    \n    // Gather edges from KNN graph restricted to current group\n    for(int u : grp) {\n        for(auto& nb : knn_adj[u]) {\n            int v = nb.to;\n            // Use u < v to avoid duplicates.\n            if (v > u && city_group[v] == group_idx) {\n                edge_buffer.push_back({u, v, nb.w_sq});\n            }\n        }\n    }\n    \n    // Quick check if enough edges exist to form a tree\n    if ((int)edge_buffer.size() < k - 1) return -1.0;\n    \n    sort(edge_buffer.begin(), edge_buffer.end());\n    \n    dsu_calc.reset();\n    int edges_count = 0;\n    double total = 0;\n    \n    for(const auto& e : edge_buffer) {\n        if(dsu_calc.unite(e.u, e.v)) {\n            total += sqrt(e.w_sq);\n            edges_count++;\n            if(edges_count == k - 1) return total;\n        }\n    }\n    \n    return -1.0; // Disconnected\n}\n\ndouble get_group_cost(const vector<int>& grp, int group_idx) {\n    if (grp.size() <= DENSE_THRESHOLD) {\n        return compute_dense_mst(grp);\n    } else {\n        double res = compute_sparse_mst(grp, group_idx);\n        if (res < 0) return compute_dense_mst(grp);\n        return res;\n    }\n}\n\n// --------------------------------------------------------------------------\n// Output / Query Logic\n// --------------------------------------------------------------------------\n// Standard MST for final output generation (always reliable)\nvector<pair<int, int>> get_mst_edges_final(const vector<int>& grp) {\n    if (grp.size() <= 1) return {};\n    int k = grp.size();\n    vector<long long> min_dist(k, 4e18);\n    vector<int> parent(k, -1);\n    vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        long long cur = 4e18;\n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur) {\n                cur = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                long long d = dist_sq(city_u, grp[v]);\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    vector<pair<int, int>> result;\n    for(int i=1; i<k; ++i) {\n        if(parent[i] != -1) result.push_back({grp[i], grp[parent[i]]});\n    }\n    return result;\n}\n\nvector<int> rem_nodes;\nvector<vector<int>> planned_queries;\nvector<vector<int>> adj_tree;\n\nvoid dfs_query(int u, int p) {\n    int subtree_start = rem_nodes.size();\n    for (int v : adj_tree[u]) {\n        if (v == p) continue;\n        dfs_query(v, u);\n    }\n    rem_nodes.push_back(u);\n    \n    int count = rem_nodes.size() - subtree_start; \n    while (count >= L) {\n        vector<int> q;\n        q.reserve(L);\n        q.push_back(u);\n        for(int i=0; i<L-1; ++i) {\n            q.push_back(rem_nodes[subtree_start]);\n            rem_nodes.erase(rem_nodes.begin() + subtree_start);\n        }\n        planned_queries.push_back(q);\n        count -= (L - 1);\n    }\n}\n\n// --------------------------------------------------------------------------\n// Main\n// --------------------------------------------------------------------------\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    edge_buffer.reserve(10000);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    cities.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cities[i].id = i;\n        cin >> cities[i].lx >> cities[i].rx >> cities[i].ly >> cities[i].ry;\n        cities[i].x = (cities[i].lx + cities[i].rx) / 2;\n        cities[i].y = (cities[i].ly + cities[i].ry) / 2;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // 1. Precompute KNN\n    vector<vector<pair<long long, int>>> dists(N);\n    for(int i=0; i<N; ++i) {\n        dists[i].reserve(N);\n        for(int j=0; j<N; ++j) {\n            if (i == j) continue;\n            dists[i].push_back({dist_sq(i, j), j});\n        }\n        // Sort/Select top K\n        int k_target = min((int)dists[i].size(), K_NN + 2);\n        nth_element(dists[i].begin(), dists[i].begin() + k_target, dists[i].end());\n        dists[i].resize(k_target);\n    }\n\n    knn_adj.resize(N);\n    knn_simple.resize(N);\n    for(int i=0; i<N; ++i) {\n        for(auto& p : dists[i]) {\n            knn_adj[i].push_back({p.second, p.first});\n            knn_simple[i].push_back(p.second);\n        }\n    }\n\n    // 2. Initial Grouping (Hilbert Sort)\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int i, int j) {\n        return hilbert(cities[i].x, cities[i].y, 14, 0) < hilbert(cities[j].x, cities[j].y, 14, 0);\n    });\n\n    groups.resize(M);\n    city_group.resize(N);\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].reserve(G[i] + 16);\n        for (int k = 0; k < G[i]; ++k) {\n            int u = p[current_idx++];\n            groups[i].push_back(u);\n            city_group[u] = i;\n        }\n    }\n\n    // 3. Simulated Annealing\n    vector<double> group_costs(M);\n    double total_cost = 0;\n    for(int i=0; i<M; ++i) {\n        group_costs[i] = get_group_cost(groups[i], i);\n        total_cost += group_costs[i];\n    }\n\n    mt19937 rng(42);\n    double time_limit = 1.70;\n    double start_temp = 300.0;\n    double end_temp = 0.0;\n\n    int iter = 0;\n    while(true) {\n        iter++;\n        if ((iter & 511) == 0) {\n            double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        int u = uniform_int_distribution<int>(0, N - 1)(rng);\n        int g1 = city_group[u];\n        \n        int g2 = -1;\n        int v = -1;\n        \n        // Smart Neighbor Swap Strategy\n        bool smart_swap = false;\n        if (uniform_real_distribution<double>(0, 1)(rng) < 0.6) {\n            if (!knn_simple[u].empty()) {\n                int idx = uniform_int_distribution<int>(0, knn_simple[u].size() - 1)(rng);\n                int neighbor = knn_simple[u][idx];\n                if (city_group[neighbor] != g1) {\n                    g2 = city_group[neighbor];\n                    // Pick random v in g2 to swap out\n                    int idx_v = uniform_int_distribution<int>(0, groups[g2].size() - 1)(rng);\n                    v = groups[g2][idx_v];\n                    smart_swap = true;\n                }\n            }\n        }\n        \n        if (!smart_swap) {\n            g2 = uniform_int_distribution<int>(0, M - 1)(rng);\n            if (g1 == g2) continue;\n            int idx_v = uniform_int_distribution<int>(0, groups[g2].size() - 1)(rng);\n            v = groups[g2][idx_v];\n        }\n        \n        int idx_u = -1;\n        for(int k=0; k<(int)groups[g1].size(); ++k) if(groups[g1][k] == u) { idx_u = k; break; }\n        \n        int idx_v_in_g2 = -1;\n        for(int k=0; k<(int)groups[g2].size(); ++k) if(groups[g2][k] == v) { idx_v_in_g2 = k; break; }\n        \n        // Perform Swap\n        swap(groups[g1][idx_u], groups[g2][idx_v_in_g2]);\n        city_group[u] = g2;\n        city_group[v] = g1;\n        \n        double new_cost_g1 = get_group_cost(groups[g1], g1);\n        double new_cost_g2 = get_group_cost(groups[g2], g2);\n        \n        double diff = (new_cost_g1 + new_cost_g2) - (group_costs[g1] + group_costs[g2]);\n        \n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n        double ratio = elapsed / time_limit;\n        double temp = start_temp * (1.0 - ratio);\n        if (temp < 1e-9) temp = 1e-9;\n        \n        if (diff < 0 || bernoulli_distribution(exp(-diff / temp))(rng)) {\n            total_cost += diff;\n            group_costs[g1] = new_cost_g1;\n            group_costs[g2] = new_cost_g2;\n        } else {\n            // Revert Swap\n            swap(groups[g1][idx_u], groups[g2][idx_v_in_g2]);\n            city_group[u] = g1;\n            city_group[v] = g2;\n        }\n    }\n\n    // 4. Query Planning\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if ((int)groups[i].size() <= L) {\n            planned_queries.push_back(groups[i]);\n            continue;\n        }\n        \n        vector<pair<int, int>> mst = get_mst_edges_final(groups[i]);\n        adj_tree.assign(N, {});\n        for (auto& e : mst) {\n            adj_tree[e.first].push_back(e.second);\n            adj_tree[e.second].push_back(e.first);\n        }\n        \n        rem_nodes.clear();\n        dfs_query(groups[i][0], -1);\n        \n        while (!rem_nodes.empty()) {\n            if ((int)rem_nodes.size() <= L) {\n                if (rem_nodes.size() > 1) planned_queries.push_back(rem_nodes);\n                rem_nodes.clear();\n            } else {\n                vector<int> q;\n                q.reserve(L);\n                for(int k=0; k<L; ++k) q.push_back(rem_nodes[k]);\n                planned_queries.push_back(q);\n                rem_nodes.erase(rem_nodes.begin(), rem_nodes.begin() + L - 1);\n            }\n        }\n    }\n    \n    shuffle(planned_queries.begin(), planned_queries.end(), rng);\n    int queries_to_run = min((int)planned_queries.size(), Q);\n    \n    vector<vector<pair<int, int>>> confirmed_edges(M);\n    \n    for(int i=0; i<queries_to_run; ++i) {\n        cout << \"? \" << planned_queries[i].size();\n        for(int c : planned_queries[i]) cout << \" \" << c;\n        cout << endl;\n        \n        for(size_t k=0; k<planned_queries[i].size()-1; ++k) {\n            int u, v;\n            cin >> u >> v;\n            confirmed_edges[city_group[u]].push_back({u, v});\n        }\n    }\n\n    // 5. Output Answers\n    cout << \"!\" << endl;\n    for(int i=0; i<M; ++i) {\n        for(size_t k=0; k<groups[i].size(); ++k) {\n            cout << groups[i][k] << (k==groups[i].size()-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n        \n        // Build final graph using confirmed edges first, then estimated MST edges\n        struct FinEdge {\n            int u, v;\n            double w;\n            bool operator<(const FinEdge& o) const { return w < o.w; }\n        };\n        vector<FinEdge> cands;\n        cands.reserve(groups[i].size() * 2);\n        \n        for(auto& e : confirmed_edges[i]) {\n            cands.push_back({e.first, e.second, -1.0}); // Priority\n        }\n        \n        vector<pair<int, int>> est = get_mst_edges_final(groups[i]);\n        for(auto& e : est) {\n            double w = sqrt(dist_sq(e.first, e.second));\n            cands.push_back({e.first, e.second, w});\n        }\n        \n        sort(cands.begin(), cands.end());\n        \n        dsu_calc.reset();\n        int added = 0;\n        int needed = groups[i].size() - 1;\n        if (needed < 0) needed = 0;\n        \n        for(auto& e : cands) {\n            if(dsu_calc.unite(e.u, e.v)) {\n                cout << e.u << \" \" << e.v << \"\\n\";\n                added++;\n                if(added == needed) break;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <map>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n    bool operator<(const Point& other) const { return tie(r, c) < tie(other.r, other.c); }\n};\n\nstruct State {\n    int dist;\n    int r, c;\n    bool operator>(const State& other) const { return dist > other.dist; }\n};\n\nstruct Action {\n    char type; // 'M', 'S', 'A'\n    char dir;  // 'U', 'D', 'L', 'R'\n};\n\nPoint start_pos;\nbool grid[N][N]; // true if block present\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dir_chars[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Simulate sliding from (r, c) in direction d\nPoint get_slide_end(int r, int c, int d, const bool current_grid[N][N]) {\n    int cr = r, cc = c;\n    while (true) {\n        int nr = cr + dr[d];\n        int nc = cc + dc[d];\n        if (!is_valid(nr, nc) || current_grid[nr][nc]) {\n            return {cr, cc};\n        }\n        cr = nr;\n        cc = nc;\n    }\n}\n\nstruct Node {\n    int dist = 1e9;\n    Point parent = {-1, -1};\n    Action action = {' ', ' '};\n    bool break_block = false; // If true, action was Move into block (breaking it)\n};\n\n// Run Dijkstra from start_p with current grid\nvoid run_dijkstra(Point start_p, const bool current_grid[N][N], Node nodes[N][N]) {\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) nodes[i][j] = Node();\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    nodes[start_p.r][start_p.c].dist = 0;\n    pq.push({0, start_p.r, start_p.c});\n\n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        int r = top.r;\n        int c = top.c;\n        int d = top.dist;\n\n        if (d > nodes[r][c].dist) continue;\n\n        // Moves & Breaks\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k];\n            int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int cost = 1;\n                bool is_break = false;\n                if (current_grid[nr][nc]) {\n                    cost = 2;\n                    is_break = true;\n                }\n                if (nodes[nr][nc].dist > d + cost) {\n                    nodes[nr][nc].dist = d + cost;\n                    nodes[nr][nc].parent = {r, c};\n                    nodes[nr][nc].action = {'M', dir_chars[k]};\n                    nodes[nr][nc].break_block = is_break;\n                    pq.push({nodes[nr][nc].dist, nr, nc});\n                }\n            }\n        }\n\n        // Slides\n        for (int k = 0; k < 4; ++k) {\n            Point end_p = get_slide_end(r, c, k, current_grid);\n            if (end_p.r != r || end_p.c != c) {\n                if (nodes[end_p.r][end_p.c].dist > d + 1) {\n                    nodes[end_p.r][end_p.c].dist = d + 1;\n                    nodes[end_p.r][end_p.c].parent = {r, c};\n                    nodes[end_p.r][end_p.c].action = {'S', dir_chars[k]};\n                    nodes[end_p.r][end_p.c].break_block = false;\n                    pq.push({nodes[end_p.r][end_p.c].dist, end_p.r, end_p.c});\n                }\n            }\n        }\n    }\n}\n\nvector<Action> reconstruct_path(Point start_p, Point end_p, Node nodes[N][N], vector<Point>& path_points) {\n    vector<Action> path;\n    Point cur = end_p;\n    while (cur != start_p) {\n        Node& n = nodes[cur.r][cur.c];\n        path_points.push_back(cur);\n        if (n.break_block) {\n            path.push_back({'M', n.action.dir});\n            path.push_back({'A', n.action.dir});\n        } else {\n            path.push_back(n.action);\n        }\n        cur = n.parent;\n    }\n    path_points.push_back(start_p);\n    reverse(path.begin(), path.end());\n    reverse(path_points.begin(), path_points.end());\n    return path;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    int _n, _m;\n    if (!(cin >> _n >> _m)) return 0;\n    \n    cin >> start_pos.r >> start_pos.c;\n    \n    vector<Point> all_points(M);\n    all_points[0] = start_pos;\n    for(int k=1; k<M; ++k) {\n        cin >> all_points[k].r >> all_points[k].c;\n    }\n\n    for(int i=0; i<N; ++i) fill(grid[i], grid[i]+N, false);\n\n    Point current_pos = start_pos;\n    \n    vector<pair<char, char>> final_actions;\n\n    for (int k = 1; k < M; ++k) {\n        Point target = all_points[k];\n        \n        // 1. Standard Dijkstra\n        static Node nodes_std[N][N];\n        run_dijkstra(current_pos, grid, nodes_std);\n        \n        int best_cost = nodes_std[target.r][target.c].dist;\n        bool use_helper = false;\n        \n        Point best_helper_B = {-1, -1};\n        Point best_helper_NB = {-1, -1};\n        Point best_helper_L = {-1, -1};\n        Node nodes_helper[N][N];\n        \n        // 2. Helper Block Strategy\n        // Try to place a block at neighbor B of Target to enable sliding\n        for (int d = 0; d < 4; ++d) {\n            int br = target.r + dr[d];\n            int bc = target.c + dc[d];\n            \n            if (!is_valid(br, bc)) continue;\n            if (grid[br][bc]) continue; \n            \n            Point B = {br, bc};\n            \n            // Need to reach a neighbor of B to place it\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int nbr = br + dr[d2];\n                int nbc = bc + dc[d2];\n                if (!is_valid(nbr, nbc)) continue;\n                \n                Point NB = {nbr, nbc};\n                int cost_to_NB = nodes_std[nbr][nbc].dist;\n                if (cost_to_NB > 1e8) continue;\n                \n                // Temporarily assume B is blocked for distance calculation from NB\n                static Node nodes_local[N][N];\n                bool saved_val = grid[br][bc];\n                grid[br][bc] = true;\n                run_dijkstra(NB, grid, nodes_local);\n                grid[br][bc] = saved_val;\n                \n                // Find valid Launch position L\n                // To hit B from L via Slide, L must be upstream.\n                // Slide direction must be 'd' (towards B).\n                // L = G - k * vec[d].\n                int opp_d;\n                if (d==0) opp_d=1; else if(d==1) opp_d=0; else if(d==2) opp_d=3; else opp_d=2;\n                \n                int curr = target.r + dr[opp_d];\n                int curc = target.c + dc[opp_d];\n                \n                while (is_valid(curr, curc)) {\n                    if (grid[curr][curc]) break; \n                    \n                    int cost_NB_L = nodes_local[curr][curc].dist;\n                    if (cost_NB_L < 1e8) {\n                        int total_helper = cost_to_NB + 1 + cost_NB_L + 1; // 1 Alter, 1 Slide\n                        if (total_helper < best_cost) {\n                            best_cost = total_helper;\n                            use_helper = true;\n                            best_helper_B = B;\n                            best_helper_NB = NB;\n                            best_helper_L = {curr, curc};\n                            for(int ii=0; ii<N; ++ii) for(int jj=0; jj<N; ++jj) nodes_helper[ii][jj] = nodes_local[ii][jj];\n                        }\n                    }\n                    curr += dr[opp_d];\n                    curc += dc[opp_d];\n                }\n            }\n        }\n\n        // 3. Execute Plan\n        auto execute_move = [&](char type, char dir, Point& pos) {\n            if (type == 'A') {\n                 int nr = pos.r, nc = pos.c;\n                 if (dir == 'U') nr--; else if (dir == 'D') nr++; else if (dir == 'L') nc--; else if (dir == 'R') nc++;\n                 if (is_valid(nr, nc)) grid[nr][nc] = !grid[nr][nc];\n            } else if (type == 'M') {\n                 if (dir == 'U') pos.r--; else if (dir == 'D') pos.r++; else if (dir == 'L') pos.c--; else if (dir == 'R') pos.c++;\n            } else if (type == 'S') {\n                 pos = get_slide_end(pos.r, pos.c, (dir=='U'?0:(dir=='D'?1:(dir=='L'?2:3))), grid);\n            }\n            final_actions.push_back({type, dir});\n        };\n\n        if (use_helper) {\n            vector<Point> pts;\n            vector<Action> p1 = reconstruct_path(current_pos, best_helper_NB, nodes_std, pts);\n            for (auto a : p1) execute_move(a.type, a.dir, current_pos);\n            \n            // Alter B\n            int d_alter = -1;\n            for(int dd=0; dd<4; ++dd) if (best_helper_NB.r + dr[dd] == best_helper_B.r && best_helper_NB.c + dc[dd] == best_helper_B.c) d_alter = dd;\n            execute_move('A', dir_chars[d_alter], current_pos);\n            \n            vector<Point> pts2;\n            vector<Action> p2 = reconstruct_path(best_helper_NB, best_helper_L, nodes_helper, pts2);\n            for (auto a : p2) execute_move(a.type, a.dir, current_pos);\n            \n            // Slide to Target\n            int d_slide = -1;\n            if (target.r > best_helper_L.r) d_slide = 1;\n            else if (target.r < best_helper_L.r) d_slide = 0;\n            else if (target.c > best_helper_L.c) d_slide = 3;\n            else d_slide = 2;\n            execute_move('S', dir_chars[d_slide], current_pos);\n\n        } else {\n            vector<Point> pts;\n            vector<Action> p = reconstruct_path(current_pos, target, nodes_std, pts);\n            for (auto a : p) execute_move(a.type, a.dir, current_pos);\n        }\n    }\n    \n    for(auto p : final_actions) {\n        cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}"},"8":{"ahc001":"/**\n * Solution for AtCoder Heuristic Contest 001\n * Algorithm: Randomized Recursive BSP with Coordinate Descent Optimization\n * \n * Key Features:\n * 1. BSP Construction: Recursively splits the space into rectangles. Considers splits along both X and Y axes.\n *    Split positions are chosen based on the ratio of required areas, with randomness added to explore different topologies.\n * 2. Optimization: Uses coordinate descent to iteratively adjust split positions in the tree.\n *    - Maximizes a score function that penalizes areas deviating from the target.\n *    - Adds a tiny penalty for areas > target to encourage \"slack\" distribution.\n *    - Uses an expanded local search around the ideal split position.\n * 3. Post-Processing: Shrinks rectangles larger than the target area to perfectly match the target area if possible, \n *    while ensuring the required point remains inside.\n * 4. Restarts: The process is repeated with different random seeds until the time limit is reached.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\n// --- Constants & Globals ---\nconst int W = 10000;\nconst int H = 10000;\n// Time limit allows for multiple restarts to explore different tree topologies\nconst double TIME_LIMIT = 4.95;\n\nstruct Point {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    inline long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n};\n\nint N;\nvector<Point> points;\n\n// Fast Random Number Generator (Xorshift128+)\nuint64_t xor_state[2] = {0x123456789LL, 0x987654321LL};\ninline uint64_t xorshift() {\n    uint64_t s1 = xor_state[0];\n    uint64_t s0 = xor_state[1];\n    xor_state[0] = s0;\n    s1 ^= s1 << 23;\n    xor_state[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);\n    return xor_state[1] + s0;\n}\ninline int rand_int(int n) { return xorshift() % n; }\ninline double rand_double() { return (xorshift() & 0xFFFFFFFFFFF) * (1.0 / 17592186044416.0); }\n\n// Score calculation for optimization phase\n// If area s >= r, we return ~1.0 but with a tiny penalty for excess area.\n// This encourages the optimizer to give \"slack\" space to neighbors who might need it,\n// effectively centering the slack distribution.\ninline double calc_leaf_score_opt(int r, long long s) {\n    if (s >= r) {\n        return 1.0 - 1e-9 * ((double)(s - r) / r);\n    }\n    double ratio = (double)s / r;\n    double tmp = 1.0 - ratio;\n    return 1.0 - tmp * tmp;\n}\n\n// Official score calculation logic (for final evaluation)\ninline double calc_leaf_score_official(int r, long long s) {\n    if (s >= r) return 1.0;\n    double ratio = (double)s / r;\n    double tmp = 1.0 - ratio;\n    return 1.0 - tmp * tmp;\n}\n\nstruct Node {\n    bool is_leaf;\n    int p_idx;           // For leaf: index into 'points'\n    int child_l, child_r; // For internal: indices into 'pool'\n    int axis;            // 0: x-axis, 1: y-axis\n    int split_pos;\n    Rect box;\n};\n\n// Static memory pool to avoid allocation overhead during restarts\nNode pool[2000]; \nint pool_ptr = 0;\ninline int new_node() { return pool_ptr++; }\n\nstruct Solution {\n    Rect rects[205];\n    double score;\n};\nSolution best_sol;\n\n// Auxiliary buffers for optimization\nvector<int> node_leaves[2000];\nlong long node_req_area[2000];\n\n// --- Construction Phase ---\n\nint build(const vector<int>& p_idxs, Rect r) {\n    int u = new_node();\n    pool[u].box = r;\n    \n    if (p_idxs.size() == 1) {\n        pool[u].is_leaf = true;\n        pool[u].p_idx = p_idxs[0];\n        return u;\n    }\n    pool[u].is_leaf = false;\n\n    long long total_r = 0;\n    for(int idx : p_idxs) total_r += points[idx].r;\n\n    struct Cand { int axis; int pos; double cost; };\n    static Cand cands[1024];\n    int cand_cnt = 0;\n    \n    int width = r.x2 - r.x1;\n    int height = r.y2 - r.y1;\n\n    auto analyze = [&](int axis) {\n        static vector<int> sorted;\n        if (sorted.capacity() < p_idxs.size()) sorted.reserve(p_idxs.size());\n        sorted = p_idxs;\n        \n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n\n        long long current_r = 0;\n        int start = (axis==0) ? r.x1 : r.y1;\n        int len = (axis==0) ? width : height;\n\n        for(size_t i=0; i<sorted.size()-1; ++i) {\n            current_r += points[sorted[i]].r;\n            int p1 = (axis==0) ? points[sorted[i]].x : points[sorted[i]].y;\n            int p2 = (axis==0) ? points[sorted[i+1]].x : points[sorted[i+1]].y;\n            \n            if (p1 >= p2) continue;\n            \n            int mn = p1 + 1;\n            int mx = p2;\n            if (mn > mx) continue;\n\n            // Calculate ideal split position based on area requirements\n            double ratio = (double)current_r / total_r;\n            int ideal = start + (int)(len * ratio);\n            int pos = std::clamp(ideal, mn, mx);\n            double cost = std::abs(pos - ideal);\n            \n            // Heuristic: mildly penalize splitting very thin rectangles along the short axis\n            if (axis == 0 && width < height * 0.5) cost += width * 0.1;\n            if (axis == 1 && height < width * 0.5) cost += height * 0.1;\n\n            if (cand_cnt < 1024) {\n                cands[cand_cnt++] = {axis, pos, cost};\n            }\n        }\n    };\n\n    // Evaluate candidates on both axes\n    analyze(0);\n    analyze(1);\n\n    int axis, pos;\n    if (cand_cnt == 0) {\n        // Fallback logic if no valid inter-point cut found (should not happen with distinct integers)\n        axis = (width > height) ? 0 : 1;\n        static vector<int> sorted; sorted = p_idxs;\n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n        \n        int mid = sorted.size() / 2;\n        int p1 = (axis==0) ? points[sorted[mid-1]].x : points[sorted[mid-1]].y;\n        int p2 = (axis==0) ? points[sorted[mid]].x : points[sorted[mid]].y;\n        pos = std::clamp((p1 + p2 + 1) / 2, (axis==0?r.x1:r.y1)+1, (axis==0?r.x2:r.y2)-1);\n    } else {\n        sort(cands, cands + cand_cnt, [](const Cand& a, const Cand& b){ return a.cost < b.cost; });\n        \n        // Probabilistic selection: Favor lower cost but allow exploration\n        int k = min(cand_cnt, 6);\n        int idx = 0;\n        double p = rand_double();\n        if (p < 0.5) idx = 0; // 50% chance to pick best\n        else if (p < 0.75 && k > 1) idx = 1; // 25% chance to pick 2nd best\n        else idx = rand_int(k);\n        \n        axis = cands[idx].axis;\n        pos = cands[idx].pos;\n    }\n\n    pool[u].axis = axis;\n    pool[u].split_pos = pos;\n\n    vector<int> L, R;\n    L.reserve(p_idxs.size());\n    R.reserve(p_idxs.size());\n    for(int idx : p_idxs) {\n        int v = (axis==0) ? points[idx].x : points[idx].y;\n        if (v < pos) L.push_back(idx);\n        else R.push_back(idx);\n    }\n    \n    // Safety fallback if one side ends up empty\n    if (L.empty() || R.empty()) {\n        static vector<int> sorted; sorted = p_idxs;\n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n        L.assign(sorted.begin(), sorted.begin() + sorted.size()/2);\n        R.assign(sorted.begin() + sorted.size()/2, sorted.end());\n    }\n\n    Rect rL = r, rR = r;\n    if (axis == 0) { rL.x2 = pos; rR.x1 = pos; }\n    else           { rL.y2 = pos; rR.y1 = pos; }\n\n    pool[u].child_l = build(L, rL);\n    pool[u].child_r = build(R, rR);\n\n    return u;\n}\n\n// --- Optimization Phase ---\n\nvoid precompute(int u) {\n    node_leaves[u].clear();\n    if (pool[u].is_leaf) {\n        node_leaves[u].push_back(u);\n        node_req_area[u] = points[pool[u].p_idx].r;\n        return;\n    }\n    precompute(pool[u].child_l);\n    precompute(pool[u].child_r);\n    node_req_area[u] = node_req_area[pool[u].child_l] + node_req_area[pool[u].child_r];\n    node_leaves[u].reserve(node_leaves[pool[u].child_l].size() + node_leaves[pool[u].child_r].size());\n    node_leaves[u].insert(node_leaves[u].end(), node_leaves[pool[u].child_l].begin(), node_leaves[pool[u].child_l].end());\n    node_leaves[u].insert(node_leaves[u].end(), node_leaves[pool[u].child_r].begin(), node_leaves[pool[u].child_r].end());\n}\n\nvoid update_boxes(int u, Rect r) {\n    pool[u].box = r;\n    if (pool[u].is_leaf) return;\n    Rect rL = r, rR = r;\n    if (pool[u].axis == 0) { rL.x2 = pool[u].split_pos; rR.x1 = pool[u].split_pos; }\n    else                   { rL.y2 = pool[u].split_pos; rR.y1 = pool[u].split_pos; }\n    update_boxes(pool[u].child_l, rL);\n    update_boxes(pool[u].child_r, rR);\n}\n\nvoid optimize(int root) {\n    precompute(root);\n    vector<int> inodes;\n    vector<int> q = {root};\n    size_t h = 0;\n    while(h < q.size()){\n        int u = q[h++];\n        if(!pool[u].is_leaf){\n            inodes.push_back(u);\n            q.push_back(pool[u].child_l);\n            q.push_back(pool[u].child_r);\n        }\n    }\n\n    int MAX_PASS = 60; \n    for(int pass=0; pass<MAX_PASS; ++pass) {\n        bool changed = false;\n        for(int u : inodes) {\n            int mn = -2e9, mx = 2e9;\n            int ax = pool[u].axis;\n            \n            // Identify valid split range\n            for(int lf : node_leaves[pool[u].child_l]) {\n                int v = (ax==0) ? points[pool[lf].p_idx].x : points[pool[lf].p_idx].y;\n                if (v > mn) mn = v;\n            }\n            for(int lf : node_leaves[pool[u].child_r]) {\n                int v = (ax==0) ? points[pool[lf].p_idx].x : points[pool[lf].p_idx].y;\n                if (v < mx) mx = v;\n            }\n            mn++;\n            if (mn > mx) continue;\n\n            int cur = pool[u].split_pos;\n            Rect r = pool[u].box;\n            int start = (ax==0) ? r.x1 : r.y1;\n            int end = (ax==0) ? r.x2 : r.y2;\n            \n            double ratio = (double)node_req_area[pool[u].child_l] / node_req_area[u];\n            int ideal = start + (int)((end - start) * ratio);\n            ideal = std::clamp(ideal, mn, mx);\n\n            // Expanded local search\n            static int tests[20];\n            int n_tests = 0;\n            tests[n_tests++] = ideal;\n            if (cur != ideal) tests[n_tests++] = cur;\n            \n            for (int d : {-2, -1, 1, 2}) {\n                if (ideal+d >= mn && ideal+d <= mx) tests[n_tests++] = ideal+d;\n                if (cur+d >= mn && cur+d <= mx) tests[n_tests++] = cur+d;\n            }\n            if (std::abs(cur - ideal) > 5) {\n                int mid = (cur + ideal) / 2;\n                if (mid >= mn && mid <= mx) tests[n_tests++] = mid;\n            }\n            \n            sort(tests, tests+n_tests);\n            n_tests = unique(tests, tests+n_tests) - tests;\n            \n            double best_s = -100.0;\n            int best_p = cur;\n            \n            // Calculate baseline score\n            double base_s = 0;\n            for(int lf : node_leaves[u]) base_s += calc_leaf_score_opt(points[pool[lf].p_idx].r, pool[lf].box.area());\n            best_s = base_s;\n\n            // Evaluate candidates\n            for(int i=0; i<n_tests; ++i) {\n                int p = tests[i];\n                if (p == cur) continue;\n                \n                pool[u].split_pos = p;\n                update_boxes(u, r);\n                \n                double s = 0;\n                for(int lf : node_leaves[u]) s += calc_leaf_score_opt(points[pool[lf].p_idx].r, pool[lf].box.area());\n                \n                if (s > best_s + 1e-10) {\n                    best_s = s;\n                    best_p = p;\n                }\n            }\n            \n            if (best_p != cur) {\n                pool[u].split_pos = best_p;\n                update_boxes(u, r);\n                changed = true;\n            } else {\n                pool[u].split_pos = cur;\n                update_boxes(u, r);\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if (!(cin >> N)) return 0;\n    points.resize(N);\n    vector<int> p_idxs(N);\n    for(int i=0; i<N; ++i) {\n        cin >> points[i].x >> points[i].y >> points[i].r;\n        points[i].id = i;\n        p_idxs[i] = i;\n    }\n\n    best_sol.score = -1.0;\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // Restart loop\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > TIME_LIMIT) break;\n        \n        pool_ptr = 0;\n        int root = build(p_idxs, {0, 0, W, H});\n        \n        optimize(root);\n        \n        double current_official_score = 0;\n        static Rect sol[205];\n        \n        for(int i=0; i<pool_ptr; ++i) {\n            if (pool[i].is_leaf) {\n                int pid = pool[i].p_idx;\n                Rect r = pool[i].box;\n                int req = points[pid].r;\n                \n                // Greedy Shrink: Reduce excess area\n                if (r.area() > req) {\n                    while (r.area() > req) {\n                        int dl = points[pid].x - r.x1;\n                        int dr = r.x2 - 1 - points[pid].x;\n                        int du = points[pid].y - r.y1;\n                        int dd = r.y2 - 1 - points[pid].y;\n                        \n                        int mv = -1; \n                        int max_dist = -1;\n                        \n                        // Shrink from side furthest from point\n                        if (dl > 0 && dl > max_dist) { max_dist = dl; mv = 0; }\n                        if (dr > 0 && dr > max_dist) { max_dist = dr; mv = 1; }\n                        if (du > 0 && du > max_dist) { max_dist = du; mv = 2; }\n                        if (dd > 0 && dd > max_dist) { max_dist = dd; mv = 3; }\n                        \n                        if (mv == -1) break;\n                        \n                        if (mv == 0) r.x1++;\n                        else if (mv == 1) r.x2--;\n                        else if (mv == 2) r.y1++;\n                        else r.y2--;\n                    }\n                }\n                \n                sol[pid] = r;\n                current_official_score += calc_leaf_score_official(req, r.area());\n            }\n        }\n        \n        double final_s = 1e9 * current_official_score / N;\n        if (final_s > best_sol.score) {\n            best_sol.score = final_s;\n            for(int i=0; i<N; ++i) best_sol.rects[i] = sol[i];\n        }\n    }\n    \n    for(int i=0; i<N; ++i) {\n        cout << best_sol.rects[i].x1 << \" \" << best_sol.rects[i].y1 << \" \"\n             << best_sol.rects[i].x2 << \" \" << best_sol.rects[i].y2 << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <array>\n#include <cstring>\n\nusing namespace std;\n\n// ==========================================\n// Constants & Configuration\n// ==========================================\nconst int N = 50;\nconst int NUM_CELLS = N * N;\nconst int MAX_TILES = 2500;\n// Time limit strictly set to leave margin for I/O and checks\nconst double TIME_LIMIT = 1.95; \n\n// Diversity constraint: Max candidates per cell per step\n// Increased to 4 to allow more distinct visited-sets to survive\nconst int MAX_PER_CELL = 4; \n// Beam Width increased to 6000 for maximum exploration\nconst int BEAM_WIDTH = 6000;    \n\n// ==========================================\n// Data Structures\n// ==========================================\n\n// Precomputed Adjacency for grid graph\nstruct Neighbors {\n    int count;\n    array<int, 4> to;\n    array<char, 4> dir;\n};\n\n// Tree node for efficient path reconstruction\nstruct TreeNode {\n    int parent;\n    char dir;\n};\n\n// Heavy State: Persists in Beam\nstruct State {\n    int u;              // Current cell index\n    int real_score;     // Actual accumulated score\n    int eval_score;     // Score with noise\n    int tree_idx;       // Index in global tree\n    uint64_t hash;      // Zobrist hash of visited set\n    bitset<MAX_TILES> visited; // Bitset copy is the main cost\n};\n\n// Lightweight Candidate: For Expansion & Pruning\nstruct Candidate {\n    int eval_score;\n    int real_score;\n    int parent_idx;     // Index in current_beam\n    int u;              // Target cell index\n    int new_tile;       // Target tile ID\n    char dir;           // Move direction\n    uint64_t hash;      // New Zobrist hash\n};\n\n// Flat Bucket for Pruning (Zero Allocation)\nstruct Bucket {\n    int count;\n    int scores[MAX_PER_CELL];\n    int indices[MAX_PER_CELL];\n    uint64_t hashes[MAX_PER_CELL]; // Store hash to detect duplicates\n};\n\n// ==========================================\n// Global Variables & Buffers\n// ==========================================\nint tile_id[NUM_CELLS];\nint base_score[NUM_CELLS];\nint iter_score[NUM_CELLS];\nNeighbors graph[NUM_CELLS];\nuint64_t zobrist[MAX_TILES]; // Zobrist keys for each tile\n\n// Pre-allocated buffers\nvector<TreeNode> tree;\nvector<State> beam_curr;\nvector<State> beam_next;\nvector<Candidate> candidates;\nvector<int> survivors;\n\n// Spatial pruning structures\nBucket buckets[NUM_CELLS];\nvector<int> touched_buckets;\n\nmt19937 rng(12345);\n\n// ==========================================\n// Main Implementation\n// ==========================================\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::system_clock::now();\n\n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    int start_node = si * N + sj;\n\n    // Read Inputs\n    for (int i = 0; i < NUM_CELLS; ++i) cin >> tile_id[i];\n    for (int i = 0; i < NUM_CELLS; ++i) cin >> base_score[i];\n\n    // Initialize Zobrist Hashing Keys\n    mt19937_64 hash_rng(12345);\n    for(int i=0; i<MAX_TILES; ++i) zobrist[i] = hash_rng();\n\n    // Build Graph (Precompute neighbors)\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            int cnt = 0;\n            if (r > 0) { graph[u].to[cnt] = u - N; graph[u].dir[cnt] = 'U'; cnt++; }\n            if (r < N - 1) { graph[u].to[cnt] = u + N; graph[u].dir[cnt] = 'D'; cnt++; }\n            if (c > 0) { graph[u].to[cnt] = u - 1; graph[u].dir[cnt] = 'L'; cnt++; }\n            if (c < N - 1) { graph[u].to[cnt] = u + 1; graph[u].dir[cnt] = 'R'; cnt++; }\n            graph[u].count = cnt;\n        }\n    }\n\n    // Allocations\n    beam_curr.reserve(BEAM_WIDTH);\n    beam_next.reserve(BEAM_WIDTH);\n    candidates.reserve(BEAM_WIDTH * 4);\n    tree.reserve(8000000); \n    touched_buckets.reserve(NUM_CELLS);\n    survivors.reserve(BEAM_WIDTH + 1000);\n\n    // Init buckets\n    for(int i=0; i<NUM_CELLS; ++i) buckets[i].count = 0;\n\n    uniform_int_distribution<int> noise_dist(0, 25);\n\n    int best_score_final = -1;\n    string best_path_final = \"\";\n    \n    int iter = 0;\n\n    // Main Iterative Loop\n    while (true) {\n        // Global time check\n        auto now = chrono::system_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0 > TIME_LIMIT) break;\n\n        iter++;\n        // 1. Iteration Setup: Perturb scores with noise\n        if (iter == 1) {\n            for (int i = 0; i < NUM_CELLS; ++i) iter_score[i] = base_score[i];\n        } else {\n            for (int i = 0; i < NUM_CELLS; ++i) iter_score[i] = base_score[i] + noise_dist(rng);\n        }\n\n        // 2. Reset Search\n        beam_curr.clear();\n        tree.clear();\n        \n        State start_s;\n        start_s.u = start_node;\n        start_s.real_score = base_score[start_node];\n        start_s.eval_score = iter_score[start_node];\n        start_s.tree_idx = -1;\n        start_s.hash = zobrist[tile_id[start_node]];\n        start_s.visited.reset();\n        start_s.visited.set(tile_id[start_node]);\n        \n        beam_curr.push_back(start_s);\n\n        if (start_s.real_score > best_score_final) {\n            best_score_final = start_s.real_score;\n            best_path_final = \"\";\n        }\n\n        // 3. Beam Search Steps\n        for (int step = 0; step < MAX_TILES; ++step) {\n            if (beam_curr.empty()) break;\n            \n            // Periodic time check\n            if ((step & 31) == 0) {\n                 if (chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - start_time).count() / 1000.0 > TIME_LIMIT) goto finish;\n            }\n\n            candidates.clear();\n            touched_buckets.clear();\n\n            // 3a. Expansion\n            for (int i = 0; i < (int)beam_curr.size(); ++i) {\n                const auto& s = beam_curr[i];\n                const int u_tile = tile_id[s.u];\n                const auto& nbrs = graph[s.u];\n\n                for (int k = 0; k < nbrs.count; ++k) {\n                    int v = nbrs.to[k];\n                    int v_tile = tile_id[v];\n\n                    // Validity check: Must cross tile boundary & tile must be unvisited\n                    if (u_tile != v_tile && !s.visited.test(v_tile)) {\n                        candidates.push_back({\n                            s.eval_score + iter_score[v],\n                            s.real_score + base_score[v],\n                            i,\n                            v,\n                            v_tile,\n                            nbrs.dir[k],\n                            s.hash ^ zobrist[v_tile] // Incremental hash update\n                        });\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // 3b. Spatial Pruning + Domination Check\n            for (int i = 0; i < (int)candidates.size(); ++i) {\n                const auto& c = candidates[i];\n                Bucket& b = buckets[c.u];\n                \n                if (b.count == 0) {\n                    touched_buckets.push_back(c.u);\n                    b.scores[0] = c.eval_score;\n                    b.indices[0] = i;\n                    b.hashes[0] = c.hash;\n                    b.count = 1;\n                } else {\n                    // Domination Check: Look for duplicate visited-set hash\n                    bool duplicate = false;\n                    for(int k=0; k<b.count; ++k) {\n                        if (b.hashes[k] == c.hash) {\n                            duplicate = true;\n                            if (c.eval_score > b.scores[k]) {\n                                // Replace dominated state with better one\n                                b.scores[k] = c.eval_score;\n                                b.indices[k] = i;\n                                // Maintain sorted order locally\n                                int p = k;\n                                while(p > 0 && b.scores[p] > b.scores[p-1]) {\n                                    swap(b.scores[p], b.scores[p-1]);\n                                    swap(b.indices[p], b.indices[p-1]);\n                                    swap(b.hashes[p], b.hashes[p-1]);\n                                    p--;\n                                }\n                            }\n                            break;\n                        }\n                    }\n                    if (duplicate) continue;\n\n                    // Standard Top-K Insertion (Unique state)\n                    if (b.count < MAX_PER_CELL) {\n                        int pos = b.count;\n                        while (pos > 0 && c.eval_score > b.scores[pos-1]) {\n                            b.scores[pos] = b.scores[pos-1];\n                            b.indices[pos] = b.indices[pos-1];\n                            b.hashes[pos] = b.hashes[pos-1];\n                            pos--;\n                        }\n                        b.scores[pos] = c.eval_score;\n                        b.indices[pos] = i;\n                        b.hashes[pos] = c.hash;\n                        b.count++;\n                    } else if (c.eval_score > b.scores[MAX_PER_CELL-1]) {\n                        int pos = MAX_PER_CELL - 1;\n                        while (pos > 0 && c.eval_score > b.scores[pos-1]) {\n                            b.scores[pos] = b.scores[pos-1];\n                            b.indices[pos] = b.indices[pos-1];\n                            b.hashes[pos] = b.hashes[pos-1];\n                            pos--;\n                        }\n                        b.scores[pos] = c.eval_score;\n                        b.indices[pos] = i;\n                        b.hashes[pos] = c.hash;\n                    }\n                }\n            }\n\n            // Collect Survivors\n            survivors.clear();\n            for (int u : touched_buckets) {\n                Bucket& b = buckets[u];\n                for(int k=0; k<b.count; ++k) {\n                    survivors.push_back(b.indices[k]);\n                }\n                b.count = 0; // Reset bucket\n            }\n\n            // 3c. Global Pruning\n            if ((int)survivors.size() > BEAM_WIDTH) {\n                nth_element(survivors.begin(), survivors.begin() + BEAM_WIDTH, survivors.end(),\n                    [&](int a, int b) {\n                        return candidates[a].eval_score > candidates[b].eval_score;\n                    });\n                survivors.resize(BEAM_WIDTH);\n            }\n\n            // 3d. State Construction (Heavy Operation)\n            beam_next.clear();\n            for (int idx : survivors) {\n                const auto& cand = candidates[idx];\n                const auto& parent = beam_curr[cand.parent_idx];\n                \n                tree.push_back({parent.tree_idx, cand.dir});\n                int new_tree_idx = (int)tree.size() - 1;\n\n                State ns;\n                ns.u = cand.u;\n                ns.real_score = cand.real_score;\n                ns.eval_score = cand.eval_score;\n                ns.tree_idx = new_tree_idx;\n                ns.hash = cand.hash;\n                ns.visited = parent.visited; // Heavy copy\n                ns.visited.set(cand.new_tile);\n\n                beam_next.push_back(ns);\n\n                // Update Global Best\n                if (ns.real_score > best_score_final) {\n                    best_score_final = ns.real_score;\n                    string p;\n                    p.reserve(step + 8);\n                    int curr = new_tree_idx;\n                    while (curr != -1) {\n                        p += tree[curr].dir;\n                        curr = tree[curr].parent;\n                    }\n                    reverse(p.begin(), p.end());\n                    best_path_final = p;\n                }\n            }\n            \n            swap(beam_curr, beam_next);\n        }\n    }\n\nfinish:;\n    cout << best_path_final << endl;\n    return 0;\n}","ahc003":"/**\n * AtCoder Heuristic Contest Solution\n * Problem: Shortest Path with Unknown Edge Lengths\n * \n * Approach:\n * 1. Modeling: The grid is treated as a graph with weighted edges. Weights are learned online.\n * 2. Pathfinding: A* search (A-Star) is used with an admissible heuristic (Manhattan distance * min_edge_weight)\n *    to find the shortest path on the current estimated graph. A* is faster than Dijkstra, allowing more time for training.\n * 3. Estimation: Online Stochastic Gradient Descent (Adam optimizer) updates edge weights based on path feedback.\n *    - Loss: Squared Relative Error.\n *    - Regularization: L1 Norm (Total Variation) on adjacent parallel edges to exploit the \"piecewise constant\" \n *      structure of the edge generation zones ($M=1, 2$).\n * 4. Stability & Performance:\n *    - Stratified sampling (recent + random old) in SGD batches prevents catastrophic forgetting while adapting fast.\n *    - Adam parameters initialized to prevent gradient explosion in early steps.\n *    - Strict time management ensures the solution runs within 2.0s, dynamically adjusting training intensity.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst int NUM_H = N * (N - 1); \nconst int NUM_V = (N - 1) * N; \nconst int NUM_EDGES = NUM_H + NUM_V; \n\n// Helper to get edge indices\n// Horizontal edges: (r, c) -> (r, c+1)\ninline int get_h_idx(int r, int c) { return r * (N - 1) + c; }\n// Vertical edges: (r, c) -> (r+1, c)\ninline int get_v_idx(int r, int c) { return NUM_H + r * N + c; }\n\n// Structure to store query history\nstruct Query {\n    vector<int> path_edges;\n    int measured_dist;\n};\n\nclass Solver {\nprivate:\n    // Estimated weights of edges\n    vector<double> weights;\n    \n    // Adam Optimizer parameters\n    vector<double> m, v; // First and second moment vectors\n    double beta1 = 0.9;\n    double beta2 = 0.999;\n    double epsilon = 1e-8;\n    \n    // Hyperparameters\n    // learning_rate: Step size for Adam. \n    // lambda_smooth: Strength of L1 regularization. Tuned to balance with data gradient magnitude (~1e-6).\n    double learning_rate = 150.0; \n    double lambda_smooth = 2.0e-6; \n    \n    long long updates_count = 0;\n    vector<Query> history;\n    mt19937 rng;\n\n    // Pre-allocated buffers for pathfinding\n    vector<double> dist;\n    vector<int> parent_edge;\n    vector<int> parent_node;\n    \n    // Time management\n    chrono::steady_clock::time_point start_time;\n\npublic:\n    Solver() {\n        // Initialize weights with expected mean value (approx 5000)\n        weights.assign(NUM_EDGES, 5000.0);\n        m.assign(NUM_EDGES, 0.0);\n        // Initialize v to small non-zero to prevent initial huge steps\n        v.assign(NUM_EDGES, 1e-12);\n        rng.seed(42);\n        \n        dist.resize(N * N);\n        parent_edge.resize(N * N);\n        parent_node.resize(N * N);\n        \n        start_time = chrono::steady_clock::now();\n    }\n\n    // Heuristic for A*: Manhattan distance * min_possible_weight (safe lower bound 1000)\n    inline double heuristic(int u, int target) {\n        int r1 = u / N, c1 = u % N;\n        int r2 = target / N, c2 = target % N;\n        return (abs(r1 - r2) + abs(c1 - c2)) * 1000.0;\n    }\n\n    // A* algorithm to find the shortest path based on current weight estimates\n    pair<string, vector<int>> find_path(int si, int sj, int ti, int tj) {\n        fill(dist.begin(), dist.end(), 1e18);\n        \n        auto get_node = [&](int r, int c) { return r * N + c; };\n        int start_node = get_node(si, sj);\n        int target_node = get_node(ti, tj);\n        \n        dist[start_node] = 0;\n        \n        // Priority Queue: {f_score, u}, where f = g + h\n        using State = pair<double, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({heuristic(start_node, target_node), start_node});\n        \n        while (!pq.empty()) {\n            auto [f, u] = pq.top();\n            pq.pop();\n            \n            // Lazy deletion check: if we found a better f-score already\n            if (f > dist[u] + heuristic(u, target_node) + 1e-9) continue;\n            if (u == target_node) break;\n            \n            int r = u / N;\n            int c = u % N;\n            double g_u = dist[u];\n            \n            // Explore neighbors: Up, Down, Left, Right\n            // Using unrolled logic for performance\n            \n            // Up\n            if (r > 0) {\n                int v_node = u - N; \n                int e_idx = NUM_H + (r - 1) * N + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_node]) {\n                    dist[v_node] = g_u + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node] + heuristic(v_node, target_node), v_node});\n                }\n            }\n            // Down\n            if (r < N - 1) {\n                int v_node = u + N;\n                int e_idx = NUM_H + r * N + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_node]) {\n                    dist[v_node] = g_u + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node] + heuristic(v_node, target_node), v_node});\n                }\n            }\n            // Left\n            if (c > 0) {\n                int v_node = u - 1;\n                int e_idx = r * (N - 1) + (c - 1); \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_node]) {\n                    dist[v_node] = g_u + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node] + heuristic(v_node, target_node), v_node});\n                }\n            }\n            // Right\n            if (c < N - 1) {\n                int v_node = u + 1;\n                int e_idx = r * (N - 1) + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_node]) {\n                    dist[v_node] = g_u + w;\n                    parent_node[v_node] = u;\n                    parent_edge[v_node] = e_idx;\n                    pq.push({dist[v_node] + heuristic(v_node, target_node), v_node});\n                }\n            }\n        }\n        \n        // Reconstruct path\n        string path = \"\";\n        vector<int> edges;\n        int curr = target_node;\n        while (curr != start_node) {\n            int prev = parent_node[curr];\n            int e_idx = parent_edge[curr];\n            edges.push_back(e_idx);\n            \n            int diff = curr - prev;\n            if (diff == N) path += 'D';\n            else if (diff == -N) path += 'U';\n            else if (diff == 1) path += 'R';\n            else path += 'L';\n            \n            curr = prev;\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges.begin(), edges.end());\n        return {path, edges};\n    }\n\n    // Train the model using the feedback from the latest query\n    void train(const vector<int>& path_edges, int measured) {\n        // 1. Time Check\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        // Safety cutoff slightly before 2.0s\n        if (elapsed > 1.90) return; \n        \n        history.push_back({path_edges, measured});\n        \n        // 2. Dynamic Training Schedule\n        // More training for early queries to establish baseline.\n        // Reduce training if getting close to time limit.\n        int base_batch = 100; \n        int base_iter = 25; \n        \n        if (history.size() < 50) {\n            base_batch = 120;\n            base_iter = 50; \n        } else if (history.size() < 200) {\n            base_batch = 110;\n            base_iter = 35; \n        }\n\n        if (elapsed > 1.6) {\n            base_iter = 15;\n            base_batch = 60;\n        }\n\n        int batch_size = base_batch;\n        int iterations = base_iter;\n        \n        static vector<double> grad(NUM_EDGES);\n        vector<int> indices;\n        indices.reserve(batch_size);\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            fill(grad.begin(), grad.end(), 0.0);\n            updates_count++;\n            \n            indices.clear();\n            int hist_size = history.size();\n            \n            // Stratified Sampling:\n            // 1. Recent history (last 25 queries) for local adaptation\n            int recent_count = min(hist_size, 25); \n            for(int i = 0; i < recent_count; ++i) indices.push_back(hist_size - 1 - i);\n            \n            // 2. Random history to maintain global constraints\n            int needed = batch_size - recent_count;\n            if (needed > 0 && hist_size > 0) {\n                 for(int i = 0; i < needed; ++i) {\n                    indices.push_back(rng() % hist_size);\n                }\n            }\n\n            // --- Gradient Accumulation ---\n\n            // 1. Prediction Error Term\n            // Loss = ((Pred - Measured)/Measured)^2\n            // Grad = 2 * (Pred - Measured) / Measured^2\n            for (int idx : indices) {\n                const auto& q = history[idx];\n                double pred = 0;\n                for (int e : q.path_edges) pred += weights[e];\n                \n                double y = q.measured_dist;\n                double diff = pred - y;\n                double g_factor = 2.0 * diff / (y * y);\n                \n                for (int e : q.path_edges) {\n                    grad[e] += g_factor;\n                }\n            }\n            \n            // 2. Smoothness Regularization Term (L1 Norm)\n            // Loss = lambda * |w_i - w_j|\n            // Grad = lambda * sign(w_i - w_j)\n            // Applied row-wise for horizontal edges, column-wise for vertical edges\n            \n            // Horizontal edges\n            for (int r = 0; r < N; ++r) {\n                int start = r * (N - 1);\n                for (int c = 0; c < N - 2; ++c) {\n                    int e1 = start + c;\n                    int e2 = e1 + 1;\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // Vertical edges\n            int v_offset = NUM_H;\n            for (int r = 0; r < N - 2; ++r) { \n                int row_start = v_offset + r * N;\n                for (int c = 0; c < N; ++c) {\n                    int e1 = row_start + c;\n                    int e2 = e1 + N; \n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // --- Adam Update ---\n            double bias_corr1 = 1.0 - pow(beta1, updates_count);\n            double bias_corr2 = 1.0 - pow(beta2, updates_count);\n            \n            for (int i = 0; i < NUM_EDGES; ++i) {\n                double g = grad[i];\n                \n                m[i] = beta1 * m[i] + (1 - beta1) * g;\n                v[i] = beta2 * v[i] + (1 - beta2) * g * g;\n                \n                double m_hat = m[i] / bias_corr1;\n                double v_hat = v[i] / bias_corr2;\n                \n                weights[i] -= learning_rate * m_hat / (sqrt(v_hat) + epsilon);\n                \n                // Clamp weights to valid domain\n                if (weights[i] < 500.0) weights[i] = 500.0;\n                if (weights[i] > 9500.0) weights[i] = 9500.0;\n            }\n        }\n    }\n};\n\nint main() {\n    // Fast I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    Solver solver;\n    \n    int query_count = 1000;\n    for (int k = 0; k < query_count; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        \n        // 1. Output Path\n        auto [path_str, path_edges] = solver.find_path(si, sj, ti, tj);\n        cout << path_str << endl;\n        \n        // 2. Read Feedback\n        int measured;\n        cin >> measured;\n        \n        // 3. Update Model\n        solver.train(path_edges, measured);\n    }\n    \n    return 0;\n}","ahc004":"/**\n * Problem: AHC004 - Genetic Information\n * Approach: Multi-start Simulated Annealing with Base-16 Rolling Hash and Delta Updates\n * \n * Key Optimizations:\n * 1. Unified Alphabet & Scoring:\n *    - The grid cells can take values 0-7 ('A'-'H') or 8 ('.').\n *    - Internal score combines primary objective (satisfied strings) and secondary (dots).\n *    - Dots contribute to the score only when all strings are satisfied, guiding the optimizer.\n * \n * 2. Efficient Delta Calculation with Caching:\n *    - Uses Base-16 Rolling Hash (4 bits per char). Values 0-7 are chars, 8 is dot.\n *    - Maintains `grid_hashes` (hash of every substring) and `grid_ids` (matched target ID or -1).\n *    - This allows evaluating a move in O(num_active_substrings) which is very small (~70),\n *      avoiding full re-scans or expensive hash map lookups for existing content.\n * \n * 3. Incremental Updates:\n *    - Updates `occ` (occurrences array) incrementally.\n *    - Avoids full revert on rejection by calculating delta first, then only applying if accepted.\n *    - Uses temporary vectors to track `occ` changes for potential rollback if rejected.\n * \n * 4. Multi-Start Strategy:\n *    - Runs multiple independent SA sessions to escape local optima.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <cmath>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconstexpr int N = 20;\nconstexpr int TIMEOUT_MS = 2950;\nconstexpr int HASH_MAP_SIZE = 8192; \nconstexpr int HASH_MAP_MASK = HASH_MAP_SIZE - 1;\nconstexpr int DOT_VAL = 8;\nconstexpr int INTERNAL_SCORE_BASE = 10000;\n\n// Fast Random Generator\nstruct Xorshift {\n    uint64_t state = 0x123456789ABCDEF;\n    inline uint64_t next() {\n        uint64_t x = state;\n        x ^= x << 13; x ^= x >> 7; x ^= x << 17;\n        return state = x;\n    }\n    inline int next_int(int n) { return next() % n; }\n    inline int next_char() { return next() & 7; }\n    inline double next_double() { return (next() & 0xFFFFFFFF) / 4294967296.0; }\n};\nXorshift rng;\n\nstruct Target {\n    int id;\n    int weight;\n};\n\n// Custom Open-Addressing Hash Map\nstruct FastHashMap {\n    uint64_t keys[HASH_MAP_SIZE];\n    int ids[HASH_MAP_SIZE]; // 0 means empty, val = id + 1\n    \n    FastHashMap() { memset(ids, 0, sizeof(ids)); }\n    void clear() { memset(ids, 0, sizeof(ids)); }\n    \n    inline void insert(uint64_t key, int id) {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        keys[idx] = key;\n        ids[idx] = id + 1;\n    }\n    \n    inline int get(uint64_t key) const {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return ids[idx] - 1;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        return -1;\n    }\n};\n\n// Context struct to store info about substrings passing through a modified cell\nstruct Context {\n    uint8_t dir; // 0: horz, 1: vert\n    uint8_t len;\n    uint8_t r;\n    uint8_t c; // Start position\n    uint8_t shift_idx; // Shift amount index (from right)\n    uint64_t base_hash; // Hash with current cell zeroed\n    int new_id; // To store the new ID found\n};\n\nstruct Solver {\n    int M;\n    int max_possible_weight;\n    \n    FastHashMap maps[13];\n    vector<Target> targets_info;\n    vector<int> active_lengths;\n    \n    int grid[N][N];\n    \n    // State caches\n    // grid_hashes[dir][len][r][c] stores the hash of the substring of length len starting at (r,c) in direction dir\n    uint64_t grid_hashes[2][13][N][N]; \n    // grid_ids stores the matched target ID (or -1) for that substring, avoiding map lookups for unchanged parts\n    int grid_ids[2][13][N][N]; \n    \n    int occ[1000]; // Tracks occurrences of each target ID\n    int current_satisfied_weight;\n    int current_dots;\n    \n    int best_grid[N][N];\n    int best_score_val; \n    \n    // Reusable buffers to avoid allocation overhead\n    vector<Context> active_contexts;\n    vector<int> dec_ids, inc_ids;\n\n    Solver() {\n        best_score_val = -1;\n        active_contexts.reserve(256);\n        dec_ids.reserve(256);\n        inc_ids.reserve(256);\n    }\n\n    void read_input() {\n        int n_dummy;\n        if (!(cin >> n_dummy >> M)) return;\n        \n        map<string, int> counts;\n        for (int i = 0; i < M; ++i) {\n            string s; cin >> s; counts[s]++;\n        }\n        \n        max_possible_weight = M;\n        int id_counter = 0;\n        targets_info.reserve(counts.size());\n        \n        vector<bool> len_active(13, false);\n        for (auto const& [s, count] : counts) {\n            int len = s.length();\n            uint64_t h = 0;\n            // Convert string to Base-16 hash (4 bits per char)\n            for (char c : s) h = (h << 4) | (c - 'A');\n            maps[len].insert(h, id_counter);\n            targets_info.push_back({id_counter, count});\n            len_active[len] = true;\n            id_counter++;\n        }\n        \n        for(int l=2; l<=12; ++l) if (len_active[l]) active_lengths.push_back(l);\n        memset(occ, 0, sizeof(occ));\n    }\n    \n    // Initialize state from scratch\n    void init_state() {\n        current_satisfied_weight = 0;\n        current_dots = 0;\n        memset(occ, 0, sizeof(occ));\n        \n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                if (grid[r][c] == DOT_VAL) current_dots++;\n            }\n        }\n        \n        for(int dir=0; dir<2; ++dir) {\n            for(int l : active_lengths) {\n                for(int r=0; r<N; ++r) {\n                    for(int c=0; c<N; ++c) {\n                        uint64_t h = 0;\n                        if (dir == 0) { // Horizontal\n                            for(int k=0; k<l; ++k) h = (h << 4) | grid[r][(c+k)%N];\n                        } else { // Vertical\n                            for(int k=0; k<l; ++k) h = (h << 4) | grid[(r+k)%N][c];\n                        }\n                        grid_hashes[dir][l][r][c] = h;\n                        \n                        int id = maps[l].get(h);\n                        grid_ids[dir][l][r][c] = id;\n                        \n                        if (id != -1) {\n                            if (occ[id] == 0) current_satisfied_weight += targets_info[id].weight;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n        \n        int score = get_internal_score();\n        if (score > best_score_val) {\n            best_score_val = score;\n            memcpy(best_grid, grid, sizeof(grid));\n        }\n    }\n    \n    // Unified scoring function\n    inline int get_internal_score() const {\n        int score = current_satisfied_weight * INTERNAL_SCORE_BASE;\n        if (current_satisfied_weight == max_possible_weight) {\n            score += current_dots;\n        }\n        return score;\n    }\n\n    void run_sa(double duration_ms, bool refinement) {\n        auto start_time = chrono::steady_clock::now();\n        \n        double t0 = refinement ? 200.0 : 2000.0;\n        double t1 = 0.1;\n        \n        int64_t steps = 0;\n        \n        while (true) {\n            steps++;\n            if ((steps & 2047) == 0) {\n                auto curr = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n                if (elapsed > duration_ms) break;\n            }\n            \n            int r = rng.next_int(N);\n            int c = rng.next_int(N);\n            int old_val = grid[r][c];\n            int new_val;\n            \n            // Pick a different character (0-8)\n            do {\n                new_val = rng.next_int(9);\n            } while (new_val == old_val);\n            \n            // 1. Prepare Contexts and calculate score Delta\n            active_contexts.clear();\n            dec_ids.clear();\n            inc_ids.clear();\n            \n            int delta_weight = 0;\n            \n            // --- Process 'removal' of old_val ---\n            // Identify all substrings passing through (r,c) and update counts\n            \n            // Horizontal\n            for (int l : active_lengths) {\n                // Substrings starting at c-k (mod N) include c at index k\n                for (int k = 0; k < l; ++k) {\n                    int start_c = (c - k + N) % N;\n                    int id = grid_ids[0][l][r][start_c];\n                    \n                    if (id != -1) {\n                        if (occ[id] == 1) delta_weight -= targets_info[id].weight;\n                        occ[id]--;\n                        dec_ids.push_back(id);\n                    }\n                    \n                    int shift_pow = l - 1 - k;\n                    uint64_t h = grid_hashes[0][l][r][start_c];\n                    // Compute base hash by removing old_val\n                    uint64_t base = h - (uint64_t(old_val) << (shift_pow * 4));\n                    \n                    active_contexts.push_back({0, (uint8_t)l, (uint8_t)r, (uint8_t)start_c, (uint8_t)shift_pow, base, -1});\n                }\n            }\n            // Vertical\n            for (int l : active_lengths) {\n                for (int k = 0; k < l; ++k) {\n                    int start_r = (r - k + N) % N;\n                    int id = grid_ids[1][l][start_r][c];\n                    \n                    if (id != -1) {\n                        if (occ[id] == 1) delta_weight -= targets_info[id].weight;\n                        occ[id]--;\n                        dec_ids.push_back(id);\n                    }\n                    \n                    int shift_pow = l - 1 - k;\n                    uint64_t h = grid_hashes[1][l][start_r][c];\n                    uint64_t base = h - (uint64_t(old_val) << (shift_pow * 4));\n                    \n                    active_contexts.push_back({1, (uint8_t)l, (uint8_t)start_r, (uint8_t)c, (uint8_t)shift_pow, base, -1});\n                }\n            }\n\n            // --- Process 'addition' of new_val ---\n            for (auto& ctx : active_contexts) {\n                uint64_t h_new = ctx.base_hash | (uint64_t(new_val) << (ctx.shift_idx * 4));\n                int id = -1;\n                // Dots never match targets (IDs are only for strings of 0-7)\n                if (new_val != DOT_VAL) {\n                    id = maps[ctx.len].get(h_new);\n                }\n                ctx.new_id = id;\n                \n                if (id != -1) {\n                    if (occ[id] == 0) delta_weight += targets_info[id].weight;\n                    occ[id]++;\n                    inc_ids.push_back(id);\n                }\n            }\n            \n            // Calculate Scores\n            int old_score = current_satisfied_weight * INTERNAL_SCORE_BASE;\n            if (current_satisfied_weight == max_possible_weight) old_score += current_dots;\n            \n            int new_sat_weight = current_satisfied_weight + delta_weight;\n            int new_dots = current_dots;\n            if (old_val == DOT_VAL) new_dots--;\n            if (new_val == DOT_VAL) new_dots++;\n            \n            int new_score = new_sat_weight * INTERNAL_SCORE_BASE;\n            if (new_sat_weight == max_possible_weight) new_score += new_dots;\n            \n            int score_diff = new_score - old_score;\n            \n            // Metropolis Acceptance Criterion\n            bool accept = false;\n            if (score_diff >= 0) accept = true;\n            else {\n                auto curr = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double, milli>(curr - start_time).count();\n                double temp = t0 + (t1 - t0) * (elapsed / duration_ms);\n                if (rng.next_double() < exp(score_diff / temp)) accept = true;\n            }\n            \n            if (accept) {\n                grid[r][c] = new_val;\n                current_satisfied_weight = new_sat_weight;\n                current_dots = new_dots;\n                \n                // Update Caches\n                for(const auto& ctx : active_contexts) {\n                    uint64_t h_new = ctx.base_hash | (uint64_t(new_val) << (ctx.shift_idx * 4));\n                    grid_hashes[ctx.dir][ctx.len][ctx.r][ctx.c] = h_new;\n                    grid_ids[ctx.dir][ctx.len][ctx.r][ctx.c] = ctx.new_id;\n                }\n                \n                if (new_score > best_score_val) {\n                    best_score_val = new_score;\n                    memcpy(best_grid, grid, sizeof(grid));\n                }\n            } else {\n                // Rollback occ changes\n                for (int id : inc_ids) occ[id]--;\n                for (int id : dec_ids) occ[id]++;\n            }\n        }\n    }\n\n    void solve() {\n        auto global_start = chrono::steady_clock::now();\n        \n        best_score_val = -1;\n        int run_count = 0;\n        \n        while(true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - global_start).count();\n            \n            // Break if near timeout\n            if (elapsed > TIMEOUT_MS - 200 && run_count > 0) break;\n            \n            // Restart with random characters (A-H)\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = rng.next_char();\n            init_state();\n            \n            double run_duration = 500.0;\n            if (elapsed + run_duration > TIMEOUT_MS - 100) {\n                run_duration = TIMEOUT_MS - elapsed - 100;\n            }\n            if (run_duration < 100) break;\n            \n            run_sa(run_duration, false);\n            run_count++;\n        }\n        \n        // Final Refinement Phase\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double, milli>(now - global_start).count();\n        if (elapsed < TIMEOUT_MS - 50) {\n            memcpy(grid, best_grid, sizeof(grid));\n            init_state();\n            run_sa(TIMEOUT_MS - elapsed - 20, true);\n        }\n        \n        // Output Result\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                int val = best_grid[i][j];\n                if (val == DOT_VAL) cout << '.';\n                else cout << (char)('A' + val);\n            }\n            cout << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver s;\n    s.read_input();\n    s.solve();\n    return 0;\n}","ahc005":"/**\n * Problem Analysis & Solution Strategy:\n *\n * 1. Problem Abstraction:\n *    We need to find a minimum cost tour that visits a set of road segments (horizontal/vertical)\n *    such that every road cell on the map is \"covered\" (i.e., belongs to at least one visited segment).\n *    This combines the Vertex Cover problem (on the bipartite graph of road cells) with the Traveling Salesperson Problem.\n *\n * 2. Core Algorithm: Iterative Greedy with Min-Weight Vertex Cover (MWVC)\n *    We build the tour step-by-step. At each step:\n *    a. Calculate shortest path distances from the current position to all other road cells.\n *    b. Identify the \"Target Segments\" to visit next.\n *       - We construct a bipartite graph where edges represent currently uncovered road cells.\n *       - Nodes are Horizontal and Vertical segments.\n *       - Node weights are derived from the distance to reach the segment (Distance + Overhead).\n *       - Solving the Min-Weight Vertex Cover (via Max-Flow Min-Cut) on this graph gives us the most efficient\n *         set of segments to cover the remaining gaps, balancing travel cost and coverage count.\n *    c. Select the best Destination Cell.\n *       - We score every reachable road cell based on `(Distance + Penalty) / Gain`.\n *       - `Gain` accumulates based on what the cell covers:\n *         - Target Segment: High Gain (1.0).\n *         - Useful Non-Target Segment (covers new cells but not in MWVC): Low Gain (0.1 - 0.4).\n *       - This scoring metric naturally favors:\n *         - Cells that cover Target segments.\n *         - Intersections of two Targets (Gain = 2.0 -> Score halved).\n *         - Intersections of Target + Useful (Gain ~ 1.2 -> Score reduced).\n *         - Very close Useful intersections (opportunistic coverage).\n *       - The `Penalty` term prevents hopping to distant cells for marginal gain improvements.\n *\n * 3. Refinements & Heuristics:\n *    - Randomized Parameters: `Overhead`, `Penalty`, and `UsefulGain` are randomized per simulation run to explore\n *      different trade-offs (e.g., depth-first vs breadth-first coverage).\n *    - Randomized Dijkstra: Small noise is added to edge weights in Dijkstra to break symmetries and generate\n *      geometrically diverse paths.\n *    - Time Management: We run as many simulations as possible within the 3.0s time limit and output the best one.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n\n// Use AtCoder Library for MaxFlow\n#include <atcoder/maxflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconst int INF = 1e9;\nconst int DX[] = {-1, 1, 0, 0};\nconst int DY[] = {0, 0, -1, 1};\nconst char DIR_CHAR[] = {'U', 'D', 'L', 'R'};\n\n// Global Grid Info\nint N;\nint SI, SJ;\nvector<string> GRID;\nvector<vector<int>> COSTS;\nbool IS_ROAD[70][70];\nvector<pair<int,int>> ROAD_CELLS;\n\n// Data Structures\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const { return r == other.r && c == other.c; }\n};\n\nstruct Segment {\n    int id;\n    int type; // 0: Horizontal, 1: Vertical\n    vector<Point> cells;\n};\n\nvector<Segment> H_SEGS, V_SEGS;\nint H_ID[70][70];\nint V_ID[70][70];\n\n// Input Parsing\nvoid parse_input() {\n    if (!(cin >> N >> SI >> SJ)) return;\n    GRID.resize(N);\n    COSTS.assign(N, vector<int>(N, 0));\n    ROAD_CELLS.clear();\n    for (int i = 0; i < N; ++i) {\n        cin >> GRID[i];\n        for (int j = 0; j < N; ++j) {\n            if (GRID[i][j] != '#') {\n                COSTS[i][j] = GRID[i][j] - '0';\n                IS_ROAD[i][j] = true;\n                ROAD_CELLS.push_back({i, j});\n            } else {\n                IS_ROAD[i][j] = false;\n            }\n        }\n    }\n\n    // Identify Horizontal Segments\n    H_SEGS.clear();\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) H_ID[i][j] = -1;\n    int h_count = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (!IS_ROAD[i][j]) { j++; continue; }\n            int k = j;\n            while (k < N && IS_ROAD[i][k]) k++;\n            Segment seg; seg.id = h_count; seg.type = 0;\n            for (int c = j; c < k; ++c) {\n                seg.cells.push_back({i, c});\n                H_ID[i][c] = h_count;\n            }\n            H_SEGS.push_back(seg);\n            h_count++;\n            j = k;\n        }\n    }\n\n    // Identify Vertical Segments\n    V_SEGS.clear();\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) V_ID[i][j] = -1;\n    int v_count = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (!IS_ROAD[i][j]) { i++; continue; }\n            int k = i;\n            while (k < N && IS_ROAD[k][j]) k++;\n            Segment seg; seg.id = v_count; seg.type = 1;\n            for (int r = i; r < k; ++r) {\n                seg.cells.push_back({r, j});\n                V_ID[r][j] = v_count;\n            }\n            V_SEGS.push_back(seg);\n            v_count++;\n            i = k;\n        }\n    }\n}\n\n// Dijkstra's Algorithm with randomized noise and neighbor shuffling\nvoid get_dist_matrix(Point start, vector<vector<int>>& dist, vector<vector<int>>& parent_dir, mt19937& rng) {\n    dist.assign(N, vector<int>(N, INF));\n    parent_dir.assign(N, vector<int>(N, -1));\n    \n    using P = pair<double, pair<int,int>>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    vector<vector<double>> dist_f(N, vector<double>(N, 1e18));\n    \n    dist[start.r][start.c] = 0;\n    dist_f[start.r][start.c] = 0;\n    pq.push({0.0, {start.r, start.c}});\n    \n    uniform_real_distribution<double> noise(0.0, 0.1);\n    vector<int> dirs = {0, 1, 2, 3};\n\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        int r = u.first, c = u.second;\n        \n        if (d > dist_f[r][c]) continue;\n        \n        shuffle(dirs.begin(), dirs.end(), rng);\n\n        for (int k : dirs) {\n            int nr = r + DX[k], nc = c + DY[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && IS_ROAD[nr][nc]) {\n                int w = COSTS[nr][nc];\n                double new_d = d + w + noise(rng);\n                if (new_d < dist_f[nr][nc]) {\n                    dist_f[nr][nc] = new_d;\n                    dist[nr][nc] = dist[r][c] + w;\n                    parent_dir[nr][nc] = k;\n                    pq.push({new_d, {nr, nc}});\n                }\n            }\n        }\n    }\n}\n\n// Path reconstruction from Dijkstra parent pointers\nstring get_path_str(Point start, Point end, const vector<vector<int>>& parent_dir) {\n    string path = \"\";\n    int r = end.r, c = end.c;\n    while (r != start.r || c != start.c) {\n        int dir = parent_dir[r][c];\n        if (dir == -1) break;\n        path += DIR_CHAR[dir];\n        r -= DX[dir];\n        c -= DY[dir];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Result {\n    string path;\n    long long score;\n    int time_cost;\n};\n\n// Single Iteration Solver\nResult solve(int seed) {\n    mt19937 rng(seed);\n    \n    // Randomized Parameters for Heuristics\n    uniform_int_distribution<int> mwvc_overhead_dist(20, 100);\n    uniform_real_distribution<double> move_penalty_dist(30.0, 100.0);\n    uniform_real_distribution<double> useful_val_dist(0.1, 0.4);\n    uniform_real_distribution<double> weight_noise(0.9, 1.1);\n\n    int mwvc_overhead = mwvc_overhead_dist(rng);\n    double move_penalty = move_penalty_dist(rng);\n    double useful_val = useful_val_dist(rng);\n\n    vector<vector<bool>> covered(N, vector<bool>(N, false));\n    int covered_cnt = 0;\n    int total_cells = ROAD_CELLS.size();\n    \n    // Track useful segments (segments that still cover at least one unvisited cell)\n    vector<bool> h_useful(H_SEGS.size(), true);\n    vector<bool> v_useful(V_SEGS.size(), true);\n    vector<int> h_rem_cnt(H_SEGS.size(), 0);\n    vector<int> v_rem_cnt(V_SEGS.size(), 0);\n    for(int i=0; i<(int)H_SEGS.size(); ++i) h_rem_cnt[i] = H_SEGS[i].cells.size();\n    for(int i=0; i<(int)V_SEGS.size(); ++i) v_rem_cnt[i] = V_SEGS[i].cells.size();\n\n    // Helper to mark cell as covered and update usefulness of segments\n    auto visit_cell = [&](int r, int c) {\n        if (!covered[r][c]) {\n            covered[r][c] = true;\n            covered_cnt++;\n            \n            int hid = H_ID[r][c];\n            int vid = V_ID[r][c];\n            if (hid != -1) {\n                h_rem_cnt[hid]--;\n                if (h_rem_cnt[hid] == 0) h_useful[hid] = false;\n            }\n            if (vid != -1) {\n                v_rem_cnt[vid]--;\n                if (v_rem_cnt[vid] == 0) v_useful[vid] = false;\n            }\n        }\n    };\n\n    // Visit all cells visible from current position\n    auto visit_pos = [&](Point p) {\n        int hid = H_ID[p.r][p.c];\n        if (hid != -1) {\n            for (auto& c : H_SEGS[hid].cells) visit_cell(c.r, c.c);\n        }\n        int vid = V_ID[p.r][p.c];\n        if (vid != -1) {\n            for (auto& c : V_SEGS[vid].cells) visit_cell(c.r, c.c);\n        }\n    };\n\n    Point current = {SI, SJ};\n    visit_pos(current);\n\n    string full_path = \"\";\n    int total_cost = 0;\n\n    while (covered_cnt < total_cells) {\n        // 1. Calculate distances\n        vector<vector<int>> dist, parent;\n        get_dist_matrix(current, dist, parent, rng);\n\n        // 2. Build MWVC Graph (Bipartite Matching formulation)\n        int S = H_SEGS.size() + V_SEGS.size();\n        int T = S + 1;\n        mf_graph<long long> g(T + 1);\n\n        // Set segment weights\n        for (auto& seg : H_SEGS) {\n            if (!h_useful[seg.id]) continue;\n            int min_d = INF;\n            for (auto& p : seg.cells) if (dist[p.r][p.c] < min_d) min_d = dist[p.r][p.c];\n            \n            // Weight = (Distance + Overhead) * Noise\n            long long w = (long long)((min_d + mwvc_overhead) * weight_noise(rng));\n            g.add_edge(S, seg.id, w);\n        }\n        for (auto& seg : V_SEGS) {\n            if (!v_useful[seg.id]) continue;\n            int min_d = INF;\n            for (auto& p : seg.cells) if (dist[p.r][p.c] < min_d) min_d = dist[p.r][p.c];\n            \n            long long w = (long long)((min_d + mwvc_overhead) * weight_noise(rng));\n            g.add_edge(H_SEGS.size() + seg.id, T, w);\n        }\n\n        // Add edges for uncovered cells (H -> V)\n        bool needed = false;\n        for (auto& p : ROAD_CELLS) {\n            if (!covered[p.first][p.second]) {\n                int h = H_ID[p.first][p.second];\n                int v = V_ID[p.first][p.second];\n                g.add_edge(h, H_SEGS.size() + v, 1e18); // Infinite capacity\n                needed = true;\n            }\n        }\n        if (!needed) break;\n\n        // Solve Min Cut\n        g.flow(S, T);\n        auto cut = g.min_cut(S);\n\n        // Identify Targets (Segments in Vertex Cover)\n        vector<bool> is_target_h(H_SEGS.size(), false);\n        vector<bool> is_target_v(V_SEGS.size(), false);\n        for (int i = 0; i < (int)H_SEGS.size(); ++i) {\n            // If node is NOT reachable from S (edge S->i cut), it's in VC\n            if (h_useful[i] && !cut[i]) is_target_h[i] = true;\n        }\n        for (int i = 0; i < (int)V_SEGS.size(); ++i) {\n            // If node IS reachable from S (edge j->T cut), it's in VC\n            if (v_useful[i] && cut[H_SEGS.size() + i]) is_target_v[i] = true;\n        }\n\n        // 3. Score all reachable cells to pick Destination\n        Point best_p = {-1, -1};\n        double best_score = 1e18;\n\n        for (auto& rc : ROAD_CELLS) {\n            int r = rc.first, c = rc.second;\n            if (dist[r][c] == INF) continue;\n\n            int h = H_ID[r][c];\n            int v = V_ID[r][c];\n\n            double gain = 0.0;\n\n            if (h != -1 && h_useful[h]) {\n                if (is_target_h[h]) gain += 1.0;\n                else gain += useful_val;\n            }\n            if (v != -1 && v_useful[v]) {\n                if (is_target_v[v]) gain += 1.0;\n                else gain += useful_val;\n            }\n\n            if (gain < 1e-5) continue;\n\n            // Metric: Cost per unit of Gain\n            double score = (dist[r][c] + move_penalty) / gain;\n            \n            // Tie-breaking\n            score *= weight_noise(rng);\n\n            if (score < best_score) {\n                best_score = score;\n                best_p = {r, c};\n            }\n        }\n\n        if (best_p.r == -1) break;\n\n        // 4. Move to selected destination\n        string sub = get_path_str(current, best_p, parent);\n        full_path += sub;\n        total_cost += dist[best_p.r][best_p.c];\n        \n        Point temp = current;\n        for (char c : sub) {\n            int dir = -1;\n            if (c == 'U') dir = 0; else if (c == 'D') dir = 1;\n            else if (c == 'L') dir = 2; else if (c == 'R') dir = 3;\n            temp.r += DX[dir]; temp.c += DY[dir];\n            visit_pos(temp);\n        }\n        current = best_p;\n        visit_pos(current);\n    }\n\n    // Return to start\n    if (current.r != SI || current.c != SJ) {\n        vector<vector<int>> dist, parent;\n        get_dist_matrix(current, dist, parent, rng);\n        string sub = get_path_str(current, {SI, SJ}, parent);\n        full_path += sub;\n        total_cost += dist[SI][SJ];\n    }\n\n    return {full_path, 10000 + (long long)(1e7 * N / max(1, total_cost)), total_cost};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    parse_input();\n\n    auto start_clock = chrono::high_resolution_clock::now();\n    double time_limit = 2.9;\n\n    Result best_res;\n    best_res.score = -1;\n\n    int seed = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_clock;\n        if (elapsed.count() > time_limit) break;\n\n        Result res = solve(seed++);\n        if (res.score > best_res.score) {\n            best_res = res;\n        }\n    }\n\n    cout << best_res.path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// --------------------------------------------------------------------------\n// Structures\n// --------------------------------------------------------------------------\n\nstruct Task {\n    int id;\n    vector<int> d;          // Required skill levels\n    vector<int> children;   // Dependent tasks\n    int unresolved_deps;    // Count of unsatisfied dependencies\n    double est_duration;    // Estimated duration for CPM\n    double cpm_height;      // Critical Path Height\n};\n\nstruct Member {\n    int id;\n    vector<int> s;          // Estimated skill levels\n    vector<pair<int, int>> history; // Log of (task_id, actual_duration)\n    int current_task;       // Currently assigned task ID, -1 if free\n    int start_day;          // Day the current task started\n};\n\n// --------------------------------------------------------------------------\n// Globals\n// --------------------------------------------------------------------------\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<int> task_status;    // 0: waiting, 1: running, 2: completed\nmt19937 rng(5489);\n\n// --------------------------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------------------------\n\n// Calculate workload w_{i,j} = sum(max(0, d_{i,k} - s_{j,k}))\ninline int calc_w(const vector<int>& d, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; ++k) {\n        int diff = d[k] - s[k];\n        if (diff > 0) w += diff;\n    }\n    return w;\n}\n\n// Calculate Expected Days based on w and uniform noise [-3, 3]\n// t = max(1, w + r)\ninline double get_expected_days(int w) {\n    if (w >= 4) return (double)w;\n    // Precomputed expectations for sum_{r=-3}^3 max(1, w+r) / 7.0\n    // w=0: (1+1+1+1+1+2+3)/7 = 10/7\n    // w=1: (1+1+1+1+2+3+4)/7 = 13/7\n    // w=2: (1+1+1+2+3+4+5)/7 = 17/7\n    // w=3: (1+1+2+3+4+5+6)/7 = 22/7\n    static const double table[] = {1.4285714, 1.8571429, 2.4285714, 3.1428571};\n    return table[w];\n}\n\n// --------------------------------------------------------------------------\n// Skill Estimation: Coordinate Descent\n// --------------------------------------------------------------------------\n\nvoid update_member_skills(int m_idx) {\n    Member& m = members[m_idx];\n    \n    // Helper to calculate cost for a given skill vector\n    auto get_cost = [&](const vector<int>& s_curr) -> long long {\n        long long total_cost = 0;\n        for (const auto& h : m.history) {\n            int tid = h.first;\n            int actual = h.second;\n            int w = calc_w(tasks[tid].d, s_curr);\n            \n            // 1. Bound Violation Penalty (Hard/Strong)\n            // t=1 => w <= 4\n            // t>1 => t-3 <= w <= t+3\n            int lb, ub;\n            if (actual == 1) {\n                lb = 0; ub = 4;\n            } else {\n                lb = max(0, actual - 3);\n                ub = actual + 3;\n            }\n            \n            long long viol = 0;\n            if (w < lb) viol = (lb - w);\n            else if (w > ub) viol = (w - ub);\n            \n            if (viol > 0) {\n                total_cost += viol * viol * 1000; // Very strong penalty\n            }\n            \n            // 2. Likelihood Maximization (Centering)\n            // We want w to be close to actual t to maximize probability.\n            long long diff = abs(w - actual);\n            total_cost += diff * diff; \n        }\n        return total_cost;\n    };\n\n    long long current_cost = get_cost(m.s);\n    long long current_sum_s = 0;\n    for(int x : m.s) current_sum_s += x;\n    \n    // Adaptive iteration count\n    int iterations = 600 + (int)m.history.size() * 15; \n    if (iterations > 3000) iterations = 3000; \n    \n    vector<int> p(K);\n    iota(p.begin(), p.end(), 0);\n\n    // Random Coordinate Descent\n    for (int iter = 0; iter < iterations; ++iter) {\n        int k = p[rng() % K];\n        int original = m.s[k];\n        \n        int best_val = original;\n        long long best_cost = current_cost;\n        long long best_reg = current_sum_s;\n        \n        for (int delta : {-1, 1, -2, 2}) {\n            int next_val = original + delta;\n            if (next_val < 0) continue;\n            \n            m.s[k] = next_val;\n            long long new_cost = get_cost(m.s);\n            long long new_sum_s = current_sum_s - original + next_val;\n            \n            // Minimize Cost first, then Regularization (Skill Sum)\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_reg = new_sum_s;\n                best_val = next_val;\n            } else if (new_cost == best_cost) {\n                if (new_sum_s < best_reg) {\n                    best_reg = new_sum_s;\n                    best_val = next_val;\n                }\n            }\n            m.s[k] = original; \n        }\n        \n        if (best_val != original) {\n            m.s[k] = best_val;\n            current_cost = best_cost;\n            current_sum_s = best_reg;\n        }\n    }\n}\n\n// --------------------------------------------------------------------------\n// CPM Logic\n// --------------------------------------------------------------------------\n\nvoid update_cpm() {\n    // Estimate duration assuming assignment to a \"good\" member (Top 25%)\n    // This reflects the potential to assign specialists to critical tasks.\n    int top_k = max(1, M / 4); \n    vector<int> w_values(M);\n    \n    // Reset heights\n    for (int i = 0; i < N; ++i) tasks[i].cpm_height = 0;\n\n    // Backward pass (Sink -> Source)\n    for (int i = N - 1; i >= 0; --i) {\n        // Calculate w for all members\n        for (int j = 0; j < M; ++j) {\n            w_values[j] = calc_w(tasks[i].d, members[j].s);\n        }\n        \n        // Get top_k smallest workloads (approximating optimal assignment)\n        nth_element(w_values.begin(), w_values.begin() + top_k, w_values.end());\n        \n        long long sum_w = 0;\n        for (int j = 0; j < top_k; ++j) sum_w += w_values[j];\n        double avg_w = (double)sum_w / top_k;\n        \n        // Use expected days for CPM duration estimate\n        double duration = get_expected_days((int)avg_w);\n        tasks[i].est_duration = duration;\n        \n        double max_child_h = 0;\n        for (int v : tasks[i].children) {\n            if (v < N) max_child_h = max(max_child_h, tasks[v].cpm_height);\n        }\n        tasks[i].cpm_height = duration + max_child_h;\n    }\n}\n\n// --------------------------------------------------------------------------\n// Main\n// --------------------------------------------------------------------------\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) cin >> tasks[i].d[k];\n        tasks[i].unresolved_deps = 0;\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; \n        tasks[u].children.push_back(v);\n        tasks[v].unresolved_deps++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].s.assign(K, 0);\n        members[i].current_task = -1;\n        members[i].start_day = -1;\n    }\n    \n    task_status.assign(N, 0);\n    \n    update_cpm();\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        // Identify candidates\n        vector<int> available_tasks;\n        available_tasks.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 0 && tasks[i].unresolved_deps == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            if (members[i].current_task == -1) {\n                free_members.push_back(i);\n            }\n        }\n\n        vector<pair<int, int>> assignments;\n        vector<bool> member_taken(M, false);\n\n        if (!available_tasks.empty() && !free_members.empty()) {\n            update_cpm(); // Update priorities daily\n            \n            // Sort by Critical Path Height (descending)\n            sort(available_tasks.begin(), available_tasks.end(), [&](int a, int b) {\n                if (abs(tasks[a].cpm_height - tasks[b].cpm_height) > 1e-6)\n                    return tasks[a].cpm_height > tasks[b].cpm_height;\n                return tasks[a].children.size() > tasks[b].children.size();\n            });\n\n            // Greedy Assignment\n            for (int t_id : available_tasks) {\n                bool any_free = false;\n                for(int m : free_members) if(!member_taken[m]) { any_free = true; break; }\n                if (!any_free) break;\n\n                int best_m = -1;\n                double min_exp_days = 1e9;\n                long long best_waste = 1e18;\n\n                for (int m_id : free_members) {\n                    if (member_taken[m_id]) continue;\n\n                    int w = calc_w(tasks[t_id].d, members[m_id].s);\n                    double exp_days = get_expected_days(w);\n                    \n                    long long current_sum_s = 0;\n                    for (int val : members[m_id].s) current_sum_s += val;\n\n                    // Metric 1: Minimize Expected Time\n                    if (exp_days < min_exp_days - 1e-9) {\n                        min_exp_days = exp_days;\n                        best_m = m_id;\n                        best_waste = current_sum_s;\n                    } \n                    // Metric 2: Tie-break by Skill Sum (Save experts)\n                    else if (abs(exp_days - min_exp_days) < 1e-9) {\n                        if (current_sum_s < best_waste) {\n                            best_m = m_id;\n                            best_waste = current_sum_s;\n                        }\n                    }\n                }\n\n                if (best_m != -1) {\n                    assignments.push_back({best_m, t_id});\n                    member_taken[best_m] = true;\n                }\n            }\n        }\n\n        // Output\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n            members[p.first].current_task = p.second;\n            members[p.first].start_day = day;\n            task_status[p.second] = 1;\n        }\n        cout << endl;\n\n        // Input\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break;\n\n        for (int i = 0; i < n_finished; ++i) {\n            int m_id_in; cin >> m_id_in;\n            int m_id = m_id_in - 1;\n            \n            int t_id = members[m_id].current_task;\n            int duration = day - members[m_id].start_day + 1;\n            \n            members[m_id].history.push_back({t_id, duration});\n            members[m_id].current_task = -1;\n            \n            task_status[t_id] = 2;\n            \n            for (int child : tasks[t_id].children) {\n                tasks[child].unresolved_deps--;\n            }\n            \n            update_member_skills(m_id);\n        }\n    }\n\n    return 0;\n}","ahc006":"#pragma GCC optimize(\"O3,unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <array>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Constants & Globals\n// ---------------------------------------------------------\nconstexpr int NUM_ORDERS = 1000;\nconstexpr int TARGET_ORDERS = 50;\nconstexpr int OFFICE_X = 400;\nconstexpr int OFFICE_Y = 400;\nconstexpr int TIME_LIMIT_MS = 1980;\n\n// Coordinates: 0-999 P, 1000-1999 D\n// -1 is Office\nalignas(64) int node_x[2000];\nalignas(64) int node_y[2000];\n\nstruct OrderRaw {\n    int a, b, c, d;\n};\nOrderRaw orders_raw[NUM_ORDERS];\n\n// ---------------------------------------------------------\n// Utils\n// ---------------------------------------------------------\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return next() / 4294967295.0;\n    }\n} rng;\n\ninline int get_dist(int u, int v) {\n    int x1 = (u == -1) ? OFFICE_X : node_x[u];\n    int y1 = (u == -1) ? OFFICE_Y : node_y[u];\n    int x2 = (v == -1) ? OFFICE_X : node_x[v];\n    int y2 = (v == -1) ? OFFICE_Y : node_y[v];\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ---------------------------------------------------------\n// Solution State\n// ---------------------------------------------------------\nstruct Solution {\n    vector<int> route; \n    bitset<NUM_ORDERS> selected;\n    int total_dist;\n\n    void calc_dist() {\n        total_dist = 0;\n        if (route.empty()) return;\n        total_dist += get_dist(-1, route[0]);\n        for (size_t i = 0; i < route.size() - 1; ++i) {\n            total_dist += get_dist(route[i], route[i+1]);\n        }\n        total_dist += get_dist(route.back(), -1);\n    }\n};\n\nstruct InsertInfo {\n    int delta;\n    int p_pos;\n    int d_pos;\n};\n\n// ---------------------------------------------------------\n// O(N) Insertion Logic\n// ---------------------------------------------------------\n// Finds the best position to insert order_idx (P and D) into route.\n// Complexity: O(N)\nInsertInfo find_best_insertion_fast(const vector<int>& route, int ord_idx) {\n    int P = ord_idx;\n    int D = ord_idx + 1000;\n    int n = route.size();\n    \n    // Arrays to store partial costs\n    // route size is at most 2*TARGET_ORDERS = 100. Max 105 is safe.\n    static int cost_p[105];\n    static int cost_d[105];\n    static pair<int, int> suffix_min[105]; // {value, index}\n    \n    // 1. Precompute insertion costs for P and D at every single position\n    // Loop covers 0 to n inclusive\n    for(int k=0; k<=n; ++k) {\n        int prev = (k==0) ? -1 : route[k-1];\n        int next = (k==n) ? -1 : route[k];\n        int base = get_dist(prev, next);\n        \n        cost_p[k] = get_dist(prev, P) + get_dist(P, next) - base;\n        cost_d[k] = get_dist(prev, D) + get_dist(D, next) - base;\n    }\n    \n    // 2. Compute Suffix Minimum for cost_d\n    // suffix_min[k] stores min(cost_d[j]) for j >= k\n    suffix_min[n] = {cost_d[n], n};\n    for(int k=n-1; k>=0; --k) {\n        if (cost_d[k] < suffix_min[k+1].first) {\n            suffix_min[k] = {cost_d[k], k};\n        } else {\n            suffix_min[k] = suffix_min[k+1];\n        }\n    }\n    \n    int best_val = 2e9;\n    int best_p = -1;\n    int best_d = -1;\n    \n    // 3. Iterate through all valid P positions (i)\n    for(int i=0; i<=n; ++i) {\n        int prev = (i==0) ? -1 : route[i-1];\n        int next = (i==n) ? -1 : route[i];\n        int base = get_dist(prev, next);\n        \n        // Case A: P and D inserted together at i (prev -> P -> D -> next)\n        // Cost = d(prev, P) + d(P, D) + d(D, next) - d(prev, next)\n        int val_eq = get_dist(prev, P) + get_dist(P, D) + get_dist(D, next) - base;\n        \n        if (val_eq < best_val) {\n            best_val = val_eq;\n            best_p = i;\n            best_d = i;\n        }\n        \n        // Case B: P at i, D at j > i\n        // Cost = cost_p[i] + cost_d[j]\n        // We can use the precomputed suffix min to find best j in O(1)\n        // Valid only if i < n because j must be > i\n        if (i < n) {\n            int val_sep = cost_p[i] + suffix_min[i+1].first;\n            if (val_sep < best_val) {\n                best_val = val_sep;\n                best_p = i;\n                best_d = suffix_min[i+1].second;\n            }\n        }\n    }\n    \n    return {best_val, best_p, best_d};\n}\n\n// Construct solution from a subset using O(N) Cheapest Insertion\nSolution build_solution_from_subset(const vector<int>& subset) {\n    Solution sol;\n    sol.selected.reset();\n    sol.route.reserve(2 * TARGET_ORDERS);\n    \n    if (subset.empty()) return sol;\n\n    // Start with first order\n    int first = subset[0];\n    sol.selected[first] = true;\n    sol.route.push_back(first);\n    sol.route.push_back(first + 1000);\n    sol.calc_dist(); \n\n    // Insert remaining orders\n    for (size_t k = 1; k < subset.size(); ++k) {\n        int ord = subset[k];\n        sol.selected[ord] = true;\n        InsertInfo info = find_best_insertion_fast(sol.route, ord);\n        \n        sol.route.insert(sol.route.begin() + info.p_pos, ord);\n        // If d_pos == p_pos, D is inserted after P.\n        // If d_pos > p_pos, D is inserted after original[d_pos-1], which is now at d_pos.\n        // In both cases, insert at d_pos + 1 works because P insertion shifts indices >= p_pos by 1.\n        // Since d_pos >= p_pos, the target index relative to new array is d_pos + 1.\n        sol.route.insert(sol.route.begin() + info.d_pos + 1, ord + 1000);\n        sol.total_dist += info.delta;\n    }\n    return sol;\n}\n\n// Generate initial solution\nSolution generate_initial_solution() {\n    Solution best_init;\n    best_init.total_dist = 2e9;\n\n    vector<int> centers;\n    centers.reserve(100);\n    centers.push_back(-1); // Office\n    for(int i=0; i<80; ++i) centers.push_back(rng.next_int(NUM_ORDERS));\n\n    static pair<int,int> dist_vec[NUM_ORDERS];\n\n    for (int c_idx : centers) {\n        int cx = (c_idx == -1) ? OFFICE_X : node_x[c_idx];\n        int cy = (c_idx == -1) ? OFFICE_Y : node_y[c_idx];\n\n        for(int i=0; i<NUM_ORDERS; ++i) {\n            dist_vec[i] = {abs(node_x[i] - cx) + abs(node_y[i] - cy), i};\n        }\n        \n        nth_element(dist_vec, dist_vec + TARGET_ORDERS, dist_vec + NUM_ORDERS);\n\n        vector<int> subset;\n        subset.reserve(TARGET_ORDERS);\n        for(int k=0; k<TARGET_ORDERS; ++k) subset.push_back(dist_vec[k].second);\n        \n        Solution s = build_solution_from_subset(subset);\n        if (s.total_dist < best_init.total_dist) {\n            best_init = s;\n        }\n    }\n    return best_init;\n}\n\nbool check_2opt_valid(const vector<int>& route, int l, int r) {\n    static int seen[NUM_ORDERS];\n    static int stamp = 0;\n    stamp++;\n    for (int i = l; i <= r; ++i) {\n        int u = route[i];\n        int oid = (u < 1000) ? u : u - 1000;\n        if (seen[oid] == stamp) return false;\n        seen[oid] = stamp;\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_t = chrono::high_resolution_clock::now();\n\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        cin >> orders_raw[i].a >> orders_raw[i].b >> orders_raw[i].c >> orders_raw[i].d;\n        node_x[i] = orders_raw[i].a;\n        node_y[i] = orders_raw[i].b;\n        node_x[i+1000] = orders_raw[i].c;\n        node_y[i+1000] = orders_raw[i].d;\n    }\n\n    Solution curr_sol = generate_initial_solution();\n    Solution best_sol = curr_sol;\n\n    double t_start = 250.0; \n    double t_end = 0.5;\n    double temp = t_start;\n\n    vector<int> temp_route; \n    temp_route.reserve(105);\n\n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 255) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(now - start_t).count() * 1000.0;\n            if (elapsed > TIME_LIMIT_MS) break;\n            temp = t_start * pow(t_end / t_start, elapsed / TIME_LIMIT_MS);\n        }\n\n        int type = rng.next_int(100);\n        \n        if (type < 20) { // SWAP ORDER (20%)\n            int r_idx = rng.next_int(curr_sol.route.size());\n            int val_rem = curr_sol.route[r_idx];\n            int ord_rem = (val_rem < 1000) ? val_rem : val_rem - 1000;\n\n            // Quick base distance calc: subtract contribution of removed order?\n            // Hard because P and D might be far apart. \n            // Simpler to reconstruct route. O(N) is fine.\n            temp_route.clear();\n            for (int u : curr_sol.route) {\n                int o = (u < 1000) ? u : u - 1000;\n                if (o != ord_rem) temp_route.push_back(u);\n            }\n            \n            int base_dist = 0;\n            if (!temp_route.empty()) {\n                base_dist += get_dist(-1, temp_route[0]);\n                for(size_t i=0; i<temp_route.size()-1; ++i) base_dist += get_dist(temp_route[i], temp_route[i+1]);\n                base_dist += get_dist(temp_route.back(), -1);\n            }\n\n            int ord_new = -1;\n            do { ord_new = rng.next_int(NUM_ORDERS); } while(curr_sol.selected[ord_new]);\n\n            InsertInfo info = find_best_insertion_fast(temp_route, ord_new);\n            int new_dist = base_dist + info.delta;\n            int diff = new_dist - curr_sol.total_dist;\n\n            if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                curr_sol.selected[ord_rem] = false;\n                curr_sol.selected[ord_new] = true;\n                curr_sol.route = temp_route;\n                curr_sol.route.insert(curr_sol.route.begin() + info.p_pos, ord_new);\n                curr_sol.route.insert(curr_sol.route.begin() + info.d_pos + 1, ord_new + 1000);\n                curr_sol.total_dist = new_dist;\n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 35) { // REINSERT ORDER (15%) - LNS Move\n            int r_idx = rng.next_int(curr_sol.route.size());\n            int val_rem = curr_sol.route[r_idx];\n            int ord_rem = (val_rem < 1000) ? val_rem : val_rem - 1000;\n\n            temp_route.clear();\n            for (int u : curr_sol.route) {\n                int o = (u < 1000) ? u : u - 1000;\n                if (o != ord_rem) temp_route.push_back(u);\n            }\n            \n            int base_dist = 0;\n            if (!temp_route.empty()) {\n                base_dist += get_dist(-1, temp_route[0]);\n                for(size_t i=0; i<temp_route.size()-1; ++i) base_dist += get_dist(temp_route[i], temp_route[i+1]);\n                base_dist += get_dist(temp_route.back(), -1);\n            }\n\n            InsertInfo info = find_best_insertion_fast(temp_route, ord_rem);\n            int new_dist = base_dist + info.delta;\n            int diff = new_dist - curr_sol.total_dist;\n\n            if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                curr_sol.route = temp_route;\n                curr_sol.route.insert(curr_sol.route.begin() + info.p_pos, ord_rem);\n                curr_sol.route.insert(curr_sol.route.begin() + info.d_pos + 1, ord_rem + 1000);\n                curr_sol.total_dist = new_dist;\n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n        \n        } else if (type < 75) { // 2-OPT (40%)\n            int sz = curr_sol.route.size();\n            int l = rng.next_int(sz - 1);\n            int r = rng.next_int(sz - l - 1) + l + 1;\n\n            if (check_2opt_valid(curr_sol.route, l, r)) {\n                int u_prev = (l==0) ? -1 : curr_sol.route[l-1];\n                int u_curr = curr_sol.route[l];\n                int v_curr = curr_sol.route[r];\n                int v_next = (r==sz-1) ? -1 : curr_sol.route[r+1];\n\n                int old_delta = get_dist(u_prev, u_curr) + get_dist(v_curr, v_next);\n                int new_delta = get_dist(u_prev, v_curr) + get_dist(u_curr, v_next);\n                int diff = new_delta - old_delta;\n\n                if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                    reverse(curr_sol.route.begin() + l, curr_sol.route.begin() + r + 1);\n                    curr_sol.total_dist += diff;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n\n        } else { // RELOCATE (25%)\n            int sz = curr_sol.route.size();\n            int u_idx = rng.next_int(sz);\n            int val = curr_sol.route[u_idx];\n            \n            int partner = (val < 1000) ? val + 1000 : val - 1000;\n            int p_idx = -1;\n            for(int i=0; i<sz; ++i) if(curr_sol.route[i] == partner) { p_idx = i; break; }\n            \n            int p_idx_reduced = (p_idx > u_idx) ? p_idx - 1 : p_idx;\n            \n            int min_ins = 0, max_ins = sz - 1;\n            if (val < 1000) max_ins = p_idx_reduced; \n            else min_ins = p_idx_reduced + 1; \n            \n            if (min_ins <= max_ins) {\n                int ins_idx = min_ins + rng.next_int(max_ins - min_ins + 1);\n                if (ins_idx != u_idx && ins_idx != u_idx + 1) {\n                    \n                    // Simulate remove and insert\n                    int u_prev = (u_idx == 0) ? -1 : curr_sol.route[u_idx-1];\n                    int u_next = (u_idx == sz-1) ? -1 : curr_sol.route[u_idx+1];\n                    int rem_cost = get_dist(u_prev, val) + get_dist(val, u_next) - get_dist(u_prev, u_next);\n                    \n                    // To get insertion context, we need to conceptually remove u.\n                    // Index mapping: if ins_idx < u, context is (ins_idx-1, ins_idx) in original (ignoring u)\n                    // We can just construct temp route for correctness/simplicity since N is small\n                    temp_route = curr_sol.route;\n                    temp_route.erase(temp_route.begin() + u_idx);\n                    \n                    int t_prev = (ins_idx == 0) ? -1 : temp_route[ins_idx-1];\n                    int t_next = (ins_idx == (int)temp_route.size()) ? -1 : temp_route[ins_idx];\n                    int add_cost = get_dist(t_prev, val) + get_dist(val, t_next) - get_dist(t_prev, t_next);\n                    \n                    int diff = add_cost - rem_cost;\n                    if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                        temp_route.insert(temp_route.begin() + ins_idx, val);\n                        curr_sol.route = temp_route;\n                        curr_sol.total_dist += diff;\n                        if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                    }\n                }\n            }\n        }\n    }\n\n    // Output\n    vector<int> out_ids;\n    out_ids.reserve(TARGET_ORDERS);\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        if(best_sol.selected[i]) out_ids.push_back(i+1);\n    }\n    cout << out_ids.size();\n    for(int id : out_ids) cout << \" \" << id;\n    cout << \"\\n\";\n    cout << best_sol.route.size() + 2 << \" \" << OFFICE_X << \" \" << OFFICE_Y;\n    for(int u : best_sol.route) {\n        cout << \" \" << node_x[u] << \" \" << node_y[u];\n    }\n    cout << \" \" << OFFICE_X << \" \" << OFFICE_Y << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\n\nusing namespace std;\n\n// --- Constants & Tuning ---\nconst double TIME_LIMIT_SEC = 1.90; // Safety margin for 2.0s limit\nconst int MAX_W = 4000;             // Upper bound for edge weights (approx 800*sqrt(2)*3)\n\n// --- Data Structures ---\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n    int id;\n};\n\nstruct SimEdge {\n    int u_c, v_c;  // Component indices\n    int d_val;     // Min possible weight\n    int w_val;     // Current simulated weight\n    int range_len; // range of random weight (3d - d + 1)\n};\n\n// Optimized Disjoint Set Union\nstruct DSU {\n    vector<int> parent;\n    \n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    // Fast reset\n    inline void reset(int n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int i) {\n        int root = i;\n        while (root != parent[root]) root = parent[root];\n        // Path compression\n        while (i != root) {\n            int next = parent[i];\n            parent[i] = root;\n            i = next;\n        }\n        return root;\n    }\n    \n    inline bool unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n            return true;\n        }\n        return false;\n    }\n    \n    inline bool same(int i, int j) {\n        return find(i) == find(j);\n    }\n};\n\n// Fast Xorshift Random Number Generator\nstruct Xorshift {\n    uint32_t state;\n    Xorshift(uint32_t seed = 123456789) : state(seed) {}\n    \n    inline uint32_t next() {\n        uint32_t x = state;\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return state = x;\n    }\n};\n\n// --- Globals ---\nint N, M;\nvector<Point> points;\nvector<Edge> all_edges;\nXorshift rng;\nauto start_time = chrono::high_resolution_clock::now();\n\n// Buffers for Counting Sort to avoid allocation in loop\nint cnt[MAX_W + 1];\nvector<SimEdge> sorted_buffer;\n\n// --- Helper Functions ---\ninline double get_elapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nint calc_dist(int i, int j) {\n    long long dx = points[i].x - points[j].x;\n    long long dy = points[i].y - points[j].y;\n    return (int)round(sqrt(dx*dx + dy*dy));\n}\n\n// O(N) Counting Sort for simulation edges\n// Much faster than std::sort for small integer keys\nvoid count_sort(vector<SimEdge>& edges, int n) {\n    memset(cnt, 0, sizeof(cnt));\n\n    for(int i=0; i<n; ++i) {\n        cnt[edges[i].w_val]++;\n    }\n\n    // Prefix sums\n    int current = 0;\n    for(int i=0; i<=MAX_W; ++i) {\n        int tmp = cnt[i];\n        cnt[i] = current;\n        current += tmp;\n    }\n\n    for(int i=0; i<n; ++i) {\n        sorted_buffer[cnt[edges[i].w_val]++] = edges[i];\n    }\n    \n    for(int i=0; i<n; ++i) edges[i] = sorted_buffer[i];\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // --- Input Parsing ---\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n    \n    if (b > 800) {\n        N = a; M = b;\n        points.resize(N);\n        for(int i=0; i<N; ++i) cin >> points[i].x >> points[i].y;\n    } else {\n        N = 400; M = 1995;\n        points.resize(N);\n        points[0].x = a; points[0].y = b;\n        for(int i=1; i<N; ++i) cin >> points[i].x >> points[i].y;\n    }\n\n    all_edges.resize(M);\n    for(int i=0; i<M; ++i) {\n        cin >> all_edges[i].u >> all_edges[i].v;\n        all_edges[i].d = calc_dist(all_edges[i].u, all_edges[i].v);\n        all_edges[i].id = i;\n    }\n\n    // --- Initialization ---\n    DSU main_dsu(N);\n    DSU sim_dsu(N);\n    \n    vector<SimEdge> candidates; candidates.reserve(M);\n    vector<SimEdge> active_sim_edges; active_sim_edges.reserve(M);\n    sorted_buffer.resize(M);\n    \n    int current_components = N;\n\n    // --- Main Interaction Loop ---\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = all_edges[i].u;\n        int v = all_edges[i].v;\n        \n        // 1. Cycle Check\n        if (main_dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int root_u = main_dsu.find(u);\n        int root_v = main_dsu.find(v);\n\n        // 2. Gather Candidates\n        // Collect all future edges that connect distinct components\n        candidates.clear();\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.find(all_edges[j].u);\n            int rv = main_dsu.find(all_edges[j].v);\n            if (ru != rv) {\n                candidates.push_back({ru, rv, all_edges[j].d, 0, 2 * all_edges[j].d + 1});\n            }\n        }\n\n        // 3. Bridge Check\n        // Check if connectivity is possible using all available candidates\n        sim_dsu.reset(N);\n        for (const auto& e : candidates) {\n            sim_dsu.unite(e.u_c, e.v_c);\n        }\n        if (!sim_dsu.same(root_u, root_v)) {\n            // Bridge detected: Must accept\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            current_components--;\n            continue;\n        }\n\n        // 4. Filter Simulation Set\n        // Heuristic: Sort by minimum length d. \n        // We only need the best edges to form the MST. \n        // K = 2*Components is usually sufficient for Euclidean graphs.\n        sort(candidates.begin(), candidates.end(), [](const SimEdge& a, const SimEdge& b){\n            return a.d_val < b.d_val;\n        });\n        \n        active_sim_edges.clear();\n        int target_size = max(current_components * 2, 400); // Keep a healthy buffer\n        if (target_size > (int)candidates.size()) target_size = (int)candidates.size();\n        \n        for(int k=0; k<target_size; ++k) {\n            active_sim_edges.push_back(candidates[k]);\n        }\n        \n        // 5. Monte Carlo Simulation\n        double elapsed = get_elapsed();\n        double budget = (TIME_LIMIT_SEC - elapsed) / (M - i + 5);\n        if (budget < 0.0002) budget = 0.0002; // Min time slice\n\n        long long sum_bottleneck = 0;\n        int sims = 0;\n        int n_active = active_sim_edges.size();\n        \n        auto step_start = chrono::high_resolution_clock::now();\n        \n        while(true) {\n            // Generate random weights\n            for (int k=0; k<n_active; ++k) {\n                 uint32_t r = rng.next();\n                 // Fast mapping to range [0, range_len-1]\n                 uint32_t offset = ((uint64_t)r * active_sim_edges[k].range_len) >> 32;\n                 active_sim_edges[k].w_val = active_sim_edges[k].d_val + offset;\n            }\n\n            // Sort (Counting Sort)\n            count_sort(active_sim_edges, n_active);\n\n            // Kruskal's Algorithm (Early Exit)\n            sim_dsu.reset(N);\n            int bottleneck = -1;\n            \n            for (int k=0; k<n_active; ++k) {\n                const auto& e = active_sim_edges[k];\n                if (sim_dsu.unite(e.u_c, e.v_c)) {\n                    // Stop as soon as our specific components are connected\n                    if (sim_dsu.same(root_u, root_v)) {\n                        bottleneck = e.w_val;\n                        break;\n                    }\n                }\n            }\n            \n            // Penalty if not connected (should not happen if bridge check passed and K is large enough)\n            if (bottleneck == -1) bottleneck = 5000;\n            sum_bottleneck += bottleneck;\n            sims++;\n\n            // Budget check (every 64 iterations to minimize overhead)\n            if ((sims & 63) == 0) {\n                auto curr = chrono::high_resolution_clock::now();\n                if ((curr - step_start).count() > budget) break;\n            }\n        }\n\n        // 6. Make Decision\n        double threshold = (sims > 0) ? (double)sum_bottleneck / sims : 1e9;\n\n        if (l_i < threshold) {\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            current_components--;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"/**\n * AtCoder Heuristic Contest 008\n * Solution: Robust Honeycomb Trap with Strict Conflict Resolution\n * \n * Strategy:\n * 1. Layout: We overlay a skeleton of \"rooms\" (approx 5x5 size) on the 30x30 grid.\n *    - Walls are planned at specific rows/cols.\n *    - Gates are planned at the centers of these wall segments.\n * 2. Dynamic Logic:\n *    - We detect \"Dirty\" components (containing pets) and \"Clean\" components.\n *    - We assign priorities: \n *      a. ESCAPE: Humans in dirty rooms must leave.\n *      b. TRAP: Close gates connecting dirty rooms to clean rooms.\n *      c. BUILD: Construct the skeleton.\n * 3. Safety & Conflict Resolution:\n *    - Strict checks to ensure no two humans move to the same square.\n *    - Strict checks to ensure no human moves into a wall being built in the same turn.\n *    - A conservative reservation system ensures that high-priority movers do not displace \n *      low-priority waiters (preventing the \"moving to occupied square\" error).\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --- Constants & Utils ---\nconst int N_ROWS = 30;\nconst int N_COLS = 30;\nconst int MAX_TURNS = 300;\n\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'}; \n\nstruct Pet {\n    int id;\n    int r, c; \n    int type;\n};\n\nstruct Human {\n    int id;\n    int r, c;\n};\n\nstruct State {\n    vector<Pet> pets;\n    vector<Human> humans;\n    bool walls[N_ROWS][N_COLS];\n};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_ROWS && c >= 0 && c < N_COLS;\n}\n\n// --- Strategic Plan ---\nbool plan_skeleton[N_ROWS][N_COLS];\nbool plan_gate[N_ROWS][N_COLS]; // True if this wall part is a gate (initially open)\n\nvoid init_plan() {\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c) {\n            plan_skeleton[r][c] = false;\n            plan_gate[r][c] = false;\n        }\n\n    // Create a grid of walls. \n    // Lines at indices: 5, 11, 17, 23. \n    // This creates 5x5 and 4x5 sized regions.\n    vector<int> lines = {5, 11, 17, 23};\n    \n    for (int r : lines) {\n        for (int c = 0; c < N_COLS; ++c) plan_skeleton[r][c] = true;\n    }\n    for (int c : lines) {\n        for (int r = 0; r < N_ROWS; ++r) plan_skeleton[r][c] = true;\n    }\n    \n    // Define Gates at midpoints of wall segments\n    // Segments: 0-4, 6-10, 12-16, 18-22, 24-29\n    // Mids: 2, 8, 14, 20, 27\n    vector<int> mids = {2, 8, 14, 20, 27};\n    \n    for(int r : lines) {\n        for(int m : mids) plan_gate[r][m] = true;\n    }\n    for(int c : lines) {\n        for(int m : mids) plan_gate[m][c] = true;\n    }\n    \n    // Intersections are always solid walls\n    for(int r : lines) {\n        for(int c : lines) plan_gate[r][c] = false;\n    }\n}\n\n// --- Analysis Helpers ---\n\nstruct Component {\n    int id;\n    bool has_pet = false;\n    vector<pair<int,int>> cells;\n};\n\nvoid get_components(const State& st, vector<vector<int>>& id_map, vector<Component>& comps) {\n    id_map.assign(N_ROWS, vector<int>(N_COLS, -1));\n    comps.clear();\n    \n    for(int r=0; r<N_ROWS; ++r){\n        for(int c=0; c<N_COLS; ++c){\n            if(!st.walls[r][c] && id_map[r][c] == -1){\n                int cid = comps.size();\n                Component comp;\n                comp.id = cid;\n                \n                queue<pair<int,int>> q;\n                q.push({r,c});\n                id_map[r][c] = cid;\n                \n                while(!q.empty()){\n                    auto [cr, cc] = q.front();\n                    q.pop();\n                    comp.cells.push_back({cr, cc});\n                    \n                    for(int i=0; i<4; ++i){\n                        int nr = cr + DR[i];\n                        int nc = cc + DC[i];\n                        if(is_valid(nr, nc) && !st.walls[nr][nc] && id_map[nr][nc] == -1){\n                            id_map[nr][nc] = cid;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                comps.push_back(comp);\n            }\n        }\n    }\n    \n    for(const auto& p : st.pets) {\n        if(id_map[p.r][p.c] != -1) comps[id_map[p.r][p.c]].has_pet = true;\n    }\n}\n\n// BFS pathfinding with strict reservation checks\n// Returns direction index (0-3) or -1\nint bfs_move(int sr, int sc, const vector<pair<int,int>>& targets, \n             const State& st, \n             const vector<vector<bool>>& reserved_next_pos, \n             const vector<vector<bool>>& reserved_new_wall,\n             const vector<bool>& processed_agents) {\n    \n    if(targets.empty()) return -1;\n\n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    \n    vector<vector<int>> dist(N_ROWS, vector<int>(N_COLS, 1e9));\n    vector<vector<pair<int,int>>> parent(N_ROWS, vector<pair<int,int>>(N_COLS, {-1,-1}));\n    \n    dist[sr][sc] = 0;\n    bool found = false;\n    int er = -1, ec = -1;\n    \n    // Optimization: Check targets quickly\n    static int target_mark[N_ROWS][N_COLS];\n    static int mark_counter = 0;\n    mark_counter++;\n    for(auto& t : targets) target_mark[t.first][t.second] = mark_counter;\n    \n    while(!q.empty()){\n        auto [cr, cc] = q.front();\n        q.pop();\n        \n        if(target_mark[cr][cc] == mark_counter){\n            found = true;\n            er = cr; ec = cc;\n            break;\n        }\n        \n        for(int i=0; i<4; ++i){\n            int nr = cr + DR[i];\n            int nc = cc + DC[i];\n            \n            if(!is_valid(nr, nc)) continue;\n            if(st.walls[nr][nc]) continue;\n            \n            // Check dynamic obstacles only for the immediate next step (t+1)\n            if(dist[cr][cc] == 0) {\n                // Cannot move into a new wall\n                if(reserved_new_wall[nr][nc]) continue;\n                // Cannot move into a spot reserved by a processed agent\n                if(reserved_next_pos[nr][nc]) continue;\n                \n                // Conservative Check: Cannot move into a spot occupied by an unprocessed agent\n                // (Because that agent might stay)\n                bool collision = false;\n                for(const auto& h : st.humans){\n                    if(!processed_agents[h.id] && h.r == nr && h.c == nc) collision = true;\n                }\n                if(collision) continue;\n            }\n            \n            if(dist[nr][nc] > dist[cr][cc] + 1){\n                dist[nr][nc] = dist[cr][cc] + 1;\n                parent[nr][nc] = {cr, cc};\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if(!found) return -1;\n    if(er == sr && ec == sc) return -1;\n    \n    // Backtrack\n    int cur_r = er, cur_c = ec;\n    while(parent[cur_r][cur_c].first != sr || parent[cur_r][cur_c].second != sc){\n        auto p = parent[cur_r][cur_c];\n        cur_r = p.first;\n        cur_c = p.second;\n    }\n    \n    for(int i=0; i<4; ++i){\n        if(sr + DR[i] == cur_r && sc + DC[i] == cur_c) return i;\n    }\n    return -1;\n}\n\n// --- Main Logic ---\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_plan();\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    \n    State state;\n    state.pets.resize(N);\n    for(int i=0; i<N; ++i){\n        state.pets[i].id = i;\n        cin >> state.pets[i].r >> state.pets[i].c >> state.pets[i].type;\n        state.pets[i].r--; state.pets[i].c--; \n    }\n    \n    int M;\n    cin >> M;\n    state.humans.resize(M);\n    for(int i=0; i<M; ++i){\n        state.humans[i].id = i;\n        cin >> state.humans[i].r >> state.humans[i].c;\n        state.humans[i].r--; state.humans[i].c--;\n    }\n    \n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c)\n            state.walls[r][c] = false;\n            \n    for(int turn=0; turn<MAX_TURNS; ++turn){\n        // 1. Component Analysis\n        vector<vector<int>> comp_map;\n        vector<Component> comps;\n        get_components(state, comp_map, comps);\n        \n        // Identify humans in danger\n        vector<bool> in_danger(M, false);\n        for(int i=0; i<M; ++i){\n            int cid = comp_map[state.humans[i].r][state.humans[i].c];\n            if(cid != -1 && comps[cid].has_pet) in_danger[i] = true;\n        }\n        \n        // 2. Generate Build Tasks\n        struct Task {\n            int r, c; // Wall location\n            int priority;\n        };\n        vector<Task> tasks;\n        \n        for(int r=0; r<N_ROWS; ++r){\n            for(int c=0; c<N_COLS; ++c){\n                if(state.walls[r][c]) continue;\n                if(!plan_skeleton[r][c]) continue;\n                \n                int prio = 0;\n                bool is_gate = plan_gate[r][c];\n                \n                // Check connectivity of this potential wall\n                set<int> adj_comps;\n                for(int k=0; k<4; ++k){\n                    int nr = r + DR[k];\n                    int nc = c + DC[k];\n                    if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                        if(comp_map[nr][nc] != -1) adj_comps.insert(comp_map[nr][nc]);\n                    }\n                }\n                \n                bool connects_dirty = false;\n                bool connects_clean = false;\n                for(int cid : adj_comps){\n                    if(comps[cid].has_pet) connects_dirty = true;\n                    else connects_clean = true;\n                }\n                \n                if(!is_gate) {\n                    prio = 50; \n                    if(connects_dirty) prio += 200; \n                } else {\n                    // Gate logic\n                    if(connects_dirty && connects_clean) prio = 1000; // MUST CLOSE\n                    else if(connects_dirty) prio = 500; // Contain dirty\n                    else prio = 10; // Clean area, keep low priority\n                }\n                \n                if(prio > 0) tasks.push_back({r, c, prio});\n            }\n        }\n        \n        // 3. Assign Agents to Plans\n        struct AgentPlan {\n            int h_idx;\n            int type; // 0: Wait, 1: Build, 2: Escape/Move\n            int target_r, target_c; \n            double score;\n        };\n        vector<AgentPlan> agents;\n        \n        auto get_dist = [&](int r1, int c1, int r2, int c2) {\n            return abs(r1 - r2) + abs(c1 - c2);\n        };\n        \n        for(int i=0; i<M; ++i){\n            AgentPlan p;\n            p.h_idx = i;\n            p.type = 0; \n            p.score = -1e9;\n            \n            if(in_danger[i]){\n                p.type = 2; \n                p.score = 100000; \n                p.target_r = -1; // Generic \"Safe Place\"\n            } else {\n                // Find best build task\n                for(const auto& t : tasks){\n                    // Verify safety (adjacent to pet rule)\n                    bool pet_adj = false;\n                    for(const auto& pt : state.pets) if(get_dist(t.r, t.c, pt.r, pt.c) <= 1) pet_adj = true;\n                    if(pet_adj) continue;\n                    \n                    // Verify no human stands on the wall site (current pos)\n                    bool human_on_site = false;\n                    for(const auto& h : state.humans) if(h.r == t.r && h.c == t.c) human_on_site = true;\n                    if(human_on_site) continue;\n                    \n                    int d = 1e9;\n                    for(int k=0; k<4; ++k){\n                        int nr = t.r + DR[k];\n                        int nc = t.c + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                            d = min(d, get_dist(state.humans[i].r, state.humans[i].c, nr, nc));\n                        }\n                    }\n                    \n                    if(d < 1e9){\n                        double s = t.priority * 100.0 - d;\n                        if(s > p.score){\n                            p.score = s;\n                            p.target_r = t.r;\n                            p.target_c = t.c;\n                            p.type = 1; // Build\n                        }\n                    }\n                }\n            }\n            agents.push_back(p);\n        }\n        \n        // Sort by score descending\n        sort(agents.begin(), agents.end(), [](const AgentPlan& a, const AgentPlan& b){\n            return a.score > b.score;\n        });\n        \n        // 4. Execute Plans with strict conflict checks\n        vector<string> res_actions(M, \".\");\n        vector<vector<bool>> reserved_next(N_ROWS, vector<bool>(N_COLS, false));\n        vector<vector<bool>> reserved_wall(N_ROWS, vector<bool>(N_COLS, false));\n        vector<bool> processed(M, false);\n        \n        // Note: reserved_next tracks FINALIZED positions.\n        // processed[id] tracks if human `id` has moved.\n        // Unprocessed humans are treated as obstacles at their current pos.\n        \n        for(const auto& ag : agents){\n            int i = ag.h_idx;\n            processed[i] = true; // Mark as processed\n            \n            int r = state.humans[i].r;\n            int c = state.humans[i].c;\n            bool done = false;\n            \n            // -- Type 2: Escape --\n            if(ag.type == 2){\n                vector<pair<int,int>> clean_targets;\n                for(const auto& comp : comps){\n                    if(!comp.has_pet) {\n                        for(auto cell : comp.cells) clean_targets.push_back(cell);\n                    }\n                }\n                \n                int dir = bfs_move(r, c, clean_targets, state, reserved_next, reserved_wall, processed);\n                if(dir != -1){\n                    int nr = r + DR[dir];\n                    int nc = c + DC[dir];\n                    res_actions[i] = string(1, MOVE_CHARS[dir]);\n                    reserved_next[nr][nc] = true;\n                    done = true;\n                }\n            }\n            // -- Type 1: Build --\n            else if(ag.type == 1){\n                int tr = ag.target_r;\n                int tc = ag.target_c;\n                \n                // Can build?\n                if(get_dist(r, c, tr, tc) == 1){\n                    bool ok = true;\n                    if(state.walls[tr][tc] || reserved_wall[tr][tc]) ok = false;\n                    // Pet adjacency check\n                    for(const auto& pt : state.pets) if(get_dist(tr, tc, pt.r, pt.c) <= 1) ok = false;\n                    // Human occupancy (processed)\n                    if(reserved_next[tr][tc]) ok = false;\n                    // Human occupancy (unprocessed)\n                    for(const auto& h : state.humans) if(!processed[h.id] && h.r == tr && h.c == tc) ok = false;\n                    \n                    if(ok){\n                        int b_dir = -1;\n                        for(int k=0; k<4; ++k) if(r+DR[k]==tr && c+DC[k]==tc) b_dir = k;\n                        \n                        res_actions[i] = string(1, BLOCK_CHARS[b_dir]);\n                        reserved_wall[tr][tc] = true;\n                        reserved_next[r][c] = true; // Stay\n                        done = true;\n                    }\n                }\n                \n                // Move to build spot\n                if(!done){\n                    vector<pair<int,int>> spots;\n                    for(int k=0; k<4; ++k){\n                        int nr = tr + DR[k];\n                        int nc = tc + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc]){\n                            spots.push_back({nr, nc});\n                        }\n                    }\n                    int dir = bfs_move(r, c, spots, state, reserved_next, reserved_wall, processed);\n                    if(dir != -1){\n                        int nr = r + DR[dir];\n                        int nc = c + DC[dir];\n                        res_actions[i] = string(1, MOVE_CHARS[dir]);\n                        reserved_next[nr][nc] = true;\n                        done = true;\n                    }\n                }\n            }\n            \n            // -- Default: Stay --\n            if(!done){\n                // Try to stay\n                if(!reserved_next[r][c]){\n                    // Double check nobody claimed it (should be covered by reserved_next)\n                    // Check new wall\n                    if(!reserved_wall[r][c]) {\n                        res_actions[i] = \".\";\n                        reserved_next[r][c] = true;\n                    } else {\n                        // Emergency: Someone built a wall on us (should be prevented by build checks, but just in case)\n                        // Try to move any adjacent free\n                        for(int k=0; k<4; ++k){\n                            int nr = r+DR[k];\n                            int nc = c+DC[k];\n                            if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc] && !reserved_next[nr][nc]){\n                                // And check unprocessed\n                                bool coll = false;\n                                for(const auto& h : state.humans) if(!processed[h.id] && h.r==nr && h.c==nc) coll = true;\n                                if(!coll){\n                                    res_actions[i] = string(1, MOVE_CHARS[k]);\n                                    reserved_next[nr][nc] = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output\n        string out_s = \"\";\n        for(const auto& s : res_actions) out_s += s;\n        cout << out_s << endl;\n        \n        // Update State\n        for(int i=0; i<M; ++i){\n            char c = res_actions[i][0];\n            if(c >= 'A' && c <= 'Z'){ \n                for(int k=0; k<4; ++k){\n                    if(MOVE_CHARS[k] == c){\n                        state.humans[i].r += DR[k];\n                        state.humans[i].c += DC[k];\n                    }\n                }\n            } else if(c >= 'a' && c <= 'z'){\n                 for(int k=0; k<4; ++k){\n                    if(BLOCK_CHARS[k] == c){\n                        state.walls[state.humans[i].r + DR[k]][state.humans[i].c + DC[k]] = true;\n                    }\n                }\n            }\n        }\n        \n        if(turn < MAX_TURNS){\n            string p_s;\n            for(int i=0; i<N; ++i){\n                cin >> p_s;\n                for(char c : p_s){\n                     for(int k=0; k<4; ++k){\n                        if(MOVE_CHARS[k] == c){\n                            state.pets[i].r += DR[k];\n                            state.pets[i].c += DC[k];\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_STEPS = 200;\nconst double EPS = 1e-5; // Pruning threshold\nconst double TIME_LIMIT = 1.90; // Safety margin\n\n// Globals\nint Si, Sj, Ti, Tj;\ndouble P;\nint H[N][N-1]; \nint V[N-1][N]; \nint flat_dist[N*N];\nint next_pos_cache[N*N][4]; \nint move_dist_cache[N*N][4]; \n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dchar[4] = {'U', 'D', 'L', 'R'};\n\nstruct Particle {\n    int u;\n    double p;\n};\n\nstruct State {\n    vector<Particle> dist; \n    double score; \n    double mass; \n    double heuristic; \n    string path;\n};\n\nstruct Candidate {\n    double heuristic;\n    int parent_idx;\n    int move_k;\n};\n\n// Timing\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_elapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\nvoid bfs_distances() {\n    for(int i=0; i<N*N; ++i) flat_dist[i] = 100000;\n    queue<pair<int,int>> q;\n    int target = Ti*N + Tj;\n    flat_dist[target] = 0;\n    q.push({Ti, Tj});\n    \n    while(!q.empty()){\n        auto [r, c] = q.front();\n        q.pop();\n        int cur_d = flat_dist[r*N+c];\n        \n        if (r > 0 && V[r-1][c] == 0) {\n            int n = (r-1)*N + c;\n            if (flat_dist[n] > cur_d + 1) { flat_dist[n] = cur_d + 1; q.push({r-1, c}); }\n        }\n        if (r < N-1 && V[r][c] == 0) {\n            int n = (r+1)*N + c;\n            if (flat_dist[n] > cur_d + 1) { flat_dist[n] = cur_d + 1; q.push({r+1, c}); }\n        }\n        if (c > 0 && H[r][c-1] == 0) {\n            int n = r*N + (c-1);\n            if (flat_dist[n] > cur_d + 1) { flat_dist[n] = cur_d + 1; q.push({r, c-1}); }\n        }\n        if (c < N-1 && H[r][c] == 0) {\n            int n = r*N + (c+1);\n            if (flat_dist[n] > cur_d + 1) { flat_dist[n] = cur_d + 1; q.push({r, c+1}); }\n        }\n    }\n}\n\nvoid precompute_moves() {\n    for(int r=0; r<N; ++r){\n        for(int c=0; c<N; ++c){\n            int u = r*N + c;\n            for(int k=0; k<4; ++k){\n                bool blocked = false;\n                if(k == 0){ if(r == 0 || V[r-1][c] == 1) blocked = true; }\n                else if(k == 1){ if(r == N-1 || V[r][c] == 1) blocked = true; }\n                else if(k == 2){ if(c == 0 || H[r][c-1] == 1) blocked = true; }\n                else if(k == 3){ if(c == N-1 || H[r][c] == 1) blocked = true; }\n                \n                if(blocked) next_pos_cache[u][k] = u;\n                else next_pos_cache[u][k] = (r + dr[k])*N + (c + dc[k]);\n                \n                move_dist_cache[u][k] = flat_dist[next_pos_cache[u][k]];\n            }\n        }\n    }\n}\n\n// Static buffers\ndouble temp_probs[N*N];\nint touched_list[N*N]; \nint touched_cnt = 0;\n\nint main(){\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    if (!(cin >> Si >> Sj >> Ti >> Tj >> P)) return 0;\n\n    for(int i=0; i<N; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N-1; ++j) H[i][j] = s[j] - '0';\n    }\n    for(int i=0; i<N-1; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) V[i][j] = s[j] - '0';\n    }\n    \n    bfs_distances();\n    precompute_moves();\n    \n    fill(temp_probs, temp_probs + N*N, 0.0);\n\n    double inv_prob_move = 1.0 / (1.0 - P);\n    int target_u = Ti*N + Tj;\n\n    State initial;\n    initial.path = \"\";\n    initial.score = 0.0;\n    initial.dist.push_back({Si*N + Sj, 1.0});\n    initial.mass = 1.0;\n    initial.heuristic = 401.0 - (flat_dist[Si*N + Sj] * inv_prob_move);\n    \n    if(Si == Ti && Sj == Tj) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    int current_beam_width = 2000;\n    vector<State> beam;\n    beam.reserve(10000);\n    beam.push_back(initial);\n    \n    vector<Candidate> candidates;\n    candidates.reserve(40000);\n\n    double stay_factor = P;\n    double move_factor = 1.0 - P;\n\n    for(int t=0; t<MAX_STEPS; ++t){\n        auto step_start = chrono::high_resolution_clock::now();\n\n        candidates.clear();\n        double time_term = 401.0 - (t + 1);\n        \n        // --- Step 1: Generate Candidates (Fast Dry Run) ---\n        for(int i=0; i < (int)beam.size(); ++i){\n            const auto& st = beam[i];\n            \n            if(st.dist.empty()) {\n                candidates.push_back({st.score, i, -1});\n                continue;\n            }\n\n            // Heuristic Base: Score + Expected Score of Remaining Mass\n            double base_val = st.score + st.mass * time_term;\n            \n            // Cost if we Stay (Prob P)\n            double stay_cost = 0.0;\n            for(const auto& p : st.dist){\n                stay_cost += p.p * flat_dist[p.u];\n            }\n            stay_cost *= stay_factor;\n            \n            double base_heur_minus_stay = base_val - stay_cost * inv_prob_move;\n\n            // Cost if we Move (Prob 1-P)\n            for(int k=0; k<4; ++k){\n                double move_cost = 0.0;\n                for(const auto& p : st.dist){\n                    move_cost += p.p * move_dist_cache[p.u][k];\n                }\n                move_cost *= move_factor;\n                \n                // Heuristic = Base - (Weighted_Dist_Stay + Weighted_Dist_Move) / (1-P)\n                double h = base_heur_minus_stay - move_cost * inv_prob_move;\n                candidates.push_back({h, i, k});\n            }\n        }\n\n        // --- Step 2: Select Best Candidates ---\n        int K = min((int)candidates.size(), current_beam_width);\n        if((int)candidates.size() > K){\n            nth_element(candidates.begin(), candidates.begin() + K, candidates.end(),\n                [](const Candidate& a, const Candidate& b){\n                    return a.heuristic > b.heuristic;\n                });\n        }\n        \n        // --- Step 3: Construct Next Beam States ---\n        vector<State> next_beam;\n        next_beam.reserve(K);\n        \n        for(int k=0; k<K; ++k){\n            const auto& cand = candidates[k];\n            const auto& parent = beam[cand.parent_idx];\n            \n            if(cand.move_k == -1){\n                next_beam.push_back(parent);\n                continue;\n            }\n            \n            State nst;\n            nst.heuristic = cand.heuristic;\n            nst.path = parent.path + dchar[cand.move_k];\n            nst.score = parent.score;\n            \n            touched_cnt = 0;\n            for(const auto& p : parent.dist){\n                int u = p.u;\n                double val = p.p;\n                \n                // Stay\n                if(temp_probs[u] == 0.0) touched_list[touched_cnt++] = u;\n                temp_probs[u] += val * stay_factor;\n                \n                // Move\n                int v = next_pos_cache[u][cand.move_k];\n                if(temp_probs[v] == 0.0) touched_list[touched_cnt++] = v;\n                temp_probs[v] += val * move_factor;\n            }\n            \n            nst.mass = 0.0;\n            nst.dist.reserve(touched_cnt);\n            \n            for(int j=0; j<touched_cnt; ++j){\n                int idx = touched_list[j];\n                double prob = temp_probs[idx];\n                temp_probs[idx] = 0.0; \n                \n                if(prob < EPS) continue;\n                \n                if(idx == target_u){\n                    nst.score += prob * time_term;\n                } else {\n                    nst.dist.push_back({idx, prob});\n                    nst.mass += prob;\n                }\n            }\n            \n            next_beam.push_back(std::move(nst));\n        }\n        \n        beam = std::move(next_beam);\n        \n        // Check if finished\n        bool active = false;\n        for(const auto& s : beam) if(!s.dist.empty()) { active = true; break; }\n        if(!active) break;\n\n        // --- Dynamic Beam Width Adjustment ---\n        auto step_end = chrono::high_resolution_clock::now();\n        double step_duration = chrono::duration<double>(step_end - step_start).count();\n        double total_elapsed = get_elapsed();\n        \n        if(total_elapsed > TIME_LIMIT) break;\n\n        double remaining_time = TIME_LIMIT - total_elapsed;\n        int remaining_steps = MAX_STEPS - (t + 1);\n        if(remaining_steps > 0){\n            double target_duration = remaining_time / remaining_steps;\n            // Adjust beam width to match target duration\n            // Ratio of Target/Actual determines scaling\n            double ratio = target_duration / (step_duration + 1e-9);\n            // Clamp ratio to prevent extreme oscillations\n            ratio = max(0.5, min(2.0, ratio));\n            \n            current_beam_width = (int)(current_beam_width * ratio);\n            // Hard limits on beam width\n            current_beam_width = max(100, min(30000, current_beam_width));\n        }\n    }\n    \n    double best_score = -1.0;\n    string best_s = \"\";\n    for(const auto& st : beam){\n        if(st.score > best_score){\n            best_score = st.score;\n            best_s = st.path;\n        }\n    }\n    \n    cout << best_s << endl;\n    \n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 30;\nconst int N2 = N * N;\n\n// Global lookup tables\nint to_tbl[8][4];\nint rotated_type_tbl[8][4];\nint adj[N2][4]; // [cell_idx][dir] -> neighbor_idx (-1 if none)\n\n// Precompute connectivity and adjacency\nvoid init_tables() {\n    // Connectivity\n    memset(to_tbl, -1, sizeof(to_tbl));\n    to_tbl[0][0] = 1; to_tbl[0][1] = 0;\n    to_tbl[1][0] = 3; to_tbl[1][3] = 0;\n    to_tbl[2][2] = 3; to_tbl[2][3] = 2;\n    to_tbl[3][2] = 1; to_tbl[3][1] = 2;\n    to_tbl[4][0] = 1; to_tbl[4][1] = 0; to_tbl[4][2] = 3; to_tbl[4][3] = 2;\n    to_tbl[5][0] = 3; to_tbl[5][3] = 0; to_tbl[5][2] = 1; to_tbl[5][1] = 2;\n    to_tbl[6][1] = 3; to_tbl[6][3] = 1;\n    to_tbl[7][0] = 2; to_tbl[7][2] = 0;\n\n    // Rotations\n    for(int t=0; t<8; ++t) {\n        for(int r=0; r<4; ++r) {\n            int curr = t;\n            for(int k=0; k<r; ++k) {\n                if (curr >= 0 && curr <= 3) curr = (curr + 1) % 4;\n                else if (curr == 4) curr = 5;\n                else if (curr == 5) curr = 4;\n                else if (curr == 6) curr = 7;\n                else if (curr == 7) curr = 6;\n            }\n            rotated_type_tbl[t][r] = curr;\n        }\n    }\n\n    // Adjacency\n    // Directions: 0: Left, 1: Up, 2: Right, 3: Down\n    const int di[] = {0, -1, 0, 1};\n    const int dj[] = {-1, 0, 1, 0};\n    \n    memset(adj, -1, sizeof(adj));\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int idx = r * N + c;\n            for(int d=0; d<4; ++d) {\n                int nr = r + di[d];\n                int nc = c + dj[d];\n                if(nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    adj[idx][d] = nr * N + nc;\n                }\n            }\n        }\n    }\n}\n\nstruct State {\n    int8_t rots[N2];\n    int8_t types[N2];\n};\n\nint initial_types[N2];\nint visited[3600]; // 900 * 4\nint gen = 0;\n\nmt19937 rng(12345);\n\nlong long evaluate(const State& st, long long& out_real_score) {\n    gen++;\n    if (gen <= 0) {\n        memset(visited, 0, sizeof(visited));\n        gen = 1;\n    }\n\n    int max_loop1 = 0;\n    int max_loop2 = 0;\n    long long sum_sq_loops = 0;\n    long long sum_sq_paths = 0;\n    int loop_count = 0;\n\n    // Iterate linearly\n    for(int idx = 0; idx < N2; ++idx) {\n        int t = st.types[idx];\n        \n        for(int d = 0; d < 4; ++d) {\n            int v_idx = (idx << 2) + d; // idx * 4 + d\n            \n            if(visited[v_idx] == gen) continue;\n            if(to_tbl[t][d] == -1) continue;\n\n            int curr_idx = idx;\n            int curr_d = d;\n            int start_idx = idx;\n            int start_d = d;\n            \n            int len = 0;\n            bool is_loop = false;\n\n            while(true) {\n                // Mark Entry\n                visited[(curr_idx << 2) + curr_d] = gen;\n                \n                int curr_t = st.types[curr_idx];\n                int out_d = to_tbl[curr_t][curr_d];\n                \n                // Mark Exit\n                visited[(curr_idx << 2) + out_d] = gen;\n                \n                len++;\n                \n                // Move using precomputed adjacency\n                int next_idx = adj[curr_idx][out_d];\n                if(next_idx == -1) {\n                    is_loop = false;\n                    break;\n                }\n                \n                // Next entry direction is opposite of out_d: (out_d + 2) % 4\n                // 0<->2, 1<->3. XOR with 2 does this.\n                int next_d = (out_d ^ 2); \n                \n                // Check connection compatibility\n                if(to_tbl[st.types[next_idx]][next_d] == -1) {\n                    is_loop = false;\n                    break;\n                }\n                \n                // Check visited\n                if(visited[(next_idx << 2) + next_d] == gen) {\n                    if(next_idx == start_idx && next_d == start_d) {\n                        is_loop = true;\n                    } else {\n                        is_loop = false;\n                    }\n                    break;\n                }\n                \n                curr_idx = next_idx;\n                curr_d = next_d;\n            }\n\n            if(is_loop) {\n                loop_count++;\n                long long l2 = (long long)len * len;\n                sum_sq_loops += l2;\n                if(len > max_loop1) {\n                    max_loop2 = max_loop1;\n                    max_loop1 = len;\n                } else if(len > max_loop2) {\n                    max_loop2 = len;\n                }\n            } else {\n                sum_sq_paths += (long long)len * len;\n            }\n        }\n    }\n\n    out_real_score = 0;\n    if(loop_count >= 2) {\n        out_real_score = (long long)max_loop1 * max_loop2;\n    }\n\n    // Scoring\n    long long score = 0;\n    if (out_real_score > 0) {\n        score += out_real_score * 1000000LL;\n    }\n    // Weight for loops restored to 50 to heavily favor loop formation\n    score += sum_sq_loops * 50; \n    score += sum_sq_paths;\n\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    init_tables();\n\n    for(int i=0; i<N2; ++i) {\n        char c; cin >> c;\n        initial_types[i] = c - '0';\n    }\n\n    State best_global_state;\n    memset(best_global_state.rots, 0, sizeof(best_global_state.rots));\n    \n    long long best_global_score_real = -1;\n    long long best_global_raw_score = -1;\n\n    auto start_time = chrono::steady_clock::now();\n    double total_time_limit = 1.98;\n\n    int num_runs = 2;\n    \n    for(int run=0; run < num_runs; ++run) {\n        State current_state;\n        // Random Init\n        for(int i=0; i<N2; ++i) {\n            current_state.rots[i] = rng() % 4;\n            current_state.types[i] = rotated_type_tbl[initial_types[i]][current_state.rots[i]];\n        }\n\n        long long current_real_score = 0;\n        long long current_score = evaluate(current_state, current_real_score);\n\n        State best_local_state = current_state;\n        long long best_local_score_real = current_real_score;\n        long long best_local_raw_score = current_score;\n\n        double t0 = 10000.0;\n        double t1 = 0.1;\n        double temp = t0;\n\n        double run_end_time = (run + 1) * (total_time_limit / num_runs);\n        auto run_start_t = chrono::steady_clock::now();\n        int iter = 0;\n\n        while(true) {\n            iter++;\n            // Batch time check every 2048 iterations for low overhead\n            if((iter & 2047) == 0) {\n                auto now = chrono::steady_clock::now();\n                double total_elapsed = chrono::duration<double>(now - start_time).count();\n                if(total_elapsed > run_end_time) break;\n\n                double run_elapsed = chrono::duration<double>(now - run_start_t).count();\n                double expected_duration = total_time_limit / num_runs; \n                double progress = run_elapsed / expected_duration;\n                if(progress > 1.0) progress = 1.0;\n                temp = t0 * pow(t1/t0, progress);\n            }\n\n            // Mutation\n            int idx1 = rng() % N2;\n            int old_rot1 = current_state.rots[idx1];\n            int old_type1 = current_state.types[idx1];\n\n            int new_rot1 = (old_rot1 + 1 + (rng() % 3)) % 4;\n            current_state.rots[idx1] = new_rot1;\n            current_state.types[idx1] = rotated_type_tbl[initial_types[idx1]][new_rot1];\n            \n            int idx2 = -1, old_rot2, old_type2;\n            \n            // Pair mutation with ~6.25% probability (1/16)\n            // Using bitwise check for speed\n            if((rng() & 15) == 0) { \n                 int d = rng() % 4;\n                 int neighbor = adj[idx1][d];\n                 if(neighbor != -1) {\n                     idx2 = neighbor;\n                     old_rot2 = current_state.rots[idx2];\n                     old_type2 = current_state.types[idx2];\n                     \n                     int new_rot2 = (old_rot2 + 1 + (rng() % 3)) % 4;\n                     current_state.rots[idx2] = new_rot2;\n                     current_state.types[idx2] = rotated_type_tbl[initial_types[idx2]][new_rot2];\n                 }\n            }\n\n            long long new_real_score = 0;\n            long long new_score = evaluate(current_state, new_real_score);\n\n            double delta = new_score - current_score;\n\n            bool accept = false;\n            if(delta >= 0) {\n                accept = true;\n            } else if (temp > 1e-5) {\n                if(bernoulli_distribution(exp(delta/temp))(rng)) {\n                    accept = true;\n                }\n            }\n\n            if(accept) {\n                current_score = new_score;\n                current_real_score = new_real_score;\n\n                if(current_real_score > best_local_score_real) {\n                    best_local_score_real = current_real_score;\n                    best_local_raw_score = current_score;\n                    best_local_state = current_state;\n                } else if(current_real_score == best_local_score_real && current_score > best_local_raw_score) {\n                    best_local_raw_score = current_score;\n                    best_local_state = current_state;\n                }\n            } else {\n                // Revert\n                current_state.rots[idx1] = old_rot1;\n                current_state.types[idx1] = old_type1;\n                if(idx2 != -1) {\n                    current_state.rots[idx2] = old_rot2;\n                    current_state.types[idx2] = old_type2;\n                }\n            }\n        }\n\n        // Update global\n        bool update = false;\n        if(best_local_score_real > best_global_score_real) update = true;\n        else if(best_local_score_real == best_global_score_real && best_local_raw_score > best_global_raw_score) update = true;\n\n        if(update) {\n            best_global_score_real = best_local_score_real;\n            best_global_raw_score = best_local_raw_score;\n            best_global_state = best_local_state;\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cout << (int)best_global_state.rots[i*N+j];\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <map>\n#include <iomanip>\n#include <cstring>\n#include <tuple>\n#include <numeric>\n#include <set>\n\nusing namespace std;\n\n// --- Constants ---\nconst int UP = 2;\nconst int DOWN = 8;\nconst int LEFT = 1;\nconst int RIGHT = 4;\nconst int DIR[4] = {UP, DOWN, LEFT, RIGHT};\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\n// --- Globals ---\nint N, T;\nvector<vector<int>> initial_board;\nvector<vector<int>> target_board;\nvector<vector<int>> tile_ids; \npair<int, int> empty_pos;\nstring moves_str = \"\";\n\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    return chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n}\n\ninline bool has_dir(int tile, int dir) { return (tile & dir) != 0; }\ninline int reverse_dir(int dir) {\n    if (dir == UP) return DOWN;\n    if (dir == DOWN) return UP;\n    if (dir == LEFT) return RIGHT;\n    if (dir == RIGHT) return LEFT;\n    return 0;\n}\n\nmt19937 rng(5489);\n\n// --- Evaluation ---\nint vis_token[16][16];\nint current_token = 0;\npair<int,int> bfs_q[256];\n\nstruct BoardScore {\n    int max_component;\n    int total_score;\n    vector<pair<int,int>> defects;\n};\n\nBoardScore evaluate(const vector<vector<int>>& board) {\n    current_token++;\n    int max_comp = 0;\n    int connections = 0;\n    int mismatches = 0;\n    int boundary_penalty = 0;\n    vector<pair<int,int>> defects;\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int tile = board[r][c];\n            if (tile == 0) continue;\n            bool defect = false;\n            // Up\n            if (has_dir(tile, UP)) {\n                if (r == 0 || board[r-1][c] == 0) { boundary_penalty++; defect=true; }\n                else if (!has_dir(board[r-1][c], DOWN)) { mismatches++; defect=true; }\n                else connections++;\n            }\n            // Down\n            if (has_dir(tile, DOWN)) {\n                if (r == N-1 || board[r+1][c] == 0) { boundary_penalty++; defect=true; }\n                else if (!has_dir(board[r+1][c], UP)) { mismatches++; defect=true; }\n                else connections++;\n            }\n            // Left\n            if (has_dir(tile, LEFT)) {\n                if (c == 0 || board[r][c-1] == 0) { boundary_penalty++; defect=true; }\n                else if (!has_dir(board[r][c-1], RIGHT)) { mismatches++; defect=true; }\n                else connections++;\n            }\n            // Right\n            if (has_dir(tile, RIGHT)) {\n                if (c == N-1 || board[r][c+1] == 0) { boundary_penalty++; defect=true; }\n                else if (!has_dir(board[r][c+1], LEFT)) { mismatches++; defect=true; }\n                else connections++;\n            }\n            if (defect) defects.push_back({r,c});\n            \n            if (vis_token[r][c] != current_token) {\n                int head = 0, tail = 0;\n                bfs_q[tail++] = {r, c};\n                vis_token[r][c] = current_token;\n                int size = 0;\n                while(head < tail) {\n                    auto [cr, cc] = bfs_q[head++];\n                    size++;\n                    int ctile = board[cr][cc];\n                    for (int d = 0; d < 4; ++d) {\n                        if (has_dir(ctile, DIR[d])) {\n                            int nr = cr + DR[d];\n                            int nc = cc + DC[d];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                                int neighbor = board[nr][nc];\n                                if (neighbor != 0 && has_dir(neighbor, reverse_dir(DIR[d]))) {\n                                    if (vis_token[nr][nc] != current_token) {\n                                        vis_token[nr][nc] = current_token;\n                                        bfs_q[tail++] = {nr, nc};\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n                if (size > max_comp) max_comp = size;\n            }\n        }\n    }\n    int score = max_comp * 5000 + connections * 50 - mismatches * 50 - boundary_penalty * 50;\n    return {max_comp, score, defects};\n}\n\nvoid find_target_configuration() {\n    vector<int> tiles;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tiles.push_back(initial_board[r][c]);\n    auto it = find(tiles.begin(), tiles.end(), 0);\n    if(it != tiles.end()) iter_swap(it, tiles.end() - 1);\n    target_board.assign(N, vector<int>(N));\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) target_board[r][c] = tiles[r*N + c];\n    \n    BoardScore current_eval = evaluate(target_board);\n    int current_score = current_eval.total_score;\n    vector<vector<int>> best_board = target_board;\n    int best_score = current_score;\n    \n    double time_limit = 1.5; \n    double start_temp = 1500.0;\n    double end_temp = 0.1;\n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 127) == 0) if (get_time() > time_limit) break;\n        \n        double t = get_time();\n        double temp = start_temp * pow(end_temp / start_temp, t / time_limit);\n        \n        int r1, c1, r2, c2;\n        if (!current_eval.defects.empty() && (rng() & 1)) {\n            int idx = rng() % current_eval.defects.size();\n            r1 = current_eval.defects[idx].first; c1 = current_eval.defects[idx].second;\n        } else {\n            r1 = rng() % N; c1 = rng() % N;\n        }\n        if (r1 == N-1 && c1 == N-1) { r1 = 0; c1 = 0; }\n        do { r2 = rng() % N; c2 = rng() % N; } while (r2 == N-1 && c2 == N-1);\n        \n        if (r1 == r2 && c1 == c2) continue;\n        if (target_board[r1][c1] == target_board[r2][c2]) continue;\n        \n        swap(target_board[r1][c1], target_board[r2][c2]);\n        BoardScore next_eval = evaluate(target_board);\n        if (next_eval.total_score >= current_score) {\n            current_score = next_eval.total_score; current_eval = next_eval;\n            if (current_score > best_score) { best_score = current_score; best_board = target_board; }\n        } else {\n            if (uniform_real_distribution<>(0,1)(rng) < exp((next_eval.total_score - current_score) / temp)) {\n                current_score = next_eval.total_score; current_eval = next_eval;\n            } else {\n                swap(target_board[r1][c1], target_board[r2][c2]);\n            }\n        }\n    }\n    target_board = best_board;\n}\n\nvoid apply_move(char c) {\n    int dr = 0, dc = 0;\n    if (c == 'U') dr = -1; else if (c == 'D') dr = 1; else if (c == 'L') dc = -1; else if (c == 'R') dc = 1;\n    int nr = empty_pos.first + dr;\n    int nc = empty_pos.second + dc;\n    if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n        swap(initial_board[empty_pos.first][empty_pos.second], initial_board[nr][nc]);\n        swap(tile_ids[empty_pos.first][empty_pos.second], tile_ids[nr][nc]);\n        empty_pos = {nr, nc};\n        moves_str += c;\n    }\n}\n\nvoid execute_moves(const string& moves) {\n    for (char c : moves) apply_move(c);\n}\n\nstatic int dist_bfs[10][10][10][10];\nstatic char move_bfs[10][10][10][10];\n\nstring get_path_for_tile(int tr, int tc, int dest_r, int dest_c, const vector<vector<bool>>& loc) {\n    if (tr == dest_r && tc == dest_c) return \"\";\n    memset(dist_bfs, -1, sizeof(dist_bfs));\n    static tuple<int,int,int,int> q[10005];\n    int head = 0, tail = 0;\n    dist_bfs[tr][tc][empty_pos.first][empty_pos.second] = 0;\n    q[tail++] = {tr, tc, empty_pos.first, empty_pos.second};\n    \n    int final_er = -1, final_ec = -1;\n    bool found = false;\n    while(head < tail) {\n        auto [ctr, ctc, cer, cec] = q[head++];\n        if (ctr == dest_r && ctc == dest_c) { final_er = cer; final_ec = cec; found = true; break; }\n        int d = dist_bfs[ctr][ctc][cer][cec];\n        for (int i=0; i<4; ++i) {\n            int ner = cer + DR[i], nec = cec + DC[i];\n            if (ner >= 0 && ner < N && nec >= 0 && nec < N && !loc[ner][nec]) {\n                if (ner == ctr && nec == ctc) { // Swap\n                    if (dist_bfs[cer][cec][ner][nec] == -1) {\n                        dist_bfs[cer][cec][ner][nec] = d + 1;\n                        move_bfs[cer][cec][ner][nec] = 'S';\n                        q[tail++] = {cer, cec, ner, nec};\n                    }\n                } else { // Move empty\n                    if (dist_bfs[ctr][ctc][ner][nec] == -1) {\n                        dist_bfs[ctr][ctc][ner][nec] = d + 1;\n                        move_bfs[ctr][ctc][ner][nec] = DIR_CHAR[i];\n                        q[tail++] = {ctr, ctc, ner, nec};\n                    }\n                }\n            }\n        }\n    }\n    if (!found) return \"\";\n    string path = \"\";\n    int ctr = dest_r, ctc = dest_c, cer = final_er, cec = final_ec;\n    int start_er = empty_pos.first, start_ec = empty_pos.second;\n    while (ctr != tr || ctc != tc || cer != start_er || cec != start_ec) {\n        char m = move_bfs[ctr][ctc][cer][cec];\n        if (m == 'S') {\n            int prev_er = ctr, prev_ec = ctc;\n            int dr = cer - prev_er, dc = cec - prev_ec;\n            char c = (dr == -1) ? 'U' : (dr == 1) ? 'D' : (dc == -1) ? 'L' : 'R';\n            path += c;\n            ctr = cer; ctc = cec; cer = prev_er; cec = prev_ec;\n        } else {\n            path += m;\n            int dr=0, dc=0;\n            if(m=='U') dr=-1; else if(m=='D') dr=1; else if(m=='L') dc=-1; else if(m=='R') dc=1;\n            cer -= dr; cec -= dc;\n        }\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstring safe_bfs_empty(int tr, int tc, const vector<vector<bool>>& loc) {\n    if (empty_pos.first == tr && empty_pos.second == tc) return \"\";\n    static int d[10][10];\n    static char m[10][10];\n    memset(d, -1, sizeof(d));\n    static pair<int,int> q[105];\n    int head = 0, tail = 0;\n    q[tail++] = empty_pos;\n    d[empty_pos.first][empty_pos.second] = 0;\n    bool found = false;\n    while(head < tail) {\n        auto [r, c] = q[head++];\n        if (r == tr && c == tc) { found = true; break; }\n        for (int i=0; i<4; ++i) {\n            int nr=r+DR[i], nc=c+DC[i];\n            if(nr>=0 && nr<N && nc>=0 && nc<N && !loc[nr][nc] && d[nr][nc]==-1) {\n                d[nr][nc] = d[r][c]+1; m[nr][nc] = DIR_CHAR[i];\n                q[tail++] = {nr, nc};\n            }\n        }\n    }\n    if(!found) return \"\";\n    string p=\"\"; int r=tr, c=tc;\n    while(r!=empty_pos.first || c!=empty_pos.second) {\n        char c_move = m[r][c]; p+=c_move;\n        int dr=0, dc=0;\n        if(c_move=='U') dr=-1; else if(c_move=='D') dr=1; else if(c_move=='L') dc=-1; else if(c_move=='R') dc=1;\n        r-=dr; c-=dc;\n    }\n    reverse(p.begin(), p.end());\n    return p;\n}\n\nvoid solve_puzzle() {\n    tile_ids.assign(N, vector<int>(N));\n    int id_counter = 0;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tile_ids[r][c] = id_counter++;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c] == 0) empty_pos = {r,c};\n\n    vector<int> target_assignment(N*N, -1);\n    vector<bool> id_used(N*N, false);\n\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int type = target_board[r][c];\n            int best_id = -1; int min_dist = 10000;\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                int id = tile_ids[i][j];\n                if (!id_used[id] && initial_board[i][j] == type) {\n                    int dist = abs(r - i) + abs(c - j);\n                    if (dist < min_dist) { min_dist = dist; best_id = id; }\n                }\n            }\n            target_assignment[r*N + c] = best_id;\n            id_used[best_id] = true;\n        }\n    }\n    \n    for (int i=0; i<N*N; ++i) for (int j=i+1; j<N*N; ++j) {\n        int id1 = target_assignment[i], id2 = target_assignment[j];\n        int r1=-1,c1=-1,r2=-1,c2=-1, t1=-1, t2=-2;\n        for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n            if (tile_ids[r][c] == id1) { r1=r; c1=c; t1=initial_board[r][c]; }\n            if (tile_ids[r][c] == id2) { r2=r; c2=c; t2=initial_board[r][c]; }\n        }\n        if (t1 == t2) {\n            int d_curr = abs(r1 - i/N) + abs(c1 - i%N) + abs(r2 - j/N) + abs(c2 - j%N);\n            int d_swap = abs(r1 - j/N) + abs(c1 - j%N) + abs(r2 - i/N) + abs(c2 - i%N);\n            if (d_swap < d_curr) swap(target_assignment[i], target_assignment[j]);\n        }\n    }\n\n    vector<int> pos_map(N*N);\n    for(int i=0; i<N*N; ++i) pos_map[target_assignment[i]] = i;\n    int swaps = 0;\n    vector<bool> visited(N*N, false);\n    for(int i=0; i<N*N; ++i) {\n        if (!visited[i]) {\n            int curr = i;\n            while (!visited[curr]) { visited[curr] = true; curr = pos_map[tile_ids[curr/N][curr%N]]; }\n            swaps++;\n        }\n    }\n    int total_swaps = N*N - swaps;\n    int empty_id = -1; for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c]==0) empty_id = tile_ids[r][c];\n    int t_empty = pos_map[empty_id];\n    int dist = abs(empty_pos.first - t_empty/N) + abs(empty_pos.second - t_empty%N);\n    \n    if ((total_swaps + dist) % 2 != 0) {\n        bool swapped = false;\n        for(int i=0; i<N*N && !swapped; ++i) for(int j=i+1; j<N*N && !swapped; ++j) {\n            int id1 = target_assignment[i], id2 = target_assignment[j];\n            if (id1==empty_id || id2==empty_id) continue;\n            int t1=-1, t2=-2;\n            for(int r=0;r<N;++r)for(int c=0;c<N;++c) {\n                 if(tile_ids[r][c]==id1) t1=initial_board[r][c];\n                 if(tile_ids[r][c]==id2) t2=initial_board[r][c];\n            }\n            if (t1==t2) { swap(target_assignment[i], target_assignment[j]); swapped=true; }\n        }\n        if(!swapped) {\n            for(int i=0; i<N*N && !swapped; ++i) for(int j=i+1; j<N*N && !swapped; ++j) {\n                if (target_assignment[i]!=empty_id && target_assignment[j]!=empty_id) {\n                    swap(target_assignment[i], target_assignment[j]); swapped=true;\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> target_ids_map(N, vector<int>(N));\n    for(int i=0; i<N*N; ++i) target_ids_map[i/N][i%N] = target_assignment[i];\n    vector<vector<bool>> locked(N, vector<bool>(N, false));\n\n    auto get_pos = [&](int id) {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n        return make_pair(-1,-1);\n    };\n    \n    for (int r = 0; r <= N - 3; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (c < N - 2) {\n                int id = target_ids_map[r][c];\n                pair<int,int> curr = get_pos(id);\n                execute_moves(get_path_for_tile(curr.first, curr.second, r, c, locked));\n                locked[r][c] = true;\n            } else {\n                int t1 = target_ids_map[r][N-2], t2 = target_ids_map[r][N-1];\n                pair<int,int> curr = get_pos(t2);\n                execute_moves(get_path_for_tile(curr.first, curr.second, r+1, N-1, locked));\n                pair<int,int> p2_pos = get_pos(t2); locked[p2_pos.first][p2_pos.second] = true;\n                curr = get_pos(t1);\n                execute_moves(get_path_for_tile(curr.first, curr.second, r, N-1, locked));\n                locked[p2_pos.first][p2_pos.second] = false;\n                pair<int,int> p1_pos = get_pos(t1); locked[p1_pos.first][p1_pos.second] = true;\n                p2_pos = get_pos(t2); locked[p2_pos.first][p2_pos.second] = true;\n                execute_moves(safe_bfs_empty(r, N-2, locked));\n                if (empty_pos.first == r && empty_pos.second == N-2) execute_moves(\"RD\");\n                locked[p1_pos.first][p1_pos.second] = false; locked[p2_pos.first][p2_pos.second] = false;\n                locked[r][N-2] = true; locked[r][N-1] = true;\n                break;\n            }\n        }\n    }\n    for(int c=0; c <= N-3; ++c) {\n        int t1 = target_ids_map[N-2][c], t2 = target_ids_map[N-1][c];\n        pair<int,int> curr = get_pos(t2);\n        execute_moves(get_path_for_tile(curr.first, curr.second, N-1, c+1, locked));\n        pair<int,int> p2_pos = get_pos(t2); locked[p2_pos.first][p2_pos.second] = true;\n        curr = get_pos(t1);\n        execute_moves(get_path_for_tile(curr.first, curr.second, N-1, c, locked));\n        locked[p2_pos.first][p2_pos.second] = false;\n        pair<int,int> p1_pos = get_pos(t1); locked[p1_pos.first][p1_pos.second] = true;\n        p2_pos = get_pos(t2); locked[p2_pos.first][p2_pos.second] = true;\n        execute_moves(safe_bfs_empty(N-2, c, locked));\n        if (empty_pos.first == N-2 && empty_pos.second == c) execute_moves(\"DR\");\n        locked[p1_pos.first][p1_pos.second] = false; locked[p2_pos.first][p2_pos.second] = false;\n        locked[N-2][c] = true; locked[N-1][c] = true;\n    }\n\n    vector<pair<int,int>> pm = {{N-2, N-3}, {N-2, N-2}, {N-2, N-1}, {N-1, N-3}, {N-1, N-2}, {N-1, N-1}};\n    map<int,int> lmap;\n    for(int i=0; i<6; ++i) lmap[target_ids_map[pm[i].first][pm[i].second]] = i;\n    int tgt_v = 0; for(int i=0; i<6; ++i) tgt_v = (tgt_v << 3) | i;\n    \n    int start_v = 0;\n    for(int i=0; i<6; ++i) start_v = (start_v << 3) | lmap[tile_ids[pm[i].first][pm[i].second]];\n    \n    if (start_v == tgt_v) return;\n\n    static int parent[270000]; static char move_c[270000]; static bool vis[270000];\n    memset(vis, 0, sizeof(vis));\n    queue<int> q; q.push(start_v); vis[start_v] = true;\n    bool solved = false; int steps=0;\n    \n    while(!q.empty()) {\n        int curr = q.front(); q.pop();\n        if (curr == tgt_v) { solved = true; break; }\n        if (++steps > 250000) break;\n        \n        int tmp = curr, z = -1;\n        int s[6]; for(int i=5; i>=0; --i) { s[i] = tmp & 7; if(s[i] == lmap[empty_id]) z = i; tmp >>= 3; }\n        \n        int r = pm[z].first, c = pm[z].second;\n        for(int d=0; d<4; ++d) {\n            int nr = r + DR[d], nc = c + DC[d];\n            int nz = -1; for(int k=0; k<6; ++k) if(pm[k].first == nr && pm[k].second == nc) nz = k;\n            if (nz != -1) {\n                swap(s[z], s[nz]);\n                int nxt = 0; for(int i=0; i<6; ++i) nxt = (nxt << 3) | s[i];\n                swap(s[z], s[nz]);\n                if (!vis[nxt]) { vis[nxt] = true; parent[nxt] = curr; move_c[nxt] = DIR_CHAR[d]; q.push(nxt); }\n            }\n        }\n    }\n    \n    if (solved) {\n        string path = \"\"; int curr = tgt_v;\n        while (curr != start_v) { path += move_c[curr]; curr = parent[curr]; }\n        reverse(path.begin(), path.end());\n        execute_moves(path);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    if(!(cin >> N >> T)) return 0;\n    initial_board.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) initial_board[i][j] = (s[j]>='0' && s[j]<='9') ? (s[j]-'0') : (s[j]-'a'+10);\n    }\n    find_target_configuration();\n    solve_puzzle();\n    cout << moves_str << endl;\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n#include <numeric>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst double PI = std::acos(-1.0);\nconst int MAX_K = 105;\nconst int MAX_N = 6000;\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\n// Global inputs\nint N;\nint K_limit;\nint A[11];\nvector<Point> points;\n\n// Random engine\nmt19937 rng(42);\n\n// Buffers for fast evaluation\n// Using flattened grid for potentially slightly faster access\nunsigned short counts_grid_flat[MAX_K * MAX_K];\n\n// Timer\nclass Timer {\n    chrono::high_resolution_clock::time_point start;\npublic:\n    Timer() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(now - start).count();\n    }\n};\n\n// Helper: Unique coordinates with tolerance\nvector<double> get_unique_coords(const vector<double>& coords) {\n    if (coords.empty()) return {};\n    vector<double> sorted = coords;\n    sort(sorted.begin(), sorted.end());\n    vector<double> uniq;\n    uniq.push_back(sorted[0]);\n    for (size_t i = 1; i < sorted.size(); ++i) {\n        if (sorted[i] - uniq.back() > 1e-3) {\n            uniq.push_back(sorted[i]);\n        }\n    }\n    return uniq;\n}\n\n// Data structures for a specific angle pair configuration\nstruct AngleConfig {\n    double theta1, theta2; // degrees\n    vector<double> uniq_1, uniq_2;\n    vector<unsigned short> rank_1, rank_2; \n    \n    // Best solution found for this config\n    vector<int> best_c1, best_c2;\n    long long best_score = -1;\n};\n\n// Solver class\nclass Solver {\n    // Internal state for incremental updates\n    vector<unsigned short> current_Lx;\n    vector<unsigned short> current_Ly;\n    vector<int> current_c1;\n    vector<int> current_c2;\n    long long current_score;\n    \npublic:\n    Solver() {\n        current_Lx.resize(MAX_N);\n        current_Ly.resize(MAX_N);\n    }\n\n    // Build lookup table for a given set of cuts\n    // rank_to_bin maps: unique_coord_rank -> bin_index\n    // out_L maps: point_index -> bin_index\n    void build_lookup(const vector<int>& cuts, int num_uniq, const vector<unsigned short>& ranks, vector<unsigned short>& out_L) {\n        static unsigned short rank_to_bin[MAX_N]; // static to reuse memory\n        \n        int current_bin = 0;\n        int cut_idx = 0;\n        int num_cuts = cuts.size();\n        \n        for(int r=0; r<num_uniq; ++r) {\n            if(cut_idx < num_cuts && r == cuts[cut_idx]) {\n                current_bin++;\n                cut_idx++;\n            }\n            rank_to_bin[r] = (unsigned short)current_bin;\n        }\n        \n        for(int i=0; i<N; ++i) {\n            out_L[i] = rank_to_bin[ranks[i]];\n        }\n    }\n\n    // Fast eval using provided L tables\n    long long eval_core(int n1, int n2, const vector<unsigned short>& L1, const vector<unsigned short>& L2) {\n        // Clear grid (only used rows)\n        // We use MAX_K stride to avoid re-calculating offsets too much\n        for(int i=0; i<n1; ++i) {\n             memset(counts_grid_flat + i * MAX_K, 0, n2 * sizeof(unsigned short));\n        }\n\n        // Fill grid\n        for(int i=0; i<N; ++i) {\n            counts_grid_flat[L1[i] * MAX_K + L2[i]]++;\n        }\n\n        // Score\n        int piece_b[11] = {0};\n        for(int i=0; i<n1; ++i) {\n            unsigned short* row = counts_grid_flat + i * MAX_K;\n            for(int j=0; j<n2; ++j) {\n                int c = row[j];\n                if(c <= 10 && c >= 1) piece_b[c]++;\n            }\n        }\n\n        long long num = 0;\n        for(int d=1; d<=10; ++d) {\n            num += min(A[d], piece_b[d]);\n        }\n        return num;\n    }\n    \n    // Initial full evaluation\n    long long eval_init(const AngleConfig& config, const vector<int>& c1, const vector<int>& c2) {\n        build_lookup(c1, config.uniq_1.size(), config.rank_1, current_Lx);\n        build_lookup(c2, config.uniq_2.size(), config.rank_2, current_Ly);\n        current_c1 = c1;\n        current_c2 = c2;\n        return eval_core(c1.size()+1, c2.size()+1, current_Lx, current_Ly);\n    }\n\n    void run_sa(AngleConfig& config, double max_duration, int max_iters, bool warm_start) {\n        Timer t;\n        \n        auto gen_quantile_cuts = [&](int n, int max_v) {\n             vector<int> res;\n             if (max_v <= 1) return res;\n             if (n > max_v - 1) n = max_v - 1;\n             for (int i = 1; i <= n; ++i) {\n                 int idx = (int)(1.0 * i * max_v / (n + 1));\n                 if (idx < 1) idx = 1;\n                 if (idx >= max_v) idx = max_v - 1;\n                 res.push_back(idx);\n             }\n             sort(res.begin(), res.end());\n             res.erase(unique(res.begin(), res.end()), res.end());\n             return res;\n        };\n\n        vector<int> init_c1, init_c2;\n        if (warm_start && config.best_score != -1) {\n            init_c1 = config.best_c1;\n            init_c2 = config.best_c2;\n        } else {\n            int k1 = K_limit / 2;\n            int k2 = K_limit - k1;\n            init_c1 = gen_quantile_cuts(k1, config.uniq_1.size());\n            init_c2 = gen_quantile_cuts(k2, config.uniq_2.size());\n        }\n        \n        current_score = eval_init(config, init_c1, init_c2);\n        \n        if (current_score > config.best_score) {\n            config.best_score = current_score;\n            config.best_c1 = current_c1;\n            config.best_c2 = current_c2;\n        }\n\n        double start_temp = 2.5; \n        if (warm_start) start_temp = 0.5;\n        \n        // Temp buffers\n        vector<unsigned short> temp_L(MAX_N);\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if (max_iters > 0) {\n                if (iter >= max_iters) break;\n            } else {\n                if ((iter & 127) == 0) {\n                    if (t.elapsed() > max_duration) break;\n                }\n            }\n\n            double progress = 0;\n            if (max_iters > 0) progress = (double)iter / max_iters;\n            else progress = t.elapsed() / max_duration;\n            if (progress > 1.0) progress = 1.0;\n\n            double temp = start_temp * (1.0 - progress);\n            if(temp < 1e-9) temp = 1e-9;\n\n            int op_dim = rng() % 2; \n            \n            vector<int> next_cuts;\n            const vector<int>& curr_cuts = (op_dim == 0) ? current_c1 : current_c2;\n            int max_val = (op_dim == 0) ? config.uniq_1.size() : config.uniq_2.size();\n            int other_size = (op_dim == 0) ? current_c2.size() : current_c1.size();\n            \n            if (max_val <= 1) continue;\n\n            next_cuts = curr_cuts;\n            int type = rng() % 3; \n\n            bool valid_move = false;\n            \n            if (type == 0 && !next_cuts.empty()) { // Shift\n                int idx = rng() % next_cuts.size();\n                int old_v = next_cuts[idx];\n                int shift = (rng() % 7) - 3; \n                int val = old_v + shift;\n                if (val < 1) val = 1;\n                if (val >= max_val) val = max_val - 1;\n                \n                bool exists = false;\n                for(int v : next_cuts) if(v == val && v != old_v) { exists = true; break; }\n                \n                if(!exists) {\n                    next_cuts[idx] = val;\n                    sort(next_cuts.begin(), next_cuts.end());\n                    valid_move = true;\n                }\n            } else if (type == 1) { // Add\n                if (next_cuts.size() + other_size < K_limit) {\n                    int val = (rng() % (max_val - 1)) + 1;\n                    bool exists = false;\n                    for(int v : next_cuts) if(v == val) { exists = true; break; }\n                    if(!exists) {\n                        next_cuts.push_back(val);\n                        sort(next_cuts.begin(), next_cuts.end());\n                        valid_move = true;\n                    }\n                }\n            } else if (type == 2 && !next_cuts.empty()) { // Delete\n                int idx = rng() % next_cuts.size();\n                next_cuts.erase(next_cuts.begin() + idx);\n                valid_move = true;\n            }\n\n            if (!valid_move) continue;\n\n            // Optimized evaluation: only rebuild L for changed dimension\n            if (op_dim == 0) {\n                build_lookup(next_cuts, config.uniq_1.size(), config.rank_1, temp_L);\n                long long new_score = eval_core(next_cuts.size()+1, current_c2.size()+1, temp_L, current_Ly);\n                \n                long long diff = new_score - current_score;\n                if (diff >= 0 || exp(diff / temp) > (double(rng())/mt19937::max())) {\n                    current_c1 = next_cuts;\n                    current_Lx = temp_L;\n                    current_score = new_score;\n                    if (current_score > config.best_score) {\n                        config.best_score = current_score;\n                        config.best_c1 = current_c1;\n                        config.best_c2 = current_c2;\n                    }\n                }\n            } else {\n                build_lookup(next_cuts, config.uniq_2.size(), config.rank_2, temp_L);\n                long long new_score = eval_core(current_c1.size()+1, next_cuts.size()+1, current_Lx, temp_L);\n                \n                long long diff = new_score - current_score;\n                if (diff >= 0 || exp(diff / temp) > (double(rng())/mt19937::max())) {\n                    current_c2 = next_cuts;\n                    current_Ly = temp_L;\n                    current_score = new_score;\n                    if (current_score > config.best_score) {\n                        config.best_score = current_score;\n                        config.best_c1 = current_c1;\n                        config.best_c2 = current_c2;\n                    }\n                }\n            }\n        }\n    }\n};\n\nAngleConfig make_config(double t1, double t2) {\n    AngleConfig cfg;\n    cfg.theta1 = t1;\n    cfg.theta2 = t2;\n    \n    vector<double> raw_vals(N);\n    \n    double rad1 = t1 * PI / 180.0;\n    double c1 = cos(rad1), s1 = sin(rad1);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c1 + points[j].y * s1;\n    \n    cfg.uniq_1 = get_unique_coords(raw_vals);\n    cfg.rank_1.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_1.begin(), cfg.uniq_1.end(), raw_vals[j] - 1e-4);\n        cfg.rank_1[j] = (unsigned short)distance(cfg.uniq_1.begin(), it);\n    }\n    \n    double rad2 = t2 * PI / 180.0;\n    double c2 = cos(rad2), s2 = sin(rad2);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c2 + points[j].y * s2;\n    \n    cfg.uniq_2 = get_unique_coords(raw_vals);\n    cfg.rank_2.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_2.begin(), cfg.uniq_2.end(), raw_vals[j] - 1e-4);\n        cfg.rank_2[j] = (unsigned short)distance(cfg.uniq_2.begin(), it);\n    }\n    \n    return cfg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> K_limit)) return 0;\n    for(int i=1; i<=10; ++i) cin >> A[i];\n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y;\n    }\n\n    Timer total_timer;\n    Solver solver;\n    \n    vector<AngleConfig> configs;\n    configs.reserve(300);\n    \n    // Phase 1: Broad Screening with Optimization\n    // Orthogonal\n    for(int i=0; i<90; i += 2) { \n        configs.push_back(make_config(i, i + 90.0));\n        configs.push_back(make_config(i + 0.5, i + 90.5));\n    }\n    \n    // Random\n    for(int i=0; i<100; ++i) {\n        double t1 = uniform_real_distribution<double>(0, 180)(rng);\n        double t2 = uniform_real_distribution<double>(0, 180)(rng);\n        double diff = abs(t1 - t2);\n        while(diff > 180) diff -= 180;\n        if(abs(diff) < 10 || abs(diff) > 170) continue;\n        configs.push_back(make_config(t1, t2));\n    }\n    \n    // With faster eval, we can screen slightly longer\n    for(auto& cfg : configs) {\n        solver.run_sa(cfg, 0, 200, false); \n    }\n    \n    vector<int> indices(configs.size());\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b){\n        return configs[a].best_score > configs[b].best_score;\n    });\n    \n    // Phase 2: Local Angle Refinement (Pattern Search)\n    int keep_top = 5;\n    vector<AngleConfig> final_candidates;\n    \n    for(int k=0; k<keep_top && k<(int)indices.size(); ++k) {\n        AngleConfig current = configs[indices[k]];\n        \n        // Attempt to improve angles using a deterministic pattern search\n        double delta = 1.0;\n        for(int step=0; step<3; ++step) {\n            bool improved = false;\n            double offsets[4][2] = {{delta, 0}, {-delta, 0}, {0, delta}, {0, -delta}};\n            \n            AngleConfig best_neighbor = current;\n            for(auto& off : offsets) {\n                AngleConfig neighbor = make_config(current.theta1 + off[0], current.theta2 + off[1]);\n                solver.run_sa(neighbor, 0, 300, false);\n                if (neighbor.best_score > best_neighbor.best_score) {\n                    best_neighbor = neighbor;\n                    improved = true;\n                }\n            }\n            if (improved) current = best_neighbor;\n            else delta *= 0.5;\n        }\n        final_candidates.push_back(current);\n    }\n    \n    // Phase 3: Deep Optimization\n    int best_idx = 0;\n    for(size_t i=1; i<final_candidates.size(); ++i) {\n        if(final_candidates[i].best_score > final_candidates[best_idx].best_score) {\n            best_idx = i;\n        }\n    }\n    \n    double remaining = 2.95 - total_timer.elapsed();\n    if (remaining < 0.1) remaining = 0.1;\n    \n    solver.run_sa(final_candidates[best_idx], remaining, -1, true);\n    \n    // Output\n    const auto& S = final_candidates[best_idx];\n    cout << S.best_c1.size() + S.best_c2.size() << endl;\n    \n    auto print_line = [&](double ang, double val) {\n        double rad = ang * PI / 180.0;\n        double A = cos(rad);\n        double B = sin(rad);\n        double C = val;\n        double Mx = C * A;\n        double My = C * B;\n        double Dx = -B;\n        double Dy = A;\n        long long scale = 400000000LL;\n        long long x1 = round(Mx - scale * Dx);\n        long long y1 = round(My - scale * Dy);\n        long long x2 = round(Mx + scale * Dx);\n        long long y2 = round(My + scale * Dy);\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    };\n    \n    for(int idx : S.best_c1) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_1.size())\n            val = (S.uniq_1[idx-1] + S.uniq_1[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_1[0] - 10.0;\n        else val = S.uniq_1.back() + 10.0;\n        print_line(S.theta1, val);\n    }\n    for(int idx : S.best_c2) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_2.size())\n            val = (S.uniq_2[idx-1] + S.uniq_2[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_2[0] - 10.0;\n        else val = S.uniq_2.back() + 10.0;\n        print_line(S.theta2, val);\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <iomanip>\n#include <random>\n\nusing namespace std;\n\nconst double TIME_LIMIT = 4.85;\nint N, M;\nint C;\nlong long weights[65][65];\nuint64_t zobrist[65][65];\n\nusing Mask = unsigned long long;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n    bool operator!=(const Point& other) const { return !(*this == other); }\n};\n\nstruct Move {\n    Point p1, p2, p3, p4;\n};\n\nstruct State {\n    Mask row_dots[65];\n    Mask col_dots[65];\n    Mask d1_dots[130]; // x + y\n    Mask d2_dots[130]; // x - y + N\n\n    Mask h_edges[65];\n    Mask v_edges[65];\n    Mask d1_edges[130];\n    Mask d2_edges[130];\n\n    long long current_score_w;\n    uint64_t hash;\n    int move_count;\n\n    State() {\n        for(int i=0; i<65; ++i) row_dots[i] = col_dots[i] = h_edges[i] = v_edges[i] = 0;\n        for(int i=0; i<130; ++i) d1_dots[i] = d2_dots[i] = d1_edges[i] = d2_edges[i] = 0;\n        current_score_w = 0;\n        hash = 0;\n        move_count = 0;\n    }\n\n    bool has_dot(int x, int y) const {\n        return (row_dots[y] >> x) & 1;\n    }\n\n    void add_dot(int x, int y) {\n        row_dots[y] |= (1ULL << x);\n        col_dots[x] |= (1ULL << y);\n        d1_dots[x + y] |= (1ULL << x);\n        d2_dots[x - y + N] |= (1ULL << x);\n        current_score_w += weights[x][y];\n        hash ^= zobrist[x][y];\n    }\n    \n    void add_edge(Point a, Point b) {\n        int l = min(a.x, b.x);\n        int r = max(a.x, b.x);\n        Mask mask = (1ULL << r) - (1ULL << l); \n\n        if (a.y == b.y) { \n            h_edges[a.y] |= mask;\n        } else if (a.x == b.x) { \n            // For vertical edges, we use Y coordinates for range mask, but store in X indexed array\n            l = min(a.y, b.y);\n            r = max(a.y, b.y);\n            mask = (1ULL << r) - (1ULL << l);\n            v_edges[a.x] |= mask;\n        } else if ((a.x + a.y) == (b.x + b.y)) { \n            d1_edges[a.x + a.y] |= mask;\n        } else { \n            d2_edges[a.x - a.y + N] |= mask;\n        }\n    }\n\n    void add_rect(const Move& m) {\n        add_edge(m.p1, m.p2);\n        add_edge(m.p2, m.p3);\n        add_edge(m.p3, m.p4);\n        add_edge(m.p4, m.p1);\n        move_count++;\n    }\n};\n\nstruct Node {\n    int parent_idx; \n    Move move;\n};\n\nconst int pairs90[8][2] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0}, \n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\nPoint find_neighbor(const State& s, Point p, int dir) {\n    int x = p.x, y = p.y;\n    if (dir == 0) { // R\n        Mask m = s.row_dots[y] & (~0ULL << (x + 1)); \n        if (!m) return {-1, -1};\n        return {__builtin_ctzll(m), y};\n    } else if (dir == 2) { // L\n        Mask m = s.row_dots[y] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        return {63 - __builtin_clzll(m), y};\n    } else if (dir == 1) { // U\n        Mask m = s.col_dots[x] & (~0ULL << (y + 1));\n        if (!m) return {-1, -1};\n        return {x, __builtin_ctzll(m)};\n    } else if (dir == 3) { // D\n        Mask m = s.col_dots[x] & ((1ULL << y) - 1);\n        if (!m) return {-1, -1};\n        return {x, 63 - __builtin_clzll(m)};\n    } else if (dir == 4) { // NE\n        int k = x - y + N;\n        Mask m = s.d2_dots[k] & (~0ULL << (x + 1));\n        if (!m) return {-1, -1};\n        int nx = __builtin_ctzll(m);\n        return {nx, nx - k + N};\n    } else if (dir == 6) { // SW\n        int k = x - y + N;\n        Mask m = s.d2_dots[k] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        int nx = 63 - __builtin_clzll(m);\n        return {nx, nx - k + N};\n    } else if (dir == 5) { // NW\n        int k = x + y;\n        Mask m = s.d1_dots[k] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        int nx = 63 - __builtin_clzll(m);\n        return {nx, k - nx};\n    } else if (dir == 7) { // SE\n        int k = x + y;\n        Mask m = s.d1_dots[k] & (~0ULL << (x + 1));\n        if (!m) return {-1, -1};\n        int nx = __builtin_ctzll(m);\n        return {nx, k - nx};\n    }\n    return {-1, -1};\n}\n\n// Fast O(1) check for dots strictly between p1 and p2\nbool check_segment_empty_fast(const State& s, Point p1, Point p2) {\n    int l, r;\n    if (p1.y == p2.y) { // Horizontal\n        l = min(p1.x, p2.x) + 1;\n        r = max(p1.x, p2.x);\n        if (l >= r) return true;\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.row_dots[p1.y] & mask) == 0;\n    } else if (p1.x == p2.x) { // Vertical\n        l = min(p1.y, p2.y) + 1;\n        r = max(p1.y, p2.y);\n        if (l >= r) return true;\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.col_dots[p1.x] & mask) == 0;\n    } else if ((p1.x + p1.y) == (p2.x + p2.y)) { // Diagonal 1\n        // For diagonals, we track by x coordinate in d1_dots/d2_dots\n        l = min(p1.x, p2.x) + 1;\n        r = max(p1.x, p2.x);\n        if (l >= r) return true;\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.d1_dots[p1.x + p1.y] & mask) == 0;\n    } else { // Diagonal 2\n        l = min(p1.x, p2.x) + 1;\n        r = max(p1.x, p2.x);\n        if (l >= r) return true;\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.d2_dots[p1.x - p1.y + N] & mask) == 0;\n    }\n}\n\n// Check if edge overlaps with existing edges\nbool check_edge_overlap(const State& s, Point a, Point b) {\n    if (a.y == b.y) {\n        int l = min(a.x, b.x), r = max(a.x, b.x);\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.h_edges[a.y] & mask) != 0;\n    } else if (a.x == b.x) {\n        int l = min(a.y, b.y), r = max(a.y, b.y);\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.v_edges[a.x] & mask) != 0;\n    } else if ((a.x + a.y) == (b.x + b.y)) {\n        int l = min(a.x, b.x), r = max(a.x, b.x);\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.d1_edges[a.x + a.y] & mask) != 0;\n    } else {\n        int l = min(a.x, b.x), r = max(a.x, b.x);\n        Mask mask = (1ULL << r) - (1ULL << l);\n        return (s.d2_edges[a.x - a.y + N] & mask) != 0;\n    }\n}\n\nbool check_all_edges_free(const State& s, const Move& m) {\n    if (check_edge_overlap(s, m.p1, m.p2)) return false;\n    if (check_edge_overlap(s, m.p2, m.p3)) return false;\n    if (check_edge_overlap(s, m.p3, m.p4)) return false;\n    if (check_edge_overlap(s, m.p4, m.p1)) return false;\n    return true;\n}\n\nstruct Candidate {\n    int parent_local_idx; \n    Move move;\n    long long score_w;\n    uint64_t new_hash;\n    double eval;\n};\n\nuint64_t rng_state = 123456789;\nuint64_t my_rand() {\n    rng_state ^= (rng_state << 13);\n    rng_state ^= (rng_state >> 7);\n    rng_state ^= (rng_state << 17);\n    return rng_state;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if (!(cin >> N >> M)) return 0;\n    C = (N - 1) / 2;\n\n    mt19937_64 rng(123);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            weights[x][y] = 1LL * (x - C) * (x - C) + 1LL * (y - C) * (y - C) + 1;\n            zobrist[x][y] = rng();\n        }\n    }\n\n    State s0;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        s0.add_dot(x, y);\n    }\n\n    vector<Node> all_nodes; \n    all_nodes.reserve(1000000); \n    all_nodes.push_back({-1, {}}); \n\n    vector<State> beam_states;\n    beam_states.reserve(3000);\n    beam_states.push_back(s0);\n    \n    vector<int> beam_node_indices;\n    beam_node_indices.reserve(3000);\n    beam_node_indices.push_back(0);\n\n    // Tuning beam width for performance vs quality\n    int BEAM_WIDTH = 1200; \n    if (N > 35) BEAM_WIDTH = 700;\n    if (N > 45) BEAM_WIDTH = 350; \n    if (N > 55) BEAM_WIDTH = 200; \n\n    auto start_time = chrono::high_resolution_clock::now();\n    vector<Candidate> candidates;\n    candidates.reserve(200000);\n    vector<Point> current_dots;\n    current_dots.reserve(N * N);\n    vector<uint64_t> seen_hashes;\n    seen_hashes.reserve(BEAM_WIDTH * 3);\n\n    long long max_score = s0.current_score_w;\n    int best_final_node_idx = 0;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        candidates.clear();\n\n        for (int i = 0; i < beam_states.size(); ++i) {\n            const State& s = beam_states[i];\n            \n            current_dots.clear();\n            // Efficiently gather all dots\n            for(int y=0; y<N; ++y) {\n                Mask m = s.row_dots[y];\n                while(m) {\n                    int x = __builtin_ctzll(m);\n                    current_dots.push_back({x, y});\n                    m &= (m - 1);\n                }\n            }\n\n            for (const auto& p3 : current_dots) {\n                for (int pair_idx = 0; pair_idx < 8; ++pair_idx) {\n                    Point p2 = find_neighbor(s, p3, pairs90[pair_idx][0]);\n                    if (p2.x == -1) continue;\n                    Point p4 = find_neighbor(s, p3, pairs90[pair_idx][1]);\n                    if (p4.x == -1) continue;\n\n                    Point p1 = {p2.x + p4.x - p3.x, p2.y + p4.y - p3.y};\n                    \n                    if (p1.x < 0 || p1.x >= N || p1.y < 0 || p1.y >= N) continue;\n                    if (s.has_dot(p1.x, p1.y)) continue;\n\n                    // Verify p1-p2 and p1-p4 are free of dots\n                    if (!check_segment_empty_fast(s, p1, p2)) continue;\n                    if (!check_segment_empty_fast(s, p1, p4)) continue;\n                    \n                    Move m = {p1, p2, p3, p4};\n                    // Verify edges don't overlap existing rects\n                    if (!check_all_edges_free(s, m)) continue;\n\n                    long long gain = weights[p1.x][p1.y];\n                    int perim = abs(p1.x - p2.x) + abs(p1.y - p2.y) + \n                                abs(p2.x - p3.x) + abs(p2.y - p3.y) + \n                                abs(p3.x - p4.x) + abs(p3.y - p4.y) + \n                                abs(p4.x - p1.x) + abs(p4.y - p1.y);\n                    \n                    uint64_t nhash = s.hash ^ zobrist[p1.x][p1.y];\n                    \n                    // Heuristic: Gain - penalty for blocking perimeter + random noise\n                    // Penalizing perimeter encourages compact or thin rectangles that don't block as much\n                    double h_val = (double)gain - (double)perim * 0.5 + ((double)(my_rand() % 1000) / 500.0);\n                    \n                    candidates.push_back({i, m, s.current_score_w + gain, nhash, h_val});\n                }\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        if (candidates.size() > BEAM_WIDTH * 3) {\n             nth_element(candidates.begin(), candidates.begin() + BEAM_WIDTH * 3, candidates.end(),\n                [](const Candidate& a, const Candidate& b) { return a.eval > b.eval; });\n             candidates.resize(BEAM_WIDTH * 3);\n        }\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.eval > b.eval;\n        });\n\n        vector<State> next_states;\n        vector<int> next_indices;\n        next_states.reserve(BEAM_WIDTH);\n        next_indices.reserve(BEAM_WIDTH);\n        seen_hashes.clear();\n\n        int accepted = 0;\n        for (const auto& cand : candidates) {\n            if (accepted >= BEAM_WIDTH) break;\n            \n            bool dup = false;\n            for (uint64_t h : seen_hashes) {\n                if (h == cand.new_hash) { dup = true; break; }\n            }\n            if (dup) continue;\n\n            all_nodes.push_back({beam_node_indices[cand.parent_local_idx], cand.move});\n            int new_node_idx = (int)all_nodes.size() - 1;\n            \n            State ns = beam_states[cand.parent_local_idx];\n            ns.add_dot(cand.move.p1.x, cand.move.p1.y);\n            ns.add_rect(cand.move);\n            \n            if (ns.current_score_w > max_score) {\n                max_score = ns.current_score_w;\n                best_final_node_idx = new_node_idx;\n            }\n\n            next_states.push_back(ns);\n            next_indices.push_back(new_node_idx);\n            seen_hashes.push_back(cand.new_hash);\n            accepted++;\n        }\n        \n        if (next_states.empty()) break;\n        beam_states = move(next_states);\n        beam_node_indices = move(next_indices);\n    }\n\n    vector<Move> result;\n    int curr = best_final_node_idx;\n    while (curr != 0) {\n        result.push_back(all_nodes[curr].move);\n        curr = all_nodes[curr].parent_idx;\n    }\n    reverse(result.begin(), result.end());\n\n    cout << result.size() << \"\\n\";\n    for (const auto& m : result) {\n        cout << m.p1.x << \" \" << m.p1.y << \" \" \n             << m.p2.x << \" \" << m.p2.y << \" \" \n             << m.p3.x << \" \" << m.p3.y << \" \" \n             << m.p4.x << \" \" << m.p4.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"/**\n * Final Optimized Solution for AtCoder Heuristic Contest (AHC015) - Halloween Candy\n * \n * Features:\n * - Bitboard state representation with Look-Up Tables (LUT).\n * - Monte Carlo Simulation with Greedy Playouts.\n * - Optimized inner loop: avoiding object copies and redundant transpositions during move selection.\n * - Fast BFS-based scoring.\n * - Dynamic time budgeting (1.85s safe limit).\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// --- Constants ---\nconstexpr int N = 10;\nconstexpr int MAX_T = 100;\nconstexpr char DIR_CHARS[] = {'F', 'B', 'L', 'R'}; \n\n// LUT Sizes\nconstexpr int LUT_SIZE = 1 << (2 * N); // 2^20 = 1MB\nconstexpr int MASK_LUT_SIZE = 1 << N; // 2^10 = 1KB\n\n// --- Global Look-Up Tables ---\nstatic uint32_t lut_move_L[LUT_SIZE];\nstatic uint32_t lut_move_R[LUT_SIZE];\nstatic uint16_t lut_row_score[LUT_SIZE]; \nstatic uint8_t lut_empty_cnt[LUT_SIZE];\nstatic uint16_t lut_row_to_mask[LUT_SIZE]; \nstatic int8_t lut_mask_kth_index[MASK_LUT_SIZE][11]; \n\nint flavors[MAX_T];\n\n// --- Fast RNG ---\nstruct XorShift128 {\n    unsigned int x = 123456789, y = 362436069, z = 521288629, w = 88675123;\n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) { return next() % n; }\n} rng;\n\n// --- Initialization ---\nvoid init_lut() {\n    for (int i = 0; i < LUT_SIZE; ++i) {\n        int cells[N];\n        int temp = i;\n        int empty = 0;\n        uint16_t mask = 0;\n        for (int k = 0; k < N; ++k) {\n            cells[k] = temp & 3;\n            temp >>= 2;\n            if (cells[k] == 0) { empty++; mask |= (1 << k); }\n        }\n        lut_empty_cnt[i] = empty;\n        lut_row_to_mask[i] = mask;\n        \n        // Move Left\n        int p = 0;\n        int new_cells_L[N] = {0};\n        for (int k = 0; k < N; ++k) if (cells[k] != 0) new_cells_L[p++] = cells[k];\n        uint32_t res_L = 0;\n        for (int k = 0; k < N; ++k) res_L |= (uint32_t(new_cells_L[k]) << (2 * k));\n        lut_move_L[i] = res_L;\n        \n        // Move Right\n        p = N - 1;\n        int new_cells_R[N] = {0};\n        for (int k = N - 1; k >= 0; --k) if (cells[k] != 0) new_cells_R[p--] = cells[k];\n        uint32_t res_R = 0;\n        for (int k = 0; k < N; ++k) res_R |= (uint32_t(new_cells_R[k]) << (2 * k));\n        lut_move_R[i] = res_R;\n        \n        // Score (Sum of squares of runs)\n        int current_run = 0, last_val = -1, score = 0;\n        for (int k = 0; k < N; ++k) {\n            if (cells[k] == 0) {\n                if (current_run > 0) score += current_run * current_run;\n                current_run = 0; last_val = -1;\n            } else {\n                if (cells[k] == last_val) current_run++;\n                else {\n                    if (current_run > 0) score += current_run * current_run;\n                    current_run = 1; last_val = cells[k];\n                }\n            }\n        }\n        if (current_run > 0) score += current_run * current_run;\n        lut_row_score[i] = score;\n    }\n    \n    for (int m = 0; m < MASK_LUT_SIZE; ++m) {\n        int count = 0;\n        for (int k = 0; k < N; ++k) {\n            if ((m >> k) & 1) {\n                count++;\n                lut_mask_kth_index[m][count] = k;\n            }\n        }\n    }\n}\n\n// --- State Structure ---\nstruct State {\n    uint32_t rows[N];\n\n    void init() { memset(rows, 0, sizeof(rows)); }\n    \n    inline void place(int r, int c, int f) {\n        rows[r] |= (uint32_t(f) << (2 * c));\n    }\n    \n    // Transpose rows to dst\n    inline void transpose(uint32_t* dst) const {\n        memset(dst, 0, sizeof(uint32_t) * N);\n        for (int r = 0; r < N; ++r) {\n            uint32_t val = rows[r];\n            int s = 2 * r;\n            dst[0] |= (val & 3) << s;\n            dst[1] |= ((val >> 2) & 3) << s;\n            dst[2] |= ((val >> 4) & 3) << s;\n            dst[3] |= ((val >> 6) & 3) << s;\n            dst[4] |= ((val >> 8) & 3) << s;\n            dst[5] |= ((val >> 10) & 3) << s;\n            dst[6] |= ((val >> 12) & 3) << s;\n            dst[7] |= ((val >> 14) & 3) << s;\n            dst[8] |= ((val >> 16) & 3) << s;\n            dst[9] |= ((val >> 18) & 3) << s;\n        }\n    }\n    \n    // Restore rows from cols\n    inline void from_cols(const uint32_t* cols) {\n        memset(rows, 0, sizeof(rows));\n        for (int c = 0; c < N; ++c) {\n            uint32_t val = cols[c];\n            int s = 2 * c;\n            rows[0] |= (val & 3) << s;\n            rows[1] |= ((val >> 2) & 3) << s;\n            rows[2] |= ((val >> 4) & 3) << s;\n            rows[3] |= ((val >> 6) & 3) << s;\n            rows[4] |= ((val >> 8) & 3) << s;\n            rows[5] |= ((val >> 10) & 3) << s;\n            rows[6] |= ((val >> 12) & 3) << s;\n            rows[7] |= ((val >> 14) & 3) << s;\n            rows[8] |= ((val >> 16) & 3) << s;\n            rows[9] |= ((val >> 18) & 3) << s;\n        }\n    }\n\n    void tilt(int dir) {\n        if (dir == 2) { // Left\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_L[rows[i]];\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_R[rows[i]];\n        } else {\n            uint32_t cols[N];\n            transpose(cols);\n            if (dir == 0) { // Fwd/Up\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_L[cols[i]];\n            } else { // Bwd/Down\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_R[cols[i]];\n            }\n            from_cols(cols);\n        }\n    }\n    \n    pair<int,int> get_kth_empty(int k) const {\n        for (int r = 0; r < N; ++r) {\n            int emp = lut_empty_cnt[rows[r]];\n            if (k <= emp) {\n                return {r, lut_mask_kth_index[lut_row_to_mask[rows[r]]][k]};\n            }\n            k -= emp;\n        }\n        return {-1, -1};\n    }\n\n    // Full BFS evaluation\n    long long eval_full() const {\n        static int8_t grid[N][N];\n        for(int r=0; r<N; ++r){\n            uint32_t v = rows[r];\n            for(int c=0; c<N; ++c) grid[r][c] = (v >> (2*c)) & 3;\n        }\n\n        long long total_sq = 0;\n        bool visited[N][N] = {false};\n        static pair<int,int> q[N*N]; // Static queue to reuse memory\n        \n        for(int r=0; r<N; ++r){\n            for(int c=0; c<N; ++c){\n                int f = grid[r][c];\n                if(f == 0 || visited[r][c]) continue;\n                \n                int q_head = 0, q_tail = 0;\n                q[q_tail++] = {r, c};\n                visited[r][c] = true;\n                int size = 0;\n                \n                while(q_head < q_tail){\n                    auto [cr, cc] = q[q_head++];\n                    size++;\n                    \n                    const int dr[] = {0,0,1,-1};\n                    const int dc[] = {1,-1,0,0};\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr>=0 && nr<N && nc>=0 && nc<N && !visited[nr][nc] && grid[nr][nc] == f){\n                            visited[nr][nc] = true;\n                            q[q_tail++] = {nr, nc};\n                        }\n                    }\n                }\n                total_sq += (long long)size * size;\n            }\n        }\n        return total_sq;\n    }\n};\n\nint main() {\n    auto start_time = chrono::high_resolution_clock::now();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_lut();\n    \n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n    \n    State current_state;\n    current_state.init();\n    \n    // 1.85s ensures we stop safely before TLE\n    const double TIME_LIMIT = 1.85;\n    \n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        pair<int,int> pos = current_state.get_kth_empty(p);\n        current_state.place(pos.first, pos.second, flavors[t]);\n        \n        int best_dir = 0;\n        \n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        \n        // Panic fallback\n        if (t == 99 || remaining < 0.015) {\n            long long max_s = -1;\n            for (int d = 0; d < 4; ++d) {\n                State nxt = current_state;\n                nxt.tilt(d);\n                long long s = nxt.eval_full();\n                if (s > max_s) { max_s = s; best_dir = d; }\n            }\n        } else {\n            // Monte Carlo\n            long long sum_scores[4] = {0};\n            int counts[4] = {0};\n            double budget = remaining / (100 - t);\n            \n            int iter = 0;\n            auto move_start = chrono::high_resolution_clock::now();\n            \n            while (true) {\n                // Check time every 64 iterations\n                if ((iter & 63) == 0) {\n                    auto curr = chrono::high_resolution_clock::now();\n                    if (chrono::duration<double>(curr - move_start).count() > budget ||\n                        chrono::duration<double>(curr - start_time).count() > TIME_LIMIT) break;\n                }\n                \n                int start_d = iter % 4;\n                iter++;\n                \n                State sim = current_state;\n                sim.tilt(start_d);\n                \n                // Playout\n                for (int k = t + 1; k < 100; ++k) {\n                    // Random placement\n                    int empty_cnt = 100 - k;\n                    int rnd = rng.next_int(empty_cnt) + 1;\n                    auto [r, c] = sim.get_kth_empty(rnd);\n                    sim.rows[r] |= (uint32_t(flavors[k]) << (2 * c));\n                    \n                    // Greedy Move Selection (Inlined for Speed)\n                    int best_h = -1;\n                    int cands[4];\n                    int n_cands = 0;\n                    \n                    // Precompute columns for current rows\n                    uint32_t curr_cols[N];\n                    sim.transpose(curr_cols);\n                    \n                    // Evaluate Vertical Moves (Fwd/Bwd) -> Modify Cols\n                    for(int d=0; d<2; ++d) {\n                        int score = 0;\n                        uint32_t next_cols[N];\n                        const uint32_t* lut = (d==0) ? lut_move_L : lut_move_R;\n                        for(int i=0; i<N; ++i) {\n                            next_cols[i] = lut[curr_cols[i]];\n                            score += lut_row_score[next_cols[i]]; // Col score\n                        }\n                        // Transpose back to evaluate rows score\n                        uint32_t next_rows[N];\n                        memset(next_rows, 0, sizeof(next_rows));\n                        for (int cc = 0; cc < N; ++cc) {\n                            uint32_t val = next_cols[cc];\n                            int s = 2 * cc;\n                            next_rows[0] |= (val & 3) << s;\n                            next_rows[1] |= ((val >> 2) & 3) << s;\n                            next_rows[2] |= ((val >> 4) & 3) << s;\n                            next_rows[3] |= ((val >> 6) & 3) << s;\n                            next_rows[4] |= ((val >> 8) & 3) << s;\n                            next_rows[5] |= ((val >> 10) & 3) << s;\n                            next_rows[6] |= ((val >> 12) & 3) << s;\n                            next_rows[7] |= ((val >> 14) & 3) << s;\n                            next_rows[8] |= ((val >> 16) & 3) << s;\n                            next_rows[9] |= ((val >> 18) & 3) << s;\n                        }\n                        for(int i=0; i<N; ++i) score += lut_row_score[next_rows[i]];\n                        \n                        if(score > best_h) { best_h = score; n_cands = 1; cands[0] = d; }\n                        else if(score == best_h) { cands[n_cands++] = d; }\n                    }\n                    \n                    // Evaluate Horizontal Moves (Left/Right) -> Modify Rows\n                    for(int d=2; d<4; ++d) {\n                        int score = 0;\n                        uint32_t next_rows[N];\n                        const uint32_t* lut = (d==2) ? lut_move_L : lut_move_R;\n                        for(int i=0; i<N; ++i) {\n                            next_rows[i] = lut[sim.rows[i]];\n                            score += lut_row_score[next_rows[i]]; // Row score\n                        }\n                        // Transpose to evaluate cols score\n                        uint32_t next_cols[N];\n                        memset(next_cols, 0, sizeof(next_cols));\n                        for (int rr = 0; rr < N; ++rr) {\n                            uint32_t val = next_rows[rr];\n                            int s = 2 * rr;\n                            next_cols[0] |= (val & 3) << s;\n                            next_cols[1] |= ((val >> 2) & 3) << s;\n                            next_cols[2] |= ((val >> 4) & 3) << s;\n                            next_cols[3] |= ((val >> 6) & 3) << s;\n                            next_cols[4] |= ((val >> 8) & 3) << s;\n                            next_cols[5] |= ((val >> 10) & 3) << s;\n                            next_cols[6] |= ((val >> 12) & 3) << s;\n                            next_cols[7] |= ((val >> 14) & 3) << s;\n                            next_cols[8] |= ((val >> 16) & 3) << s;\n                            next_cols[9] |= ((val >> 18) & 3) << s;\n                        }\n                        for(int i=0; i<N; ++i) score += lut_row_score[next_cols[i]];\n                        \n                        if(score > best_h) { best_h = score; n_cands = 1; cands[0] = d; }\n                        else if(score == best_h) { cands[n_cands++] = d; }\n                    }\n                    \n                    sim.tilt(cands[rng.next_int(n_cands)]);\n                }\n                \n                sum_scores[start_d] += sim.eval_full();\n                counts[start_d]++;\n            }\n            \n            double best_avg = -1.0;\n            for(int d=0; d<4; ++d) {\n                if(counts[d]) {\n                    double avg = (double)sum_scores[d] / counts[d];\n                    if(avg > best_avg) { best_avg = avg; best_dir = d; }\n                }\n            }\n        }\n        \n        cout << DIR_CHARS[best_dir] << endl;\n        current_state.tilt(best_dir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nmt19937 rng(12345);\n\n// Helper for random numbers\nint rand_int(int l, int r) {\n    if (l > r) return l;\n    return uniform_int_distribution<int>(l, r)(rng);\n}\n\ndouble rand_double() {\n    return uniform_real_distribution<double>(0.0, 1.0)(rng);\n}\n\n// Type for Sorted Degree Sequence\ntypedef vector<int> SDS;\n\n// Compute Sorted Degree Sequence from adjacency matrix\nSDS get_sds(const vector<string>& adj, int N) {\n    SDS degs(N, 0);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (i != j && adj[i][j] == '1') {\n                degs[i]++;\n            }\n        }\n    }\n    sort(degs.begin(), degs.end());\n    return degs;\n}\n\n// Generate a random graph using Randomized Stochastic Block Model\n// This creates graphs with diverse degree structures\nvector<string> generate_sbm_graph(int N) {\n    // Random number of blocks from 1 to 10\n    int K = rand_int(1, 10);\n    \n    // Random vertex assignment\n    vector<int> assign(N);\n    for(int i=0; i<N; ++i) assign[i] = rand_int(0, K-1);\n    \n    // Random block interaction probabilities\n    // We bias probabilities towards 0 or 1 to create stronger signals\n    vector<vector<double>> probs(K, vector<double>(K));\n    for(int i=0; i<K; ++i) {\n        for(int j=i; j<K; ++j) {\n            double p = rand_double();\n            // Polarize p to increase variance\n            if (rand_double() < 0.6) {\n                p = (p < 0.5) ? 0.05 : 0.95; \n            }\n            probs[i][j] = probs[j][i] = p;\n        }\n    }\n    \n    // Generate adjacency matrix\n    vector<string> adj(N, string(N, '0'));\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if (rand_double() < probs[assign[i]][assign[j]]) {\n                adj[i][j] = adj[j][i] = '1';\n            }\n        }\n    }\n    return adj;\n}\n\n// Calculate squared Euclidean distance between two SDS vectors\ndouble calc_sq_dist(const SDS& a, const SDS& b) {\n    double d = 0;\n    for(size_t i=0; i<a.size(); ++i) {\n        double diff = a[i] - b[i];\n        d += diff * diff;\n    }\n    return d;\n}\n\nstruct Candidate {\n    vector<string> adj;\n    SDS sds;\n};\n\nvoid solve() {\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return;\n\n    // Strategy 1: Low Epsilon -> Compact encoding\n    // If noise is negligible, minimize N using simple edge count encoding\n    if (eps < 0.0001) { \n         for(int n=4; n<=100; ++n) {\n            if (n*(n-1)/2 + 1 >= M) {\n                cout << n << endl;\n                for(int i=0; i<M; ++i) {\n                    string s(n*(n-1)/2, '0');\n                    for(int k=0; k<i; ++k) s[k] = '1';\n                    cout << s << endl;\n                }\n                cout << flush;\n                for(int q=0; q<100; ++q) {\n                    string s; cin >> s;\n                    int cnt=0; for(char c:s) if(c=='1') cnt++;\n                    cout << min(cnt, M-1) << endl << flush;\n                }\n                return;\n            }\n        }\n    }\n    \n    // Strategy 2: General Case -> Robust SDS Encoding\n    // For significant noise, we prioritize E=0 by using N=100.\n    // For mild noise, we can reduce N slightly to improve score.\n    int N = 100;\n    if (eps <= 0.15) {\n        // Heuristic reduction of N for lower noise levels\n        // Needs to be large enough to support M distinct degree profiles\n        N = max(12, (int)(sqrt(M)*2.5)); \n        if (N > 100) N = 100;\n    }\n\n    // Generate a pool of candidate graphs\n    vector<Candidate> pool;\n    // We can generate fewer candidates if N is small to save time, \n    // but for N=100 we want good diversity.\n    int pool_size = 2500; \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    while((int)pool.size() < pool_size) {\n        Candidate c;\n        c.adj = generate_sbm_graph(N);\n        c.sds = get_sds(c.adj, N);\n        pool.push_back(c);\n        \n        // Time safety check (2.0 sec limit for generation)\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 2000) break;\n    }\n    \n    // Fallback if generation was too slow\n    if ((int)pool.size() < M) {\n        while((int)pool.size() < M) {\n             Candidate c;\n             c.adj = vector<string>(N, string(N, '0'));\n             c.sds = vector<int>(N, 0);\n             pool.push_back(c);\n        }\n    }\n\n    // Greedy Selection: Select M graphs that maximize Minimum Distance (MaxMin)\n    vector<int> selected_indices;\n    vector<double> min_dists(pool.size(), 1e18);\n    \n    // Pick the first one (highest variance usually implies more information, or just random)\n    // Let's pick one with high variance in degrees? Or just random index 0.\n    selected_indices.push_back(0);\n    \n    // Initialize distances\n    for(size_t i=0; i<pool.size(); ++i) {\n        min_dists[i] = calc_sq_dist(pool[i].sds, pool[0].sds);\n    }\n    \n    while((int)selected_indices.size() < M) {\n        int best_idx = -1;\n        double max_val = -1.0;\n        \n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] > max_val) {\n                max_val = min_dists[i];\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) break;\n        \n        selected_indices.push_back(best_idx);\n        min_dists[best_idx] = -1.0; // Mark as used\n        \n        // Update distances\n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] >= 0) {\n                double d = calc_sq_dist(pool[i].sds, pool[best_idx].sds);\n                if (d < min_dists[i]) min_dists[i] = d;\n            }\n        }\n    }\n    \n    // Output N and Graphs\n    cout << N << endl;\n    \n    // Prepare expected feature vectors for decoding\n    vector<vector<double>> code_expected_sds(M);\n    \n    for(int k=0; k<M; ++k) {\n        int idx = selected_indices[k];\n        const auto& cand = pool[idx];\n        \n        string s_out;\n        s_out.reserve(N*(N-1)/2);\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                s_out += cand.adj[i][j];\n            }\n        }\n        cout << s_out << endl;\n        \n        // Calculate Expected SDS under noise\n        // E[deg_new] = deg_old * (1 - epsilon) + (N - 1 - deg_old) * epsilon\n        //            = deg_old * (1 - 2*epsilon) + (N - 1) * epsilon\n        // We assume the sorted order is largely preserved or effectively approximated by transforming the sorted vector.\n        vector<double> exp_sds(N);\n        for(int i=0; i<N; ++i) {\n            exp_sds[i] = cand.sds[i] * (1.0 - 2.0 * eps) + (N - 1) * eps;\n        }\n        code_expected_sds[k] = exp_sds;\n    }\n    cout << flush;\n    \n    // Process Queries\n    for(int q=0; q<100; ++q) {\n        string s; cin >> s;\n        \n        // Compute observed SDS\n        SDS obs_sds(N, 0);\n        int p = 0;\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                if(s[p] == '1') {\n                    obs_sds[i]++;\n                    obs_sds[j]++;\n                }\n                p++;\n            }\n        }\n        sort(obs_sds.begin(), obs_sds.end());\n        \n        // Find nearest codeword in Euclidean space\n        int best_m = 0;\n        double min_dist = 1e18;\n        \n        for(int m=0; m<M; ++m) {\n            double d = 0;\n            const auto& target = code_expected_sds[m];\n            for(int i=0; i<N; ++i) {\n                double diff = obs_sds[i] - target[i];\n                d += diff * diff;\n            }\n            \n            if (d < min_dist) {\n                min_dist = d;\n                best_m = m;\n            }\n        }\n        cout << best_m << endl << flush;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <set>\n#include <cassert>\n\nusing namespace std;\n\n// Constants\nconst long long INF_DIST = 1e18;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nstruct Point {\n    int x, y;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<Point> coords;\nvector<vector<pair<int, int>>> adj; // u -> {v, edge_index}\n\n// Precomputed data\nvector<vector<int16_t>> edge_hop_dist; // MxM matrix storing hop distances between edges\nvector<double> edge_importance; // size M, stores approximate betweenness centrality\n\n// Solution state\nvector<int> assignment; // edge_id -> day (1-based)\nvector<vector<int>> day_edges; // day (1-based) -> list of edge_ids\n\n// Random number generator\nmt19937 rng(12345);\n\n// Time management\nauto start_time = chrono::steady_clock::now();\ndouble get_time() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Union Find for connectivity checks\nstruct DSU {\n    vector<int> parent;\n    DSU(int n) : parent(n + 1) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        if (parent[x] == x) return x;\n        return parent[x] = find(parent[x]);\n    }\n    void unite(int x, int y) {\n        int rootX = find(x);\n        int rootY = find(y);\n        if (rootX != rootY) parent[rootX] = rootY;\n    }\n};\n\n// Preprocessing: Hop distances between all pairs of nodes and then edges\nvoid compute_hop_distances() {\n    // node_hop_dist[u][v]: min hops between node u and node v\n    vector<vector<int16_t>> node_dist(N + 1, vector<int16_t>(N + 1, 0));\n\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        vector<int> d(N + 1, -1);\n        queue<int> q;\n        \n        d[start_node] = 0;\n        q.push(start_node);\n        \n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            \n            for (auto& edge : adj[u]) {\n                int v = edge.first;\n                if (d[v] == -1) {\n                    d[v] = d[u] + 1;\n                    q.push(v);\n                }\n            }\n        }\n        for(int i=1; i<=N; ++i) node_dist[start_node][i] = (int16_t)d[i];\n    }\n\n    // Compute edge_hop_dist[i][j]: min hops between any endpoint of edge i and any endpoint of edge j\n    edge_hop_dist.assign(M, vector<int16_t>(M));\n    for (int i = 0; i < M; ++i) {\n        for (int j = i; j < M; ++j) {\n            if (i == j) {\n                edge_hop_dist[i][j] = 0;\n            } else {\n                int u1 = edges[i].u;\n                int v1 = edges[i].v;\n                int u2 = edges[j].u;\n                int v2 = edges[j].v;\n                \n                int d1 = node_dist[u1][u2];\n                int d2 = node_dist[u1][v2];\n                int d3 = node_dist[v1][u2];\n                int d4 = node_dist[v1][v2];\n                \n                int min_d = min({d1, d2, d3, d4});\n                edge_hop_dist[i][j] = min_d;\n                edge_hop_dist[j][i] = min_d;\n            }\n        }\n    }\n}\n\n// Preprocessing: Importance (Betweenness Centrality approximation)\nvoid compute_importance() {\n    edge_importance.assign(M, 0.0);\n    \n    // Run Dijkstra from each node to count how often an edge is part of a Shortest Path Tree\n    for (int start_node = 1; start_node <= N; ++start_node) {\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        vector<long long> dist(N + 1, INF_DIST);\n        vector<int> parent_edge(N + 1, -1);\n        \n        dist[start_node] = 0;\n        pq.push({0, start_node});\n        \n        while (!pq.empty()) {\n            long long d = pq.top().first;\n            int u = pq.top().second;\n            pq.pop();\n            \n            if (d > dist[u]) continue;\n            \n            for (auto& e : adj[u]) {\n                int v = e.first;\n                int idx = e.second;\n                int w = edges[idx].w;\n                \n                if (dist[u] + w < dist[v]) {\n                    dist[v] = dist[u] + w;\n                    parent_edge[v] = idx;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        // Backtrack to increment counts\n        for (int i = 1; i <= N; ++i) {\n            if (i == start_node) continue;\n            int curr = i;\n            while (curr != start_node && parent_edge[curr] != -1) {\n                int e_idx = parent_edge[curr];\n                edge_importance[e_idx] += 1.0;\n                \n                int u = edges[e_idx].u;\n                int v = edges[e_idx].v;\n                // Determine which node is closer to start_node\n                if (dist[u] < dist[v]) curr = u;\n                else curr = v;\n            }\n        }\n    }\n    \n    // Normalize\n    double max_imp = 0;\n    for (double v : edge_importance) max_imp = max(max_imp, v);\n    if (max_imp > 0) {\n        for (auto& v : edge_importance) v /= max_imp;\n    }\n}\n\n// Initial Solution Generation\nvoid initial_solution() {\n    assignment.assign(M, 0);\n    day_edges.assign(D + 1, vector<int>());\n    \n    // Use BFS on the dual-like structure or just BFS on edges starting from center\n    // to ensure nearby edges get consecutive indices.\n    vector<bool> visited(M, false);\n    queue<int> q;\n    \n    // Find node closest to center (500, 500)\n    int center_node = 1;\n    int min_dist = 1e9;\n    if (!coords.empty()) {\n        for(int i=1; i<=N; ++i) {\n            int d = (coords[i-1].x - 500)*(coords[i-1].x - 500) + (coords[i-1].y - 500)*(coords[i-1].y - 500);\n            if (d < min_dist) {\n                min_dist = d;\n                center_node = i;\n            }\n        }\n    }\n    \n    // Push edges of center node\n    for(auto& p : adj[center_node]) {\n        q.push(p.second);\n        visited[p.second] = true;\n    }\n    if(q.empty()) { q.push(0); visited[0] = true; }\n\n    vector<int> ordered_edges;\n    ordered_edges.reserve(M);\n    \n    while(ordered_edges.size() < M) {\n        if (q.empty()) {\n            for(int i=0; i<M; ++i) if(!visited[i]) { q.push(i); visited[i]=true; break; }\n        }\n        \n        while(!q.empty()){\n            int e_idx = q.front();\n            q.pop();\n            ordered_edges.push_back(e_idx);\n            \n            int u = edges[e_idx].u;\n            int v = edges[e_idx].v;\n            \n            for(auto& p : adj[u]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n            for(auto& p : adj[v]) {\n                if (!visited[p.second]) {\n                    visited[p.second] = true;\n                    q.push(p.second);\n                }\n            }\n        }\n    }\n    \n    // Assign days in a round-robin fashion to spatially separate edges on the same day\n    vector<int> counts(D + 1, 0);\n    int current_day = 1;\n    for(int e_idx : ordered_edges) {\n        // Ensure we don't exceed K\n        while(counts[current_day] >= K) {\n            current_day = (current_day % D) + 1;\n        }\n        assignment[e_idx] = current_day;\n        day_edges[current_day].push_back(e_idx);\n        counts[current_day]++;\n        current_day = (current_day % D) + 1;\n    }\n}\n\n// Cost Function for SA\n// Calculate contribution of a pair of removed edges (i, j)\ninline double pair_cost(int i, int j) {\n    double dist = edge_hop_dist[i][j];\n    // Penalty is high if distance is small.\n    // Penalty is scaled by importance: removing two important edges nearby is very bad.\n    double imp_factor = 1.0 + 10.0 * edge_importance[i] * edge_importance[j]; \n    return imp_factor / ((dist + 1.0) * (dist + 1.0));\n}\n\n// Calculate total dispersion cost for a day\ndouble calculate_day_cost(int d) {\n    double cost = 0;\n    const auto& es = day_edges[d];\n    for (size_t i = 0; i < es.size(); ++i) {\n        for (size_t j = i + 1; j < es.size(); ++j) {\n            cost += pair_cost(es[i], es[j]);\n        }\n    }\n    return cost;\n}\n\n// Check if graph remains connected when edges of day 'd' are removed\nbool check_connectivity(int d) {\n    DSU dsu(N);\n    int components = N;\n    for(int i=0; i<M; ++i) {\n        if (assignment[i] != d) {\n            if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                dsu.unite(edges[i].u, edges[i].v);\n                components--;\n            }\n        }\n    }\n    return components == 1;\n}\n\n// Try to fix connectivity issues greedily\nbool fix_connectivity() {\n    bool changed = false;\n    for (int d = 1; d <= D; ++d) {\n        if (!check_connectivity(d)) {\n            // Identify components\n            DSU dsu(N);\n            for(int i=0; i<M; ++i) {\n                if (assignment[i] != d) {\n                    dsu.unite(edges[i].u, edges[i].v);\n                }\n            }\n            \n            // Find an edge currently scheduled for day 'd' that connects two different components\n            // If we move this edge to another day, it will be present on day 'd', fixing connectivity.\n            int best_edge = -1;\n            \n            for (int e_idx : day_edges[d]) {\n                if (dsu.find(edges[e_idx].u) != dsu.find(edges[e_idx].v)) {\n                    best_edge = e_idx;\n                    break; // Found a bridging edge\n                }\n            }\n            \n            if (best_edge != -1) {\n                // Move best_edge to a day with capacity < K\n                for (int target = 1; target <= D; ++target) {\n                    if (target != d && day_edges[target].size() < K) {\n                        // Perform move\n                        vector<int>& vec_d = day_edges[d];\n                        vec_d.erase(remove(vec_d.begin(), vec_d.end(), best_edge), vec_d.end());\n                        \n                        day_edges[target].push_back(best_edge);\n                        assignment[best_edge] = target;\n                        changed = true;\n                        break; \n                    }\n                }\n            }\n        }\n    }\n    return changed;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> D >> K)) return 0;\n    \n    adj.resize(N + 1);\n    edges.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        edges.push_back({u, v, w, i});\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n    \n    coords.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coords[i].x >> coords[i].y;\n    }\n\n    // 1. Preprocessing\n    compute_hop_distances();\n    compute_importance();\n    \n    // 2. Initial Assignment\n    initial_solution();\n\n    // Calculate initial costs\n    vector<double> day_costs(D + 1);\n    double total_cost = 0;\n    for (int d = 1; d <= D; ++d) {\n        day_costs[d] = calculate_day_cost(d);\n        total_cost += day_costs[d];\n    }\n\n    // 3. Simulated Annealing\n    double time_limit = 5.6; \n    double t0 = 5.0;\n    double t1 = 0.0001;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) { \n            if (get_time() > time_limit) break;\n        }\n        \n        double temp = t0 + (t1 - t0) * (get_time() / time_limit);\n        \n        // Swap Move: Pick two different days and swap an edge\n        int d1 = uniform_int_distribution<int>(1, D)(rng);\n        int d2 = uniform_int_distribution<int>(1, D)(rng);\n        if (d1 == d2) continue;\n        \n        if (day_edges[d1].empty() || day_edges[d2].empty()) continue;\n\n        int idx1 = uniform_int_distribution<int>(0, day_edges[d1].size() - 1)(rng);\n        int idx2 = uniform_int_distribution<int>(0, day_edges[d2].size() - 1)(rng);\n        \n        int e1 = day_edges[d1][idx1];\n        int e2 = day_edges[d2][idx2];\n        \n        // Calculate cost delta incrementally\n        double d1_old = day_costs[d1];\n        double d2_old = day_costs[d2];\n        \n        // Remove e1 from d1, add e2 to d1\n        double cost_e1_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e1_in_d1 += pair_cost(e1, other);\n        }\n        double cost_e2_in_d1 = 0;\n        for(int other : day_edges[d1]) {\n            if(other != e1) cost_e2_in_d1 += pair_cost(e2, other);\n        }\n        \n        // Remove e2 from d2, add e1 to d2\n        double cost_e2_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e2_in_d2 += pair_cost(e2, other);\n        }\n        double cost_e1_in_d2 = 0;\n        for(int other : day_edges[d2]) {\n            if(other != e2) cost_e1_in_d2 += pair_cost(e1, other);\n        }\n        \n        double d1_new = d1_old - cost_e1_in_d1 + cost_e2_in_d1;\n        double d2_new = d2_old - cost_e2_in_d2 + cost_e1_in_d2;\n        \n        double delta = (d1_new + d2_new) - (d1_old + d2_old);\n        \n        if (delta < 0 || bernoulli_distribution(exp(-delta / temp))(rng)) {\n            // Accept swap\n            day_edges[d1][idx1] = e2;\n            day_edges[d2][idx2] = e1;\n            assignment[e1] = d2;\n            assignment[e2] = d1;\n            day_costs[d1] = d1_new;\n            day_costs[d2] = d2_new;\n            total_cost += delta;\n        }\n    }\n    \n    // 4. Ensure Connectivity\n    // Keep trying to fix until valid or time is up (allow slight over time if needed, but keep safe)\n    while (get_time() < 5.9) {\n        if (!fix_connectivity()) break; \n    }\n\n    // Output\n    for (int i = 0; i < M; ++i) {\n        cout << assignment[i] << (i == M - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cstring>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global Constants and Time\nconst int MAX_D = 14;\nint D;\nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Data Structures\nstruct Point {\n    int x, y, z;\n    auto operator<=>(const Point&) const = default;\n    Point operator+(const Point& other) const { return {x + other.x, y + other.y, z + other.z}; }\n    Point operator-(const Point& other) const { return {x - other.x, y - other.y, z - other.z}; }\n};\n\nstruct Rotation {\n    int p[3];\n    int s[3];\n};\nvector<Rotation> rotations;\n\nvoid init_rotations() {\n    int perms[6][3] = {{0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}};\n    for (int i = 0; i < 6; ++i) {\n        for (int mask = 0; mask < 8; ++mask) {\n            Rotation r;\n            for (int j = 0; j < 3; ++j) {\n                r.p[j] = perms[i][j];\n                r.s[j] = (mask & (1 << j)) ? -1 : 1;\n            }\n            int mat[3][3] = {0};\n            for(int j=0; j<3; ++j) mat[j][r.p[j]] = r.s[j];\n            int det = mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1])\n                    - mat[0][1]*(mat[1][0]*mat[2][2] - mat[1][2]*mat[2][0])\n                    + mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]);\n            if (det == 1) rotations.push_back(r);\n        }\n    }\n}\n\nPoint apply_rot(const Point& pt, int rot_idx) {\n    const Rotation& r = rotations[rot_idx];\n    int coords[3] = {pt.x, pt.y, pt.z};\n    return {\n        coords[r.p[0]] * r.s[0],\n        coords[r.p[1]] * r.s[1],\n        coords[r.p[2]] * r.s[2]\n    };\n}\n\n// Inputs\nvector<string> f1_in, r1_in, f2_in, r2_in;\n\n// Helpers\nbool is_set(const vector<string>& s, int r, int c) { return s[r][c] == '1'; }\n\n// Get all valid positions\nvector<Point> get_maximal_voxels(const vector<string>& f, const vector<string>& r_s) {\n    vector<Point> v;\n    for(int x=0; x<D; ++x)\n        for(int y=0; y<D; ++y)\n            for(int z=0; z<D; ++z)\n                if(is_set(f, z, x) && is_set(r_s, z, y))\n                    v.push_back({x,y,z});\n    return v;\n}\n\nstruct Solution {\n    vector<int> grid1;\n    vector<int> grid2;\n    int num_blocks;\n    double score;\n};\n\n// Solver State\nstruct SolverState {\n    vector<Point> M1, M2;\n    vector<bool> used1, used2;\n    vector<int> cover_f1, cover_r1, cover_f2, cover_r2; // counts of coverage\n    vector<int> grid1, grid2;\n    int block_counter;\n    \n    SolverState() : grid1(D*D*D, 0), grid2(D*D*D, 0), block_counter(1) {}\n\n    void init(const vector<Point>& m1, const vector<Point>& m2) {\n        M1 = m1; M2 = m2;\n        used1.assign(M1.size(), false);\n        used2.assign(M2.size(), false);\n        cover_f1.assign(D*D, 0); cover_r1.assign(D*D, 0);\n        cover_f2.assign(D*D, 0); cover_r2.assign(D*D, 0);\n    }\n\n    void add_block(const vector<Point>& shape, int rot, Point shift, const vector<int>& indices1, const vector<int>& indices2) {\n        int id = block_counter++;\n        for(int idx : indices1) {\n            used1[idx] = true;\n            Point p = M1[idx];\n            grid1[p.x*D*D + p.y*D + p.z] = id;\n            cover_f1[p.z*D + p.x]++;\n            cover_r1[p.z*D + p.y]++;\n        }\n        for(int idx : indices2) {\n            used2[idx] = true;\n            Point p = M2[idx];\n            grid2[p.x*D*D + p.y*D + p.z] = id;\n            cover_f2[p.z*D + p.x]++;\n            cover_r2[p.z*D + p.y]++;\n        }\n    }\n};\n\n// Compute weights dynamically\nvoid update_weights(SolverState& state, vector<double>& w1, vector<double>& w2, mt19937& rng) {\n    // Counts of available voxels for each pixel\n    vector<int> cnt_f1(D*D, 0), cnt_r1(D*D, 0);\n    vector<int> cnt_f2(D*D, 0), cnt_r2(D*D, 0);\n\n    int n1 = state.M1.size();\n    int n2 = state.M2.size();\n\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        Point p = state.M1[i];\n        cnt_f1[p.z*D + p.x]++;\n        cnt_r1[p.z*D + p.y]++;\n    }\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        Point p = state.M2[i];\n        cnt_f2[p.z*D + p.x]++;\n        cnt_r2[p.z*D + p.y]++;\n    }\n\n    auto calc_w = [&](const Point& p, const vector<int>& cnt_f, const vector<int>& cnt_r, \n                      const vector<int>& cov_f, const vector<int>& cov_r) {\n        double w = 1.0; // base volume weight\n        int zx = p.z*D + p.x;\n        int zy = p.z*D + p.y;\n        \n        // If pixel not covered yet, high value. Inversely proportional to availability.\n        if (cov_f[zx] == 0) w += 50.0 / (cnt_f[zx] + 1e-5);\n        if (cov_r[zy] == 0) w += 50.0 / (cnt_r[zy] + 1e-5);\n        \n        return w;\n    };\n\n    w1.assign(n1, 0);\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        w1[i] = calc_w(state.M1[i], cnt_f1, cnt_r1, state.cover_f1, state.cover_r1);\n        w1[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n\n    w2.assign(n2, 0);\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        w2[i] = calc_w(state.M2[i], cnt_f2, cnt_r2, state.cover_f2, state.cover_r2);\n        w2[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n}\n\n// Voting grid\ndouble votes[30*30*30];\nint vote_dim = 0;\nint vote_dim_sq = 0;\nint vote_offset = 0;\n\nvoid reset_votes() {\n    vote_offset = D;\n    vote_dim = 2 * D + 1;\n    vote_dim_sq = vote_dim * vote_dim;\n    fill(votes, votes + vote_dim*vote_dim*vote_dim, 0.0);\n}\n\nstruct MatchResult {\n    vector<Point> shape;\n    vector<int> indices1;\n    vector<int> indices2;\n    double total_weight;\n    int rotation;\n    Point shift;\n};\n\nMatchResult find_best_block(SolverState& state, const vector<double>& w1, const vector<double>& w2) {\n    MatchResult best_res;\n    best_res.total_weight = -1.0;\n\n    // Collect available indices\n    vector<int> c1, c2;\n    for(size_t i=0; i<state.M1.size(); ++i) if(!state.used1[i]) c1.push_back(i);\n    for(size_t i=0; i<state.M2.size(); ++i) if(!state.used2[i]) c2.push_back(i);\n\n    if (c1.empty() || c2.empty()) return best_res;\n\n    // Subsample for voting to speed up\n    vector<int> vote_c1 = c1;\n    vector<int> vote_c2 = c2;\n    \n    // Heuristic: Vote only with highest weight voxels to find promising alignments\n    // This avoids O(N^2) in the voting loop\n    int limit = 300;\n    if (vote_c1.size() > limit) {\n        partial_sort(vote_c1.begin(), vote_c1.begin()+limit, vote_c1.end(), [&](int a, int b){ return w1[a] > w1[b]; });\n        vote_c1.resize(limit);\n    }\n    if (vote_c2.size() > limit) {\n        partial_sort(vote_c2.begin(), vote_c2.begin()+limit, vote_c2.end(), [&](int a, int b){ return w2[a] > w2[b]; });\n        vote_c2.resize(limit);\n    }\n\n    // Iterate Rotations\n    for(int rot=0; rot<24; ++rot) {\n        reset_votes();\n        \n        // Precompute rotated V2 subset\n        vector<Point> v2_rot(vote_c2.size());\n        for(size_t i=0; i<vote_c2.size(); ++i) v2_rot[i] = apply_rot(state.M2[vote_c2[i]], rot);\n\n        // Voting\n        for(size_t i=0; i<vote_c1.size(); ++i) {\n            Point p1 = state.M1[vote_c1[i]];\n            double val1 = w1[vote_c1[i]];\n            for(size_t j=0; j<vote_c2.size(); ++j) {\n                Point d = p1 - v2_rot[j];\n                if(abs(d.x) < D && abs(d.y) < D && abs(d.z) < D) {\n                    int idx = (d.x + vote_offset) * vote_dim_sq + (d.y + vote_offset) * vote_dim + (d.z + vote_offset);\n                    votes[idx] += val1 + w2[vote_c2[j]];\n                }\n            }\n        }\n\n        // Find top candidate shifts\n        priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n        for(int i=0; i<vote_dim*vote_dim*vote_dim; ++i) {\n            if(votes[i] > 1e-3) {\n                pq.push({votes[i], i});\n                if(pq.size() > 5) pq.pop();\n            }\n        }\n\n        vector<int> candidates;\n        while(!pq.empty()) {\n            candidates.push_back(pq.top().second);\n            pq.pop();\n        }\n\n        // Evaluate candidates with full sets\n        for(int cand_idx : candidates) {\n            int dz = cand_idx % vote_dim;\n            int dy = (cand_idx / vote_dim) % vote_dim;\n            int dx = (cand_idx / vote_dim_sq);\n            Point shift = {dx - vote_offset, dy - vote_offset, dz - vote_offset};\n\n            // Build map of V2 points (rotated and shifted) -> original index\n            map<Point, int> v2_map;\n            for(int idx : c2) {\n                Point p = apply_rot(state.M2[idx], rot) + shift;\n                if (p.x >= 0 && p.x < D && p.y >= 0 && p.y < D && p.z >= 0 && p.z < D) {\n                    v2_map[p] = idx;\n                }\n            }\n\n            // Intersection nodes\n            struct Node {\n                Point p;\n                int idx1;\n                int idx2;\n                double w;\n            };\n            vector<Node> intersection;\n            for(int idx1 : c1) {\n                Point p = state.M1[idx1];\n                if (v2_map.count(p)) {\n                    int idx2 = v2_map[p];\n                    intersection.push_back({p, idx1, idx2, w1[idx1] + w2[idx2]});\n                }\n            }\n\n            if (intersection.empty()) continue;\n\n            // Find largest weighted connected component\n            set<Point> int_pts;\n            for(const auto& node : intersection) int_pts.insert(node.p);\n            set<Point> visited;\n            map<Point, int> p_to_node;\n            for(size_t k=0; k<intersection.size(); ++k) p_to_node[intersection[k].p] = k;\n\n            for(const auto& node : intersection) {\n                if (visited.count(node.p)) continue;\n\n                vector<Point> comp_shape;\n                vector<int> comp_idx1, comp_idx2;\n                double comp_w = 0;\n                \n                queue<Point> q;\n                q.push(node.p);\n                visited.insert(node.p);\n                \n                while(!q.empty()){\n                    Point u = q.front(); q.pop();\n                    int u_node_idx = p_to_node[u];\n                    comp_shape.push_back(u);\n                    comp_idx1.push_back(intersection[u_node_idx].idx1);\n                    comp_idx2.push_back(intersection[u_node_idx].idx2);\n                    comp_w += intersection[u_node_idx].w;\n\n                    Point neighbors[6] = {\n                        {u.x+1, u.y, u.z}, {u.x-1, u.y, u.z},\n                        {u.x, u.y+1, u.z}, {u.x, u.y-1, u.z},\n                        {u.x, u.y, u.z+1}, {u.x, u.y, u.z-1}\n                    };\n\n                    for(const auto& v : neighbors) {\n                        if(int_pts.count(v) && !visited.count(v)) {\n                            visited.insert(v);\n                            q.push(v);\n                        }\n                    }\n                }\n\n                if (comp_w > best_res.total_weight) {\n                    best_res.total_weight = comp_w;\n                    best_res.shape = comp_shape;\n                    best_res.indices1 = comp_idx1;\n                    best_res.indices2 = comp_idx2;\n                    best_res.rotation = rot;\n                    best_res.shift = shift;\n                }\n            }\n        }\n    }\n    return best_res;\n}\n\nvoid fill_residuals(SolverState& state, const vector<string>& f, const vector<string>& r_s, bool is_second) {\n    vector<pair<int,int>> needed_f, needed_r;\n    const vector<int>& cov_f = (is_second ? state.cover_f2 : state.cover_f1);\n    const vector<int>& cov_r = (is_second ? state.cover_r2 : state.cover_r1);\n\n    for(int z=0; z<D; ++z) {\n        for(int x=0; x<D; ++x) \n            if(is_set(f, z, x) && cov_f[z*D+x] == 0) needed_f.push_back({x, z});\n        for(int y=0; y<D; ++y) \n            if(is_set(r_s, z, y) && cov_r[z*D+y] == 0) needed_r.push_back({y, z});\n    }\n\n    vector<Point> candidates;\n    const vector<Point>& M = (is_second ? state.M2 : state.M1);\n    const vector<bool>& used = (is_second ? state.used2 : state.used1);\n    \n    for(size_t i=0; i<M.size(); ++i) if(!used[i]) candidates.push_back(M[i]);\n\n    vector<bool> done_f(needed_f.size(), false);\n    vector<bool> done_r(needed_r.size(), false);\n    int rem_f = needed_f.size();\n    int rem_r = needed_r.size();\n\n    while(rem_f > 0 || rem_r > 0) {\n        int best_idx = -1;\n        int best_cnt = -1;\n        \n        int step = (candidates.size() > 500) ? 2 : 1;\n        for(size_t i=0; i<candidates.size(); i+=step) {\n            if(candidates[i].x == -1) continue;\n            int cnt = 0;\n            const Point& p = candidates[i];\n            for(size_t k=0; k<needed_f.size(); ++k) \n                if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) cnt++;\n            for(size_t k=0; k<needed_r.size(); ++k) \n                if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) cnt++;\n            \n            if(cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = i;\n            }\n        }\n\n        if(best_idx == -1 || best_cnt == 0) break;\n\n        Point p = candidates[best_idx];\n        candidates[best_idx].x = -1; \n        \n        int id = state.block_counter++;\n        if (is_second) state.grid2[p.x*D*D + p.y*D + p.z] = id;\n        else state.grid1[p.x*D*D + p.y*D + p.z] = id;\n\n        for(size_t k=0; k<needed_f.size(); ++k) \n            if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) { done_f[k]=true; rem_f--; }\n        for(size_t k=0; k<needed_r.size(); ++k) \n            if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) { done_r[k]=true; rem_r--; }\n    }\n}\n\ndouble calc_score(const SolverState& state) {\n    map<int, int> vol;\n    set<int> s1, s2;\n    \n    for(int x : state.grid1) if(x) { vol[x]++; s1.insert(x); }\n    for(int x : state.grid2) if(x) { vol[x]++; s2.insert(x); }\n    \n    double score = 0;\n    for(int id : s1) {\n        if(s2.count(id)) score += 1.0 / vol[id];\n        else score += vol[id];\n    }\n    for(int id : s2) {\n        if(!s1.count(id)) score += vol[id];\n    }\n    return round(1e9 * score);\n}\n\nvoid run_solve() {\n    cin >> D;\n    f1_in.resize(D); r1_in.resize(D);\n    f2_in.resize(D); r2_in.resize(D);\n    for(int i=0; i<D; ++i) cin >> f1_in[i];\n    for(int i=0; i<D; ++i) cin >> r1_in[i];\n    for(int i=0; i<D; ++i) cin >> f2_in[i];\n    for(int i=0; i<D; ++i) cin >> r2_in[i];\n\n    init_rotations();\n    vector<Point> M1 = get_maximal_voxels(f1_in, r1_in);\n    vector<Point> M2 = get_maximal_voxels(f2_in, r2_in);\n    \n    Solution best_sol;\n    best_sol.score = 1e18;\n\n    mt19937 rng(42);\n\n    while (get_time() < 5.8) {\n        SolverState state;\n        state.init(M1, M2);\n        \n        int consecutive_fails = 0;\n        while(consecutive_fails < 5) {\n            vector<double> w1, w2;\n            update_weights(state, w1, w2, rng);\n            \n            MatchResult res = find_best_block(state, w1, w2);\n            \n            // If the best block is empty or has very low value (meaning it probably contributes nothing to silhouettes)\n            if(res.shape.empty() || res.total_weight < 0.5) { \n                break;\n            }\n            \n            // Heuristic: if the block is just 1x1 and contributes only to volume (weight approx 2.0)\n            // and doesn't help cover new silhouette (which would add ~50 weight), \n            // it might be better to stop greedy matching and let residuals handle it,\n            // UNLESS we still have large unmatched chunks. \n            // But 1x1 common (cost 1) is better than 1x1 residual (cost 1) if we need it for both.\n            // If we need it for only one, 1x1 common is cost 1 (0 unmatched, 1 inv).\n            // 1x1 residual is cost 1 (1 unmatched).\n            // So common is never strictly worse.\n            \n            state.add_block(res.shape, res.rotation, res.shift, res.indices1, res.indices2);\n            \n            // Check if block was \"trivial\" (small volume, low weight)\n            if (res.total_weight < 20.0 && res.shape.size() < 2) {\n                 consecutive_fails++;\n            } else {\n                 consecutive_fails = 0;\n            }\n        }\n        \n        fill_residuals(state, f1_in, r1_in, false);\n        fill_residuals(state, f2_in, r2_in, true);\n        \n        double s = calc_score(state);\n        if (s < best_sol.score) {\n            best_sol.score = s;\n            best_sol.grid1 = state.grid1;\n            best_sol.grid2 = state.grid2;\n            best_sol.num_blocks = state.block_counter - 1;\n        }\n    }\n\n    cout << best_sol.num_blocks << endl;\n    for(int i=0; i<(int)best_sol.grid1.size(); ++i) cout << best_sol.grid1[i] << (i==best_sol.grid1.size()-1?\"\":\" \");\n    cout << endl;\n    for(int i=0; i<(int)best_sol.grid2.size(); ++i) cout << best_sol.grid2[i] << (i==best_sol.grid2.size()-1?\"\":\" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    run_solve();\n    return 0;\n}","ahc020":"/**\n * Problem: AHC020 - Broadcasting\n * Approach: Simulated Annealing with Multi-Root Takahashi Steiner Tree\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 105;\nconst int MAX_K = 5005;\nconst int MAX_M = 305;\nconst long long INF = 1e18;\nconst int MAX_P = 5000;\n\n// Structures\nstruct Point { int x, y; };\nstruct Edge { int u, v, w, id; };\nstruct AdjEdge { int to; int w; int id; };\n\n// Global Inputs\nint N, M, K;\nPoint stations[MAX_N];\nEdge edges[MAX_M];\nPoint residents[MAX_K];\nvector<AdjEdge> adj_list[MAX_N];\n\n// Precomputed Data\nlong long adj_dist[MAX_N][MAX_N]; // Shortest path distances\nint dist_res_stat[MAX_K][MAX_N];  // Required P for resident k at station i\nvector<int> nearby_stations[MAX_K]; // Valid stations sorted by distance\n\n// Random number generator\nmt19937 rng(12345);\n\n// Helper Functions\nlong long distSq(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint get_P(long long sq_dist) {\n    if (sq_dist == 0) return 0;\n    return (int)ceil(sqrt((double)sq_dist));\n}\n\nvoid precompute_paths() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            adj_dist[i][j] = (i == j ? 0 : INF);\n        }\n    }\n    for(int i=0; i<M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int w = edges[i].w;\n        if(w < adj_dist[u][v]) {\n            adj_dist[u][v] = adj_dist[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(adj_dist[i][k] != INF && adj_dist[k][j] != INF) {\n                    if(adj_dist[i][k] + adj_dist[k][j] < adj_dist[i][j]) {\n                        adj_dist[i][j] = adj_dist[i][k] + adj_dist[k][j];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Proxy Cost: MST on Metric Closure\n// Used in SA loop for fast evaluation.\nlong long calc_mst_proxy(const vector<int>& terminals) {\n    static int nodes[MAX_N];\n    int T = 0;\n    bool has_root = false;\n    for(int t : terminals) {\n        nodes[T++] = t;\n        if(t == 0) has_root = true;\n    }\n    if(!has_root) nodes[T++] = 0;\n    \n    if(T <= 1) return 0;\n    \n    long long cost = 0;\n    static long long min_d[MAX_N];\n    static bool visited[MAX_N];\n    \n    for(int i=0; i<T; ++i) { min_d[i] = INF; visited[i] = false; }\n    min_d[0] = 0;\n    \n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_d[j] < best) {\n                best = min_d[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        cost += best;\n        \n        int idx_u = nodes[u];\n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[idx_u][nodes[v]];\n                if(d < min_d[v]) min_d[v] = d;\n            }\n        }\n    }\n    return cost;\n}\n\n// Multi-root Takahashi Algorithm\n// Runs the greedy Steiner heuristic rooted at each terminal and returns the best result.\n// Guaranteed to connect all terminals and node 0.\npair<long long, vector<int>> takahashi_steiner_multiroot(const vector<int>& terminals) {\n    static bool is_target[MAX_N];\n    for(int i=0; i<N; ++i) is_target[i] = false;\n    \n    int target_count = 0;\n    for(int t : terminals) {\n        if(!is_target[t]) {\n            is_target[t] = true;\n            target_count++;\n        }\n    }\n    if(!is_target[0]) {\n        is_target[0] = true;\n        target_count++;\n    }\n\n    if (target_count <= 1) return {0, {}};\n\n    vector<int> roots;\n    roots.reserve(target_count);\n    for(int i=0; i<N; ++i) if(is_target[i]) roots.push_back(i);\n    \n    long long best_total_cost = INF;\n    vector<int> best_edges;\n\n    static long long dist[MAX_N];\n    static int parent_node[MAX_N];\n    static int parent_edge[MAX_N];\n    static bool connected[MAX_N];\n    static int current_edge_cost[MAX_M];\n\n    for(int root : roots) {\n        for(int i=0; i<M; ++i) current_edge_cost[i] = edges[i].w;\n        for(int i=0; i<N; ++i) connected[i] = false;\n        \n        connected[root] = true;\n        int connected_count = 1;\n        long long current_tree_cost = 0;\n        vector<int> current_tree_edges;\n        \n        while(connected_count < target_count) {\n            for(int i=0; i<N; ++i) dist[i] = INF;\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<N; ++i) {\n                if(connected[i]) {\n                    dist[i] = 0;\n                    pq.push({0, i});\n                }\n            }\n            \n            int best_node = -1;\n            \n            while(!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if(d > dist[u]) continue;\n                \n                if(is_target[u] && !connected[u]) {\n                    best_node = u;\n                    break; \n                }\n                \n                for(auto& edge : adj_list[u]) {\n                    int v = edge.to;\n                    int w = current_edge_cost[edge.id];\n                    if(dist[u] + w < dist[v]) {\n                        dist[v] = dist[u] + w;\n                        parent_node[v] = u;\n                        parent_edge[v] = edge.id;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            \n            if(best_node == -1) break; \n            \n            int curr = best_node;\n            while(!connected[curr]) {\n                connected[curr] = true;\n                if(is_target[curr]) connected_count++;\n                int eid = parent_edge[curr];\n                current_tree_edges.push_back(eid);\n                current_tree_cost += edges[eid].w;\n                current_edge_cost[eid] = 0; \n                curr = parent_node[curr];\n            }\n        }\n        \n        if(current_tree_cost < best_total_cost) {\n            best_total_cost = current_tree_cost;\n            best_edges = current_tree_edges;\n        }\n    }\n    \n    return {best_total_cost, best_edges};\n}\n\nstruct State {\n    vector<int> assignment;\n    vector<multiset<int>> station_radii;\n    vector<int> active_counts;\n    vector<int> terminals;\n    long long power_cost;\n    long long network_cost;\n    long long total_cost;\n    \n    void update_terminals() {\n        terminals.clear();\n        for(int i=1; i<N; ++i) if(active_counts[i] > 0) terminals.push_back(i);\n    }\n    \n    void recalc_network_cost() {\n        update_terminals();\n        network_cost = calc_mst_proxy(terminals);\n        total_cost = power_cost + network_cost;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K)) return 0;\n    for(int i=0; i<N; ++i) cin >> stations[i].x >> stations[i].y;\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_list[edges[i].u].push_back({edges[i].v, edges[i].w, i});\n        adj_list[edges[i].v].push_back({edges[i].u, edges[i].w, i});\n    }\n    for(int i=0; i<K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    precompute_paths();\n\n    for(int k=0; k<K; ++k) {\n        vector<pair<int, int>> dists;\n        for(int i=0; i<N; ++i) {\n            long long sq = distSq(residents[k].x, residents[k].y, stations[i].x, stations[i].y);\n            int P = get_P(sq);\n            if (P <= MAX_P) {\n                dist_res_stat[k][i] = P;\n                dists.push_back({P, i});\n            } else {\n                dist_res_stat[k][i] = MAX_P + 1;\n            }\n        }\n        for(auto& p : dists) nearby_stations[k].push_back(p.second);\n    }\n\n    State cur;\n    cur.assignment.resize(K);\n    cur.station_radii.resize(N);\n    cur.active_counts.assign(N, 0);\n    cur.power_cost = 0;\n\n    // Initial assignment: Nearest valid station\n    for(int k=0; k<K; ++k) {\n        int u = nearby_stations[k][0]; \n        cur.assignment[k] = u;\n        cur.station_radii[u].insert(dist_res_stat[k][u]);\n        cur.active_counts[u]++;\n    }\n\n    for(int i=0; i<N; ++i) {\n        if(!cur.station_radii[i].empty()) {\n            long long r = *cur.station_radii[i].rbegin();\n            cur.power_cost += r * r;\n        }\n    }\n    cur.recalc_network_cost();\n    \n    State best = cur;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double start_temp = 1000000.0; \n    double end_temp = 100.0;\n\n    int iter = 0;\n    while(true) {\n        iter++;\n        if((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if(elapsed > time_limit) break;\n        }\n\n        double progress = chrono::duration_cast<chrono::duration<double>>(chrono::steady_clock::now() - start_time).count() / time_limit;\n        double temp = start_temp + (end_temp - start_temp) * progress;\n\n        int move_type = (rng() % 100 < 96) ? 0 : 1;\n\n        if (move_type == 0) { // === Shift Move ===\n            int k = rng() % K;\n            int u = cur.assignment[k];\n            int v = -1;\n            \n            // Biased selection for clustering\n            if (rng() % 100 < 75) {\n                for(int t=0; t<10; ++t) {\n                    int idx = rng() % min((int)nearby_stations[k].size(), 20);\n                    int cand = nearby_stations[k][idx];\n                    if(cand != u && cur.active_counts[cand] > 0) {\n                        v = cand; break;\n                    }\n                }\n            }\n            if(v == -1 || v == u) {\n                int idx = rng() % min((int)nearby_stations[k].size(), 10);\n                v = nearby_stations[k][idx];\n            }\n\n            if(v == -1 || v == u) continue;\n            if (dist_res_stat[k][v] > MAX_P) continue;\n\n            long long old_Pu_sq = 0;\n            if(!cur.station_radii[u].empty()) old_Pu_sq = (long long)(*cur.station_radii[u].rbegin()) * (*cur.station_radii[u].rbegin());\n            \n            int r_k_u = dist_res_stat[k][u];\n            long long new_Pu_sq = old_Pu_sq;\n            \n            if(cur.active_counts[u] == 1) {\n                new_Pu_sq = 0;\n            } else {\n                int max_u = *cur.station_radii[u].rbegin();\n                if (r_k_u == max_u && cur.station_radii[u].count(max_u) == 1) {\n                     auto it_prev = prev(cur.station_radii[u].end(), 2);\n                     new_Pu_sq = (long long)(*it_prev) * (*it_prev);\n                }\n            }\n\n            long long old_Pv_sq = 0;\n            if(!cur.station_radii[v].empty()) old_Pv_sq = (long long)(*cur.station_radii[v].rbegin()) * (*cur.station_radii[v].rbegin());\n            \n            int r_k_v = dist_res_stat[k][v];\n            long long new_Pv_sq;\n            if(cur.active_counts[v] == 0) {\n                new_Pv_sq = (long long)r_k_v * r_k_v;\n            } else {\n                int max_v = *cur.station_radii[v].rbegin();\n                int new_max = max(max_v, r_k_v);\n                new_Pv_sq = (long long)new_max * new_max;\n            }\n\n            long long power_delta = (new_Pu_sq - old_Pu_sq) + (new_Pv_sq - old_Pv_sq);\n            long long network_delta = 0;\n            \n            bool u_empty = (cur.active_counts[u] == 1);\n            bool v_active = (cur.active_counts[v] == 0);\n\n            if (u_empty || v_active) {\n                vector<int> next_terminals = cur.terminals;\n                if (u_empty) {\n                    for(auto it = next_terminals.begin(); it != next_terminals.end(); ++it) {\n                        if(*it == u) { next_terminals.erase(it); break; }\n                    }\n                }\n                if (v_active && v != 0) {\n                    next_terminals.push_back(v);\n                }\n                network_delta = calc_mst_proxy(next_terminals) - cur.network_cost;\n            }\n\n            long long total_delta = power_delta + network_delta;\n            \n            if (total_delta <= 0 || generate_canonical<double, 10>(rng) < exp(-total_delta / temp)) {\n                cur.assignment[k] = v;\n                cur.station_radii[u].erase(cur.station_radii[u].find(r_k_u));\n                cur.active_counts[u]--;\n                cur.station_radii[v].insert(r_k_v);\n                cur.active_counts[v]++;\n                \n                cur.power_cost += power_delta;\n                cur.network_cost += network_delta;\n                cur.total_cost += total_delta;\n                if(u_empty || v_active) cur.update_terminals();\n                \n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n\n        } else { // === Clear Move ===\n            if (cur.terminals.size() <= 1) continue;\n            int idx = rng() % cur.terminals.size();\n            int u = cur.terminals[idx];\n            if(u == 0) continue;\n\n            vector<int> residents_in_u;\n            residents_in_u.reserve(cur.active_counts[u]);\n            for(int k=0; k<K; ++k) if(cur.assignment[k] == u) residents_in_u.push_back(k);\n            \n            long long power_delta = 0;\n            if(!cur.station_radii[u].empty()) {\n                long long r = *cur.station_radii[u].rbegin();\n                power_delta -= r*r;\n            }\n\n            vector<int> targets = cur.terminals;\n            auto it_u = find(targets.begin(), targets.end(), u);\n            if(it_u != targets.end()) targets.erase(it_u);\n            bool has_zero = false;\n            for(int t : targets) if(t==0) has_zero=true;\n            if(!has_zero) targets.push_back(0);\n\n            map<int, int> next_max_r; \n            bool ok = true;\n            vector<pair<int,int>> moves;\n            moves.reserve(residents_in_u.size());\n\n            for(int k : residents_in_u) {\n                int best_v = -1;\n                int min_cost_increase = 2e9;\n                int min_r_req = MAX_P + 1;\n                \n                for(int v : targets) {\n                    int r = dist_res_stat[k][v];\n                    if(r > MAX_P) continue;\n                    \n                    int current_max = 0;\n                    if(next_max_r.count(v)) current_max = next_max_r[v];\n                    else current_max = (cur.station_radii[v].empty() ? 0 : *cur.station_radii[v].rbegin());\n                    \n                    int diff = max(0, r - current_max);\n                    if(diff < min_cost_increase) {\n                        min_cost_increase = diff;\n                        best_v = v;\n                        min_r_req = r;\n                    }\n                }\n                \n                if(best_v == -1) { ok = false; break; }\n                moves.push_back({k, best_v});\n                \n                if(!next_max_r.count(best_v)) {\n                    next_max_r[best_v] = (cur.station_radii[best_v].empty() ? 0 : *cur.station_radii[best_v].rbegin());\n                }\n                next_max_r[best_v] = max(next_max_r[best_v], min_r_req);\n            }\n\n            if(!ok) continue;\n\n            long long added_power = 0;\n            for(auto const& [v, new_r] : next_max_r) {\n                int old_r = (cur.station_radii[v].empty() ? 0 : *cur.station_radii[v].rbegin());\n                if(new_r > old_r) {\n                    added_power += (long long)new_r*new_r - (long long)old_r*old_r;\n                }\n            }\n            \n            power_delta += added_power;\n            if(!has_zero && targets.back() == 0) targets.pop_back();\n            long long net_delta = calc_mst_proxy(targets) - cur.network_cost;\n            long long total_delta = power_delta + net_delta;\n\n            if (total_delta <= 0 || generate_canonical<double, 10>(rng) < exp(-total_delta / temp)) {\n                cur.station_radii[u].clear();\n                cur.active_counts[u] = 0;\n                for(int i=0; i<(int)moves.size(); ++i) {\n                    int k = moves[i].first;\n                    int v = moves[i].second;\n                    int r = dist_res_stat[k][v];\n                    cur.assignment[k] = v;\n                    cur.station_radii[v].insert(r);\n                    cur.active_counts[v]++;\n                }\n                cur.power_cost += power_delta;\n                cur.network_cost += net_delta;\n                cur.total_cost += total_delta;\n                cur.update_terminals();\n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n        }\n    }\n\n    // Output Generation\n    vector<int> final_P(N, 0);\n    vector<int> terminals;\n    \n    // Ensure we check all stations including 0\n    for(int i=0; i<N; ++i) {\n        if(best.active_counts[i] > 0) {\n            if(i != 0) terminals.push_back(i);\n            final_P[i] = *best.station_radii[i].rbegin();\n        }\n    }\n\n    auto result = takahashi_steiner_multiroot(terminals);\n    vector<int> final_edges = result.second;\n\n    vector<bool> edge_active(M, false);\n    for(int id : final_edges) edge_active[id] = true;\n\n    for(int i=0; i<N; ++i) cout << final_P[i] << (i == N-1 ? \"\" : \" \");\n    cout << \"\\n\";\n    for(int i=0; i<M; ++i) cout << (edge_active[i] ? 1 : 0) << (i == M-1 ? \"\" : \" \");\n    cout << \"\\n\";\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 30;\nconst int MAX_OPS = 10000;\n\n// Output Move Structure\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\n// Heuristic Weights\nstruct Weights {\n    int w_val_p;      // Parent Value\n    int w_val_c;      // Child Value\n    int w_row;        // Row Index\n    int w_diff;       // Value Difference (P-C)\n    int w_ideal_diff; // Ideal Tier Difference (Tier(P) - Tier(C))\n    int w_down;       // Downward Lookahead (Future violations at target)\n    int w_up;         // Upward Lookahead (Violations created at parents)\n    int w_rand;       // Random Noise\n};\n\n// Global Static Buffers for Performance\nint initial_board[N][N];\nint board[N][N];\nbool in_violation[N][N]; // Lookup table to prevent duplicates\n\n// Violation Queue/Stack\nstruct Violation {\n    int x, y;\n};\nViolation violations[2000]; \nint v_count = 0;\n\n// Moves Buffers\nMove moves_buffer[MAX_OPS + 100]; \nMove best_ops_buffer[MAX_OPS + 100];\nint best_ops_count = MAX_OPS + 1;\n\n// Precomputed Ideal Tiers\nint ideal_tier[465];\n\n// Fast Random Number Generator (Xorshift128) for inner loop\nstruct FastRNG {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n} fast_rng;\n\n// Inline check for heap property violation\ninline bool is_violation(int x, int y) {\n    if (x >= N - 1) return false;\n    // Violation if node is greater than either child\n    return (board[x][y] > board[x+1][y] || board[x][y] > board[x+1][y+1]);\n}\n\n// Solver Function\n// Simulates the repair process with specific heuristic weights.\n// Updates global best if a better solution is found.\nvoid solve(const Weights& w, int limit_k) {\n    // Fast State Reset\n    for(int i=0; i<N; ++i) {\n        memcpy(board[i], initial_board[i], (i+1)*sizeof(int));\n        memset(in_violation[i], 0, (i+1)*sizeof(bool));\n    }\n    v_count = 0;\n    int move_count = 0;\n\n    auto add_violation = [&](int x, int y) {\n        if (x < 0 || x >= N - 1 || y < 0 || y > x) return;\n        if (!in_violation[x][y] && is_violation(x, y)) {\n            in_violation[x][y] = true;\n            violations[v_count++] = {x, y};\n        }\n    };\n\n    // Initial scan\n    for(int x = 0; x < N - 1; ++x) {\n        for(int y = 0; y <= x; ++y) add_violation(x, y);\n    }\n\n    // Processing Loop\n    while (v_count > 0) {\n        // Pruning\n        if (move_count >= limit_k) return;\n\n        int best_idx = 0;\n        long long best_score = -9e18; // Initialize with very small number\n\n        // Scan active violations to pick the best one\n        for (int i = 0; i < v_count; ++i) {\n            int x = violations[i].x;\n            int y = violations[i].y;\n            int p_val = board[x][y];\n            int l = board[x+1][y];\n            int r = board[x+1][y+1];\n            bool go_left = (l < r);\n            int c_val = go_left ? l : r;\n            \n            long long score = 0;\n            // Base Heuristics\n            if (w.w_val_p) score += (long long)w.w_val_p * p_val;\n            if (w.w_val_c) score += (long long)w.w_val_c * c_val;\n            if (w.w_row)   score += (long long)w.w_row * x;\n            if (w.w_diff)  score += (long long)w.w_diff * (p_val - c_val);\n            \n            // Ideal Tier Logic\n            if (w.w_ideal_diff) {\n                // We want to maximize this: ideally P goes down (tier increases) and C goes up (tier decreases)\n                score += (long long)w.w_ideal_diff * (ideal_tier[p_val] - ideal_tier[c_val]);\n            }\n\n            // Lookahead Down\n            if (w.w_down) {\n                int nx = x + 1;\n                int ny = go_left ? y : y + 1;\n                int future_v = 0;\n                if (nx < N - 1) {\n                    if (p_val > board[nx+1][ny]) future_v++;\n                    if (p_val > board[nx+1][ny+1]) future_v++;\n                }\n                score += (long long)w.w_down * future_v;\n            }\n            // Lookahead Up (Parents)\n            if (w.w_up) {\n                int up_v = 0;\n                if (x > 0) {\n                    // Left Parent\n                    if (y > 0 && board[x-1][y-1] > c_val) up_v++;\n                    // Right Parent\n                    if (y < x && board[x-1][y] > c_val) up_v++;\n                }\n                score += (long long)w.w_up * up_v;\n            }\n            \n            // Random Noise\n            if (w.w_rand) {\n                score += (long long)w.w_rand * (int)(fast_rng.next() & 0xFF);\n            }\n\n            if (score > best_score) {\n                best_score = score;\n                best_idx = i;\n            }\n        }\n\n        // Extract Best Candidate\n        int x = violations[best_idx].x;\n        int y = violations[best_idx].y;\n        in_violation[x][y] = false;\n        violations[best_idx] = violations[--v_count]; // Swap remove\n\n        // Check Validity\n        if (!is_violation(x, y)) continue;\n\n        // Setup Swap\n        int l = board[x+1][y];\n        int r = board[x+1][y+1];\n        bool go_left = (l < r);\n        int nx = x + 1;\n        int ny = go_left ? y : y + 1;\n\n        // Execute Swap\n        int tmp = board[x][y];\n        board[x][y] = board[nx][ny];\n        board[nx][ny] = tmp;\n\n        moves_buffer[move_count++] = {x, y, nx, ny};\n\n        // Update Neighborhood\n        // 1. Parents of (x,y)\n        if (x > 0) {\n            if (y < x) add_violation(x-1, y);\n            if (y > 0) add_violation(x-1, y-1);\n        }\n        // 2. The new position of the large value (nx, ny)\n        add_violation(nx, ny);\n    }\n\n    // If successful and better, save result\n    if (move_count < best_ops_count) {\n        best_ops_count = move_count;\n        for(int i=0; i<move_count; ++i) best_ops_buffer[i] = moves_buffer[i];\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Precompute ideal tiers\n    int cnt = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            if (cnt < 465) ideal_tier[cnt++] = i;\n        }\n    }\n\n    // Input\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> initial_board[i][j];\n        }\n    }\n\n    // Time Control\n    const double TIME_LIMIT = 1.85; // Safe limit below 2.0s\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist(-100, 100);\n    uniform_int_distribution<int> dist_noise(-20, 20);\n\n    // 1. Run Deterministic Baseline Strategies\n    solve({100, 0, 0, 0, 0, 0, 0, 0}, best_ops_count); // Max Parent\n    solve({0, 0, 0, 0, 100, 0, 0, 0}, best_ops_count); // Max Ideal Diff\n    solve({0, 0, 0, 0, 0, -100, -100, 0}, best_ops_count); // Min Disruption\n\n    Weights best_w = {0, 0, 0, 0, 0, 0, 0, 0};\n    bool found_good = false;\n\n    // 2. Adaptive Search Loop\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > TIME_LIMIT) break;\n\n        Weights w;\n        // Strategy: With 40% chance, mutate the best weights found so far. \n        // Otherwise, try completely random weights to explore.\n        if (found_good && best_ops_count < MAX_OPS && (rng() % 100 < 40)) {\n            w = best_w;\n            w.w_val_p += dist_noise(rng);\n            w.w_val_c += dist_noise(rng);\n            w.w_row   += dist_noise(rng);\n            w.w_diff  += dist_noise(rng);\n            w.w_ideal_diff += dist_noise(rng);\n            w.w_down  += dist_noise(rng);\n            w.w_up    += dist_noise(rng);\n            w.w_rand  = abs(w.w_rand + dist_noise(rng)); \n        } else {\n            w.w_val_p = dist(rng);\n            w.w_val_c = dist(rng);\n            w.w_row   = dist(rng) * 2;\n            w.w_diff  = dist(rng);\n            w.w_ideal_diff = dist(rng) * 3; // Stronger structural weight\n            w.w_down  = dist(rng) * 5;      // Stronger lookahead\n            w.w_up    = dist(rng) * 5; \n            w.w_rand  = dist(rng);    \n        }\n\n        int old_best = best_ops_count;\n        solve(w, best_ops_count);\n        \n        if (best_ops_count < old_best) {\n            best_w = w;\n            found_good = true;\n        }\n    }\n\n    // Output\n    cout << best_ops_count << \"\\n\";\n    for (int i = 0; i < best_ops_count; ++i) {\n        cout << best_ops_buffer[i].x1 << \" \" << best_ops_buffer[i].y1 << \" \" \n             << best_ops_buffer[i].x2 << \" \" << best_ops_buffer[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <bitset>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst int D = 9;\nconst int TOTAL_CELLS = 81;\n\n// Heuristics Weights - Tuned\nconst double W_DIST = 28.0;      // Primary driver: Distance percentile matching\nconst double W_NEIGHBOR = 6.0;   // Secondary: Prefer filling dead ends/corners\nconst double W_IMPACT = 1.5;     // Tertiary: Avoid placing in transit bottlenecks\n\n// Globals\nint N;\nint grid_fixed[D][D]; // 0: empty, 1: obstacle\nint dist_map[D][D];\nint visited_token[D][D];\nint bfs_token = 0;\n\nstruct Point {\n    int r, c;\n};\n\n// Directions\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// Fast BFS for distance and connectivity analysis\n// Returns {count, sum_dist} of reachable empty cells\n// Used in Placement Phase\npair<int, int> bfs_analysis(const int grid[D][D]) {\n    bfs_token++;\n    visited_token[0][4] = bfs_token;\n    dist_map[0][4] = 0;\n    \n    static Point q[TOTAL_CELLS];\n    int head = 0, tail = 0;\n    q[tail++] = {0, 4};\n    \n    int count = 0;\n    int sum = 0;\n    \n    while(head < tail) {\n        Point p = q[head++];\n        int d = dist_map[p.r][p.c];\n        \n        for(int i=0; i<4; ++i) {\n            int nr = p.r + dr[i];\n            int nc = p.c + dc[i];\n            \n            // Check boundaries and obstacles/containers\n            if(is_valid(nr, nc) && visited_token[nr][nc] != bfs_token && grid[nr][nc] == 0) {\n                visited_token[nr][nc] = bfs_token;\n                dist_map[nr][nc] = d + 1;\n                q[tail++] = {nr, nc};\n                \n                // Count only storage cells (exclude entrance)\n                if(nr != 0 || nc != 4) {\n                    count++;\n                    sum += (d + 1);\n                }\n            }\n        }\n    }\n    return {count, sum};\n}\n\n// Temporary grid for placement logic\nint grid_place[D][D];\n\n// Beam Search Node\nstruct BeamNode {\n    bitset<TOTAL_CELLS> removed_mask;\n    int cost;\n    int parent_idx; \n    int move_id;    \n};\n\nvector<vector<BeamNode>> beam_layers;\n\n// Retrieval Phase Logic\nvoid solve_retrieval(int K, const vector<int>& pos_to_id, const vector<Point>& id_to_pos) {\n    vector<int> container_indices;\n    container_indices.reserve(K);\n    for(int i=0; i<TOTAL_CELLS; ++i) {\n        if(pos_to_id[i] != -1) container_indices.push_back(i);\n    }\n\n    // Increased Beam Width for better search\n    int BEAM_WIDTH = 2500; \n    \n    beam_layers.clear();\n    beam_layers.reserve(K + 1);\n    \n    beam_layers.push_back({});\n    beam_layers[0].push_back({bitset<TOTAL_CELLS>(), 0, -1, -1});\n    \n    struct Candidate {\n        int parent_idx;\n        int move_id;\n        int new_cost;\n        bitset<TOTAL_CELLS> mask;\n    };\n    \n    // Reuse buffer to reduce allocation\n    vector<Candidate> candidates;\n    candidates.reserve(BEAM_WIDTH * 10);\n    \n    // BFS Queue Buffer (static)\n    static Point q[TOTAL_CELLS];\n    \n    for(int step = 0; step < K; ++step) {\n        vector<BeamNode>& current_beam = beam_layers[step];\n        candidates.clear();\n        \n        for(int i=0; i < (int)current_beam.size(); ++i) {\n            const auto& node = current_beam[i];\n            \n            // Identify reachable containers\n            bfs_token++;\n            visited_token[0][4] = bfs_token;\n            int head = 0, tail = 0;\n            q[tail++] = {0, 4};\n            \n            // Collect reachable IDs\n            static int reachable_ids[TOTAL_CELLS];\n            int r_count = 0;\n            \n            while(head < tail) {\n                Point p = q[head++];\n                \n                for(int d=0; d<4; ++d) {\n                    int nr = p.r + dr[d];\n                    int nc = p.c + dc[d];\n                    \n                    if(!is_valid(nr, nc)) continue;\n                    if(visited_token[nr][nc] == bfs_token) continue;\n                    if(grid_fixed[nr][nc] == 1) continue; \n                    \n                    int idx = nr * D + nc;\n                    int id = pos_to_id[idx];\n                    \n                    // Accessible if empty OR holds a REMOVED container\n                    bool is_removed = (id != -1) && node.removed_mask[idx];\n                    bool is_empty_slot = (id == -1);\n                    \n                    visited_token[nr][nc] = bfs_token;\n                    \n                    if(id != -1 && !is_removed) {\n                        // Found a reachable existing container\n                        reachable_ids[r_count++] = id;\n                        // Cannot pass through\n                    } else if(is_empty_slot || is_removed) {\n                        // Passable\n                        q[tail++] = {nr, nc};\n                    }\n                }\n            }\n            \n            // Evaluate moves\n            for(int k=0; k<r_count; ++k) {\n                int rid = reachable_ids[k];\n                int cost_inc = 0;\n                \n                // Optimized cost calc: check all remaining containers\n                // If `oid < rid`, then picking `rid` causes an inversion\n                for(int idx : container_indices) {\n                    if(node.removed_mask[idx]) continue;\n                    int oid = pos_to_id[idx];\n                    if(oid < rid) {\n                        cost_inc++;\n                    }\n                }\n                \n                Candidate cand;\n                cand.parent_idx = i;\n                cand.move_id = rid;\n                cand.new_cost = node.cost + cost_inc;\n                cand.mask = node.removed_mask;\n                \n                Point p = id_to_pos[rid];\n                cand.mask[p.r * D + p.c] = 1;\n                \n                candidates.push_back(cand);\n            }\n        }\n        \n        if(candidates.empty()) break;\n\n        // Sort candidates by cost\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.new_cost < b.new_cost;\n        });\n        \n        beam_layers.push_back({});\n        auto& next_layer = beam_layers.back();\n        next_layer.reserve(BEAM_WIDTH);\n        \n        int taken = 0;\n        for(const auto& cand : candidates) {\n            if(taken >= BEAM_WIDTH) break;\n            next_layer.push_back({cand.mask, cand.new_cost, cand.parent_idx, cand.move_id});\n            taken++;\n        }\n    }\n    \n    // Reconstruct\n    if(beam_layers.size() <= K) return; \n    \n    const auto& last_layer = beam_layers[K];\n    int best_idx = 0;\n    int min_cost = 2e9;\n    for(int i=0; i<(int)last_layer.size(); ++i) {\n        if(last_layer[i].cost < min_cost) {\n            min_cost = last_layer[i].cost;\n            best_idx = i;\n        }\n    }\n    \n    vector<int> removal_order;\n    removal_order.reserve(K);\n    \n    int curr_layer = K;\n    int curr_idx = best_idx;\n    \n    while(curr_layer > 0) {\n        const auto& node = beam_layers[curr_layer][curr_idx];\n        removal_order.push_back(node.move_id);\n        curr_idx = node.parent_idx;\n        curr_layer--;\n    }\n    reverse(removal_order.begin(), removal_order.end());\n    \n    for(int id : removal_order) {\n        Point p = id_to_pos[id];\n        cout << p.r << \" \" << p.c << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int d_in;\n    if (!(cin >> d_in)) return 0;\n    cin >> N;\n    \n    for(int r=0; r<D; ++r) {\n        for(int c=0; c<D; ++c) {\n            grid_fixed[r][c] = 0;\n            grid_place[r][c] = 0;\n            visited_token[r][c] = 0;\n        }\n    }\n    \n    for(int i=0; i<N; ++i){\n        int r, c;\n        cin >> r >> c;\n        grid_fixed[r][c] = 1;\n        grid_place[r][c] = 1;\n    }\n    \n    int K = D*D - 1 - N;\n    vector<bool> id_seen(D*D, false);\n    vector<int> pos_to_id(TOTAL_CELLS, -1);\n    vector<Point> id_to_pos(D*D);\n    \n    vector<Point> candidates; candidates.reserve(TOTAL_CELLS);\n    vector<int> cand_dists; cand_dists.reserve(TOTAL_CELLS);\n    vector<int> all_dists; all_dists.reserve(TOTAL_CELLS);\n\n    for(int step=0; step<K; ++step){\n        int t;\n        cin >> t;\n        \n        int rem_count = 0;\n        int rank_t = 0;\n        for(int i=0; i<K; ++i){\n            if(!id_seen[i] || i == t) {\n                rem_count++;\n                if(i < t) rank_t++;\n            }\n        }\n        id_seen[t] = true;\n        double P = (rem_count > 1) ? (double)rank_t / (rem_count - 1) : 0.5;\n        \n        pair<int, int> state = bfs_analysis(grid_place);\n        int reachable_cnt = state.first;\n        int current_sum_dist = state.second;\n        \n        candidates.clear();\n        cand_dists.clear();\n        all_dists.clear();\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_place[r][c] == 0 && (r!=0 || c!=4)){\n                    if(visited_token[r][c] == bfs_token) {\n                        int d = dist_map[r][c];\n                        candidates.push_back({r, c});\n                        cand_dists.push_back(d);\n                        all_dists.push_back(d);\n                    }\n                }\n            }\n        }\n        \n        sort(all_dists.begin(), all_dists.end());\n        double target_dist = 0;\n        if(!all_dists.empty()) {\n            target_dist = all_dists[(int)round(P * (all_dists.size()-1))];\n        }\n        \n        double best_score = -1e18;\n        Point best_p = candidates[0]; \n        bool found = false;\n        \n        for(size_t i=0; i<candidates.size(); ++i) {\n            Point p = candidates[i];\n            int d = cand_dists[i];\n            \n            // Connectivity check\n            grid_place[p.r][p.c] = 2;\n            pair<int, int> res = bfs_analysis(grid_place);\n            grid_place[p.r][p.c] = 0;\n            \n            if(res.first != reachable_cnt - 1) continue; \n            found = true;\n            \n            double dist_err = (d - target_dist) * (d - target_dist);\n            \n            // Impact: How much extra distance did we cause to the remaining empty cells?\n            // Base expectation: sum decreases by 'd'.\n            // If new sum is higher than (old - d), it means other paths got longer.\n            int expected_new_sum = current_sum_dist - d;\n            int impact = res.second - expected_new_sum;\n            if(impact < 0) impact = 0;\n            \n            // Neighbor count (prefer dead ends)\n            int empty_neighbors = 0;\n            for(int k=0; k<4; ++k){\n                int nr = p.r + dr[k];\n                int nc = p.c + dc[k];\n                if(is_valid(nr, nc) && grid_place[nr][nc] == 0 && (nr!=0 || nc!=4)) {\n                    empty_neighbors++;\n                }\n            }\n            \n            double score = -W_DIST * dist_err - W_NEIGHBOR * empty_neighbors - W_IMPACT * impact;\n            \n            if(score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        \n        if(!found && !candidates.empty()) best_p = candidates[0];\n        \n        cout << best_p.r << \" \" << best_p.c << endl;\n        grid_place[best_p.r][best_p.c] = 2; \n        pos_to_id[best_p.r * D + best_p.c] = t;\n        id_to_pos[t] = best_p;\n    }\n    \n    solve_retrieval(K, pos_to_id, id_to_pos);\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\nconst int TIME_LIMIT_MS = 1950;\n\nint grid[N][N];\nint best_grid[N][N];\nint current_score = 0;\nint best_score = 0;\n\n// Adjacency Tracking\n// adj_count[u][v] tracks the number of shared unit edges between color u and v.\n// Symmetry is enforced: adj_count[u][v] == adj_count[v][u].\nint adj_count[M + 1][M + 1];\nbool is_required[M + 1][M + 1];\n\n// Directions\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\n// BFS/Connectivity Structures\nint visited[N][N];\nint visited_token = 0;\nint q_r[N * N];\nint q_c[N * N];\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// Fast RNG\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n} rng;\n\n// Check global connectivity\n// Ensures that after removing (rem_r, rem_c), the region of 'color' remains valid.\nbool check_global_connectivity(int rem_r, int rem_c, int color) {\n    visited_token++;\n    \n    // Neighbors of the same color\n    int neighbors_r[4], neighbors_c[4];\n    int k = 0;\n    \n    for (int i = 0; i < 4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) {\n                neighbors_r[k] = nr;\n                neighbors_c[k] = nc;\n                k++;\n            }\n        }\n    }\n\n    if (k == 0) return true; \n\n    if (color != 0) {\n        // For non-0 colors, all neighbors must belong to the same connected component\n        int head = 0, tail = 0;\n        q_r[tail] = neighbors_r[0];\n        q_c[tail] = neighbors_c[0];\n        tail++;\n        visited[neighbors_r[0]][neighbors_c[0]] = visited_token;\n        \n        int found_neighbors = 1;\n        \n        while(head < tail) {\n            int r = q_r[head++];\n            int c = q_c[head-1];\n            \n            for(int i=0; i<4; ++i) {\n                int nr = r + dr[i];\n                int nc = c + dc[i];\n                \n                if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_token) {\n                    if(nr == rem_r && nc == rem_c) continue;\n                    \n                    visited[nr][nc] = visited_token;\n                    q_r[tail] = nr;\n                    q_c[tail] = nc;\n                    tail++;\n                    \n                    if (abs(nr - rem_r) + abs(nc - rem_c) == 1) found_neighbors++;\n                }\n            }\n        }\n        return found_neighbors == k;\n    } else {\n        // For color 0, every neighbor component must reach the boundary\n        for(int j=0; j<k; ++j) {\n            if(visited[neighbors_r[j]][neighbors_c[j]] == visited_token) continue;\n            \n            int head = 0, tail = 0;\n            q_r[tail] = neighbors_r[j];\n            q_c[tail] = neighbors_c[j];\n            tail++;\n            visited[neighbors_r[j]][neighbors_c[j]] = visited_token;\n            \n            bool reached_boundary = false;\n            if (neighbors_r[j] == 0 || neighbors_r[j] == N-1 || neighbors_c[j] == 0 || neighbors_c[j] == N-1) \n                reached_boundary = true;\n                \n            while(head < tail) {\n                int r = q_r[head++];\n                int c = q_c[head-1];\n                \n                for(int i=0; i<4; ++i) {\n                    int nr = r + dr[i];\n                    int nc = c + dc[i];\n                    \n                    if (!is_valid(nr, nc)) {\n                        reached_boundary = true;\n                        continue;\n                    }\n                    if (nr == rem_r && nc == rem_c) continue;\n                    \n                    if (grid[nr][nc] == 0 && visited[nr][nc] != visited_token) {\n                        visited[nr][nc] = visited_token;\n                        q_r[tail] = nr;\n                        q_c[tail] = nc;\n                        tail++;\n                        \n                        if (!reached_boundary) {\n                            if (nr == 0 || nr == N-1 || nc == 0 || nc == N-1) reached_boundary = true;\n                        }\n                    }\n                }\n            }\n            if (!reached_boundary) return false;\n        }\n        return true;\n    }\n}\n\n// Fast Local Check\nbool check_local_connectivity(int r, int c, int color) {\n    int n_idx[4], k = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) n_idx[k++] = i;\n        } else if (color == 0) {\n            n_idx[k++] = i;\n        }\n    }\n    if (k <= 1) return true;\n\n    int parent[4] = {0, 1, 2, 3};\n    auto find = [&](int i) { while(i != parent[i]) i = parent[i]; return i; };\n    auto unite = [&](int i, int j) { \n        int ri = find(i), rj = find(j);\n        if (ri != rj) parent[ri] = rj;\n    };\n\n    int pos[4]; memset(pos, -1, sizeof(pos));\n    for(int i=0; i<k; ++i) pos[n_idx[i]] = i;\n\n    // Check diagonals for connectivity\n    auto check_diag = [&](int d1, int d2, int diag_r, int diag_c) {\n        if (pos[d1] != -1 && pos[d2] != -1) {\n            bool conn = false;\n            if (is_valid(diag_r, diag_c)) {\n                if (grid[diag_r][diag_c] == color) conn = true;\n            } else if (color == 0) {\n                conn = true;\n            }\n            if (conn) unite(pos[d1], pos[d2]);\n        }\n    };\n    check_diag(0, 2, r - 1, c - 1);\n    check_diag(0, 3, r - 1, c + 1);\n    check_diag(1, 2, r + 1, c - 1);\n    check_diag(1, 3, r + 1, c + 1);\n\n    int root = find(0);\n    for (int i = 1; i < k; ++i) if (find(i) != root) return false;\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n\n    int n_in, m_in;\n    if (!(cin >> n_in >> m_in)) return 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> grid[i][j];\n            best_grid[i][j] = grid[i][j];\n        }\n    }\n\n    // Initialize Adjacency Counts\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int u = grid[i][j];\n            for(int k=0; k<4; ++k) {\n                int nr = i + dr[k];\n                int nc = j + dc[k];\n                int v = 0; // Outside\n                if (is_valid(nr, nc)) v = grid[nr][nc];\n                if (u != v) adj_count[u][v]++;\n            }\n        }\n    }\n    // Symmetrize for 0-edges which were only counted from inside\n    for(int i=1; i<=M; ++i) adj_count[0][i] = adj_count[i][0];\n    \n    // Determine Requirements\n    for(int i=0; i<=M; ++i) {\n        for(int j=0; j<=M; ++j) {\n            if (adj_count[i][j] > 0) is_required[i][j] = true;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    double start_temp = 4.0;\n    double end_temp = 0.0;\n    \n    int iter = 0;\n    // Increased array size to prevent stack overflow\n    int change_u[16], change_v[16], change_val[16];\n    \n    while(true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        int r = rng.next_int(N);\n        int c = rng.next_int(N);\n        int current_color = grid[r][c];\n        \n        int k = rng.next_int(4);\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n        int target_color = 0;\n        if (is_valid(nr, nc)) target_color = grid[nr][nc];\n\n        if (current_color == target_color) continue;\n\n        int score_diff = 0;\n        if (current_color == 0) score_diff--;\n        if (target_color == 0) score_diff++;\n        \n        if (score_diff < 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            double temp = start_temp + (end_temp - start_temp) * (elapsed / TIME_LIMIT_MS);\n            if (rng.next_double() > exp(score_diff / temp)) continue;\n        }\n\n        int num_changes = 0;\n        auto add_change = [&](int u, int v, int d) {\n            if (u > v) swap(u, v);\n            for(int i=0; i<num_changes; ++i) {\n                if (change_u[i] == u && change_v[i] == v) {\n                    change_val[i] += d;\n                    return;\n                }\n            }\n            change_u[num_changes] = u;\n            change_v[num_changes] = v;\n            change_val[num_changes] = d;\n            num_changes++;\n        };\n\n        for(int i=0; i<4; ++i) {\n            int nnr = r + dr[i];\n            int nnc = c + dc[i];\n            int neighbor_col = 0;\n            if (is_valid(nnr, nnc)) neighbor_col = grid[nnr][nnc];\n            \n            if (neighbor_col != current_color) {\n                add_change(current_color, neighbor_col, -1);\n            }\n            if (neighbor_col != target_color) {\n                add_change(target_color, neighbor_col, 1);\n            }\n        }\n\n        bool adj_ok = true;\n        for(int i=0; i<num_changes; ++i) {\n            int u = change_u[i];\n            int v = change_v[i];\n            int val = change_val[i];\n            int final_count = adj_count[u][v] + val;\n            \n            if (is_required[u][v]) {\n                if (final_count <= 0) { adj_ok = false; break; }\n            } else {\n                if (final_count > 0) { adj_ok = false; break; }\n            }\n        }\n        if (!adj_ok) continue;\n\n        if (!check_local_connectivity(r, c, current_color)) {\n            if (!check_global_connectivity(r, c, current_color)) continue;\n        }\n        \n        for(int i=0; i<num_changes; ++i) {\n            int u = change_u[i];\n            int v = change_v[i];\n            int val = change_val[i];\n            adj_count[u][v] += val;\n            adj_count[v][u] += val;\n        }\n        \n        grid[r][c] = target_color;\n        current_score += score_diff;\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) \n                memcpy(best_grid[i], grid[i], sizeof(grid[i]));\n        }\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    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\nvector<vector<int>> memo; // Memoization for item comparisons\n\n// Perform a query: Output L size, R size, then elements of L and R\nvoid ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    query_count++;\n}\n\n// Read the judge's response\nint get_response() {\n    string res;\n    cin >> res;\n    if (res == \"<\") return 1;\n    if (res == \">\") return -1;\n    if (res == \"=\") return 2;\n    return 0; \n}\n\n// Pad remaining queries with dummy operations to meet the exact Q requirement\nvoid pad_queries() {\n    while (query_count < Q) {\n        // Compare item 0 and item 1. They are always valid indices (N >= 30).\n        // This consumes a query without changing state.\n        ask({0}, {1});\n        get_response(); \n    }\n}\n\n// Compare items a and b using the balance scale.\n// Returns 1 if a < b, -1 if a > b, 0 if a == b.\n// Uses memoization to avoid redundant queries.\nint compare_items(int a, int b) {\n    if (a == b) return 0;\n    if (memo[a][b] != 0) return (memo[a][b] == 2 ? 0 : memo[a][b]);\n\n    ask({a}, {b});\n    int res = get_response();\n    \n    if (res == 1) {\n        memo[a][b] = 1;\n        memo[b][a] = -1;\n        return 1;\n    } else if (res == -1) {\n        memo[a][b] = -1;\n        memo[b][a] = 1;\n        return -1;\n    } else {\n        memo[a][b] = 2;\n        memo[b][a] = 2;\n        return 0;\n    }\n}\n\n// Compute expected values of order statistics for the Exponential Distribution\nvector<double> compute_expected_weights(int n) {\n    vector<double> w(n);\n    double current = 0;\n    for (int i = 0; i < n; ++i) {\n        current += 1.0 / (n - i);\n        w[i] = current;\n    }\n    return w;\n}\n\n// Isotonic Regression (Pool Adjacent Violators Algorithm)\n// Fits data to be monotonically non-decreasing minimizing MSE.\nvector<double> isotonic_regression(const vector<double>& y) {\n    vector<pair<double, double>> stack; \n    for (double val : y) {\n        double current_val = val;\n        double current_w = 1.0;\n        while (!stack.empty() && stack.back().first >= current_val) {\n            double prev_val = stack.back().first;\n            double prev_w = stack.back().second;\n            stack.pop_back();\n            current_val = (prev_val * prev_w + current_val * current_w) / (prev_w + current_w);\n            current_w += prev_w;\n        }\n        stack.push_back({current_val, current_w});\n    }\n    vector<double> res;\n    for (auto p : stack) {\n        for (int i = 0; i < (int)p.second; ++i) res.push_back(p.first);\n    }\n    return res;\n}\n\nint main() {\n    // IO setup\n    ios_base::sync_with_stdio(false);\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    memo.assign(N, vector<int>(N, 0));\n    srand(123); \n\n    // Determine budget for initial sorting.\n    // We reserve queries for the refinement phase (sorting sets + adjusting).\n    // Sorting D sets takes approx D * log2(D) queries. We want a few rounds.\n    // Maximize sort budget but ensure we can do at least some refinement.\n    int refinement_budget = max(Q / 4, min(Q / 2, D * D * 2));\n    int sort_budget = Q - refinement_budget;\n    if (sort_budget < 0) sort_budget = 0;\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // 1. Sort items (partially if budget is tight)\n    // We use stable_sort. If we hit the query limit, we stop comparing, \n    // effectively leaving the remaining items in their original relative order.\n    try {\n        stable_sort(p.begin(), p.end(), [&](int a, int b) {\n            if (query_count >= sort_budget) return false; \n            int res = compare_items(a, b);\n            return res == 1; // a < b\n        });\n    } catch(...) {}\n\n    // 2. Assign Expected Weights based on rank\n    vector<double> exp_w_sorted = compute_expected_weights(N);\n    vector<double> item_w(N);\n    // The item at p[i] is the i-th smallest found.\n    for (int i = 0; i < N; ++i) {\n        item_w[p[i]] = exp_w_sorted[i];\n    }\n\n    // 3. Greedy Partitioning (Largest Items First)\n    // This heuristic generally works well for minimizing variance.\n    vector<int> p_desc = p;\n    reverse(p_desc.begin(), p_desc.end());\n\n    vector<vector<int>> sets(D);\n    vector<double> set_sums(D, 0.0);\n\n    for (int idx : p_desc) {\n        int best_s = -1;\n        double min_sum = 1e18;\n        for (int s = 0; s < D; ++s) {\n            if (set_sums[s] < min_sum) {\n                min_sum = set_sums[s];\n                best_s = s;\n            }\n        }\n        sets[best_s].push_back(idx);\n        set_sums[best_s] += item_w[idx];\n    }\n\n    // 4. Local Search (In Silico)\n    // Optimize the partition using the estimated weights before spending more queries.\n    int ls_iter = 0;\n    while (ls_iter < 20000) {\n        ls_iter++;\n        int s1 = rand() % D;\n        int s2 = rand() % D;\n        if (s1 == s2) continue;\n        if (sets[s1].empty()) continue;\n\n        int type = (sets[s2].empty() ? 0 : rand() % 2);\n        int idx1 = rand() % sets[s1].size();\n        int u = sets[s1][idx1];\n\n        if (type == 0) { // Move u from s1 to s2\n            double new_s1 = set_sums[s1] - item_w[u];\n            double new_s2 = set_sums[s2] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n            \n            if (new_sq < old_sq) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        } else { // Swap u (from s1) with v (from s2)\n            int idx2 = rand() % sets[s2].size();\n            int v = sets[s2][idx2];\n            \n            double new_s1 = set_sums[s1] - item_w[u] + item_w[v];\n            double new_s2 = set_sums[s2] - item_w[v] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n\n            if (new_sq < old_sq) {\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        }\n    }\n\n    // 5. Refinement Phase with Physical Queries\n    // We sort the sets by weight using the scale, then update our belief (estimates)\n    // using Isotonic Regression, and finally try to balance the extremes.\n    while (true) {\n        // Check if we have enough queries to perform a set sort.\n        int needed = D * log2(D) + 2;\n        if (query_count + needed > Q) break;\n\n        // 5.1 Sort sets physically\n        vector<int> set_indices(D);\n        iota(set_indices.begin(), set_indices.end(), 0);\n        \n        bool possible = true;\n        stable_sort(set_indices.begin(), set_indices.end(), [&](int a, int b){\n            if (query_count >= Q) { possible = false; return false; }\n            ask(sets[a], sets[b]);\n            int res = get_response();\n            return res == 1; // a < b\n        });\n        if (!possible) break;\n\n        // 5.2 Correct estimates\n        // We extract the current estimates in the physical sorted order\n        vector<double> sorted_estimates;\n        for (int idx : set_indices) sorted_estimates.push_back(set_sums[idx]);\n        \n        // Apply PAVA to enforce monotonicity\n        vector<double> pav_res = isotonic_regression(sorted_estimates);\n        \n        // Slightly perturb to enforce strict inequality where PAVA flattens,\n        // to encourage movement.\n        for (int i = 1; i < D; ++i) {\n            if (pav_res[i] <= pav_res[i-1] + 1e-9) {\n                pav_res[i] = pav_res[i-1] + 1e-5;\n            }\n        }\n        // Update set_sums\n        for (int i = 0; i < D; ++i) set_sums[set_indices[i]] = pav_res[i];\n\n        // 5.3 Balance Heaviest and Lightest\n        int light_idx = set_indices[0];\n        int heavy_idx = set_indices.back();\n\n        double diff = set_sums[heavy_idx] - set_sums[light_idx];\n        if (diff < 1e-5) break; // Already balanced within estimate precision\n\n        double target = diff / 2.0; // Amount to transfer from Heavy to Light\n        int best_type = -1;\n        int best_u_idx = -1, best_v_idx = -1;\n        double min_err = 1e18;\n\n        // Try Move\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            int u = sets[heavy_idx][i];\n            double err = abs(item_w[u] - target);\n            if (err < min_err) {\n                min_err = err;\n                best_type = 0;\n                best_u_idx = i;\n            }\n        }\n        // Try Swap\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            for (int j = 0; j < (int)sets[light_idx].size(); ++j) {\n                int u = sets[heavy_idx][i];\n                int v = sets[light_idx][j];\n                double delta = item_w[u] - item_w[v];\n                if (delta <= 0) continue; // Must move mass from heavy to light\n                double err = abs(delta - target);\n                if (err < min_err) {\n                    min_err = err;\n                    best_type = 1;\n                    best_u_idx = i;\n                    best_v_idx = j;\n                }\n            }\n        }\n\n        // Apply best operation\n        if (best_type == 0) {\n            int u = sets[heavy_idx][best_u_idx];\n            sets[heavy_idx].erase(sets[heavy_idx].begin() + best_u_idx);\n            sets[light_idx].push_back(u);\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[light_idx] += item_w[u];\n        } else if (best_type == 1) {\n            int u = sets[heavy_idx][best_u_idx];\n            int v = sets[light_idx][best_v_idx];\n            swap(sets[heavy_idx][best_u_idx], sets[light_idx][best_v_idx]);\n            set_sums[heavy_idx] -= item_w[u] - item_w[v];\n            set_sums[light_idx] += item_w[u] - item_w[v];\n        } else {\n            break; // Cannot find a move/swap that matches target\n        }\n    }\n\n    // Ensure exactly Q queries are performed\n    pad_queries();\n\n    // Output final assignment\n    vector<int> ans(N);\n    for (int i = 0; i < D; ++i) {\n        for (int x : sets[i]) ans[x] = i;\n    }\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"/**\n * Highly Optimized Heuristic Solution for \"Stack of Boxes\" using Incremental Beam Search.\n * \n * Strategy:\n * The problem is modeled as a sequential retrieval process (1 to N).\n * When a target box is buried, we use Beam Search to find the optimal sequence of moves\n * to uncover it.\n * \n * Key Algorithm Features:\n * 1. Beam Search: Explores multiple future possibilities to avoid getting stuck in bad states.\n * 2. Incremental Heuristic Update: Instead of recalculating the score of the entire warehouse\n *    (O(N)) for every candidate move, we only recalculate the scores of the modified source \n *    and destination stacks (O(N/M)). This speedup allows for a much wider beam width.\n * 3. Sorted Chunk Constraint: We only consider moving chunks of boxes that are already sorted\n *    in descending order. This naturally decomposes unsorted stacks into sorted ones and\n *    drastically reduces the branching factor of the search.\n * 4. Tuned Evaluation Function:\n *    - Heavy penalties for blocking \"urgent\" boxes (those needed soon).\n *    - Rewards for tight packing (small numeric gaps).\n *    - Dynamic valuation of empty stacks (valuable resource vs temporary buffer).\n * \n * Performance:\n * - Beam Width: 300 (Balanced for 2.0s time limit with N=200).\n * - Complexity: O(N_targets * Depth * Beam_Width * Stack_Height).\n *   With optimizations, this fits comfortably within the limit.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\n// --- Constants & Tuning ---\nconst int MAX_OPS = 5000;\nconst int BEAM_WIDTH = 300;  // Optimized width\nconst int MAX_DEPTH = 60;    // Max search depth per target\n\n// Heuristic Weights\nconst double W_ENERGY = 1.0;\nconst double W_BAD_LINK_BASE = 100.0;\nconst double W_BAD_LINK_URGENCY = 3000.0; \nconst double W_GAP = 1.0;                 \nconst double W_BURIED = 400.0;            \nconst double W_EMPTY_STACK = 500.0;       \nconst double W_EMPTY_VAL_FACTOR = 2.0;    \n\nstruct OutputMove {\n    int v;\n    int i;\n};\n\nint N, M;\nint global_ops = 0;\n\n// Calculate heuristic score for a single stack\ndouble get_stack_score(const vector<int>& s, int current_target) {\n    if (s.empty()) return 0.0;\n    \n    double score = 0.0;\n    int h = s.size();\n    \n    // 1. Link Analysis\n    for (int i = 0; i < h - 1; ++i) {\n        int below = s[i];\n        int above = s[i+1];\n        \n        if (above > below) {\n            // Bad Link: Larger on Smaller\n            int dist = below - current_target;\n            if (dist < 1) dist = 1;\n            double urgency = 1.0 / (double)dist;\n            score += W_BAD_LINK_BASE + W_BAD_LINK_URGENCY * urgency;\n        } else {\n            // Good Link: Smaller on Larger\n            score += (double)(below - above) * W_GAP;\n        }\n    }\n    \n    // 2. Buried Urgency\n    for (int i = 0; i < h; ++i) {\n        int val = s[i];\n        if (val >= current_target) {\n            int dist = val - current_target;\n            if (dist < 20) { // Only check very urgent boxes\n                 double urgency = 1.0 / (double)(dist + 1);\n                 int height_above = h - 1 - i;\n                 score += height_above * W_BURIED * urgency;\n            }\n        }\n    }\n    \n    // 3. Base Bonus (Reward large bases on stacks)\n    score -= (double)s[0] * W_EMPTY_VAL_FACTOR;\n    \n    return score;\n}\n\nstruct State {\n    vector<vector<int>> stacks;\n    double g_cost; \n    double h_val; \n    vector<OutputMove> history;\n    int op_count;\n    \n    bool operator>(const State& other) const {\n        return (g_cost + h_val) > (other.g_cost + other.h_val);\n    }\n};\n\n// Locate box v in stacks\npair<int, int> get_pos(const vector<vector<int>>& st, int v) {\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<(int)st[i].size(); ++j) {\n            if(st[i][j] == v) return {i, j};\n        }\n    }\n    return {-1, -1};\n}\n\n// Full heuristic calculation (initialization only)\ndouble calculate_full_heuristic(const vector<vector<int>>& stacks, int current_target) {\n    double score = 0;\n    int empty_count = 0;\n    for(const auto& s : stacks) {\n        if(s.empty()) empty_count++;\n        else score += get_stack_score(s, current_target);\n    }\n    // Penalize lack of empty stacks (Reward having them)\n    score += (M - empty_count) * W_EMPTY_STACK;\n    return score;\n}\n\nvector<OutputMove> global_result;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M)) return 0;\n\n    vector<vector<int>> stacks(M);\n    for(int i=0; i<M; ++i) {\n        stacks[i].reserve(N);\n        for(int j=0; j<N/M; ++j) {\n            int val; cin >> val;\n            stacks[i].push_back(val);\n        }\n    }\n\n    // Iterate through targets 1..N\n    for (int target = 1; target <= N; ++target) {\n        if (global_ops >= MAX_OPS) break;\n\n        while (true) {\n            pair<int, int> loc = get_pos(stacks, target);\n            int src = loc.first;\n            int idx = loc.second;\n            \n            // Target exposed?\n            if (idx == (int)stacks[src].size() - 1) {\n                global_result.push_back({target, 0});\n                stacks[src].pop_back();\n                global_ops++;\n                break;\n            }\n            \n            // --- Beam Search Start ---\n            priority_queue<State, vector<State>, greater<State>> beam;\n            \n            State start_state;\n            start_state.stacks = stacks;\n            start_state.g_cost = 0;\n            start_state.h_val = calculate_full_heuristic(stacks, target);\n            start_state.op_count = global_ops;\n            beam.push(start_state);\n            \n            bool solved = false;\n            State best_state;\n            double best_f = 1e18;\n            \n            int depth = 0;\n            \n            while (!beam.empty() && depth < MAX_DEPTH) {\n                vector<State> current_level;\n                int cnt = 0;\n                while(!beam.empty() && cnt < BEAM_WIDTH) {\n                    current_level.push_back(beam.top());\n                    beam.pop();\n                    cnt++;\n                }\n                \n                priority_queue<State, vector<State>, greater<State>> next_beam;\n                \n                for(const auto& s : current_level) {\n                    pair<int, int> sloc = get_pos(s.stacks, target);\n                    int s_src = sloc.first;\n                    int s_idx = sloc.second;\n                    \n                    // Check if solved\n                    if(s_idx == (int)s.stacks[s_src].size() - 1) {\n                        double f = s.g_cost + s.h_val;\n                        if(f < best_f) {\n                            best_f = f;\n                            best_state = s;\n                            solved = true;\n                        }\n                        continue; \n                    }\n                    \n                    if(solved && (s.g_cost + s.h_val >= best_f)) continue;\n                    \n                    // Move Generation: Only from source stack\n                    int top = s.stacks[s_src].size() - 1;\n                    int sorted_start = top;\n                    // Identify longest sorted suffix [sorted_start, top]\n                    while(sorted_start > s_idx + 1) {\n                        if(s.stacks[s_src][sorted_start-1] > s.stacks[s_src][sorted_start]) sorted_start--;\n                        else break;\n                    }\n                    \n                    // Score of source before move\n                    double score_src_old = get_stack_score(s.stacks[s_src], target);\n                    bool src_was_empty = s.stacks[s_src].empty(); // Should be false\n                    \n                    // Try all chunks in sorted suffix\n                    for(int k = sorted_start; k <= top; ++k) {\n                        int chunk_sz = top - k + 1;\n                        double energy = (double)(chunk_sz + 1);\n                        int moved_v = s.stacks[s_src][k];\n                        \n                        for(int dst = 0; dst < M; ++dst) {\n                            if(dst == s_src) continue;\n                            \n                            State next_s = s; \n                            \n                            double score_dst_old = get_stack_score(next_s.stacks[dst], target);\n                            bool dst_was_empty = next_s.stacks[dst].empty();\n                            \n                            // Execute Move\n                            vector<int> chunk; \n                            chunk.reserve(chunk_sz);\n                            for(int p=k; p<=top; ++p) chunk.push_back(next_s.stacks[s_src][p]);\n                            next_s.stacks[s_src].resize(k);\n                            next_s.stacks[dst].insert(next_s.stacks[dst].end(), chunk.begin(), chunk.end());\n                            \n                            // Incremental Heuristic Update\n                            double h_new = next_s.h_val;\n                            \n                            // Subtract old scores\n                            h_new -= score_src_old;\n                            h_new -= score_dst_old;\n                            \n                            // Add new scores\n                            h_new += get_stack_score(next_s.stacks[s_src], target);\n                            h_new += get_stack_score(next_s.stacks[dst], target);\n                            \n                            // Update Empty Stack Penalty\n                            // Score increases if empty_count decreases (M - empty increases)\n                            if (!src_was_empty && next_s.stacks[s_src].empty()) h_new -= W_EMPTY_STACK;\n                            if (dst_was_empty && !next_s.stacks[dst].empty()) h_new += W_EMPTY_STACK;\n                            \n                            next_s.h_val = h_new;\n                            next_s.g_cost += energy * W_ENERGY;\n                            next_s.history.push_back({moved_v, dst + 1});\n                            next_s.op_count++;\n                            \n                            if(next_s.op_count <= MAX_OPS) {\n                                next_beam.push(next_s);\n                            }\n                        }\n                    }\n                }\n                \n                beam = move(next_beam);\n                depth++;\n                if(solved && beam.empty()) break; \n            }\n            \n            if (solved) {\n                for(const auto& mv : best_state.history) global_result.push_back(mv);\n                stacks = best_state.stacks;\n                global_ops = best_state.op_count;\n            } else {\n                // Fallback: Greedy Move (Move best chunk to best location)\n                // This handles cases where search depth was insufficient\n                int top = stacks[src].size() - 1;\n                int k = top;\n                while(k > idx + 1 && stacks[src][k-1] > stacks[src][k]) k--;\n                \n                int moved_v = stacks[src][k];\n                int best_dst = -1;\n                double best_h = 1e18;\n                \n                double s_src_old = get_stack_score(stacks[src], target);\n                \n                for(int dst = 0; dst < M; ++dst) {\n                    if(dst == src) continue;\n                    vector<vector<int>> tmp = stacks;\n                    \n                    double s_dst_old = get_stack_score(tmp[dst], target);\n                    bool dst_empty = tmp[dst].empty();\n                    \n                    // Move\n                    vector<int> chunk;\n                    for(int p=k; p<=top; ++p) chunk.push_back(tmp[src][p]);\n                    tmp[src].resize(k);\n                    tmp[dst].insert(tmp[dst].end(), chunk.begin(), chunk.end());\n                    \n                    double h = calculate_full_heuristic(tmp, target); // Safer to recalc full for fallback\n                    \n                    if(h < best_h) {\n                        best_h = h;\n                        best_dst = dst;\n                    }\n                }\n                \n                // Execute Fallback\n                vector<int> chunk;\n                for(int p=k; p<=top; ++p) chunk.push_back(stacks[src][p]);\n                stacks[src].resize(k);\n                stacks[best_dst].insert(stacks[best_dst].end(), chunk.begin(), chunk.end());\n                global_result.push_back({moved_v, best_dst + 1});\n                global_ops++;\n            }\n            \n            if(global_ops >= MAX_OPS) break;\n        }\n    }\n\n    for(const auto& m : global_result) cout << m.v << \" \" << m.i << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Timer class to manage execution time\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    Timer() { reset(); }\n    void reset() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto end = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end - start).count() / 1000.0;\n    }\n};\n\nint N;\nvector<string> h_walls, v_walls;\nvector<int> D_vals; // Flattened dirtiness values\nvector<int> dist_mat_flat; // Flattened All-Pairs Shortest Paths matrix\n\n// Directions: Up, Down, Left, Right\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\nchar dc_char[] = {'U', 'D', 'L', 'R'};\nconst int INF = 1e9;\n\n// Check if a move is blocked by a wall\nbool can_move(int r, int c, int dir) {\n    if (dir == 0) return r > 0 && h_walls[r-1][c] == '0';\n    if (dir == 1) return r < N-1 && h_walls[r][c] == '0';\n    if (dir == 2) return c > 0 && v_walls[r][c-1] == '0';\n    if (dir == 3) return c < N-1 && v_walls[r][c] == '0';\n    return false;\n}\n\n// Compute APSP using BFS since edge weights are 1\nvoid compute_apsp() {\n    int num_nodes = N * N;\n    dist_mat_flat.assign(num_nodes * num_nodes, INF);\n    \n    // Static vectors to reuse memory\n    static vector<int> q_vec;\n    static vector<int> d_local; \n    if (q_vec.capacity() < num_nodes) { \n        q_vec.resize(num_nodes); \n        d_local.resize(num_nodes); \n    }\n    \n    for (int u = 0; u < num_nodes; ++u) {\n        // BFS from u\n        fill(d_local.begin(), d_local.end(), INF);\n        int head = 0, tail = 0;\n        q_vec[tail++] = u;\n        d_local[u] = 0;\n        dist_mat_flat[u * num_nodes + u] = 0;\n        \n        while(head < tail){\n            int curr = q_vec[head++];\n            int d_c = d_local[curr];\n            dist_mat_flat[u * num_nodes + curr] = d_c;\n            \n            int cr = curr / N;\n            int cc = curr % N;\n            \n            for(int k=0; k<4; ++k){\n                if(can_move(cr, cc, k)){\n                    int nr = cr + dr[k];\n                    int nc = cc + dc[k];\n                    int v = nr * N + nc;\n                    if(d_local[v] == INF){\n                        d_local[v] = d_c + 1;\n                        q_vec[tail++] = v;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate the average dirtiness score for the given cycle\nlong long calculate_score_cycle(const string& path) {\n    if (path.empty()) return 2e18;\n    long long L = path.length();\n    \n    int num_nodes = N * N;\n    vector<vector<int>> visits(num_nodes);\n    \n    // Simulation starts at (0,0). We assume (0,0) is cleaned at t=0.\n    int r = 0, c = 0;\n    visits[0].push_back(0);\n    \n    for(int t=1; t<=L; ++t){\n        char m = path[t-1];\n        if(m=='U') r--;\n        else if(m=='D') r++;\n        else if(m=='L') c--;\n        else if(m=='R') c++;\n        visits[r*N + c].push_back(t);\n    }\n    \n    double total_sum = 0;\n    for(int u=0; u<num_nodes; ++u){\n        // If a node is not visited, the cost is infinite (conceptually)\n        // But our construction guarantees visitation.\n        if(visits[u].empty()) return 2e18; \n        \n        long long s_sq = 0;\n        // Sum of (interval * (interval - 1))\n        for(size_t i=0; i<visits[u].size()-1; ++i){\n            long long diff = visits[u][i+1] - visits[u][i];\n            s_sq += diff * (diff - 1);\n        }\n        // Wrap-around interval: distance from last visit back to first visit (+L)\n        long long diff = (visits[u][0] + L) - visits[u].back();\n        s_sq += diff * (diff - 1);\n        \n        total_sum += (double)D_vals[u] * s_sq;\n    }\n    \n    // The formula for average dirtiness simplifies to: sum(d * sum(intervals^2)) / 2L\n    return (long long)round(total_sum / (2.0 * L));\n}\n\nint main() {\n    // Initialize IO and timer\n    Timer timer;\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Input reading\n    if(!(cin >> N)) return 0;\n    h_walls.resize(N-1);\n    for(int i=0; i<N-1; ++i) cin >> h_walls[i];\n    v_walls.resize(N);\n    for(int i=0; i<N; ++i) cin >> v_walls[i];\n    \n    int num_nodes = N*N;\n    D_vals.resize(num_nodes);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> D_vals[i*N + j];\n        }\n    }\n\n    // Preprocessing\n    compute_apsp();\n\n    // Parameter exploration strategy\n    // params represent the exponent 'k' in the gravity formula 1 / dist^k\n    // Small k: global attraction (visit far away dirty nodes)\n    // Large k: local attraction (clean nearby dirty nodes first)\n    vector<double> params = {2.5, 1.5, 3.5, 1.0, 4.0, 0.5, 5.0, 2.0};\n    \n    long long best_score = -1;\n    string best_path = \"\";\n    \n    mt19937 rng(123);\n    \n    // Limit path length to save time. 25,000 is sufficient for N<=40.\n    const int MAX_PATH_LEN = 25000; \n    \n    int p_idx = 0;\n    \n    // Loop until time is close to limit\n    while(timer.elapsed() < 1.85) {\n        // Select parameter\n        double k_pow;\n        if (p_idx < params.size()) k_pow = params[p_idx++];\n        else {\n            uniform_real_distribution<double> dist_p(0.5, 5.0);\n            k_pow = dist_p(rng);\n        }\n\n        // Precompute lookup table for power function to avoid calls in loop\n        vector<double> pow_lookup(2 * num_nodes + 5);\n        for(int d=0; d<pow_lookup.size(); ++d) pow_lookup[d] = 1.0 / pow(d + 1, k_pow);\n\n        // Precompute Weight matrix W based on APSP\n        // W[u][v] = weight of node u viewed from v (symmetric)\n        // Stored flat, effectively row-major\n        vector<double> W(num_nodes * num_nodes);\n        for(int i=0; i<num_nodes * num_nodes; ++i) {\n            if(dist_mat_flat[i] == INF) W[i] = 0;\n            else W[i] = pow_lookup[dist_mat_flat[i]];\n        }\n        \n        // Incremental score tracking\n        // static_score[v]: potential dirtiness gain rate from v's perspective\n        // dynamic_score[v]: penalty reduction based on recent visits\n        vector<double> static_score(num_nodes, 0.0);\n        vector<double> dynamic_score(num_nodes, 0.0);\n        vector<int> last_visit(num_nodes, -MAX_PATH_LEN); \n        \n        // Initialize static scores\n        for(int v=0; v<num_nodes; ++v) {\n            double s = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                s += D_vals[u] * w_row[u];\n            }\n            static_score[v] = s;\n        }\n        \n        // Initialize state\n        int curr = 0;\n        last_visit[0] = 0; // (0,0) visited at t=0\n        \n        // Initialize dynamic scores (urgency)\n        for(int v=0; v<num_nodes; ++v) {\n            double d = 0;\n            const double* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) {\n                d += (double)D_vals[u] * last_visit[u] * w_row[u];\n            }\n            dynamic_score[v] = d;\n        }\n        \n        string path;\n        path.reserve(MAX_PATH_LEN + 5);\n        \n        // Greedy Construction Step\n        for(int t=1; t<=MAX_PATH_LEN; ++t) {\n            // Frequent time check to prevent TLE\n            if((t & 1023) == 0) {\n                if(timer.elapsed() > 1.95) break;\n            }\n\n            int best_next = -1;\n            \n            // Check return condition: if we can't extend much further without violating return ability\n            int dist_to_home = dist_mat_flat[curr * num_nodes + 0];\n            bool must_return = (t + dist_to_home >= MAX_PATH_LEN);\n            \n            if(must_return) {\n                // Move towards (0,0) via shortest path\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        // Distance strictly decreases in BFS tree towards root\n                        if(dist_mat_flat[next_node * num_nodes + 0] < dist_to_home) {\n                            best_next = next_node;\n                            break; \n                        }\n                    }\n                }\n                if(best_next == -1) break; // Should not happen\n            } else {\n                // Greedy choice: Maximize (t * static - dynamic)\n                double max_s = -1e18;\n                \n                // Inspect valid neighbors\n                // dr/dc arrays are small, loop unrolling is implicit\n                for(int k=0; k<4; ++k) {\n                    if(can_move(curr/N, curr%N, k)) {\n                        int nr = curr/N + dr[k];\n                        int nc = curr%N + dc[k];\n                        int next_node = nr*N + nc;\n                        \n                        // Heuristic score\n                        double s = (double)t * static_score[next_node] - dynamic_score[next_node];\n                        \n                        if(s > max_s) {\n                            max_s = s;\n                            best_next = next_node;\n                        }\n                    }\n                }\n            }\n            \n            if(best_next == -1) break;\n            \n            // Record Move\n            if(best_next == curr - N) path += 'U';\n            else if(best_next == curr + N) path += 'D';\n            else if(best_next == curr - 1) path += 'L';\n            else path += 'R';\n            \n            // Update State\n            // Only update dynamic scores based on the change in `last_visit` of `best_next`\n            long long old_last = last_visit[best_next];\n            double update_factor = (double)D_vals[best_next] * (t - old_last);\n            \n            // Optimized Update: Access W memory sequentially\n            const double* w_vec = &W[best_next * num_nodes];\n            for(int v=0; v<num_nodes; ++v) {\n                dynamic_score[v] += update_factor * w_vec[v];\n            }\n            \n            last_visit[best_next] = t;\n            curr = best_next;\n            \n            // Check if we successfully closed the cycle\n            if(curr == 0 && must_return) {\n                break;\n            }\n        }\n        \n        // Evaluate result\n        if(curr == 0 && !path.empty()) {\n            long long sc = calculate_score_cycle(path);\n            if(best_score == -1 || sc < best_score) {\n                best_score = sc;\n                best_path = path;\n            }\n        }\n    }\n\n    cout << best_path << endl;\n\n    return 0;\n}","ahc028":"/**\n * Solution for AtCoder Heuristic Contest 028\n * \n * Algorithm:\n * 1. Preprocessing:\n *    - Map character positions on grid.\n *    - Compute Overlaps between all pairs of strings t_k.\n *    - Compute ATSP (Asymmetric TSP) Heuristic Matrix:\n *      dist_matrix[i][j] = cost to type the extension of t_j immediately after t_i.\n *      This cost is minimized over all valid physical end positions of t_i to provide a tight lower bound.\n * \n * 2. Phase 1: Initialization (GRASP)\n *    - Run multiple Randomized Greedy constructions using the heuristic matrix.\n *    - Select the best initial solution.\n * \n * 3. Phase 2: Heuristic Simulated Annealing\n *    - Optimize the permutation of strings using the ATSP Heuristic cost.\n *    - O(1) delta updates allow high iteration count.\n *    - Periodically synchronize with the Exact Cost (calculated via DP) to update the global best.\n * \n * 4. Phase 3: Exact Cost Local Search\n *    - In the remaining time, perform a Randomized Local Search (Hill Climbing) using the EXACT cost function.\n *    - Moves: Swap, Insert, Short Reversal.\n *    - This phase refines the solution by considering the actual global path constraints that the heuristic might miss.\n * \n * 5. Output the reconstructed path of the best found permutation.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <cstring>\n\nusing namespace std;\n\n// -------------------- Constants & Globals --------------------\nint N, M;\nint start_r, start_c;\nvector<string> A;\nvector<string> T;\nvector<pair<int, int>> char_positions[26];\n\n// overlaps[i][j] = length of suffix of T[i] matching prefix of T[j]\nint overlaps[205][205];\n\n// ATSP Distance Matrix (Heuristic)\nint dist_matrix[205][205];\nint start_dist[205];\n\n// Global Best\nvector<int> global_best_p;\nint global_min_exact_cost = INT_MAX;\n\nmt19937 rng(12345);\n\n// -------------------- Helper Functions --------------------\ninline int c2i(char c) { return c - 'A'; }\ninline int dist(int r1, int c1, int r2, int c2) { return abs(r1 - r2) + abs(c1 - c2); }\n\nint calc_overlap(const string& s1, const string& s2) {\n    for (int len = 4; len >= 1; --len) {\n        bool match = true;\n        for (int k = 0; k < len; ++k) {\n            if (s1[5 - len + k] != s2[k]) {\n                match = false;\n                break;\n            }\n        }\n        if (match) return len;\n    }\n    return 0;\n}\n\n// Precompute heuristic cost: Min cost to type s starting from any of start_coords\nint calc_segment_cost_heuristic(const vector<pair<int,int>>& start_coords, const string& s) {\n    if (s.empty()) return 0;\n    int L = s.size();\n    vector<int> dp_prev(start_coords.size());\n    \n    // Initialize first char cost\n    int c0 = c2i(s[0]);\n    const auto& pos0 = char_positions[c0];\n    vector<int> next_dp(pos0.size());\n    \n    for(size_t j=0; j<pos0.size(); ++j) {\n        int min_d = 1000000;\n        for(const auto& sp : start_coords) {\n            int d = dist(sp.first, sp.second, pos0[j].first, pos0[j].second) + 1;\n            if(d < min_d) min_d = d;\n        }\n        next_dp[j] = min_d;\n    }\n    dp_prev = next_dp;\n    \n    // Iterate rest of string\n    for(int i=1; i<L; ++i) {\n        int cc = c2i(s[i]);\n        const auto& cpos = char_positions[cc];\n        const auto& ppos = char_positions[c2i(s[i-1])];\n        vector<int> curr_dp(cpos.size());\n        for(size_t j=0; j<cpos.size(); ++j) {\n            int min_val = 1000000;\n            for(size_t k=0; k<ppos.size(); ++k) {\n                int val = dp_prev[k] + dist(ppos[k].first, ppos[k].second, cpos[j].first, cpos[j].second) + 1;\n                if(val < min_val) min_val = val;\n            }\n            curr_dp[j] = min_val;\n        }\n        dp_prev = curr_dp;\n    }\n    int ans = 1000000;\n    for(int v : dp_prev) if(v < ans) ans = v;\n    return ans;\n}\n\n// Optimized Exact Cost Calculation using DP\n// Uses static arrays to minimize overhead\nint get_exact_cost(const vector<int>& p) {\n    static int dp_prev[300];\n    static int dp_curr[300];\n    \n    // Init with start position -> First char of first string\n    int s0_idx = p[0];\n    int c0 = c2i(T[s0_idx][0]);\n    const auto* pos0 = &char_positions[c0];\n    int sz0 = pos0->size();\n    \n    for(int j=0; j<sz0; ++j) {\n        dp_prev[j] = dist(start_r, start_c, (*pos0)[j].first, (*pos0)[j].second) + 1;\n    }\n    \n    int prev_c = c0;\n    int prev_sz = sz0;\n    const vector<pair<int,int>>* prev_pos_ptr = pos0;\n    \n    // Helper lambda or macro not needed, simplified loop\n    // Iterate through the logical sequence\n    \n    // 1. Rest of first string\n    for(int k=1; k<5; ++k) {\n        int cc = c2i(T[s0_idx][k]);\n        const auto& cpos = char_positions[cc];\n        int sz_curr = cpos.size();\n        \n        for(int j=0; j<sz_curr; ++j) {\n            int r = cpos[j].first;\n            int c = cpos[j].second;\n            int min_val = 100000000;\n            for(int m=0; m<prev_sz; ++m) {\n                int d = dist((*prev_pos_ptr)[m].first, (*prev_pos_ptr)[m].second, r, c);\n                int total = dp_prev[m] + d + 1;\n                if(total < min_val) min_val = total;\n            }\n            dp_curr[j] = min_val;\n        }\n        for(int j=0; j<sz_curr; ++j) dp_prev[j] = dp_curr[j];\n        prev_c = cc;\n        prev_sz = sz_curr;\n        prev_pos_ptr = &cpos;\n    }\n    \n    // 2. Rest of the strings (extensions only)\n    for(size_t i=1; i<p.size(); ++i) {\n        int u = p[i-1];\n        int v = p[i];\n        int ov = overlaps[u][v];\n        const string& t = T[v];\n        \n        for(int k=ov; k<5; ++k) {\n            int cc = c2i(t[k]);\n            const auto& cpos = char_positions[cc];\n            int sz_curr = cpos.size();\n            \n            for(int j=0; j<sz_curr; ++j) {\n                int r = cpos[j].first;\n                int c = cpos[j].second;\n                int min_val = 100000000;\n                for(int m=0; m<prev_sz; ++m) {\n                    int d = dist((*prev_pos_ptr)[m].first, (*prev_pos_ptr)[m].second, r, c);\n                    int total = dp_prev[m] + d + 1;\n                    if(total < min_val) min_val = total;\n                }\n                dp_curr[j] = min_val;\n            }\n            for(int j=0; j<sz_curr; ++j) dp_prev[j] = dp_curr[j];\n            prev_c = cc;\n            prev_sz = sz_curr;\n            prev_pos_ptr = &cpos;\n        }\n    }\n    \n    int ans = 100000000;\n    for(int j=0; j<prev_sz; ++j) {\n        if(dp_prev[j] < ans) ans = dp_prev[j];\n    }\n    return ans;\n}\n\nvoid check_candidate(const vector<int>& p) {\n    int cost = get_exact_cost(p);\n    if (cost < global_min_exact_cost) {\n        global_min_exact_cost = cost;\n        global_best_p = p;\n    }\n}\n\n// Final solution reconstruction\nvoid solve_final(const vector<int>& p) {\n    vector<int> S;\n    S.reserve(1200);\n    for(char c : T[p[0]]) S.push_back(c2i(c));\n    for(size_t i=1; i<p.size(); ++i) {\n        int ov = overlaps[p[i-1]][p[i]];\n        for(int k=ov; k<5; ++k) S.push_back(c2i(T[p[i]][k]));\n    }\n    \n    int L = S.size();\n    vector<vector<int>> dp(L), parent(L);\n    \n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp[0].resize(pos0.size());\n    parent[0].resize(pos0.size(), -1);\n    \n    for(size_t j=0; j<pos0.size(); ++j) {\n        dp[0][j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    for(int i=1; i<L; ++i) {\n        int cc = S[i];\n        int pc = S[i-1];\n        const auto& cpos = char_positions[cc];\n        const auto& ppos = char_positions[pc];\n        dp[i].resize(cpos.size());\n        parent[i].resize(cpos.size());\n        \n        for(size_t j=0; j<cpos.size(); ++j) {\n            int r = cpos[j].first;\n            int c = cpos[j].second;\n            int min_val = 1e9;\n            int best_p = -1;\n            for(size_t k=0; k<ppos.size(); ++k) {\n                int d = dist(ppos[k].first, ppos[k].second, r, c);\n                int val = dp[i-1][k] + d + 1;\n                if(val < min_val) { min_val = val; best_p = k; }\n            }\n            dp[i][j] = min_val;\n            parent[i][j] = best_p;\n        }\n    }\n    \n    int min_total = 1e9;\n    int idx = -1;\n    for(size_t j=0; j<dp[L-1].size(); ++j) {\n        if(dp[L-1][j] < min_total) { min_total = dp[L-1][j]; idx = j; }\n    }\n    \n    vector<pair<int,int>> path;\n    for(int i=L-1; i>=0; --i) {\n        path.push_back(char_positions[S[i]][idx]);\n        idx = parent[i][idx];\n    }\n    reverse(path.begin(), path.end());\n    for(auto& pt : path) cout << pt.first << \" \" << pt.second << \"\\n\";\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    cin >> N >> M >> start_r >> start_c;\n    A.resize(N);\n    for(int i=0; i<N; ++i) cin >> A[i];\n    T.resize(M);\n    for(int i=0; i<M; ++i) cin >> T[i];\n    \n    // Preprocessing\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            char_positions[c2i(A[i][j])].push_back({i, j});\n            \n    for(int i=0; i<M; ++i)\n        for(int j=0; j<M; ++j)\n            overlaps[i][j] = (i==j ? 0 : calc_overlap(T[i], T[j]));\n            \n    vector<pair<int,int>> s_pos = {{start_r, start_c}};\n    for(int i=0; i<M; ++i) start_dist[i] = calc_segment_cost_heuristic(s_pos, T[i]);\n    \n    for(int i=0; i<M; ++i) {\n        int li = c2i(T[i].back());\n        const auto& ends = char_positions[li];\n        for(int j=0; j<M; ++j) {\n            if(i==j) { dist_matrix[i][j]=1e9; continue; }\n            dist_matrix[i][j] = calc_segment_cost_heuristic(ends, T[j].substr(overlaps[i][j]));\n        }\n    }\n    \n    // --- Phase 1: GRASP Initialization ---\n    int best_approx = 1e9;\n    vector<int> current_p;\n    // Generate diverse initial solutions\n    for(int iter=0; iter<400; ++iter) {\n        vector<int> p; p.reserve(M);\n        vector<bool> used(M, false);\n        int curr = rng()%M;\n        p.push_back(curr); used[curr]=true;\n        int c = start_dist[curr];\n        \n        for(int i=1; i<M; ++i) {\n            int min_d = 1e9;\n            for(int j=0; j<M; ++j) if(!used[j] && dist_matrix[curr][j] < min_d) min_d = dist_matrix[curr][j];\n            \n            vector<int> cands;\n            // Consider all candidates close to minimum\n            for(int j=0; j<M; ++j) if(!used[j] && dist_matrix[curr][j] <= min_d+2) cands.push_back(j);\n            \n            // Fail-safe\n            if(cands.empty()) for(int j=0; j<M; ++j) if(!used[j]) { cands.push_back(j); break; }\n            \n            int next = cands[rng()%cands.size()];\n            p.push_back(next); used[next]=true;\n            c += dist_matrix[curr][next]; \n            curr = next;\n        }\n        if(c < best_approx) { best_approx=c; current_p=p; }\n        if(iter % 20 == 0) check_candidate(p);\n    }\n    check_candidate(current_p);\n    \n    // --- Phase 2: Heuristic Simulated Annealing ---\n    vector<int> p = current_p;\n    int cur_h_cost = best_approx;\n    double T0=12.0, T1=0.1;\n    \n    int iters = 0;\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        double el = chrono::duration<double>(now - start_time).count();\n        if(el > 1.50) break;\n        double temp = T0 + (T1-T0)*(el/1.50);\n        \n        // Batch moves to check time less frequently\n        for(int b=0; b<100; ++b) {\n             int type = rng()%100;\n             if(type < 40) { // SWAP\n                 int i = rng()%M, j = rng()%M;\n                 if(i==j) continue;\n                 if(i>j) swap(i,j);\n                 int u=p[i], v=p[j];\n                 int pi=(i>0)?p[i-1]:-1, ni=p[i+1];\n                 int pj=p[j-1], nj=(j<M-1)?p[j+1]:-1;\n                 int delta = 0;\n                 if(j==i+1) {\n                     delta += (pi!=-1 ? dist_matrix[pi][v] : start_dist[v]) - (pi!=-1 ? dist_matrix[pi][u] : start_dist[u]);\n                     delta += dist_matrix[v][u] - dist_matrix[u][v];\n                     if(nj!=-1) delta += dist_matrix[u][nj] - dist_matrix[v][nj];\n                 } else {\n                     delta += (pi!=-1 ? dist_matrix[pi][v] : start_dist[v]) - (pi!=-1 ? dist_matrix[pi][u] : start_dist[u]);\n                     delta += dist_matrix[v][ni] - dist_matrix[u][ni];\n                     delta += dist_matrix[pj][u] - dist_matrix[pj][v];\n                     if(nj!=-1) delta += dist_matrix[u][nj] - dist_matrix[v][nj];\n                 }\n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     swap(p[i], p[j]); cur_h_cost += delta;\n                 }\n             } else if(type < 70) { // BLOCK INSERT\n                 int len = (rng()%3)+1;\n                 if(M<len+1) len=1;\n                 int i = rng()%(M-len+1);\n                 int k = rng()%(M-len+1); // Index in remaining array\n                 if(k==i) continue;\n                 \n                 // Calculate delta using neighbors\n                 int bs = p[i], be = p[i+len-1];\n                 int pb = (i>0)?p[i-1]:-1, nb = (i+len<M)?p[i+len]:-1;\n                 \n                 int u_idx = (k < i) ? k-1 : k+len-1;\n                 int v_idx = (k < i) ? k : k+len;\n                 int u = (u_idx>=0)?p[u_idx]:-1;\n                 int v = (v_idx<M)?p[v_idx]:-1;\n                 \n                 int delta = 0;\n                 delta -= (pb!=-1?dist_matrix[pb][bs]:start_dist[bs]);\n                 if(nb!=-1) delta -= dist_matrix[be][nb];\n                 if(pb!=-1 && nb!=-1) delta += dist_matrix[pb][nb];\n                 else if(pb==-1 && nb!=-1) delta += start_dist[nb];\n                 \n                 if(u!=-1 && v!=-1) delta -= dist_matrix[u][v];\n                 else if(u==-1 && v!=-1) delta -= start_dist[v];\n                 \n                 if(u!=-1) delta += dist_matrix[u][bs];\n                 else delta += start_dist[bs];\n                 if(v!=-1) delta += dist_matrix[be][v];\n                 \n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     vector<int> blk(p.begin()+i, p.begin()+i+len);\n                     p.erase(p.begin()+i, p.begin()+i+len);\n                     p.insert(p.begin()+k, blk.begin(), blk.end());\n                     cur_h_cost += delta;\n                 }\n             } else { // 2-OPT (Reversal)\n                 int i = rng()%M, j = rng()%M;\n                 if(i>j) swap(i,j);\n                 if(j-i+1 > 20 || j==i) continue; // Limit size for speed\n                 int pi = (i>0)?p[i-1]:-1;\n                 int nj = (j<M-1)?p[j+1]:-1;\n                 int start_val = p[i], end_val = p[j];\n                 \n                 int d_old = 0;\n                 if(pi!=-1) d_old += dist_matrix[pi][start_val]; else d_old += start_dist[start_val];\n                 if(nj!=-1) d_old += dist_matrix[end_val][nj];\n                 for(int k=i; k<j; ++k) d_old += dist_matrix[p[k]][p[k+1]];\n                 \n                 int d_new = 0;\n                 if(pi!=-1) d_new += dist_matrix[pi][end_val]; else d_new += start_dist[end_val];\n                 if(nj!=-1) d_new += dist_matrix[start_val][nj];\n                 for(int k=j; k>i; --k) d_new += dist_matrix[p[k]][p[k-1]];\n                 \n                 int delta = d_new - d_old;\n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     reverse(p.begin()+i, p.begin()+j+1);\n                     cur_h_cost += delta;\n                 }\n             }\n        }\n        iters += 100;\n        if((iters & 255) == 0) check_candidate(p);\n    }\n    check_candidate(p);\n    \n    // --- Phase 3: Exact Cost Randomized Local Search ---\n    // Start from best found solution\n    p = global_best_p;\n    int cur_exact = global_min_exact_cost;\n    \n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.97) break;\n        \n        // Try random move, accept if better or equal (to escape plateaus)\n        int type = rng()%3;\n        if(type == 0) { // Swap\n            int i = rng()%M, j = rng()%M;\n            if(i==j) continue;\n            swap(p[i], p[j]);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                swap(p[i], p[j]); // Revert\n            }\n        } else if(type == 1) { // Insert\n            int i = rng()%M;\n            int j = rng()%M;\n            if(i==j) continue;\n            int val = p[i];\n            p.erase(p.begin()+i);\n            p.insert(p.begin()+j, val);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                p.erase(p.begin()+j);\n                p.insert(p.begin()+i, val);\n            }\n        } else { // Short Reverse\n            int i = rng()%M, j = rng()%M;\n            if(i>j) swap(i,j);\n            if(i==j || j-i > 15) continue; \n            reverse(p.begin()+i, p.begin()+j+1);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                reverse(p.begin()+i, p.begin()+j+1);\n            }\n        }\n    }\n    \n    solve_final(global_best_p);\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------------------- Utils ----------------------\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool is_time_over() {\n        return elapsed() > limit;\n    }\n};\n\nmt19937 rng(12345);\n\n// ---------------------- Globals ----------------------\n\nint N, M;\ndouble EPS;\nint op_count = 0;\nint max_ops;\n\nstruct Point { int r, c; };\n\nstruct Polyomino {\n    vector<Point> shape;\n};\nvector<Polyomino> fields;\n\nstruct Operation {\n    int type; // 0: drill, 1: divine\n    int r, c; // for drill\n    vector<Point> set_points; // for divine\n    int result_drill;\n    int result_divine;\n    \n    double divine_mean_base; \n    double divine_mean_coeff; \n    double divine_var_inv; \n};\nvector<Operation> history;\nvector<vector<vector<int>>> cell_to_ops;\n\nstruct ValidPos {\n    int r, c; // top-left\n    vector<Point> cells;\n};\nvector<vector<ValidPos>> possible_positions; // [field_id][pos_id]\nvector<vector<int>> active_indices; // [field_id] -> list of valid pos_ids\n\nvector<vector<int>> grid_known; // -1: unknown, >=0: exact value\n\n// ---------------------- Functions ----------------------\n\nvoid precompute_positions() {\n    possible_positions.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = 0, max_c = 0;\n        for (auto& p : fields[k].shape) {\n            max_r = max(max_r, p.r);\n            max_c = max(max_c, p.c);\n        }\n        for (int r = 0; r < N - max_r; ++r) {\n            for (int c = 0; c < N - max_c; ++c) {\n                ValidPos vp;\n                vp.r = r;\n                vp.c = c;\n                for (auto& p : fields[k].shape) {\n                    vp.cells.push_back({p.r + r, p.c + c});\n                }\n                possible_positions[k].push_back(vp);\n            }\n        }\n    }\n}\n\nvoid add_history(Operation op) {\n    int idx = history.size();\n    if (op.type == 1) {\n        int k_sz = op.set_points.size();\n        double var = k_sz * EPS * (1.0 - EPS);\n        op.divine_mean_base = k_sz * EPS;\n        op.divine_mean_coeff = 1.0 - 2.0 * EPS;\n        op.divine_var_inv = 0.5 / max(1e-9, var);\n    } \n    \n    history.push_back(op);\n    \n    if (op.type == 0) {\n        cell_to_ops[op.r][op.c].push_back(idx);\n        grid_known[op.r][op.c] = op.result_drill;\n    } else {\n        for (auto& p : op.set_points) {\n            cell_to_ops[p.r][p.c].push_back(idx);\n        }\n    }\n}\n\nvoid prune_positions() {\n    active_indices.assign(M, {});\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < (int)possible_positions[k].size(); ++i) {\n            bool ok = true;\n            const auto& cells = possible_positions[k][i].cells;\n            for (const auto& p : cells) {\n                if (grid_known[p.r][p.c] == 0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                active_indices[k].push_back(i);\n            }\n        }\n    }\n}\n\nstruct State {\n    vector<int> config; \n    vector<vector<int>> counts;\n    vector<int> op_preds; \n    double energy;\n};\n\ninline double get_op_energy(int op_idx, int pred_val) {\n    const auto& op = history[op_idx];\n    if (op.type == 0) { \n        return 100000.0 * abs(pred_val - op.result_drill);\n    } else { \n        double mean = op.divine_mean_base + pred_val * op.divine_mean_coeff;\n        double diff = op.result_divine - mean;\n        double sq = diff * diff * op.divine_var_inv;\n        // Robust loss to handle noisy Divine data\n        return min(sq, 15.0);\n    }\n}\n\nvector<vector<int>> run_sa(int num_solutions, double duration) {\n    vector<vector<int>> solutions;\n    Timer t(duration);\n    \n    for (int k = 0; k < M; ++k) {\n        if (active_indices[k].empty()) return {}; \n    }\n\n    while (solutions.size() < (size_t)num_solutions && !t.is_time_over()) {\n        State S;\n        S.config.resize(M);\n        S.counts.assign(N, vector<int>(N, 0));\n        S.op_preds.assign(history.size(), 0);\n        S.energy = 0;\n\n        for (int k = 0; k < M; ++k) {\n            int idx = active_indices[k][rng() % active_indices[k].size()];\n            S.config[k] = idx;\n            for (const auto& p : possible_positions[k][idx].cells) {\n                S.counts[p.r][p.c]++;\n                for (int op_idx : cell_to_ops[p.r][p.c]) {\n                    S.op_preds[op_idx]++;\n                }\n            }\n        }\n\n        for (int i = 0; i < (int)history.size(); ++i) {\n            S.energy += get_op_energy(i, S.op_preds[i]);\n        }\n        \n        State best_S = S;\n\n        double Temp = 5.0;\n        double decay = 0.92;\n        int iter = 0;\n        int max_iter = 1500;\n        \n        static vector<int> changed_ops;\n        changed_ops.reserve(history.size());\n\n        while (iter < max_iter) { \n            iter++;\n            int k = rng() % M;\n            if (active_indices[k].size() <= 1) continue;\n\n            int old_idx = S.config[k];\n            int new_idx = active_indices[k][rng() % active_indices[k].size()];\n            if (old_idx == new_idx) continue;\n\n            const auto& old_cells = possible_positions[k][old_idx].cells;\n            const auto& new_cells = possible_positions[k][new_idx].cells;\n\n            changed_ops.clear();\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            sort(changed_ops.begin(), changed_ops.end());\n            changed_ops.erase(unique(changed_ops.begin(), changed_ops.end()), changed_ops.end());\n\n            double delta = 0;\n            for (int op_idx : changed_ops) delta -= get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n            }\n\n            for (int op_idx : changed_ops) delta += get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            if (delta < 0 || exp(-delta / Temp) > (double)rng() / 4294967296.0) {\n                S.energy += delta;\n                S.config[k] = new_idx;\n                for (const auto& p : old_cells) S.counts[p.r][p.c]--;\n                for (const auto& p : new_cells) S.counts[p.r][p.c]++;\n                if(S.energy < best_S.energy) best_S = S;\n            } else {\n                for (const auto& p : new_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n                }\n                for (const auto& p : old_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n                }\n            }\n            Temp *= decay;\n            if (Temp < 0.05) break;\n        }\n        solutions.push_back(best_S.config);\n    }\n    return solutions;\n}\n\nint main() {\n    cin.tie(nullptr);\n    ios_base::sync_with_stdio(false);\n\n    if (!(cin >> N >> M >> EPS)) return 0;\n    max_ops = 2 * N * N;\n\n    fields.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int d; cin >> d;\n        fields[i].shape.resize(d);\n        for (int j = 0; j < d; ++j) {\n            cin >> fields[i].shape[j].r >> fields[i].shape[j].c;\n        }\n    }\n\n    precompute_positions();\n    grid_known.assign(N, vector<int>(N, -1));\n    cell_to_ops.assign(N, vector<vector<int>>(N));\n\n    // Initial Scan\n    int block_size = max(2, N / 5);\n    \n    for(int r=0; r<N; r+=block_size) {\n        for(int c=0; c<N; c+=block_size) {\n            if(op_count >= max_ops) break;\n            \n            vector<Point> pts;\n            for(int rr=r; rr<min(N, r+block_size); ++rr) {\n                for(int cc=c; cc<min(N, c+block_size); ++cc) {\n                    pts.push_back({rr, cc});\n                }\n            }\n            if(pts.size() >= 2) {\n                cout << \"q \" << pts.size();\n                for(auto& p : pts) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                op_count++;\n                int res; \n                if(!(cin >> res)) return 0;\n                add_history({1, 0, 0, pts, 0, res});\n            }\n        }\n    }\n\n    Timer global_timer(2.85);\n\n    while (!global_timer.is_time_over() && op_count < max_ops) {\n        prune_positions();\n\n        vector<vector<int>> solutions = run_sa(40, 0.05);\n\n        vector<vector<int>> pos_counts(N, vector<int>(N, 0));\n        int sol_cnt = solutions.size();\n        \n        if (sol_cnt > 0) {\n            for(const auto& cfg : solutions) {\n                for(int k=0; k<M; ++k) {\n                    int idx = cfg[k];\n                    for(auto& p : possible_positions[k][idx].cells) {\n                        pos_counts[p.r][p.c]++;\n                    }\n                }\n            }\n        }\n\n        vector<Point> answer_candidates;\n        bool confident = true;\n        if (sol_cnt == 0) confident = false;\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                bool cell_oil = false;\n                if (grid_known[r][c] != -1) {\n                    if (grid_known[r][c] > 0) cell_oil = true;\n                } else {\n                    if (sol_cnt > 0) {\n                        if (pos_counts[r][c] == sol_cnt) cell_oil = true;\n                        else if (pos_counts[r][c] == 0) cell_oil = false;\n                        else confident = false;\n                    } else {\n                        confident = false;\n                    }\n                }\n                if (cell_oil) answer_candidates.push_back({r, c});\n            }\n        }\n        \n        if (confident) {\n            bool consistent = true;\n            for (auto& p : answer_candidates) {\n                if (grid_known[p.r][p.c] == 0) consistent = false;\n            }\n            if (consistent) {\n                for(int r=0; r<N; ++r) {\n                    for(int c=0; c<N; ++c) {\n                        if (grid_known[r][c] > 0) {\n                            bool in_ans = false;\n                            for(auto& p : answer_candidates) if(p.r==r && p.c==c) in_ans=true;\n                            if(!in_ans) consistent = false;\n                        }\n                    }\n                }\n            }\n\n            if (consistent) {\n                cout << \"a \" << answer_candidates.size();\n                for(auto& p : answer_candidates) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                op_count++;\n                int res; \n                if(!(cin >> res)) return 0;\n                if (res == 1) return 0;\n            }\n        }\n        \n        if (op_count >= max_ops) break;\n\n        int best_r = -1, best_c = -1;\n        \n        if (sol_cnt > 0) {\n            int max_ent = -1;\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    if (grid_known[r][c] != -1) continue;\n                    int yes = pos_counts[r][c];\n                    int no = sol_cnt - yes;\n                    int score = min(yes, no);\n                    if (score > max_ent) {\n                        max_ent = score;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n            if (max_ent == 0) best_r = -1;\n        }\n        \n        if (best_r == -1) {\n             vector<Point> unknowns;\n             for(int r=0; r<N; ++r)\n                 for(int c=0; c<N; ++c)\n                     if(grid_known[r][c] == -1) unknowns.push_back({r, c});\n             \n             if (unknowns.empty()) break; \n             \n             vector<Point> adj_candidates;\n             for(auto& u : unknowns) {\n                 bool adj = false;\n                 int dr[] = {0,0,1,-1};\n                 int dc[] = {1,-1,0,0};\n                 for(int i=0; i<4; ++i) {\n                     int nr=u.r+dr[i], nc=u.c+dc[i];\n                     if(nr>=0 && nr<N && nc>=0 && nc<N && grid_known[nr][nc]>0) adj=true;\n                 }\n                 if(adj) adj_candidates.push_back(u);\n             }\n             \n             if (!adj_candidates.empty()) {\n                 int idx = rng() % adj_candidates.size();\n                 best_r = adj_candidates[idx].r;\n                 best_c = adj_candidates[idx].c;\n             } else {\n                 vector<Point> checker;\n                 for(auto& u : unknowns) if((u.r+u.c)%2==0) checker.push_back(u);\n                 if (!checker.empty()) {\n                     int idx = rng() % checker.size();\n                     best_r = checker[idx].r;\n                     best_c = checker[idx].c;\n                 } else {\n                     int idx = rng() % unknowns.size();\n                     best_r = unknowns[idx].r;\n                     best_c = unknowns[idx].c;\n                 }\n             }\n        }\n        \n        cout << \"q 1 \" << best_r << \" \" << best_c << endl;\n        op_count++;\n        int val; \n        if(!(cin >> val)) return 0;\n        add_history({0, best_r, best_c, {}, val, 0});\n    }\n    \n    vector<Point> final_ans;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            if(grid_known[r][c] > 0) final_ans.push_back({r, c});\n        }\n    }\n    if(final_ans.empty()) {\n        for(int r=0;r<N;++r)for(int c=0;c<N;++c) final_ans.push_back({r, c});\n    }\n    cout << \"a \" << final_ans.size();\n    for(auto& p : final_ans) cout << \" \" << p.r << \" \" << p.c;\n    cout << endl;\n    int res; cin >> res;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global Inputs\nint W_GRID;\nint D, N;\nvector<vector<int>> A;\n\nconst int SHORTAGE_PENALTY = 100;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct SolutionState {\n    vector<int> partition_cuts;\n    vector<int> widths;\n    long long score;\n    vector<vector<int>> groups;\n};\n\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\nclass Solver {\npublic:\n    // Buffers\n    vector<int> needs;\n    vector<int> R;\n    vector<int> curr_cuts;\n    vector<int> prev_cuts;\n    vector<int> next_day_needs; // For lookahead\n\n    Solver() {\n        needs.resize(60); \n        R.resize(60); \n        curr_cuts.resize(60); \n        prev_cuts.resize(60);\n        next_day_needs.resize(60);\n    }\n\n    // Solves for a column configuration\n    long long solve_column_cost(const vector<int>& items, int width, vector<vector<int>>* out_cuts = nullptr) {\n        if (items.empty()) return 0;\n        if (width <= 0) return 1e17; \n\n        int m = items.size();\n        long long total_cost = 0;\n        \n        fill(prev_cuts.begin(), prev_cuts.begin() + m, 0);\n        if (out_cuts) out_cuts->assign(D, vector<int>(m));\n\n        for (int d = 0; d < D; ++d) {\n            // 1. Calculate needs for today\n            for(int i=0; i<m; ++i) {\n                needs[i] = (A[d][items[i]] + width - 1) / width;\n            }\n            \n            // Calculate R (future needs lower bound)\n            R[m-1] = 0;\n            for(int i=m-2; i>=0; --i) {\n                R[i] = R[i+1] + needs[i+1];\n            }\n\n            // Lookahead for Day 0: peek at Day 1's needs to prep stability\n            if (d == 0 && D > 1) {\n                for(int i=0; i<m; ++i) {\n                    next_day_needs[i] = (A[1][items[i]] + width - 1) / width;\n                }\n            }\n\n            int current_y = 0;\n            int lookahead_y = 0;\n\n            for(int i=0; i<m-1; ++i) {\n                // Hard Constraints for validity (height >= 1 for all remaining items)\n                int min_cut = current_y + 1;\n                int max_cut = W_GRID - (m - 1 - i);\n                \n                // Soft Constraints (Shortage Avoidance)\n                int ideal_cut = current_y + needs[i]; \n                int future_limit = W_GRID - R[i];\n                \n                // Safe window where shortage is minimized for current and future\n                int safe_min = max(min_cut, ideal_cut);\n                int safe_max = min(max_cut, future_limit);\n                \n                int chosen = safe_min; // Default: prioritize satisfying current need\n\n                if (safe_min <= safe_max) {\n                    // We have slack. \n                    if (d > 0) {\n                        // Try to match yesterday\n                        int p = prev_cuts[i];\n                        if (p >= safe_min && p <= safe_max) chosen = p;\n                        else if (p < safe_min) chosen = safe_min;\n                        else chosen = safe_max;\n                    } else if (d == 0 && D > 1) {\n                        // On Day 0, try to match Day 1's ideal structure\n                        // Ideal position for Day 1 would be lookahead_y + next_day_needs[i]\n                        int target = lookahead_y + next_day_needs[i];\n                        lookahead_y = target; // Update for next item\n                        \n                        if (target >= safe_min && target <= safe_max) chosen = target;\n                        else if (target < safe_min) chosen = safe_min;\n                        else chosen = safe_max;\n                    }\n                } else {\n                    // Oversubscribed. Clamp to valid range.\n                    // safe_min > safe_max implies ideal_cut > future_limit usually.\n                    // We prioritize current item -> ideal_cut, but clamped to max_cut.\n                    chosen = max(min_cut, min(ideal_cut, max_cut));\n                }\n\n                curr_cuts[i] = chosen;\n                current_y = chosen;\n            }\n            curr_cuts[m-1] = W_GRID; \n            \n            // Calculate Cost\n            long long d_cost = 0;\n            int prev_y = 0;\n            for(int i=0; i<m; ++i) {\n                int h = curr_cuts[i] - prev_y;\n                long long area = (long long)h * width;\n                long long req = A[d][items[i]];\n                if (area < req) d_cost += (req - area) * SHORTAGE_PENALTY;\n                prev_y = curr_cuts[i];\n            }\n            \n            if (d > 0) {\n                for(int i=0; i<m-1; ++i) {\n                    if (curr_cuts[i] != prev_cuts[i]) d_cost += (width << 1);\n                }\n            }\n            \n            total_cost += d_cost;\n            if (out_cuts) (*out_cuts)[d] = vector<int>(curr_cuts.begin(), curr_cuts.begin() + m);\n            \n            for(int i=0; i<m; ++i) prev_cuts[i] = curr_cuts[i];\n        }\n        return total_cost;\n    }\n} solver;\n\n// Optimize widths for a given partition\n// Uses iterative transfer (Greedy Descent)\nvoid optimize_widths(const vector<vector<int>>& groups, vector<int>& widths, long long& current_total_score) {\n    int K = groups.size();\n    vector<long long> col_scores(K);\n    \n    current_total_score = 0;\n    for(int c=0; c<K; ++c) {\n        col_scores[c] = solver.solve_column_cost(groups[c], widths[c]);\n        current_total_score += col_scores[c];\n    }\n\n    // To speed up, we only compute deltas for potential moves.\n    // Cache deltas.\n    vector<long long> delta_minus(K);\n    vector<long long> delta_plus(K);\n\n    auto update_deltas = [&](int c) {\n        delta_minus[c] = 1e18;\n        delta_plus[c] = 1e18;\n        if (widths[c] > 1) {\n            delta_minus[c] = solver.solve_column_cost(groups[c], widths[c] - 1) - col_scores[c];\n        }\n        // Ensure minimal width for others (at least 1)\n        if (widths[c] < W_GRID - (K-1)) {\n            delta_plus[c] = solver.solve_column_cost(groups[c], widths[c] + 1) - col_scores[c];\n        }\n    };\n\n    for(int c=0; c<K; ++c) update_deltas(c);\n\n    int iter = 0;\n    while(iter < 50) { \n        iter++;\n        long long best_gain = 0;\n        int best_src = -1;\n        int best_dst = -1;\n        \n        // We want to minimize: score_new - score_old < 0\n        // Change = delta_minus[src] + delta_plus[dst]\n        \n        for(int src=0; src<K; ++src) {\n            if (widths[src] <= 1) continue;\n            // Optimization: if delta_minus is already huge positive, skip\n            if (delta_minus[src] > 0) {\n                // Only skip if we can't possibly find a dst with large enough negative delta_plus\n            }\n            \n            for(int dst=0; dst<K; ++dst) {\n                if (src == dst) continue;\n                long long change = delta_minus[src] + delta_plus[dst];\n                if (change < -best_gain) {\n                    best_gain = -change;\n                    best_src = src;\n                    best_dst = dst;\n                }\n            }\n        }\n        \n        if (best_src != -1) {\n            widths[best_src]--;\n            widths[best_dst]++;\n            current_total_score -= best_gain;\n            \n            col_scores[best_src] = solver.solve_column_cost(groups[best_src], widths[best_src]);\n            col_scores[best_dst] = solver.solve_column_cost(groups[best_dst], widths[best_dst]);\n            update_deltas(best_src);\n            update_deltas(best_dst);\n        } else {\n            break;\n        }\n    }\n}\n\n// Full Evaluation function\nSolutionState evaluate_full(const vector<int>& cuts, int K) {\n    vector<vector<int>> groups(K);\n    for(int c=0; c<K; ++c) {\n        groups[c].reserve(cuts[c+1]-cuts[c]);\n        for(int i=cuts[c]; i<cuts[c+1]; ++i) groups[c].push_back(i);\n    }\n\n    // Initial Width Allocation\n    vector<long long> max_demands(K, 0);\n    long long total_demand = 0;\n    for(int c=0; c<K; ++c) {\n        for(int d=0; d<D; ++d) {\n            long long s = 0;\n            for(int idx : groups[c]) s += A[d][idx];\n            if (s > max_demands[c]) max_demands[c] = s;\n        }\n        total_demand += max_demands[c];\n    }\n    \n    vector<int> widths(K, 1);\n    if (total_demand > 0) {\n        int remaining_w = W_GRID - K;\n        if (remaining_w > 0) {\n            vector<pair<long long, int>> remainders(K);\n            long long distributed = 0;\n            for(int c=0; c<K; ++c) {\n                long long share = (long long)remaining_w * max_demands[c];\n                long long base = share / total_demand;\n                widths[c] += (int)base;\n                distributed += base;\n                remainders[c] = { share % total_demand, c };\n            }\n            int leftover = remaining_w - distributed;\n            sort(remainders.rbegin(), remainders.rend());\n            for(int i=0; i<leftover; ++i) widths[remainders[i].second]++;\n        }\n    } else {\n        widths[0] += (W_GRID - K);\n    }\n    \n    long long sum_w = 0;\n    for(int w : widths) sum_w += w;\n    while(sum_w > W_GRID) {\n        for(int c=0; c<K; ++c) if(widths[c]>1) { widths[c]--; sum_w--; if(sum_w==W_GRID) break; }\n    }\n    while(sum_w < W_GRID) {\n        widths[0]++; sum_w++;\n    }\n\n    long long score = 0;\n    optimize_widths(groups, widths, score);\n    \n    return {cuts, widths, score, groups};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> W_GRID >> D >> N)) return 0;\n    A.resize(D, vector<int>(N));\n    for(int d=0; d<D; ++d) for(int k=0; k<N; ++k) cin >> A[d][k];\n\n    long long start_time = get_time_ms();\n    mt19937 rng(42);\n\n    SolutionState best_sol;\n    best_sol.score = -1;\n\n    // K search range\n    int max_k = min(N, 14); \n    \n    for(int K=1; K<=max_k; ++K) {\n        if (get_time_ms() - start_time > 2850) break;\n\n        // Initial Uniform Partition\n        vector<int> cuts(K+1);\n        cuts[0] = 0; cuts[K] = N;\n        for(int i=1; i<K; ++i) cuts[i] = (N * i) / K;\n\n        SolutionState current = evaluate_full(cuts, K);\n        if (best_sol.score == -1 || current.score < best_sol.score) best_sol = current;\n        \n        if (K == 1) continue;\n\n        // Simulated Annealing\n        // Parameters\n        double T0 = 1e6; // Initial temp (arbitrary high cost diff)\n        double T1 = 1e1; // End temp\n        \n        // Estimate iterations based on time\n        int iter = 0;\n        \n        double temp = T0;\n        \n        while(iter < 300) {\n            if (iter % 10 == 0) {\n                if (get_time_ms() - start_time > 2900) break;\n            }\n            iter++;\n            \n            // Generate neighbor: Move a random cut\n            int idx = uniform_int_distribution<int>(1, K-1)(rng);\n            // Move range: small usually better, but sometimes large jumps\n            int shift = 0;\n            if (uniform_real_distribution<double>(0,1)(rng) < 0.8) {\n                shift = uniform_int_distribution<int>(0,1)(rng) ? 1 : -1;\n            } else {\n                shift = uniform_int_distribution<int>(-3, 3)(rng);\n            }\n            \n            if (shift == 0) shift = 1;\n\n            vector<int> next_cuts = current.partition_cuts;\n            next_cuts[idx] += shift;\n            \n            // Validity check\n            if (next_cuts[idx] <= next_cuts[idx-1] || next_cuts[idx] >= next_cuts[idx+1]) continue;\n            \n            SolutionState next_sol = evaluate_full(next_cuts, K);\n            \n            long long diff = next_sol.score - current.score;\n            \n            // Acceptance criteria\n            bool accept = false;\n            if (diff < 0) accept = true;\n            else {\n                if (uniform_real_distribution<double>(0,1)(rng) < exp(-diff / temp)) {\n                    accept = true;\n                }\n            }\n            \n            if (accept) {\n                current = next_sol;\n                if (current.score < best_sol.score) best_sol = current;\n            }\n            \n            // Cool down\n            temp *= 0.95;\n            if (temp < T1) temp = T1;\n        }\n    }\n\n    // Output\n    vector<vector<Rect>> final_rects(D, vector<Rect>(N));\n    int current_x = 0;\n    for(size_t c=0; c<best_sol.groups.size(); ++c) {\n        int w = best_sol.widths[c];\n        vector<vector<int>> cuts;\n        solver.solve_column_cost(best_sol.groups[c], w, &cuts);\n        \n        for(int d=0; d<D; ++d) {\n            int prev_y = 0;\n            for(size_t i=0; i<best_sol.groups[c].size(); ++i) {\n                int idx = best_sol.groups[c][i];\n                int y = cuts[d][i];\n                \n                // Safety Clamp\n                int x0 = min(W_GRID, max(0, current_x));\n                int x1 = min(W_GRID, max(0, current_x + w));\n                int y0 = min(W_GRID, max(0, prev_y));\n                int y1 = min(W_GRID, max(0, y));\n\n                final_rects[d][idx] = {y0, x0, y1, x1};\n                prev_y = y;\n            }\n        }\n        current_x += w;\n    }\n    \n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            cout << final_rects[d][k].r0 << \" \" << final_rects[d][k].c0 << \" \" \n                 << final_rects[d][k].r1 << \" \" << final_rects[d][k].c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#pragma GCC optimize(\"Ofast\")\n#pragma GCC optimize(\"unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\n\nusing namespace std;\n\n// Problem Constants\nconstexpr int N = 9;\nconstexpr int TOTAL_CELLS = 81;\nconstexpr int MOD = 998244353;\n\n// Fast Xorshift Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    \n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    \n    inline int next_int(int n) {\n        return (uint64_t)next() * n >> 32;\n    }\n    \n    inline double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Compact move representation\nstruct FastMove {\n    int m, p, q;\n    int indices[9]; // Flattened 1D indices affected by this stamp\n    int values[9];  // Values added by this stamp\n};\n\n// Buffer for tracking changes during delta calculation\nstruct Change {\n    int idx;\n    int old_val;\n    int new_val;\n};\n\n// Global Data\nint N_in, M_in, K_in;\nint initial_board[TOTAL_CELLS];\nint board[TOTAL_CELLS];\nint stamps[20][9];\n\nFastMove possible_moves[1000]; // Stores all valid (stamp, p, q) combinations\nint num_possible_moves = 0;\n\n// State\nint current_ops[81];\nlong long current_score;\nint best_ops[81];\nlong long best_score = -1;\n\n// Lookup table for O(1) overlap detection in delta calculation\nint pos_in_buffer[TOTAL_CELLS]; \n\n// Precompute all valid stamp placements\nvoid init_moves() {\n    num_possible_moves = 0;\n    for (int m = 0; m < M_in; ++m) {\n        for (int p = 0; p <= N - 3; ++p) {\n            for (int q = 0; q <= N - 3; ++q) {\n                FastMove& fm = possible_moves[num_possible_moves];\n                fm.m = m; fm.p = p; fm.q = q;\n                int idx = 0;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        fm.indices[idx] = (p + i) * N + (q + j);\n                        fm.values[idx] = stamps[m][i * 3 + j];\n                        idx++;\n                    }\n                }\n                num_possible_moves++;\n            }\n        }\n    }\n}\n\n// Helper: Permanently apply or remove a move from the board\nvoid apply_permanent(int move_idx, bool adding) {\n    if (move_idx == -1) return;\n    const auto& mv = possible_moves[move_idx];\n    for (int i = 0; i < 9; ++i) {\n        int idx = mv.indices[i];\n        int val = board[idx];\n        current_score -= val;\n        if (adding) {\n            val += mv.values[i];\n            if (val >= MOD) val -= MOD;\n        } else {\n            val -= mv.values[i];\n            if (val < 0) val += MOD;\n        }\n        board[idx] = val;\n        current_score += val;\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N_in >> M_in >> K_in)) return 0;\n\n    for (int i = 0; i < TOTAL_CELLS; ++i) cin >> initial_board[i];\n    for (int m = 0; m < M_in; ++m) {\n        for (int i = 0; i < 9; ++i) cin >> stamps[m][i];\n    }\n\n    init_moves();\n\n    // Initialize State\n    for (int i = 0; i < TOTAL_CELLS; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < TOTAL_CELLS; ++i) current_score += board[i];\n    for (int i = 0; i < K_in; ++i) current_ops[i] = -1;\n    \n    memset(pos_in_buffer, -1, sizeof(pos_in_buffer));\n\n    // 1. Greedy Initialization\n    // Sequentially pick the best move for each slot\n    for (int k = 0; k < K_in; ++k) {\n        int best_mv = -1;\n        long long best_delta = 0;\n        for (int mv = 0; mv < num_possible_moves; ++mv) {\n            long long d = 0;\n            const auto& m = possible_moves[mv];\n            for (int i = 0; i < 9; ++i) {\n                int idx = m.indices[i];\n                int v = board[idx] + m.values[i];\n                if (v >= MOD) v -= MOD;\n                d += (v - board[idx]);\n            }\n            if (d > best_delta) {\n                best_delta = d;\n                best_mv = mv;\n            }\n        }\n        if (best_mv != -1) {\n            current_ops[k] = best_mv;\n            apply_permanent(best_mv, true);\n        }\n    }\n\n    // 2. Hill Climbing Refinement\n    // Refine the greedy solution by revisiting each slot\n    for (int pass = 0; pass < 2; ++pass) {\n        bool improved = false;\n        for (int k = 0; k < K_in; ++k) {\n            int old_mv = current_ops[k];\n            apply_permanent(old_mv, false); // Remove current\n            \n            long long current_base = current_score; \n            int best_mv = -1; \n            long long max_val = current_base; \n\n            for(int mv = 0; mv < num_possible_moves; ++mv) {\n                 long long d = 0;\n                 const auto& m = possible_moves[mv];\n                 for(int i=0; i<9; ++i) {\n                     int idx = m.indices[i];\n                     int v = board[idx] + m.values[i];\n                     if (v >= MOD) v -= MOD;\n                     d += (v - board[idx]);\n                 }\n                 if (current_base + d > max_val) {\n                     max_val = current_base + d;\n                     best_mv = mv;\n                 }\n            }\n            \n            if (best_mv != -1) {\n                 current_ops[k] = best_mv;\n                 apply_permanent(best_mv, true);\n                 if (best_mv != old_mv) improved = true;\n            } else {\n                 current_ops[k] = -1;\n                 if (old_mv != -1) improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    best_score = current_score;\n    for (int i = 0; i < K_in; ++i) best_ops[i] = current_ops[i];\n\n    // 3. Simulated Annealing\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    \n    // Tuned parameters for modulo landscape\n    double t0 = 2e9; \n    double t1 = 2e-1;\n    double current_temp = t0;\n    long long iter = 0;\n    \n    Change changes[18]; // Buffer for delta calculation (max 9 remove + 9 add)\n\n    while (true) {\n        // Time check every 1024 iters\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n            current_temp = t0 * pow(t1 / t0, elapsed / time_limit);\n        }\n        iter++;\n\n        int slot = rng.next_int(K_in);\n        int old_mv = current_ops[slot];\n        \n        int new_mv = -1;\n        int type = rng.next_int(100); \n        \n        // Move Generation Logic\n        if (type < 50 || old_mv == -1) {\n            // Standard: Random Replacement\n            int r = rng.next_int(num_possible_moves + 1);\n            new_mv = (r == num_possible_moves) ? -1 : r;\n        } else {\n            const auto& om = possible_moves[old_mv];\n            if (type < 75) {\n                // Shift Position: Move (p,q) by 1 step\n                int dir = rng.next_int(4);\n                int np = om.p, nq = om.q;\n                if (dir == 0) np++;\n                else if (dir == 1) np--;\n                else if (dir == 2) nq++;\n                else nq--;\n                \n                if (np >= 0 && np <= 6 && nq >= 0 && nq <= 6) {\n                    // Valid shift: calculate linear index\n                    new_mv = om.m * 49 + np * 7 + nq;\n                } else {\n                    // Out of bounds -> Remove stamp\n                    new_mv = -1; \n                }\n            } else {\n                // Swap Stamp: Keep (p,q), change stamp ID\n                int nm = rng.next_int(M_in);\n                if (nm == om.m) {\n                     // Fallback to random move\n                     int r = rng.next_int(num_possible_moves);\n                     new_mv = r;\n                } else {\n                     new_mv = nm * 49 + om.p * 7 + om.q;\n                }\n            }\n        }\n        \n        if (old_mv == new_mv) continue;\n\n        // Delta Calculation using Changes Buffer\n        int change_cnt = 0;\n\n        // 1. Simulate removal of old move\n        if (old_mv != -1) {\n            const auto& m = possible_moves[old_mv];\n            for (int i = 0; i < 9; ++i) {\n                int idx = m.indices[i];\n                int v = board[idx];\n                int nv = v - m.values[i];\n                if (nv < 0) nv += MOD;\n                \n                changes[change_cnt] = {idx, v, nv};\n                pos_in_buffer[idx] = change_cnt;\n                change_cnt++;\n            }\n        }\n\n        // 2. Simulate addition of new move\n        if (new_mv != -1) {\n            const auto& m = possible_moves[new_mv];\n            for (int i = 0; i < 9; ++i) {\n                int idx = m.indices[i];\n                int val_add = m.values[i];\n                \n                int pos = pos_in_buffer[idx];\n                if (pos != -1) {\n                    // Cell already modified by removal (overlap)\n                    int nv = changes[pos].new_val + val_add;\n                    if (nv >= MOD) nv -= MOD;\n                    changes[pos].new_val = nv;\n                } else {\n                    // New cell modification\n                    int v = board[idx];\n                    int nv = v + val_add;\n                    if (nv >= MOD) nv -= MOD;\n                    changes[change_cnt] = {idx, v, nv};\n                    pos_in_buffer[idx] = change_cnt;\n                    change_cnt++;\n                }\n            }\n        }\n\n        // 3. Compute Score Delta\n        long long delta = 0;\n        for (int i = 0; i < change_cnt; ++i) {\n            delta += (changes[i].new_val - changes[i].old_val);\n        }\n\n        // 4. Acceptance Criteria\n        bool accept = (delta >= 0);\n        if (!accept) {\n             if (delta > -current_temp * 12.0) { \n                 if (rng.next_double() < exp(delta / current_temp)) accept = true;\n             }\n        }\n\n        if (accept) {\n            current_score += delta;\n            current_ops[slot] = new_mv;\n            \n            // Commit changes to board\n            for (int i = 0; i < change_cnt; ++i) {\n                board[changes[i].idx] = changes[i].new_val;\n                pos_in_buffer[changes[i].idx] = -1; // Cleanup lookup\n            }\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int k = 0; k < K_in; ++k) best_ops[k] = current_ops[k];\n            }\n        } else {\n            // Reject: Just cleanup lookup table\n            for (int i = 0; i < change_cnt; ++i) {\n                pos_in_buffer[changes[i].idx] = -1;\n            }\n        }\n    }\n\n    // Output Results\n    vector<FastMove> res;\n    res.reserve(K_in);\n    for (int i = 0; i < K_in; ++i) {\n        if (best_ops[i] != -1) res.push_back(possible_moves[best_ops[i]]);\n    }\n    cout << res.size() << \"\\n\";\n    for (const auto& m : res) cout << m.m << \" \" << m.p << \" \" << m.q << \"\\n\";\n\n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <deque>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Congestion Control\n// We allow a small number of items to be buffered to help with ordering.\n// However, if the grid exceeds this limit, we force eviction to prevent deadlock.\n// N=5 grid has 25 cells. 5 Dispatch (Right), 5 Receive (Left).\n// Safe buffer limit is kept low to ensure free movement.\nconst int STRICT_BUFFER_LIMIT = 2; \n\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Coord& other) const { return !(*this == other); }\n};\n\nstruct Crane {\n    Coord pos;\n    bool holding;\n    int container_id;\n};\n\nstruct State {\n    int grid[N][N];\n    deque<int> queues[N];\n    Crane crane;\n    vector<int> next_needed_val; \n    vector<bool> dispatched;\n    int items_on_grid;\n    vector<string> history;\n\n    State() {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = -1;\n        items_on_grid = 0;\n        history.resize(N);\n        next_needed_val.resize(N);\n        // Each row i expects 5*i, 5*i+1, ..., 5*i+4\n        for(int i=0; i<N; ++i) next_needed_val[i] = i * N;\n        dispatched.assign(N*N, false);\n        crane = {{0,0}, false, -1};\n    }\n};\n\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\n// Helper to update the \"next needed\" counter for a row.\n// Skips over items that have already been dispatched (evicted out of order).\nvoid update_next_needed(State& st, int row) {\n    while (st.next_needed_val[row] < (row + 1) * N) {\n        if (st.dispatched[st.next_needed_val[row]]) {\n            st.next_needed_val[row]++;\n        } else {\n            break;\n        }\n    }\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in;\n    if (!(cin >> n_in)) return 0;\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    State st;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) st.queues[i].push_back(A[i][j]);\n    }\n\n    for (int turn = 1; turn <= MAX_TURNS; ++turn) {\n        // --- Check Completion ---\n        bool all_done = true;\n        for(int i=0; i<N; ++i) {\n            update_next_needed(st, i);\n            if(st.next_needed_val[i] < (i+1)*N) all_done = false;\n        }\n        // Only stop if all items are dispatched and nothing is left on grid/crane\n        if (all_done && st.items_on_grid == 0 && !st.crane.holding) break;\n\n        // --- STEP 1: REFILL ---\n        for(int i=0; i<N; ++i) {\n            if (!st.queues[i].empty()) {\n                bool cell_free = (st.grid[i][0] == -1);\n                // Refill is blocked if crane is holding a container at the gate\n                bool crane_blocking = (st.crane.pos.r == i && st.crane.pos.c == 0 && st.crane.holding);\n                if (cell_free && !crane_blocking) {\n                    st.grid[i][0] = st.queues[i].front();\n                    st.queues[i].pop_front();\n                    st.items_on_grid++;\n                }\n            }\n        }\n\n        // --- STEP 2: CRANE ACTIONS ---\n        // Small Cranes (1-4) perform 'B' (Bomb) on Turn 1 to remove themselves.\n        for(int i=1; i<N; ++i) st.history[i] += (turn == 1 ? 'B' : '.');\n\n        char act = '.';\n        \n        // Safety: Large Crane (0) waits on Turn 1 to avoid collision with Small Cranes.\n        if (turn == 1) {\n            act = '.';\n        } else {\n            Crane& c = st.crane;\n            if (c.holding) {\n                int held = c.container_id;\n                int r_owner = held / N;\n                bool is_strict_next = (held == st.next_needed_val[r_owner]);\n                \n                Coord gate_dest = {r_owner, N-1};\n                \n                bool should_store = false;\n                \n                // LOGIC: \n                // 1. Always deliver strictly needed items immediately.\n                // 2. If not strict next:\n                //    - Check if it's needed \"very soon\" (next in line).\n                //    - If so, AND grid is empty (<= STRICT_BUFFER_LIMIT), store it in buffer.\n                //    - Otherwise, force EVICTION (deliver to gate) to prevent clogging.\n                if (!is_strict_next) {\n                    bool needed_soon = (held == st.next_needed_val[r_owner] + 1);\n                    if (needed_soon && st.items_on_grid <= STRICT_BUFFER_LIMIT) {\n                        should_store = true;\n                    }\n                }\n\n                if (should_store) {\n                    // Try to find a storage spot in columns 1, 2, 3\n                    Coord best_spot = {-1, -1};\n                    int min_dist = 9999;\n                    // Preferred columns for buffer\n                    vector<int> cols = {1, 2, 3}; \n                    for(int cc : cols) {\n                        for(int rr=0; rr<N; ++rr) {\n                            if (st.grid[rr][cc] == -1) {\n                                int d = dist(c.pos, {rr, cc});\n                                if (d < min_dist) {\n                                    min_dist = d;\n                                    best_spot = {rr, cc};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (best_spot.r != -1) {\n                         if (c.pos == best_spot) act = 'Q';\n                         else {\n                             // Move logic\n                             if (c.pos.r < best_spot.r) act = 'D';\n                             else if (c.pos.r > best_spot.r) act = 'U';\n                             else if (c.pos.c < best_spot.c) act = 'R';\n                             else act = 'L';\n                         }\n                    } else {\n                        should_store = false; // No space found, fallback to evict\n                    }\n                }\n                \n                if (!should_store && !is_strict_next) {\n                    // EVICTION MODE\n                    // Move to dispatch gate. Even though it's out of order (M1 penalty),\n                    // it clears the grid and prevents M3 penalty (missing item).\n                    // Step 3 automatically removes items at dispatch gate.\n                    if (c.pos == gate_dest) act = 'Q';\n                    else {\n                        if (c.pos.r < gate_dest.r) act = 'D';\n                        else if (c.pos.r > gate_dest.r) act = 'U';\n                        else if (c.pos.c < gate_dest.c) act = 'R';\n                        else act = 'L';\n                    }\n                } else if (is_strict_next) {\n                    // DELIVERY MODE\n                     if (c.pos == gate_dest) act = 'Q';\n                     else {\n                        if (c.pos.r < gate_dest.r) act = 'D';\n                        else if (c.pos.r > gate_dest.r) act = 'U';\n                        else if (c.pos.c < gate_dest.c) act = 'R';\n                        else act = 'L';\n                    }\n                }\n\n            } else {\n                // PICK LOGIC\n                Coord target = {-1, -1};\n                int best_cost = 99999;\n                \n                // 1. Priority: Pick Visible \"Strict Next\" items on grid\n                for(int r=0; r<N; ++r) {\n                    for(int cc=0; cc<N; ++cc) {\n                        int id = st.grid[r][cc];\n                        if (id != -1 && id == st.next_needed_val[id/N]) {\n                             // Don't pick if already at gate waiting for Step 3\n                             if (cc == N-1 && r == id/N) continue;\n                             int d = dist(c.pos, {r, cc});\n                             if (d < best_cost) {\n                                 best_cost = d;\n                                 target = {r, cc};\n                             }\n                        }\n                    }\n                }\n                \n                // 2. Priority: Dig \"Strict Next\" from Queues\n                // We calculate the cost including depth.\n                // We target (r, 0). If there are items in front (depth k > 0),\n                // the crane will pick the front item (a blocker). \n                // The \"Holding\" logic will then see it's not needed and Evict it.\n                // This effectively clears the queue to reach the needed item.\n                if (target.r == -1) {\n                     for(int r=0; r<N; ++r) {\n                        int needed = st.next_needed_val[r];\n                        if (needed >= (r+1)*N) continue; // Row complete\n                        \n                        for(int k=0; k<(int)st.queues[r].size(); ++k) {\n                            if (st.queues[r][k] == needed) {\n                                // Heuristic cost: distance + penalty for digging depth\n                                int cost = dist(c.pos, {r, 0}) + k * 10; \n                                // Limit digging if grid is completely full to avoid deadlock\n                                if (k == 0 || st.items_on_grid < 15) {\n                                    if (cost < best_cost) {\n                                        best_cost = cost;\n                                        target = {r, 0};\n                                    }\n                                }\n                                break;\n                            }\n                        }\n                     }\n                }\n                \n                // 3. Priority: Cleanup / Unblock\n                // If no strictly needed item is reachable, pick ANY item to clear space.\n                // We prioritize items in the buffer zone that are not needed.\n                if (target.r == -1) {\n                    int min_d = 9999;\n                    // Search columns 1, 2, 3, 0\n                    for(int cc : {1, 2, 3, 0}) {\n                        for(int r=0; r<N; ++r) {\n                            if (st.grid[r][cc] != -1) {\n                                // Not strict next (otherwise covered by Priority 1)\n                                int d = dist(c.pos, {r, cc});\n                                if (d < min_d) {\n                                    min_d = d;\n                                    target = {r, cc};\n                                }\n                            }\n                        }\n                        if (target.r != -1) break;\n                    }\n                }\n                \n                // Execute Move\n                if (target.r != -1) {\n                    if (c.pos == target) {\n                        if (st.grid[target.r][target.c] != -1) act = 'P';\n                        else act = '.'; // Wait for refill\n                    } else {\n                        if (c.pos.r < target.r) act = 'D';\n                        else if (c.pos.r > target.r) act = 'U';\n                        else if (c.pos.c < target.c) act = 'R';\n                        else act = 'L';\n                    }\n                }\n            }\n\n            // Update State based on Action\n            if (act == 'U') st.crane.pos.r--;\n            else if (act == 'D') st.crane.pos.r++;\n            else if (act == 'L') st.crane.pos.c--;\n            else if (act == 'R') st.crane.pos.c++;\n            else if (act == 'P') {\n                st.crane.holding = true;\n                st.crane.container_id = st.grid[st.crane.pos.r][st.crane.pos.c];\n                st.grid[st.crane.pos.r][st.crane.pos.c] = -1;\n                st.items_on_grid--;\n            } else if (act == 'Q') {\n                st.crane.holding = false;\n                st.grid[st.crane.pos.r][st.crane.pos.c] = st.crane.container_id;\n                st.crane.container_id = -1;\n                st.items_on_grid++;\n            }\n        }\n        st.history[0] += act;\n\n        // --- STEP 3: DISPATCH ---\n        // Items placed at the Dispatch Gate (col N-1) are removed.\n        for(int i=0; i<N; ++i) {\n            int id = st.grid[i][N-1];\n            if (id != -1) {\n                st.grid[i][N-1] = -1;\n                st.items_on_grid--;\n                st.dispatched[id] = true;\n            }\n        }\n    }\n\n    for(int i=0; i<N; ++i) cout << st.history[i] << endl;\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/mincostflow>\n#include <chrono>\n#include <random>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Directions: 0:U, 1:D, 2:L, 3:R\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint N = 20;\nlong long grid_h[20][20];\n\n// Job represents a single unit of transport derived from flow\nstruct Job {\n    int id;\n    int start_node;\n    int end_node;\n    long long amount;\n};\n\nstruct Result {\n    long long cost;\n    vector<string> ops;\n};\n\n// Configuration for a single randomized iteration\nstruct SearchParams {\n    double mcf_noise_factor; // Magnitude of random noise in edge costs\n    \n    // Heuristic coefficients\n    double dist_weight;      // Weight for movement cost\n    double drop_base;        // Constant bonus for dropping\n    double drop_mult;        // Bonus per unit dropped\n    double pick_base;        // Constant bonus/penalty for picking\n    double pick_mult;        // Bonus/penalty per unit picked\n};\n\n// Global random engine\nmt19937 rng(12345);\n\n// Manhattan distance\ninline int dist(int u, int v) {\n    int r1 = u / N, c1 = u % N;\n    int r2 = v / N, c2 = v % N;\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Helper for flow decomposition\nstruct EdgeInfo {\n    int to;\n    long long flow;\n};\n\nResult solve_iteration(const SearchParams& p) {\n    // 1. Construct Min-Cost Flow Graph with Noisy Costs\n    mcf_graph<int, long long> g(N * N + 2);\n    int S = N * N;\n    int T = N * N + 1;\n    long long BASE_COST = 1000; \n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = i * N + j;\n            // Source/Sink connections\n            if (grid_h[i][j] > 0) {\n                g.add_edge(S, u, grid_h[i][j], 0);\n            } else if (grid_h[i][j] < 0) {\n                g.add_edge(u, T, -grid_h[i][j], 0);\n            }\n            \n            // Grid connections\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int v = ni * N + nj;\n                    long long noise = 0;\n                    if (p.mcf_noise_factor > 1e-9) {\n                        noise = uniform_int_distribution<long long>(0, (long long)(p.mcf_noise_factor * 100))(rng);\n                    }\n                    g.add_edge(u, v, 1e9, BASE_COST + noise);\n                }\n            }\n        }\n    }\n\n    g.flow(S, T);\n    \n    // 2. Decompose Flow into Jobs\n    auto edges = g.edges();\n    vector<vector<EdgeInfo>> flow_adj(N*N+2);\n    for(const auto& e : edges) {\n        if(e.flow > 0) {\n             // Filter relevant edges for path reconstruction\n             if (e.from == S || e.to == T || (e.from < N*N && e.to < N*N)) {\n                 flow_adj[e.from].push_back({e.to, e.flow});\n             }\n        }\n    }\n\n    vector<Job> jobs;\n    int job_counter = 0;\n    \n    while(true) {\n        queue<int> q;\n        q.push(S);\n        vector<int> parent(N*N+2, -1);\n        vector<int> edge_index(N*N+2, -1);\n        parent[S] = S;\n        \n        bool found = false;\n        while(!q.empty()){\n            int u = q.front(); q.pop();\n            if(u == T) { found = true; break; }\n            \n            // Randomize traversal order for diverse path decomposition\n            if (!flow_adj[u].empty()) {\n                for (int i = flow_adj[u].size() - 1; i > 0; i--) {\n                    int j = uniform_int_distribution<int>(0, i)(rng);\n                    swap(flow_adj[u][i], flow_adj[u][j]);\n                }\n                for(int i=0; i<(int)flow_adj[u].size(); ++i) {\n                    if(flow_adj[u][i].flow > 0 && parent[flow_adj[u][i].to] == -1) {\n                        parent[flow_adj[u][i].to] = u;\n                        edge_index[flow_adj[u][i].to] = i;\n                        q.push(flow_adj[u][i].to);\n                    }\n                }\n            }\n        }\n        \n        if(!found) break;\n        \n        // Extract path and capacity\n        long long path_cap = 1e18;\n        int curr = T;\n        while(curr != S) {\n            int pr = parent[curr];\n            int idx = edge_index[curr];\n            path_cap = min(path_cap, flow_adj[pr][idx].flow);\n            curr = pr;\n        }\n        \n        int u_start = -1, u_end = -1;\n        curr = T;\n        while(curr != S) {\n            int pr = parent[curr];\n            int idx = edge_index[curr];\n            flow_adj[pr][idx].flow -= path_cap;\n            if(curr == T) u_end = pr;\n            if(pr == S) u_start = curr;\n            curr = pr;\n        }\n        jobs.push_back({job_counter++, u_start, u_end, path_cap});\n    }\n    \n    // 3. Greedy Simulation\n    int truck_r = 0, truck_c = 0;\n    long long truck_load = 0;\n    vector<string> ops;\n    long long total_cost = 0;\n    \n    vector<bool> is_picked(jobs.size(), false);\n    vector<bool> is_done(jobs.size(), false);\n    int completed_count = 0;\n    int step_limit = 200000; // Safety break\n    \n    while(completed_count < jobs.size() && ops.size() < step_limit) {\n        int u = truck_r * N + truck_c;\n        \n        // Opportunistic Unload\n        for(auto &j : jobs) {\n            if(is_picked[j.id] && !is_done[j.id] && j.end_node == u) {\n                ops.push_back(\"-\" + to_string(j.amount));\n                total_cost += j.amount;\n                truck_load -= j.amount;\n                is_done[j.id] = true;\n                completed_count++;\n            }\n        }\n        \n        // Opportunistic Load\n        for(auto &j : jobs) {\n            if(!is_picked[j.id] && j.start_node == u) {\n                ops.push_back(\"+\" + to_string(j.amount));\n                total_cost += j.amount;\n                truck_load += j.amount;\n                is_picked[j.id] = true;\n            }\n        }\n        \n        if(completed_count == jobs.size()) break;\n        \n        // Select Next Target based on Score\n        int best_target = -1;\n        double best_score = 1e18;\n        \n        for(const auto &j : jobs) {\n            if(is_done[j.id]) continue;\n            \n            int target = -1;\n            bool is_drop = false;\n            \n            if(is_picked[j.id]) {\n                target = j.end_node;\n                is_drop = true;\n            } else {\n                target = j.start_node;\n                is_drop = false;\n            }\n            \n            int d = dist(u, target);\n            \n            // Cost component: Moving there\n            double move_cost = d * (100.0 + truck_load);\n            double score = p.dist_weight * move_cost;\n            \n            // Heuristic incentives\n            if(is_drop) {\n                score += p.drop_base;\n                score += p.drop_mult * j.amount;\n            } else {\n                score += p.pick_base;\n                score += p.pick_mult * j.amount;\n            }\n            \n            if(score < best_score) {\n                best_score = score;\n                best_target = target;\n            }\n        }\n        \n        // Move one step\n        if(best_target != -1) {\n            int tr = best_target / N;\n            int tc = best_target % N;\n            \n            vector<int> dirs;\n            if(tr < truck_r) dirs.push_back(0);\n            if(tr > truck_r) dirs.push_back(1);\n            if(tc < truck_c) dirs.push_back(2);\n            if(tc > truck_c) dirs.push_back(3);\n            \n            if(!dirs.empty()) {\n                // Randomize valid moves to avoid bias\n                int dir = dirs[uniform_int_distribution<int>(0, dirs.size()-1)(rng)];\n                ops.push_back(string(1, dir_char[dir]));\n                total_cost += (100 + truck_load);\n                truck_r += dr[dir];\n                truck_c += dc[dir];\n            }\n        } else {\n            break;\n        }\n    }\n    \n    return {total_cost, ops};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (cin >> N) {}\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> grid_h[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.95; // Maximize usage of 2.0s\n    \n    long long best_cost = -1;\n    vector<string> best_ops;\n    \n    // Loop until time limit\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> diff = now - start_time;\n        if(diff.count() > time_limit) break;\n        \n        // Generate random parameters for this iteration\n        SearchParams p;\n        p.mcf_noise_factor = uniform_real_distribution<double>(0.0, 15.0)(rng);\n        p.dist_weight = 1.0;\n        \n        // Drop incentives: usually negative (reduces score -> preferred)\n        p.drop_base = uniform_real_distribution<double>(-600.0, 0.0)(rng);\n        p.drop_mult = uniform_real_distribution<double>(-25.0, -5.0)(rng);\n        \n        // Pickup incentives: mix of positive (penalty) and negative (bonus)\n        // Penalty encourages deferring heavy loads. Bonus encourages clustering.\n        p.pick_base = uniform_real_distribution<double>(-200.0, 200.0)(rng);\n        p.pick_mult = uniform_real_distribution<double>(-5.0, 15.0)(rng);\n        \n        Result res = solve_iteration(p);\n        \n        if(best_cost == -1 || res.cost < best_cost) {\n            best_cost = res.cost;\n            best_ops = res.ops;\n        }\n    }\n    \n    for (const auto& s : best_ops) cout << s << \"\\n\";\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n\nusing namespace std;\n\n// --- Global Constants ---\nint N, M, T;\nint SEED_COUNT;     // 2*N*(N-1)\nint GRID_SIZE;      // N*N\n\n// --- Tunable Parameters ---\n// K_MIN: Strictly prioritize keeping at least this many copies of the max value for each attribute.\n// Increased to 2 to provide a safety buffer against probabilistic loss during breeding.\nconst int K_MIN = 2; \n// K_TARGET_BASE: Prefer up to this many copies to ensure redundancy and mixing opportunities.\nconst int K_TARGET_BASE = 5; \n\n// Bonuses for selection scoring:\n// CRITICAL: Massive bonus to ensure K_MIN is met (preservation).\nconst long long BONUS_CRITICAL = 1e15; \n// TARGET: Large bonus to reach K_TARGET density (redundancy).\nconst long long BONUS_TARGET = 1e9;\n// CARRY: Moderate bonus for carrying a max gene. Prioritizes seeds that act as \"linkers\".\nconst long long BONUS_CARRY = 10000; \n\n// --- Structures ---\nstruct Seed {\n    int id;\n    vector<int> x;\n    int total_val;\n};\n\n// --- Random Engine ---\nmt19937 rng(5489u);\n\n// --- Timer Helper ---\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool check() {\n        return elapsed() < limit;\n    }\n};\n\n// --- Grid & Adjacency ---\nvector<vector<int>> adj;\nvector<int> degrees;\n\nvoid init_grid() {\n    GRID_SIZE = N * N;\n    adj.assign(GRID_SIZE, vector<int>());\n    degrees.assign(GRID_SIZE, 0);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // Neighbor Down\n            if (r + 1 < N) {\n                int v = (r + 1) * N + c;\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            // Neighbor Right\n            if (c + 1 < N) {\n                int v = r * N + (c + 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n        }\n    }\n    for(int i=0; i<GRID_SIZE; ++i) degrees[i] = adj[i].size();\n}\n\n// --- Potential Calculation ---\n// Calculates the theoretical best offspring value from two parents.\n// Sum of max(a_i, b_i) for all attributes.\ninline int calc_potential(const Seed& a, const Seed& b) {\n    int score = 0;\n    for (int k = 0; k < M; ++k) {\n        score += (a.x[k] > b.x[k]) ? a.x[k] : b.x[k];\n    }\n    return score;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> T)) return 0;\n    SEED_COUNT = 2 * N * (N - 1);\n    init_grid();\n\n    vector<Seed> seeds(SEED_COUNT);\n    // Read initial seeds\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        seeds[i].id = i;\n        seeds[i].x.resize(M);\n        seeds[i].total_val = 0;\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i].x[j];\n            seeds[i].total_val += seeds[i].x[j];\n        }\n    }\n\n    // Pre-allocate vectors\n    vector<int> global_max(M);\n    vector<Seed> selected_seeds;\n    selected_seeds.reserve(GRID_SIZE);\n    vector<bool> used(SEED_COUNT);\n    vector<int> current_counts(M);\n    \n    // Sort grid nodes by degree for heuristic initialization\n    vector<pair<int, int>> node_degrees(GRID_SIZE);\n    for(int i=0; i<GRID_SIZE; ++i) node_degrees[i] = { degrees[i], i };\n    sort(node_degrees.rbegin(), node_degrees.rend());\n\n    // Time budget per turn (2.0s total / 10 turns = 0.2s, keep safe buffer)\n    const double TIME_PER_TURN = 0.19; \n    \n    for (int t = 0; t < T; ++t) {\n        Timer timer(TIME_PER_TURN);\n\n        // 1. Identify global maximums for each attribute in current pool\n        fill(global_max.begin(), global_max.end(), -1);\n        for(const auto& s : seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] > global_max[j]) global_max[j] = s.x[j];\n            }\n        }\n\n        // Determine Dynamic Diversity Target\n        int k_target = K_TARGET_BASE;\n        // In the very last turn, we don't need to preserve diversity for future generations.\n        // We simply want the best possible parents to maximize the final harvest.\n        // Relaxing the cap allows strict elitism.\n        if (t == T - 1) k_target = GRID_SIZE; \n\n        // 2. Iterative Greedy Selection\n        selected_seeds.clear();\n        fill(used.begin(), used.end(), false);\n        fill(current_counts.begin(), current_counts.end(), 0);\n\n        for(int step = 0; step < GRID_SIZE; ++step) {\n            int best_idx = -1;\n            long long best_score = -1;\n\n            for(int k = 0; k < SEED_COUNT; ++k) {\n                if(used[k]) continue;\n\n                long long score = seeds[k].total_val; \n                \n                // Calculate dynamic bonuses based on current selection state\n                for(int j = 0; j < M; ++j) {\n                    if(seeds[k].x[j] == global_max[j]) {\n                        score += BONUS_CARRY; \n                        if(current_counts[j] < K_MIN) {\n                            score += BONUS_CRITICAL;\n                        } else if(current_counts[j] < k_target) {\n                            score += BONUS_TARGET;\n                        }\n                    }\n                }\n\n                if(score > best_score) {\n                    best_score = score;\n                    best_idx = k;\n                }\n            }\n\n            used[best_idx] = true;\n            selected_seeds.push_back(seeds[best_idx]);\n            for(int j = 0; j < M; ++j) {\n                if(seeds[best_idx].x[j] == global_max[j]) {\n                    current_counts[j]++;\n                }\n            }\n        }\n\n        // 3. Initial Placement Heuristic\n        // Assign priority to seeds based on Value + Scarcity.\n        // Rare genes get higher priority to be placed in high-degree nodes (center).\n        vector<long long> placement_prio(GRID_SIZE);\n        vector<int> subset_max_counts(M, 0);\n        for(const auto& s : selected_seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] == global_max[j]) subset_max_counts[j]++;\n            }\n        }\n\n        for(int i=0; i<GRID_SIZE; ++i) {\n            long long prio = selected_seeds[i].total_val;\n            for(int j=0; j<M; ++j) {\n                if(selected_seeds[i].x[j] == global_max[j]) {\n                    // Scarcity Bonus: Higher if fewer selected seeds carry this gene\n                    long long scarcity_bonus = 1000000000LL / (subset_max_counts[j] + 1); \n                    prio += scarcity_bonus;\n                }\n            }\n            placement_prio[i] = prio;\n        }\n\n        vector<int> p(GRID_SIZE);\n        iota(p.begin(), p.end(), 0);\n        sort(p.begin(), p.end(), [&](int a, int b){\n            return placement_prio[a] > placement_prio[b];\n        });\n\n        // Assign sorted seeds to degree-sorted nodes\n        vector<int> layout(GRID_SIZE);\n        for(int i=0; i<GRID_SIZE; ++i) {\n            layout[node_degrees[i].second] = p[i];\n        }\n\n        // 4. Precompute Potentials for Simulated Annealing\n        vector<vector<int>> potentials(GRID_SIZE, vector<int>(GRID_SIZE));\n        for(int i=0; i<GRID_SIZE; ++i) {\n            for(int j=i+1; j<GRID_SIZE; ++j) {\n                potentials[i][j] = potentials[j][i] = calc_potential(selected_seeds[i], selected_seeds[j]);\n            }\n        }\n\n        // Calculate initial score\n        long long current_score = 0;\n        for (int u = 0; u < GRID_SIZE; ++u) {\n            for (int v : adj[u]) {\n                if (u < v) {\n                    current_score += potentials[layout[u]][layout[v]];\n                }\n            }\n        }\n\n        long long best_score = current_score;\n        vector<int> best_layout = layout;\n\n        // 5. Simulated Annealing\n        double t0 = 1000.0; \n        double t1 = 0.1;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 255) == 0) {\n                if (!timer.check()) break;\n            }\n\n            double progress = timer.elapsed() / TIME_PER_TURN;\n            if(progress >= 1.0) break;\n            double temp = t0 * pow(t1/t0, progress);\n\n            int c1 = rng() % GRID_SIZE;\n            int c2 = rng() % GRID_SIZE;\n            while (c1 == c2) c2 = rng() % GRID_SIZE;\n\n            int s1 = layout[c1];\n            int s2 = layout[c2];\n\n            long long delta = 0;\n            \n            // Efficient delta calculation\n            for (int u : adj[c1]) {\n                if (u == c2) continue;\n                delta += (potentials[s2][layout[u]] - potentials[s1][layout[u]]);\n            }\n            for (int u : adj[c2]) {\n                if (u == c1) continue;\n                delta += (potentials[s1][layout[u]] - potentials[s2][layout[u]]);\n            }\n            \n            if (delta >= 0 || bernoulli_distribution(exp(delta / temp))(rng)) {\n                layout[c1] = s2;\n                layout[c2] = s1;\n                current_score += delta;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_layout = layout;\n                }\n            }\n        }\n\n        // 6. Output\n        vector<vector<int>> output_grid(N, vector<int>(N));\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                int cell = r*N + c;\n                int seed_idx = best_layout[cell];\n                output_grid[r][c] = selected_seeds[seed_idx].id;\n            }\n        }\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cout << output_grid[r][c] << (c == N-1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        // 7. Input Next Generation\n        for(int i=0; i<SEED_COUNT; ++i) {\n            seeds[i].id = i;\n            seeds[i].total_val = 0;\n            for(int j=0; j<M; ++j) {\n                cin >> seeds[i].x[j];\n                seeds[i].total_val += seeds[i].x[j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --------------------------------------------------------\n// Constants & Globals\n// --------------------------------------------------------\nconst int MAX_N = 35;\nconst int DR[] = {0, 1, 0, -1};\nconst int DC[] = {1, 0, -1, 0};\nconst char MOVE_CHARS[] = {'R', 'D', 'L', 'U'};\n\nint N, M, V;\nint s_grid[MAX_N][MAX_N]; // Source grid\nint t_grid[MAX_N][MAX_N]; // Target grid (drop locations)\nint t_original[MAX_N][MAX_N]; // Tracks if a cell is originally a target\n\nint root_r, root_c;\nint turns = 0;\nint delivered_count = 0;\n\nstruct Leaf {\n    int id;\n    int len;\n    int dir; // 0:R, 1:D, 2:L, 3:U\n    bool holding;\n};\nvector<Leaf> leaves;\n\nstruct LockedTask {\n    bool active;\n    int leaf_idx;\n    int r, c; // Target coordinates\n    int root_r, root_c; // Intended root position\n};\nLockedTask current_lock = {false, -1, -1, -1, -1, -1};\n\n// --------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------\n\ninline pair<int, int> get_leaf_pos(int rr, int rc, int len, int dir) {\n    return {rr + DR[dir] * len, rc + DC[dir] * len};\n}\n\ninline int get_rot_diff(int current, int target) {\n    return (target - current + 4) % 4;\n}\n\nchar get_rot_cmd(int diff) {\n    if (diff == 0) return '.';\n    if (diff == 1) return 'R';\n    if (diff == 3) return 'L';\n    if (diff == 2) return 'R'; \n    return '.';\n}\n\ninline int get_rot_cost(int diff) {\n    if (diff == 0) return 0;\n    if (diff == 1 || diff == 3) return 1;\n    return 2;\n}\n\n// --------------------------------------------------------\n// Main\n// --------------------------------------------------------\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> V)) return 0;\n    \n    vector<string> s_in(N), t_in(N);\n    for(int i=0; i<N; ++i) cin >> s_in[i];\n    for(int i=0; i<N; ++i) cin >> t_in[i];\n\n    // Initialize Grids\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            bool is_s = (s_in[i][j] == '1');\n            bool is_t = (t_in[i][j] == '1');\n            t_original[i][j] = is_t ? 1 : 0;\n            \n            if (is_s && is_t) {\n                delivered_count++;\n                s_grid[i][j] = 0;\n                t_grid[i][j] = 0;\n            } else {\n                s_grid[i][j] = is_s ? 1 : 0;\n                t_grid[i][j] = is_t ? 1 : 0;\n            }\n        }\n    }\n    \n    // 1. Arm Design\n    // Strategy: Cyclic lengths 1..~N/2. \n    // This proved superior to small-length bias in previous tests.\n    cout << V << endl;\n    int max_len = max(1, (N + 1) / 2); \n    for(int i=1; i<V; ++i) {\n        int len = (i - 1) % max_len + 1; \n        cout << \"0 \" << len << endl;\n    }\n    \n    // Initial position: Center\n    root_r = N/2; \n    root_c = N/2;\n    cout << root_r << \" \" << root_c << endl;\n\n    // Initialize Leaf State\n    leaves.resize(V-1);\n    for(int i=0; i<V-1; ++i) {\n        leaves[i].id = i;\n        leaves[i].len = (i) % max_len + 1;\n        leaves[i].dir = 0;\n        leaves[i].holding = false;\n    }\n\n    // Main Simulation Loop\n    while (delivered_count < M && turns < 100000) {\n        \n        // Collect Active Targets\n        vector<pair<int,int>> picks, drops;\n        picks.reserve(M);\n        drops.reserve(M);\n        for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n            if (s_grid[r][c]) picks.push_back({r, c});\n            if (t_grid[r][c]) drops.push_back({r, c});\n        }\n\n        if (picks.empty() && drops.empty()) break;\n\n        // -------------------------------------------------\n        // Candidate Generation\n        // -------------------------------------------------\n        \n        // Validate Lock\n        if (current_lock.active) {\n            // Check bounds & existence\n            if (current_lock.r < 0 || current_lock.r >= N || current_lock.c < 0 || current_lock.c >= N) {\n                current_lock.active = false;\n            } else if (leaves[current_lock.leaf_idx].holding) {\n                if (!t_grid[current_lock.r][current_lock.c]) current_lock.active = false;\n            } else {\n                if (!s_grid[current_lock.r][current_lock.c]) current_lock.active = false;\n            }\n        }\n\n        struct Candidate {\n            int leaf_idx;\n            int r, c; // Target\n            int rr, rc; // Root\n            int leaf_dir;\n            double score;\n        };\n\n        vector<Candidate> candidates;\n        // Only consider a subset of targets closest to current root to speed up\n        int K = 6; \n\n        for(int i=0; i<V-1; ++i) {\n            const auto& targets = leaves[i].holding ? drops : picks;\n            if (targets.empty()) continue;\n\n            // Find closest K targets by Manhattan distance\n            vector<pair<int, int>> dists;\n            dists.reserve(targets.size());\n            for(int k=0; k<targets.size(); ++k) {\n                int d = abs(targets[k].first - root_r) + abs(targets[k].second - root_c);\n                dists.push_back({d, k});\n            }\n            \n            // Partial sort to get top K\n            int count = min((int)dists.size(), K);\n            partial_sort(dists.begin(), dists.begin() + count, dists.end());\n            \n            for(int k=0; k<count; ++k) {\n                auto& t = targets[dists[k].second];\n                // Try 4 approach directions\n                for(int d=0; d<4; ++d) {\n                    int rr = t.first - DR[d] * leaves[i].len;\n                    int rc = t.second - DC[d] * leaves[i].len;\n                    if (rr < 0 || rr >= N || rc < 0 || rc >= N) continue;\n                    \n                    int move_cost = abs(rr - root_r) + abs(rc - root_c);\n                    int rot_cost = get_rot_cost(get_rot_diff(leaves[i].dir, d));\n                    \n                    // Base score is max turns needed\n                    candidates.push_back({i, t.first, t.second, rr, rc, d, (double)max(move_cost, rot_cost)});\n                }\n            }\n        }\n\n        // Sort candidates by base score\n        int cand_limit = min((int)candidates.size(), 60);\n        partial_sort(candidates.begin(), candidates.begin() + cand_limit, candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.score < b.score;\n        });\n        candidates.resize(cand_limit);\n\n        // -------------------------------------------------\n        // Scoring Refinement (Lookahead & Hysteresis)\n        // -------------------------------------------------\n        Candidate best_cand = {-1, -1, -1, -1, -1, -1, 1e18};\n\n        for(auto& cand : candidates) {\n            double bonus = 0;\n            int primary_turns = (int)cand.score;\n            \n            // Hysteresis: persist with current lock unless significantly better option appears\n            if (current_lock.active && cand.leaf_idx == current_lock.leaf_idx && \n                cand.r == current_lock.r && cand.c == current_lock.c) {\n                bonus += 3.0; \n            }\n            \n            // Bias: Prefer Drops to prevent filling up\n            if (leaves[cand.leaf_idx].holding) bonus += 1.0;\n\n            // Parallelism: Check if other leaves can do something useful at destination (cand.rr, cand.rc)\n            // We check the 4 reachable cells for each other leaf.\n            for(int j=0; j<V-1; ++j) {\n                if (j == cand.leaf_idx) continue;\n                \n                for(int d=0; d<4; ++d) {\n                    int tip_r = cand.rr + DR[d] * leaves[j].len;\n                    int tip_c = cand.rc + DC[d] * leaves[j].len;\n                    \n                    if (tip_r < 0 || tip_r >= N || tip_c < 0 || tip_c >= N) continue;\n                    \n                    bool useful = false;\n                    if (leaves[j].holding) {\n                        if (t_grid[tip_r][tip_c]) useful = true;\n                    } else {\n                        if (s_grid[tip_r][tip_c]) useful = true;\n                    }\n\n                    if (useful) {\n                        int rot_needed = get_rot_cost(get_rot_diff(leaves[j].dir, d));\n                        // Action is parallel if rotation fits within movement time\n                        if (rot_needed <= primary_turns + 1) {\n                            double val = 2.0; // Base parallelism bonus\n                            if (leaves[j].holding) val += 1.0; // Priority for drop\n                            // Penalize if it slightly extends time (should rarely happen due to check)\n                            if (rot_needed > primary_turns) val -= 0.5;\n                            \n                            bonus += val;\n                            break; // Only count one potential action per leaf to avoid overestimation\n                        }\n                    }\n                }\n            }\n            \n            cand.score -= bonus;\n            if (cand.score < best_cand.score) {\n                best_cand = cand;\n            }\n        }\n\n        // Update Lock\n        if (best_cand.leaf_idx != -1) {\n            current_lock = {true, best_cand.leaf_idx, best_cand.r, best_cand.c, best_cand.rr, best_cand.rc};\n        } else {\n            // Should not happen if targets exist, but safe break\n            break;\n        }\n\n        // -------------------------------------------------\n        // Execution Step\n        // -------------------------------------------------\n        \n        // 1. Determine Root Movement\n        int move_dir = -1;\n        if (current_lock.root_r > root_r) move_dir = 1;\n        else if (current_lock.root_r < root_r) move_dir = 3;\n        else if (current_lock.root_c > root_c) move_dir = 0;\n        else if (current_lock.root_c < root_c) move_dir = 2;\n        \n        int next_rr = root_r + (move_dir == -1 ? 0 : DR[move_dir]);\n        int next_rc = root_c + (move_dir == -1 ? 0 : DC[move_dir]);\n\n        vector<char> rot_cmds(V-1, '.');\n        vector<char> act_cmds(V, '.');\n        vector<bool> leaf_busy(V-1, false);\n        vector<pair<int,int>> used_locs;\n\n        // 2. Opportunistic Actions (Immediate P/D)\n        // Order: Leaves holding items first (to Drop), then empty (to Pick)\n        vector<int> order(V-1);\n        for(int i=0; i<V-1; ++i) order[i] = i;\n        sort(order.begin(), order.end(), [&](int a, int b){\n            if (leaves[a].holding != leaves[b].holding) return leaves[a].holding > leaves[b].holding;\n            return leaves[a].len < leaves[b].len;\n        });\n\n        for(int i : order) {\n            int best_d = -1;\n            for(int d=0; d<4; ++d) {\n                int diff = get_rot_diff(leaves[i].dir, d);\n                if (diff == 2) continue; // Cannot do 180 turn instantly\n\n                auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, d);\n                if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n                \n                // Collision Check\n                bool collision = false;\n                for(auto& u : used_locs) if(u.first == tr && u.second == tc) collision = true;\n                if(collision) continue;\n\n                if(leaves[i].holding) {\n                    if(t_grid[tr][tc]) { best_d = d; break; }\n                } else {\n                    if(s_grid[tr][tc]) { best_d = d; break; }\n                }\n            }\n            \n            if (best_d != -1) {\n                leaf_busy[i] = true;\n                rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, best_d));\n                act_cmds[i+1] = 'P';\n                used_locs.push_back(get_leaf_pos(next_rr, next_rc, leaves[i].len, best_d));\n            }\n        }\n\n        // 3. Rotate Primary Leaf (if not busy)\n        if (best_cand.leaf_idx != -1 && !leaf_busy[best_cand.leaf_idx]) {\n            rot_cmds[best_cand.leaf_idx] = get_rot_cmd(get_rot_diff(leaves[best_cand.leaf_idx].dir, best_cand.leaf_dir));\n            leaf_busy[best_cand.leaf_idx] = true;\n        }\n\n        // 4. Rotate Idle Leaves towards future utility\n        // They aim for useful targets relative to the DESTINATION root pos\n        if (best_cand.leaf_idx != -1) {\n            int dest_r = best_cand.rr;\n            int dest_c = best_cand.rc;\n            \n            for(int i=0; i<V-1; ++i) {\n                if (leaf_busy[i]) continue;\n                \n                int best_d = -1;\n                int min_cost = 10;\n\n                // Check all 4 directions for utility\n                for(int d=0; d<4; ++d) {\n                    int tr = dest_r + DR[d] * leaves[i].len;\n                    int tc = dest_c + DC[d] * leaves[i].len;\n                    \n                    if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n\n                    bool has_target = false;\n                    if (leaves[i].holding) { if (t_grid[tr][tc]) has_target = true; }\n                    else { if (s_grid[tr][tc]) has_target = true; }\n\n                    if (has_target) {\n                        int cost = get_rot_cost(get_rot_diff(leaves[i].dir, d));\n                        if (cost < min_cost) {\n                            min_cost = cost;\n                            best_d = d;\n                        }\n                    }\n                }\n                \n                if (best_d != -1) {\n                     rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, best_d));\n                }\n            }\n        }\n\n        // -------------------------------------------------\n        // Output & State Update\n        // -------------------------------------------------\n        cout << (move_dir == -1 ? '.' : MOVE_CHARS[move_dir]);\n        for(char c : rot_cmds) cout << c;\n        for(int k=0; k<V; ++k) cout << act_cmds[k];\n        cout << \"\\n\";\n\n        // Update positions/directions\n        root_r = next_rr;\n        root_c = next_rc;\n        for(int i=0; i<V-1; ++i) {\n            if (rot_cmds[i] == 'R') leaves[i].dir = (leaves[i].dir + 1) % 4;\n            else if (rot_cmds[i] == 'L') leaves[i].dir = (leaves[i].dir + 3) % 4;\n            \n            // Handle Pick/Drop\n            if (act_cmds[i+1] == 'P') {\n                auto [tr, tc] = get_leaf_pos(root_r, root_c, leaves[i].len, leaves[i].dir);\n                if (leaves[i].holding) {\n                    if (tr>=0 && tr<N && tc>=0 && tc<N && t_grid[tr][tc]) {\n                        t_grid[tr][tc] = 0;\n                        delivered_count++;\n                        leaves[i].holding = false;\n                    }\n                } else {\n                    if (tr>=0 && tr<N && tc>=0 && tc<N && s_grid[tr][tc]) {\n                        s_grid[tr][tc] = 0;\n                        // If the picked spot was originally a target, mark it as open target\n                        if (t_original[tr][tc]) t_grid[tr][tc] = 1;\n                        leaves[i].holding = true;\n                    }\n                }\n            }\n        }\n\n        turns++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <set>\n#include <queue>\n#include <chrono>\n#include <map>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst long long MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\nconst double TIME_LIMIT = 1.95; \n\nstruct Point {\n    int x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nlong long start_time;\nlong long get_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(\n        std::chrono::steady_clock::now().time_since_epoch()).count();\n}\n\ntypedef vector<Point> Polygon;\n\nbool is_inside(const Polygon& poly, const Point& p) {\n    bool inside = false;\n    size_t n = poly.size();\n    for (size_t i = 0; i < n; ++i) {\n        const Point& p1 = poly[i];\n        const Point& p2 = poly[(i + 1) % n];\n        if (p1.x == p2.x) { \n            if (p1.x == p.x && p.y >= min(p1.y, p2.y) && p.y <= max(p1.y, p2.y)) return true;\n        } else { \n            if (p1.y == p.y && p.x >= min(p1.x, p2.x) && p.x <= max(p1.x, p2.x)) return true;\n        }\n        if ((p1.y > p.y) != (p2.y > p.y)) {\n            double intersect_x = (double)(p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x;\n            if (p.x < intersect_x) inside = !inside;\n        }\n    }\n    return inside;\n}\n\nint raw_score(const Polygon& poly) {\n    if (poly.empty()) return 0;\n    int m = 0, s = 0;\n    int min_x = MAX_COORD, max_x = 0, min_y = MAX_COORD, max_y = 0;\n    for (const auto& p : poly) {\n        min_x = min(min_x, p.x);\n        max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y);\n        max_y = max(max_y, p.y);\n    }\n    for (const auto& p : mackerels) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) m++;\n    }\n    for (const auto& p : sardines) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) s++;\n    }\n    return m - s;\n}\n\nlong long perimeter(const Polygon& poly) {\n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        perim += abs(poly[i].x - poly[(i + 1) % poly.size()].x) + abs(poly[i].y - poly[(i + 1) % poly.size()].y);\n    }\n    return perim;\n}\n\nstruct GridSolver {\n    int cell_size;\n    int offset_x, offset_y;\n    int GX, GY;\n    vector<vector<int>> grid_score;\n    vector<vector<bool>> active;\n    \n    GridSolver(int cs, int ox, int oy) : cell_size(cs), offset_x(ox), offset_y(oy) {\n        GX = (MAX_COORD + offset_x) / cell_size + 2; \n        GY = (MAX_COORD + offset_y) / cell_size + 2;\n        grid_score.assign(GX, vector<int>(GY, 0));\n        active.assign(GX, vector<bool>(GY, false));\n    }\n    \n    void build() {\n        for (const auto& p : mackerels) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]++;\n        }\n        for (const auto& p : sardines) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) grid_score[gx][gy]--;\n        }\n    }\n    \n    void threshold_and_smooth(int smooth_mode, int thresh) {\n        if (smooth_mode == 0) {\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    if (grid_score[x][y] > thresh) active[x][y] = true;\n                }\n            }\n        } else {\n            vector<vector<int>> smoothed = grid_score;\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    int sum = 0;\n                    for(int dx=-1; dx<=1; ++dx) {\n                        for(int dy=-1; dy<=1; ++dy) {\n                            int nx = x+dx, ny = y+dy;\n                            if (nx>=0 && nx<GX && ny>=0 && ny<GY) {\n                                int w = 1;\n                                if (dx==0 && dy==0) w = (smooth_mode == 1 ? 2 : 3);\n                                sum += grid_score[nx][ny] * w;\n                            }\n                        }\n                    }\n                    smoothed[x][y] = sum;\n                }\n            }\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    if (smoothed[x][y] > thresh) active[x][y] = true;\n                }\n            }\n        }\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                long long xR = (long long)(x + 1) * cell_size - offset_x;\n                long long yR = (long long)(y + 1) * cell_size - offset_y;\n                long long xL = (long long)x * cell_size - offset_x;\n                long long yL = (long long)y * cell_size - offset_y;\n                if (xR <= 0 || xL >= MAX_COORD || yR <= 0 || yL >= MAX_COORD) active[x][y] = false;\n            }\n        }\n    }\n    \n    void repair_topology() {\n        for(int iter=0; iter<2; ++iter) {\n            bool changed = false;\n            for(int x=0; x<GX-1; ++x) {\n                for(int y=0; y<GY-1; ++y) {\n                    bool bl = active[x][y];\n                    bool br = active[x+1][y];\n                    bool tl = active[x][y+1];\n                    bool tr = active[x+1][y+1];\n                    int cnt = bl+br+tl+tr;\n                    if (cnt == 2) {\n                        if (bl && tr) {\n                            if (grid_score[x][y+1] >= grid_score[x+1][y]) active[x][y+1] = true;\n                            else active[x+1][y] = true;\n                            changed = true;\n                        } else if (tl && br) {\n                            if (grid_score[x+1][y+1] >= grid_score[x][y]) active[x+1][y+1] = true;\n                            else active[x][y] = true;\n                            changed = true;\n                        }\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n    }\n    \n    bool safe_remove(int x, int y) {\n        bool n = (y+1 < GY && active[x][y+1]);\n        bool s = (y-1 >= 0 && active[x][y-1]);\n        bool e = (x+1 < GX && active[x+1][y]);\n        bool w = (x-1 >= 0 && active[x-1][y]);\n        \n        if (n && s && !e && !w) return false;\n        if (e && w && !n && !s) return false;\n        \n        bool ne = (x+1 < GX && y+1 < GY && active[x+1][y+1]);\n        bool se = (x+1 < GX && y-1 >= 0 && active[x+1][y-1]);\n        bool sw = (x-1 >= 0 && y-1 >= 0 && active[x-1][y-1]);\n        bool nw = (x-1 >= 0 && y+1 < GY && active[x-1][y+1]);\n        \n        if (n && e && !ne) return false; \n        if (e && s && !se) return false;\n        if (s && w && !sw) return false;\n        if (w && n && !nw) return false;\n        return true;\n    }\n\n    bool safe_add(int x, int y) {\n        bool n = (y+1 < GY && active[x][y+1]);\n        bool s = (y-1 >= 0 && active[x][y-1]);\n        bool e = (x+1 < GX && active[x+1][y]);\n        bool w = (x-1 >= 0 && active[x-1][y]);\n        if (!n && !s && !e && !w) return false; \n        \n        bool ne = (x+1 < GX && y+1 < GY && active[x+1][y+1]);\n        bool se = (x+1 < GX && y-1 >= 0 && active[x+1][y-1]);\n        bool sw = (x-1 >= 0 && y-1 >= 0 && active[x-1][y-1]);\n        bool nw = (x-1 >= 0 && y+1 < GY && active[x-1][y+1]);\n        \n        if (!n && !e && ne) return false;\n        if (!e && !s && se) return false;\n        if (!s && !w && sw) return false;\n        if (!w && !n && nw) return false;\n        return true;\n    }\n\n    Polygon solve(int smooth_mode, int thresh) {\n        threshold_and_smooth(smooth_mode, thresh);\n        repair_topology();\n        \n        int best_comp_start_x = -1, best_comp_start_y = -1;\n        int best_comp_score = -1e9;\n        vector<vector<bool>> visited(GX, vector<bool>(GY, false));\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (active[x][y] && !visited[x][y]) {\n                    int current_score = 0;\n                    queue<pair<int,int>> q;\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    while(!q.empty()) {\n                        auto [cx, cy] = q.front(); q.pop();\n                        current_score += grid_score[cx][cy];\n                        int dx[] = {1, -1, 0, 0}; int dy[] = {0, 0, 1, -1};\n                        for(int k=0; k<4; ++k) {\n                            int nx=cx+dx[k], ny=cy+dy[k];\n                            if (nx>=0 && nx<GX && ny>=0 && ny<GY && active[nx][ny] && !visited[nx][ny]) {\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                            }\n                        }\n                    }\n                    if (current_score > best_comp_score) {\n                        best_comp_score = current_score;\n                        best_comp_start_x = x;\n                        best_comp_start_y = y;\n                    }\n                }\n            }\n        }\n        \n        if (best_comp_start_x == -1) return {};\n        \n        vector<vector<bool>> new_active(GX, vector<bool>(GY, false));\n        queue<pair<int,int>> q;\n        q.push({best_comp_start_x, best_comp_start_y});\n        new_active[best_comp_start_x][best_comp_start_y] = true;\n        vector<pair<int,int>> boundary_candidates;\n\n        while(!q.empty()) {\n            auto [cx, cy] = q.front(); q.pop();\n            int dx[] = {1, -1, 0, 0}; int dy[] = {0, 0, 1, -1};\n            for(int k=0; k<4; ++k) {\n                int nx=cx+dx[k], ny=cy+dy[k];\n                if (nx>=0 && nx<GX && ny>=0 && ny<GY) {\n                    if (active[nx][ny] && !new_active[nx][ny]) {\n                        new_active[nx][ny] = true;\n                        q.push({nx, ny});\n                    }\n                }\n            }\n        }\n        active = new_active;\n\n        // Optimized Refinement Loop\n        // Instead of iterating over the whole grid, we iterate until convergence.\n        // We do passes.\n        for(int iter=0; iter<8; ++iter) {\n            bool changed = false;\n            // To speed up, we can just scan the bounding box of the active region\n            // But finding BB update is complex, simple scan is fine for these grid sizes (max 100x100 typically)\n            \n            // Erosion\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    if (active[x][y] && grid_score[x][y] < 0) {\n                        if (safe_remove(x, y)) {\n                            active[x][y] = false;\n                            changed = true;\n                        }\n                    }\n                }\n            }\n            \n            // Expansion\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    long long xR = (long long)(x + 1) * cell_size - offset_x;\n                    long long yR = (long long)(y + 1) * cell_size - offset_y;\n                    long long xL = (long long)x * cell_size - offset_x;\n                    long long yL = (long long)y * cell_size - offset_y;\n                    \n                    if (!active[x][y] && grid_score[x][y] > 0 && xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                        if (safe_add(x, y)) {\n                            active[x][y] = true;\n                            changed = true;\n                        }\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n        \n        set<pair<int,int>> cell_set;\n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (active[x][y]) cell_set.insert({x, y});\n            }\n        }\n        \n        return trace(cell_set);\n    }\n    \n    Polygon trace(const set<pair<int,int>>& cells) {\n        if (cells.empty()) return {};\n        int sx = GX, sy = GY;\n        for(auto p : cells) {\n            if (p.second < sy || (p.second == sy && p.first < sx)) {\n                sx = p.first; sy = p.second;\n            }\n        }\n        \n        int vx = sx, vy = sy;\n        int dir = 0; \n        vector<pair<int,int>> path;\n        path.push_back({vx, vy});\n        \n        int start_vx = vx, start_vy = vy;\n        int steps = 0;\n        bool closed = false;\n        auto check = [&](int cx, int cy) { return cells.count({cx, cy}); };\n        \n        do {\n            int search_order[] = {(dir + 1) % 4, dir, (dir + 3) % 4, (dir + 2) % 4};\n            int next_dir = -1;\n            for (int nd : search_order) {\n                pair<int,int> l, r;\n                if (nd == 0) { l = {vx, vy}; r = {vx, vy-1}; }\n                else if (nd == 1) { l = {vx-1, vy}; r = {vx, vy}; }\n                else if (nd == 2) { l = {vx-1, vy-1}; r = {vx-1, vy}; }\n                else { l = {vx, vy-1}; r = {vx-1, vy-1}; }\n                \n                if (check(l.first, l.second) && !check(r.first, r.second)) {\n                    next_dir = nd; break;\n                }\n            }\n            if (next_dir == -1) return {};\n            dir = next_dir;\n            if (dir == 0) vx++; else if (dir == 1) vy++; else if (dir == 2) vx--; else vy--;\n            \n            path.push_back({vx, vy});\n            steps++;\n            if (steps > 20000) return {}; \n            if (vx == start_vx && vy == start_vy) closed = true;\n        } while (!closed);\n        \n        if (path.size() <= 1) return {};\n        path.pop_back();\n        \n        auto get_pt = [&](pair<int,int> p) {\n            long long X = (long long)p.first * cell_size - offset_x;\n            long long Y = (long long)p.second * cell_size - offset_y;\n            return Point{(int)clamp(X, 0LL, (long long)MAX_COORD), (int)clamp(Y, 0LL, (long long)MAX_COORD)};\n        };\n        \n        vector<Point> simple_poly;\n        simple_poly.push_back(get_pt(path[0]));\n        \n        for(size_t i = 1; i < path.size(); ++i) {\n            Point curr = get_pt(path[i]);\n            if (simple_poly.size() >= 2) {\n                Point prev = simple_poly.back();\n                Point pprev = simple_poly[simple_poly.size()-2];\n                bool p_v = (prev.x == pprev.x); bool c_v = (curr.x == prev.x);\n                bool p_h = (prev.y == pprev.y); bool c_h = (curr.y == prev.y);\n                if ((p_v && c_v) || (p_h && c_h)) simple_poly.back() = curr;\n                else simple_poly.push_back(curr);\n            } else simple_poly.push_back(curr);\n        }\n        \n        if (simple_poly.size() > 2) {\n            Point f = simple_poly[0];\n            Point l = simple_poly.back();\n            Point p = simple_poly[simple_poly.size()-2];\n            bool l_v = (l.x == p.x); bool c_v = (f.x == l.x);\n            bool l_h = (l.y == p.y); bool c_h = (f.y == l.y);\n            if ((l_v && c_v) || (l_h && c_h)) { simple_poly.pop_back(); l = simple_poly.back(); }\n            Point s = simple_poly[1];\n            bool f_v = (s.x == f.x); bool nc_v = (f.x == l.x);\n            bool f_h = (s.y == f.y); bool nc_h = (f.y == l.y);\n            if ((f_v && nc_v) || (f_h && nc_h)) simple_poly.erase(simple_poly.begin());\n        }\n        return simple_poly;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = get_time_ms();\n    \n    if (!(cin >> N)) return 0;\n    mackerels.resize(N);\n    for(int i=0; i<N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    sardines.resize(N);\n    for(int i=0; i<N; ++i) cin >> sardines[i].x >> sardines[i].y;\n    \n    Polygon best_poly = {{0,0}, {1,0}, {1,1}, {0,1}};\n    int best_score = 0;\n    \n    mt19937 rng(1337);\n    // Expanded grid size range for diversity\n    vector<int> grid_sizes;\n    // Add some specific good sizes\n    grid_sizes = {5000, 2500, 1000, 4000, 2000, 800, 1500, 3000, 1200, 600, 7000, 500};\n    \n    int iter = 0;\n    while (get_time_ms() - start_time < TIME_LIMIT * 1000) {\n        iter++;\n        int cs;\n        if (iter <= (int)grid_sizes.size()) cs = grid_sizes[iter-1];\n        else {\n            // Continuous range random\n            cs = 500 + (rng() % 6000);\n        }\n        \n        int ox = rng() % cs;\n        int oy = rng() % cs;\n        \n        int smooth_mode = rng() % 3;\n        int thresh = 0;\n        if (smooth_mode > 0) thresh = rng() % 5;\n        \n        GridSolver solver(cs, ox, oy);\n        solver.build();\n        Polygon poly = solver.solve(smooth_mode, thresh);\n        \n        if (poly.size() < 4) continue;\n        \n        bool ok = true;\n        if (poly.size() > MAX_VERTICES) ok = false;\n        if (ok && perimeter(poly) > MAX_PERIMETER) ok = false;\n        \n        if (ok) {\n            int current_score = raw_score(poly);\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_poly = poly;\n            }\n        }\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Constants & Globals ---\nconst int MAX_N = 105;\nint N, T, sigma_val;\nint w_prime[MAX_N], h_prime[MAX_N];\ndouble w_est[MAX_N], h_est[MAX_N];\n\nstruct Rect {\n    int x, y, w, h;\n};\n\nstruct Op {\n    short p; \n    short r; \n    short d; \n    short b; \n};\n\n// Fixed-size State structure to avoid dynamic allocation overhead\nstruct State {\n    Rect rects[MAX_N];\n    Op ops[MAX_N];\n    int W, H;\n    long long score;          // Primary objective: W + H\n    long long secondary;      // Secondary objective: W * H (Area)\n    \n    void add(int idx, int r_flag, int d_flag, int b_idx, const Rect& r) {\n        ops[idx] = { (short)idx, (short)r_flag, (short)d_flag, (short)b_idx };\n        rects[idx] = r;\n        W = max(W, r.x + r.w);\n        H = max(H, r.y + r.h);\n        score = (long long)W + H;\n        secondary = (long long)W * H;\n    }\n};\n\nstruct Candidate {\n    int parent_idx;\n    int r, d, b;\n    Rect geometry;\n    long long score;\n    long long secondary;\n};\n\n// --- Helpers ---\n\n// Calculate the position of a new rectangle given a base and direction.\n// Checks collisions against rects[0...idx-1].\npair<int, int> get_pos(int idx, int d, int b, int rw, int rh, const Rect* current_rects) {\n    int x = 0, y = 0;\n    if (d == 0) { // Direction U: Moves \"Upward\" (stops at bottom of others)\n        // X is determined by the base rectangle's right edge\n        if (b != -1) x = current_rects[b].x + current_rects[b].w;\n        \n        // Y is determined by \"gravity\" falling towards 0 (stacking in +y direction relative to blockers)\n        y = 0;\n        for (int j = 0; j < idx; ++j) {\n            // Check x-interval overlap: [x, x+rw) vs [j.x, j.x+j.w)\n            if (x < current_rects[j].x + current_rects[j].w && x + rw > current_rects[j].x) {\n                y = max(y, current_rects[j].y + current_rects[j].h);\n            }\n        }\n    } else { // Direction L: Moves \"Leftward\" (stops at right of others)\n        // Y is determined by the base rectangle's bottom edge\n        if (b != -1) y = current_rects[b].y + current_rects[b].h;\n        \n        // X is determined by \"gravity\" falling towards 0\n        x = 0;\n        for (int j = 0; j < idx; ++j) {\n            // Check y-interval overlap: [y, y+rh) vs [j.y, j.y+j.h)\n            if (y < current_rects[j].y + current_rects[j].h && y + rh > current_rects[j].y) {\n                x = max(x, current_rects[j].x + current_rects[j].w);\n            }\n        }\n    }\n    return {x, y};\n}\n\nState solve_beam(int K) {\n    // Use static buffers to reduce allocation\n    static vector<State> beam;\n    static vector<State> next_beam;\n    static vector<Candidate> candidates;\n    \n    beam.clear();\n    beam.reserve(K);\n    \n    State init_state;\n    init_state.W = 0;\n    init_state.H = 0;\n    init_state.score = 0;\n    init_state.secondary = 0;\n    beam.push_back(init_state);\n    \n    // Reusable buffer for unique coordinate generation\n    static vector<pair<int,int>> coords; \n    coords.reserve(MAX_N);\n\n    for (int i = 0; i < N; ++i) {\n        candidates.clear();\n        \n        // Expand each state in the current beam\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& S = beam[s_idx];\n            \n            // Calculate dimensions for current rect based on rotation\n            int dims[2][2]; // r=0, r=1\n            dims[0][0] = (int)lround(w_est[i]); dims[0][1] = (int)lround(h_est[i]);\n            dims[1][0] = (int)lround(h_est[i]); dims[1][1] = (int)lround(w_est[i]);\n            \n            for(int r=0; r<2; ++r) {\n                if (dims[r][0] < 1) dims[r][0] = 1;\n                if (dims[r][1] < 1) dims[r][1] = 1;\n            }\n            \n            // -- Try Direction U --\n            // Collect potential bases (unique X coordinates)\n            coords.clear();\n            coords.push_back({0, -1});\n            for(int j=0; j<i; ++j) coords.push_back({S.rects[j].x + S.rects[j].w, j});\n            \n            // Filter unique coordinates to prune branching factor\n            sort(coords.begin(), coords.end());\n            int unique_count = unique(coords.begin(), coords.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n                return a.first == b.first;\n            }) - coords.begin();\n            \n            for(int k=0; k<unique_count; ++k) {\n                int base = coords[k].second;\n                for(int r=0; r<2; ++r) {\n                    int rw = dims[r][0];\n                    int rh = dims[r][1];\n                    pair<int,int> pos = get_pos(i, 0, base, rw, rh, S.rects);\n                    \n                    int nW = max(S.W, pos.first + rw);\n                    int nH = max(S.H, pos.second + rh);\n                    long long sc = (long long)nW + nH;\n                    long long sec = (long long)nW * nH;\n                    candidates.push_back({s_idx, r, 0, base, {pos.first, pos.second, rw, rh}, sc, sec});\n                }\n            }\n\n            // -- Try Direction L --\n            // Collect potential bases (unique Y coordinates)\n            coords.clear();\n            coords.push_back({0, -1});\n            for(int j=0; j<i; ++j) coords.push_back({S.rects[j].y + S.rects[j].h, j});\n            \n            sort(coords.begin(), coords.end());\n            unique_count = unique(coords.begin(), coords.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n                return a.first == b.first;\n            }) - coords.begin();\n            \n            for(int k=0; k<unique_count; ++k) {\n                int base = coords[k].second;\n                for(int r=0; r<2; ++r) {\n                    int rw = dims[r][0];\n                    int rh = dims[r][1];\n                    pair<int,int> pos = get_pos(i, 1, base, rw, rh, S.rects);\n                    \n                    int nW = max(S.W, pos.first + rw);\n                    int nH = max(S.H, pos.second + rh);\n                    long long sc = (long long)nW + nH;\n                    long long sec = (long long)nW * nH;\n                    candidates.push_back({s_idx, r, 1, base, {pos.first, pos.second, rw, rh}, sc, sec});\n                }\n            }\n        }\n        \n        // Select top K candidates\n        if ((int)candidates.size() > K) {\n            nth_element(candidates.begin(), candidates.begin() + K, candidates.end(), \n                [](const Candidate& a, const Candidate& b){\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.secondary < b.secondary;\n                });\n            candidates.resize(K);\n        }\n        \n        next_beam.clear();\n        next_beam.reserve(candidates.size());\n        for(const auto& c : candidates) {\n            State ns = beam[c.parent_idx];\n            ns.add(i, c.r, c.d, c.b, c.geometry);\n            next_beam.push_back(ns);\n        }\n        beam = next_beam;\n    }\n    \n    // Return best\n    if(beam.empty()) return init_state;\n    auto best_it = min_element(beam.begin(), beam.end(), [](const State& a, const State& b){\n         if (a.score != b.score) return a.score < b.score;\n         return a.secondary < b.secondary;\n    });\n    return *best_it;\n}\n\nvoid update_estimates(const State& state, int W_obs, int H_obs) {\n    int diff_W = W_obs - state.W;\n    int diff_H = H_obs - state.H;\n    \n    // Rebuild dependency graph to trace critical paths\n    static int px[MAX_N], py[MAX_N];\n    fill(px, px+N, -1);\n    fill(py, py+N, -1);\n    \n    for(int i=0; i<N; ++i) {\n        const auto& op = state.ops[i];\n        const auto& r = state.rects[i];\n        if(op.d == 0) { // U\n            px[i] = op.b;\n            int best_k = -1, max_v = 0;\n            for(int k=0; k<i; ++k) {\n                if(state.rects[k].x < r.x+r.w && state.rects[k].x+state.rects[k].w > r.x) {\n                    int bot = state.rects[k].y + state.rects[k].h;\n                    if(bot > max_v) { max_v = bot; best_k = k; }\n                }\n            }\n            py[i] = best_k;\n        } else { // L\n            py[i] = op.b;\n            int best_k = -1, max_v = 0;\n            for(int k=0; k<i; ++k) {\n                if(state.rects[k].y < r.y+r.h && state.rects[k].y+state.rects[k].h > r.y) {\n                    int right = state.rects[k].x + state.rects[k].w;\n                    if(right > max_v) { max_v = right; best_k = k; }\n                }\n            }\n            px[i] = best_k;\n        }\n    }\n    \n    static bool crit[MAX_N];\n    \n    // Update Width Estimates\n    fill(crit, crit+N, false);\n    int cnt_w = 0;\n    vector<int> q; q.reserve(N);\n    for(int i=0; i<N; ++i) if(state.rects[i].x + state.rects[i].w == state.W) {\n        crit[i] = true; q.push_back(i);\n    }\n    int hd = 0;\n    while(hd < (int)q.size()){\n        int u = q[hd++];\n        int p = px[u];\n        if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n    }\n    for(int i=0; i<N; ++i) if(crit[i]) cnt_w++;\n    \n    if(cnt_w > 0) {\n        double delta = (double)diff_W / cnt_w * 0.4;\n        for(int i=0; i<N; ++i) if(crit[i]) {\n            if(state.ops[i].r == 0) w_est[i] += delta;\n            else h_est[i] += delta;\n        }\n    }\n    \n    // Update Height Estimates\n    fill(crit, crit+N, false);\n    int cnt_h = 0;\n    q.clear();\n    for(int i=0; i<N; ++i) if(state.rects[i].y + state.rects[i].h == state.H) {\n        crit[i] = true; q.push_back(i);\n    }\n    hd = 0;\n    while(hd < (int)q.size()){\n        int u = q[hd++];\n        int p = py[u];\n        if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n    }\n    for(int i=0; i<N; ++i) if(crit[i]) cnt_h++;\n\n    if(cnt_h > 0) {\n        double delta = (double)diff_H / cnt_h * 0.4;\n        for(int i=0; i<N; ++i) if(crit[i]) {\n            if(state.ops[i].r == 0) h_est[i] += delta;\n            else w_est[i] += delta;\n        }\n    }\n    \n    // Clamp values\n    for(int i=0; i<N; ++i) {\n        if(w_est[i] < 1) w_est[i] = 1;\n        if(h_est[i] < 1) h_est[i] = 1;\n        if(w_est[i] > 1e9) w_est[i] = 1e9;\n        if(h_est[i] > 1e9) h_est[i] = 1e9;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> T >> sigma_val)) return 0;\n    for(int i=0; i<N; ++i) {\n        cin >> w_prime[i] >> h_prime[i];\n        w_est[i] = w_prime[i];\n        h_est[i] = h_prime[i];\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Initial Beam Width Calculation\n    // We aim to keep total operations roughly constant ~ 2e8 ops over T turns\n    long long estimated_ops_per_K = (long long)T * N * N * 10; \n    int K = 300000000LL / estimated_ops_per_K;\n    if (K < 1) K = 1;\n    if (K > 80) K = 80;\n    \n    // Strict cap for very large N to ensure 3.0s safety\n    if (N > 80 && K > 5) K = 5;\n    if (N > 90 && K > 3) K = 3;\n    \n    for(int t=0; t<T; ++t) {\n        // Time management: if we are behind schedule, reduce K\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double expected_time = (double)(t) / T * 2.85;\n        \n        if (elapsed > expected_time && K > 1) {\n            K = max(1, K - 1);\n        }\n        \n        State sol = solve_beam(K);\n        \n        cout << N << \"\\n\";\n        for(int i=0; i<N; ++i) {\n            const auto& op = sol.ops[i];\n            char c = (op.d==0?'U':'L');\n            cout << op.p << \" \" << op.r << \" \" << c << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        int W_obs, H_obs;\n        cin >> W_obs >> H_obs;\n        update_estimates(sol, W_obs, H_obs);\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Problem Constants\nconst int MAXN = 1005;\nconst int H_LIMIT = 10;\n\n// Global Data\nint N, M, H_in;\nint A[MAXN];\nvector<int> adj[MAXN];\n\n// Solution State\nint p[MAXN];                  // Parent of u (-1 if root)\nint S[MAXN];                  // Sum of A in subtree u\nint d_max[MAXN];              // Height of subtree u (max distance to leaf)\nint cnt_h[MAXN][H_LIMIT + 5]; // cnt_h[u][h] = number of children with height contribution h\n\n// Random Generator\nmt19937 rng(12345);\n\n// Helper: Get depth of u (root is 0, returns -1 if u is -1)\n// Complexity: O(H)\nint get_depth(int u) {\n    int d = -1;\n    while (u != -1) {\n        d++;\n        u = p[u];\n    }\n    return d;\n}\n\n// Helper: Check if 'ancestor' is an ancestor of 'node'\n// Used to detect cycles (if we make 'node' the parent of 'ancestor', it's a cycle)\n// Complexity: O(H)\nbool is_ancestor(int ancestor, int node) {\n    if (ancestor == -1) return false;\n    if (ancestor == node) return true;\n    while (node != -1) {\n        if (node == ancestor) return true;\n        node = p[node];\n    }\n    return false;\n}\n\n// Forward declarations for recursive stat updates\nvoid add_stat(int u, int h_val);\nvoid remove_stat(int u, int h_val);\n\n// Add height contribution 'h_val' to node u and propagate changes up\nvoid add_stat(int u, int h_val) {\n    if (u == -1) return;\n    cnt_h[u][h_val]++;\n    \n    // If the new child path is deeper than current max\n    if (h_val > d_max[u]) {\n        int old_h = d_max[u];\n        d_max[u] = h_val;\n        // Propagate change: remove old contribution from parent, add new\n        remove_stat(p[u], old_h + 1);\n        add_stat(p[u], d_max[u] + 1);\n    }\n}\n\n// Remove height contribution 'h_val' from node u and propagate changes up\nvoid remove_stat(int u, int h_val) {\n    if (u == -1) return;\n    cnt_h[u][h_val]--;\n    \n    // If the removed path was defining the max height, we might need to reduce d_max\n    if (h_val == d_max[u]) {\n        if (cnt_h[u][h_val] == 0) {\n            int old_h = d_max[u];\n            int new_h = 0;\n            // Scan downwards to find the new max height\n            for (int k = old_h - 1; k >= 0; --k) {\n                if (cnt_h[u][k] > 0) {\n                    new_h = k;\n                    break;\n                }\n            }\n            d_max[u] = new_h;\n            // Propagate change\n            remove_stat(p[u], old_h + 1);\n            add_stat(p[u], d_max[u] + 1);\n        }\n    }\n}\n\n// Update Sum of Beauty values upwards\nvoid update_S(int u, int diff) {\n    while (u != -1) {\n        S[u] += diff;\n        u = p[u];\n    }\n}\n\n// Reset all state variables\nvoid clear_state() {\n    fill(p, p + N, -1);\n    copy(A, A + N, S);\n    fill(d_max, d_max + N, 0);\n    for(int i=0; i<N; ++i) {\n        memset(cnt_h[i], 0, sizeof(cnt_h[i]));\n    }\n}\n\n// Calculate total score for validation/best tracking\nlong long calculate_total_score() {\n    long long sc = 0;\n    for (int i = 0; i < N; ++i) {\n        sc += (long long)(get_depth(i) + 1) * A[i];\n    }\n    return sc;\n}\n\nint main() {\n    // Optimize I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    if (!(cin >> N >> M >> H_in)) return 0;\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for (int i = 0; i < N; ++i) { int x, y; cin >> x >> y; }\n\n    auto start_time = chrono::steady_clock::now();\n\n    // ---------------------------------------------------------\n    // Phase 1: Randomized Greedy Construction\n    // ---------------------------------------------------------\n    vector<int> best_p(N);\n    long long best_score = -1;\n    int greedy_trials = 100; // Number of restarts\n\n    for (int t = 0; t < greedy_trials; ++t) {\n        clear_state();\n        \n        // Order vertices by Beauty (A), with noise for diversity\n        // Heuristic: Process smaller A first (likely to be roots/shallow), larger A later (deep).\n        vector<pair<float, int>> order(N);\n        for (int i = 0; i < N; ++i) {\n            float key = A[i];\n            if (t > 0) {\n                key *= (1.0f + std::uniform_real_distribution<float>(0.0f, 0.8f)(rng));\n            }\n            order[i] = {key, i};\n        }\n        sort(order.begin(), order.end());\n\n        for (auto& op : order) {\n            int v = op.second;\n            int best_u = -1;\n            int best_depth_val = -1;\n\n            vector<int>& neighbors = adj[v];\n            // Randomized start index for neighbor traversal\n            int start_idx = (t == 0) ? 0 : (rng() % (neighbors.size() + 1)); \n            if (neighbors.empty()) continue;\n\n            for(size_t k=0; k<neighbors.size(); ++k) {\n                int idx = (k + start_idx) % neighbors.size();\n                int u = neighbors[idx];\n                \n                // Check Cycle: u cannot be in v's subtree (v is ancestor of u)\n                if (is_ancestor(v, u)) continue; \n                \n                int depth_u = get_depth(u);\n                // Check Height: depth(u) + 1 + subtree_height(v) <= H\n                if (depth_u + 1 + d_max[v] <= H_in) {\n                    if (depth_u + 1 > best_depth_val) {\n                        best_depth_val = depth_u + 1;\n                        best_u = u;\n                        // Optimization: If we reached max possible improvement (greedy), stop\n                        if (best_depth_val == H_in - d_max[v]) break; \n                    }\n                }\n            }\n\n            if (best_u != -1) {\n                p[v] = best_u;\n                update_S(best_u, S[v]);\n                add_stat(best_u, d_max[v] + 1);\n            }\n        }\n\n        long long current_score = calculate_total_score();\n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) best_p[i] = p[i];\n        }\n    }\n\n    // ---------------------------------------------------------\n    // Phase 2: Simulated Annealing\n    // ---------------------------------------------------------\n    \n    // Restore best greedy state\n    clear_state();\n    for(int i=0; i<N; ++i) p[i] = best_p[i];\n    \n    // Efficiently rebuild S, d_max, and cnt_h bottom-up\n    vector<vector<int>> kids(N);\n    for(int i=0; i<N; ++i) if (p[i] != -1) kids[p[i]].push_back(i);\n    \n    vector<int> depth(N);\n    vector<vector<int>> nodes_by_depth(H_in + 2);\n    for(int i=0; i<N; ++i) {\n        depth[i] = get_depth(i);\n        int d_idx = min(depth[i], H_in + 1);\n        nodes_by_depth[d_idx].push_back(i);\n    }\n    \n    // Bottom-up traversal to set stats\n    for (int d = H_in; d >= 0; --d) {\n        for (int u : nodes_by_depth[d]) {\n            S[u] = A[u];\n            d_max[u] = 0;\n            for (int c : kids[u]) {\n                S[u] += S[c];\n                int h_c = d_max[c] + 1;\n                if (h_c <= H_in + 1) {\n                    cnt_h[u][h_c]++;\n                    if (h_c > d_max[u]) d_max[u] = h_c;\n                }\n            }\n        }\n    }\n\n    // SA Configuration\n    double time_limit = 1.96;\n    double T0 = 300.0; \n    double T1 = 0.05;\n    const double time_mult = log(T1/T0) / time_limit;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 2047) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        // 1. Pick random node v\n        int v = rng() % N;\n        int old_parent = p[v];\n        \n        // 2. Pick random candidate parent u\n        int u = -1;\n        if (!adj[v].empty()) {\n            // 3% chance to detach and become root, otherwise pick neighbor\n            if ((rng() & 31) == 0) u = -1;\n            else u = adj[v][rng() % adj[v].size()];\n        }\n        \n        if (u == old_parent) continue;\n        \n        // 3. Validity Checks\n        // Cycle: is v an ancestor of u?\n        if (is_ancestor(v, u)) continue; \n        \n        // Height: new depth + subtree height <= H\n        int u_depth = get_depth(u);\n        int new_depth_v = u_depth + 1;\n        \n        if (new_depth_v + d_max[v] > H_in) continue;\n        \n        // 4. Score Delta\n        // Delta = (new_depth - old_depth) * SubtreeSum(v)\n        int old_depth_v = get_depth(old_parent) + 1;\n        long long diff = (long long)(new_depth_v - old_depth_v) * S[v];\n        \n        // 5. Acceptance\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            double T = T0 * exp(time_mult * elapsed);\n            if (generate_canonical<double, 10>(rng) < exp(diff / T)) {\n                accept = true;\n            }\n        }\n        \n        // 6. Apply Move\n        if (accept) {\n            if (old_parent != -1) {\n                update_S(old_parent, -S[v]);\n                remove_stat(old_parent, d_max[v] + 1);\n            }\n            p[v] = u;\n            if (u != -1) {\n                update_S(u, S[v]);\n                add_stat(u, d_max[v] + 1);\n            }\n        }\n    }\n\n    // Output\n    for(int i=0; i<N; ++i) cout << p[i] << (i==N-1?\"\":\" \");\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <array>\n#include <random>\n#include <cstring>\n#include <bit>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_OPS = 4 * N * N;\nconst int INF = 1e9;\nconst char DIR_CHARS[] = {'L', 'R', 'U', 'D'};\n// Using a beam width optimized for performance with bitmask state representation.\n// 400 is generally safe with bitmasks within 2.0s.\nint BEAM_WIDTH = 400; \n\n// Time checking\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Zobrist Hashing\nunsigned long long zobrist[N][N][3]; // 0: ., 1: x, 2: o\nvoid init_zobrist() {\n    mt19937_64 rng(1337);\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            for(int k=0; k<3; ++k)\n                zobrist[i][j][k] = rng();\n}\n\n// Bitmask Utils\ninline int count_set_bits(uint32_t n) { return popcount(n); }\ninline int count_trailing_zeros(uint32_t n) { return countr_zero(n); }\ninline int count_leading_zeros(uint32_t n) { return countl_zero(n) - (32 - N); } // Adjust for 20 bits\n\nstruct Board {\n    uint32_t r_oni[N];  // Row view of Oni\n    uint32_t r_fuku[N]; // Row view of Fuku\n    uint32_t c_oni[N];  // Col view of Oni\n    uint32_t c_fuku[N]; // Col view of Fuku\n    unsigned long long hash;\n\n    // Recompute column masks from row masks\n    void sync_cols_from_rows() {\n        for(int j=0; j<N; ++j) {\n            c_oni[j] = 0;\n            c_fuku[j] = 0;\n            for(int i=0; i<N; ++i) {\n                if((r_oni[i] >> j) & 1) c_oni[j] |= (1 << i);\n                if((r_fuku[i] >> j) & 1) c_fuku[j] |= (1 << i);\n            }\n        }\n    }\n    \n    // Initialize from input\n    void init(const array<string, N>& s) {\n        hash = 0;\n        for(int i=0; i<N; ++i) {\n            r_oni[i] = 0;\n            r_fuku[i] = 0;\n            for(int j=0; j<N; ++j) {\n                if(s[i][j] == 'x') {\n                    r_oni[i] |= (1 << j);\n                    hash ^= zobrist[i][j][1];\n                } else if(s[i][j] == 'o') {\n                    r_fuku[i] |= (1 << j);\n                    hash ^= zobrist[i][j][2];\n                } else {\n                    hash ^= zobrist[i][j][0];\n                }\n            }\n        }\n        sync_cols_from_rows();\n    }\n};\n\nstruct Move {\n    char type; // P: Permanent, E: Eject\n    int dir;\n    int line;\n    int amount;\n};\n\nstruct Node {\n    int id;\n    int parent_id;\n    Move op;\n    int cost;\n    int heuristic;\n    int removed;\n    unsigned long long hash;\n    int total_score() const { return cost + heuristic; }\n};\n\n// Global Pools\nvector<Node> node_pool;\nvector<Board> board_pool;\n\n// Heuristic using bitmasks for O(N) calculation per row/col\nint calc_heuristic(const Board& b) {\n    int h = 0;\n    for(int r=0; r<N; ++r) {\n        uint32_t oni_row = b.r_oni[r];\n        if(oni_row == 0) continue;\n        \n        uint32_t fuku_row = b.r_fuku[r];\n        \n        // Iterate set bits\n        while(oni_row) {\n            int c = countr_zero(oni_row); // Index of LSB\n            oni_row &= (oni_row - 1); // Clear LSB\n            \n            int min_d = INF;\n            \n            // L check\n            if ((fuku_row & ((1<<c)-1)) == 0) {\n                min_d = min(min_d, c + 1);\n            }\n            // R check\n            if ((fuku_row & ~((1<<(c+1))-1) & ((1<<N)-1)) == 0) {\n                min_d = min(min_d, N - c);\n            }\n            \n            uint32_t fuku_col = b.c_fuku[c];\n            // U check\n            if ((fuku_col & ((1<<r)-1)) == 0) {\n                min_d = min(min_d, r + 1);\n            }\n            // D check\n            if ((fuku_col & ~((1<<(r+1))-1) & ((1<<N)-1)) == 0) {\n                min_d = min(min_d, N - r);\n            }\n            \n            if(min_d == INF) h += 200;\n            else h += min_d;\n        }\n    }\n    return h;\n}\n\n// Apply Permanent Shift\nvoid apply_perm(Board& b, int dir, int line, int amt) {\n    if (dir == 0) { // Left Shift Row\n        uint32_t old_oni = b.r_oni[line];\n        uint32_t old_fuku = b.r_fuku[line];\n        b.r_oni[line] = (old_oni >> amt);\n        b.r_fuku[line] = (old_fuku >> amt);\n        b.sync_cols_from_rows();\n    } else if (dir == 1) { // Right Shift Row\n        uint32_t old_oni = b.r_oni[line];\n        uint32_t old_fuku = b.r_fuku[line];\n        b.r_oni[line] = (old_oni << amt) & ((1<<N)-1);\n        b.r_fuku[line] = (old_fuku << amt) & ((1<<N)-1);\n        b.sync_cols_from_rows();\n    } else if (dir == 2) { // Up Shift Col\n        uint32_t old_oni = b.c_oni[line];\n        uint32_t old_fuku = b.c_fuku[line];\n        b.c_oni[line] = (old_oni >> amt);\n        b.c_fuku[line] = (old_fuku >> amt);\n        // Sync Rows from Cols logic\n        for(int r=0; r<N; ++r) {\n            b.r_oni[r] &= ~(1 << line);\n            b.r_fuku[r] &= ~(1 << line);\n            if((b.c_oni[line] >> r) & 1) b.r_oni[r] |= (1 << line);\n            if((b.c_fuku[line] >> r) & 1) b.r_fuku[r] |= (1 << line);\n        }\n    } else { // Down Shift Col\n        uint32_t old_oni = b.c_oni[line];\n        uint32_t old_fuku = b.c_fuku[line];\n        b.c_oni[line] = (old_oni << amt) & ((1<<N)-1);\n        b.c_fuku[line] = (old_fuku << amt) & ((1<<N)-1);\n        for(int r=0; r<N; ++r) {\n            b.r_oni[r] &= ~(1 << line);\n            b.r_fuku[r] &= ~(1 << line);\n            if((b.c_oni[line] >> r) & 1) b.r_oni[r] |= (1 << line);\n            if((b.c_fuku[line] >> r) & 1) b.r_fuku[r] |= (1 << line);\n        }\n    }\n    \n    // Recompute hash\n    b.hash = 0;\n    for(int i=0; i<N; ++i) {\n        uint32_t r_o = b.r_oni[i];\n        uint32_t r_f = b.r_fuku[i];\n        for(int j=0; j<N; ++j) {\n            if((r_o >> j) & 1) b.hash ^= zobrist[i][j][1];\n            else if((r_f >> j) & 1) b.hash ^= zobrist[i][j][2];\n            else b.hash ^= zobrist[i][j][0];\n        }\n    }\n}\n\n// Apply Eject (Clear range)\nvoid apply_eject(Board& b, int dir, int line, int amt) {\n    uint32_t mask = 0;\n    if (dir == 0) { // Clear first amt bits\n        mask = (1 << amt) - 1;\n        b.r_oni[line] &= ~mask;\n        b.r_fuku[line] &= ~mask;\n        b.sync_cols_from_rows();\n    } else if (dir == 1) { // Clear last amt bits\n        mask = ~((1 << (N - amt)) - 1) & ((1 << N) - 1);\n        b.r_oni[line] &= ~mask;\n        b.r_fuku[line] &= ~mask;\n        b.sync_cols_from_rows();\n    } else if (dir == 2) { // U\n        mask = (1 << amt) - 1;\n        b.c_oni[line] &= ~mask;\n        b.c_fuku[line] &= ~mask;\n        for(int r=0; r<amt; ++r) {\n             b.r_oni[r] &= ~(1 << line);\n             b.r_fuku[r] &= ~(1 << line);\n        }\n    } else { // D\n        for(int r=N-amt; r<N; ++r) {\n             b.r_oni[r] &= ~(1 << line);\n             b.r_fuku[r] &= ~(1 << line);\n        }\n        mask = ~((1 << (N - amt)) - 1) & ((1 << N) - 1);\n        b.c_oni[line] &= ~mask;\n        b.c_fuku[line] &= ~mask;\n    }\n    \n    b.hash = 0;\n    for(int i=0; i<N; ++i) {\n        uint32_t r_o = b.r_oni[i];\n        uint32_t r_f = b.r_fuku[i];\n        for(int j=0; j<N; ++j) {\n            if((r_o >> j) & 1) b.hash ^= zobrist[i][j][1];\n            else if((r_f >> j) & 1) b.hash ^= zobrist[i][j][2];\n            else b.hash ^= zobrist[i][j][0];\n        }\n    }\n}\n\nint count_oni(const Board& b) {\n    int c = 0;\n    for(int i=0; i<N; ++i) c += count_set_bits(b.r_oni[i]);\n    return c;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    init_zobrist();\n\n    int dummy; if(cin >> dummy){}\n    \n    array<string, N> raw_board;\n    for(int i=0; i<N; ++i) cin >> raw_board[i];\n    \n    Board start_b;\n    start_b.init(raw_board);\n    \n    int start_oni = count_oni(start_b);\n    \n    // Preallocate to avoid reallocation and pointer invalidation\n    node_pool.reserve(1000000);\n    board_pool.reserve(1000000);\n    \n    Node root;\n    root.id = 0;\n    root.parent_id = -1;\n    root.cost = 0;\n    root.heuristic = calc_heuristic(start_b);\n    root.removed = 0;\n    root.op = {' ', -1, -1, -1};\n    root.hash = start_b.hash;\n    \n    node_pool.push_back(root);\n    board_pool.push_back(start_b);\n    \n    vector<vector<int>> beams(start_oni + 1);\n    beams[0].push_back(0);\n    \n    for(int k=0; k<start_oni; ++k) {\n        if(beams[k].empty()) continue;\n        \n        // Check time remaining\n        if(get_time() > 1.85) {\n            BEAM_WIDTH = 10; \n        }\n        \n        // Sort to find duplicates\n        sort(beams[k].begin(), beams[k].end(), [&](int a, int b){\n             if(node_pool[a].hash != node_pool[b].hash) return node_pool[a].hash < node_pool[b].hash;\n             return node_pool[a].cost < node_pool[b].cost;\n        });\n        \n        vector<int> unique_beam;\n        if(!beams[k].empty()) {\n            unique_beam.push_back(beams[k][0]);\n            for(size_t i=1; i<beams[k].size(); ++i) {\n                int curr = beams[k][i];\n                int prev = unique_beam.back();\n                if(node_pool[curr].hash != node_pool[prev].hash) {\n                    unique_beam.push_back(curr);\n                }\n            }\n        }\n        \n        // Sort by Total Score (Heuristic + Cost)\n        sort(unique_beam.begin(), unique_beam.end(), [&](int a, int b){\n            return node_pool[a].total_score() < node_pool[b].total_score();\n        });\n        \n        if(unique_beam.size() > BEAM_WIDTH) unique_beam.resize(BEAM_WIDTH);\n        \n        for(int idx : unique_beam) {\n            // Copy by value is cheap with bitmasks (approx 320 bytes)\n            Node curr_node = node_pool[idx];\n            Board curr_b = board_pool[idx];\n            \n            if(curr_node.cost >= MAX_OPS) continue;\n            \n            for(int dir=0; dir<4; ++dir) {\n                for(int line=0; line<N; ++line) {\n                    // Determine Max Safe Shift\n                    int max_safe = 0;\n                    \n                    if(dir == 0) { // L: check row 'line' from 0\n                        uint32_t f = curr_b.r_fuku[line];\n                        if(f == 0) max_safe = N;\n                        else max_safe = countr_zero(f);\n                    } else if(dir == 1) { // R: check row 'line' from N-1\n                        uint32_t f = curr_b.r_fuku[line];\n                        if(f == 0) max_safe = N;\n                        else max_safe = countl_zero(f) - (32 - N);\n                    } else if(dir == 2) { // U: check col 'line'\n                        uint32_t f = curr_b.c_fuku[line];\n                        if(f == 0) max_safe = N;\n                        else max_safe = countr_zero(f);\n                    } else { // D: check col 'line'\n                         uint32_t f = curr_b.c_fuku[line];\n                        if(f == 0) max_safe = N;\n                        else max_safe = countl_zero(f) - (32 - N);\n                    }\n                    \n                    if(max_safe == 0) continue;\n                    \n                    // Candidates: First and Last Oni in range\n                    int first_s = -1, last_s = -1;\n                    \n                    uint32_t oni_line;\n                    if(dir < 2) oni_line = curr_b.r_oni[line];\n                    else oni_line = curr_b.c_oni[line];\n                    \n                    if(dir == 0 || dir == 2) {\n                        uint32_t safe_mask = (1 << max_safe) - 1;\n                        uint32_t target = oni_line & safe_mask;\n                        if(target == 0) continue;\n                        first_s = countr_zero(target) + 1;\n                        last_s = 32 - countl_zero(target); \n                    } else {\n                        uint32_t safe_mask = ~((1 << (N - max_safe)) - 1) & ((1 << N) - 1);\n                        uint32_t target = oni_line & safe_mask;\n                        if(target == 0) continue;\n                        int highest_bit = 31 - countl_zero(target);\n                        int lowest_bit = countr_zero(target);\n                        first_s = N - highest_bit;\n                        last_s = N - lowest_bit;\n                    }\n                    \n                    int candidates[2] = {first_s, last_s};\n                    int cand_cnt = (first_s == last_s) ? 1 : 2;\n                    \n                    for(int i=0; i<cand_cnt; ++i) {\n                        int s = candidates[i];\n                        int delta = 0;\n                        if(dir == 0 || dir == 2) {\n                             uint32_t mask = (1 << s) - 1;\n                             delta = count_set_bits(oni_line & mask);\n                        } else {\n                             uint32_t mask = ~((1 << (N - s)) - 1) & ((1 << N) - 1);\n                             delta = count_set_bits(oni_line & mask);\n                        }\n                        \n                        int next_removed = min(start_oni, curr_node.removed + delta);\n                        \n                        // Perm\n                        if(curr_node.cost + s <= MAX_OPS) {\n                            Board next_b = curr_b;\n                            apply_perm(next_b, dir, line, s);\n                            \n                            Node next_node;\n                            next_node.id = (int)node_pool.size();\n                            next_node.parent_id = idx;\n                            next_node.cost = curr_node.cost + s;\n                            next_node.heuristic = calc_heuristic(next_b);\n                            next_node.removed = next_removed;\n                            next_node.op = {'P', dir, line, s};\n                            next_node.hash = next_b.hash;\n                            \n                            node_pool.push_back(next_node);\n                            board_pool.push_back(next_b);\n                            beams[next_removed].push_back(next_node.id);\n                        }\n                        \n                        // Eject\n                         if(curr_node.cost + 2*s <= MAX_OPS) {\n                            Board next_b = curr_b;\n                            apply_eject(next_b, dir, line, s);\n                            \n                            Node next_node;\n                            next_node.id = (int)node_pool.size();\n                            next_node.parent_id = idx;\n                            next_node.cost = curr_node.cost + 2*s;\n                            next_node.heuristic = calc_heuristic(next_b);\n                            next_node.removed = next_removed;\n                            next_node.op = {'E', dir, line, s};\n                            next_node.hash = next_b.hash;\n                            \n                            node_pool.push_back(next_node);\n                            board_pool.push_back(next_b);\n                            beams[next_removed].push_back(next_node.id);\n                        }\n                    }\n                }\n            }\n        }\n        vector<int>().swap(beams[k]);\n    }\n    \n    int best_idx = -1;\n    int min_cost = INF;\n    \n    if(!beams[start_oni].empty()) {\n        for(int idx : beams[start_oni]) {\n            if(node_pool[idx].cost < min_cost) {\n                min_cost = node_pool[idx].cost;\n                best_idx = idx;\n            }\n        }\n    } else {\n        for(int k=start_oni-1; k>=0; --k) {\n            if(!beams[k].empty()) {\n                for(int idx : beams[k]) {\n                    if(node_pool[idx].cost < min_cost) {\n                        min_cost = node_pool[idx].cost;\n                        best_idx = idx;\n                    }\n                }\n                break;\n            }\n        }\n    }\n    \n    if(best_idx != -1) {\n        vector<pair<string, int>> output;\n        int curr = best_idx;\n        while(node_pool[curr].parent_id != -1) {\n            const Move& m = node_pool[curr].op;\n            char d = DIR_CHARS[m.dir];\n            if(m.type == 'P') {\n                for(int i=0; i<m.amount; ++i) output.push_back({string(1, d), m.line});\n            } else {\n                char opp = DIR_CHARS[m.dir ^ 1];\n                for(int i=0; i<m.amount; ++i) output.push_back({string(1, opp), m.line});\n                for(int i=0; i<m.amount; ++i) output.push_back({string(1, d), m.line});\n            }\n            curr = node_pool[curr].parent_id;\n        }\n        reverse(output.begin(), output.end());\n        for(const auto& p : output) cout << p.first << \" \" << p.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\n// ==========================================\n// Constants & Globals\n// ==========================================\nconst int N = 100;\nconst int L_TOTAL = 500000;\n\n// Input\nint T[N];\n\n// Graph State\n// Flattened Adjacency List for locality:\n// adj[2*i]     -> B_i (target for even visit counts)\n// adj[2*i + 1] -> A_i (target for odd visit counts)\nint adj[2 * N]; \nint best_adj[2 * N];\n\n// Simulation Counts\nint sim_counts[N];\nint backup_counts[N]; // To restore state upon rejection\n\n// Phase 1 State (Flow Proxy)\nint current_inflow[N];\nint est_flow[2 * N]; // est_flow[2*u] for B, [2*u+1] for A\n\n// Time Control\nauto start_time = chrono::high_resolution_clock::now();\nconst double TIME_LIMIT = 1.96; // Safe margin below 2.0s\n\n// Fast RNG\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967295.0;\n    }\n} rng;\n\n// ==========================================\n// Logic Functions\n// ==========================================\n\n// Phase 1: Static Flow Proxy Error\n// Calculates error based on expected flow vs target T.\n// Adds heavy penalty for unreachable nodes to ensure connectivity.\nlong long calc_flow_error() {\n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        int target = T[i];\n        if (i == 0 && target > 0) target--;\n        err += abs(current_inflow[i] - target);\n    }\n    \n    // Reachability BFS\n    static bool visited[N];\n    memset(visited, 0, N);\n    static int q[N];\n    int head = 0, tail = 0;\n    \n    if (T[0] > 0 || N==1) { \n         visited[0] = true;\n         q[tail++] = 0;\n    }\n\n    while(head < tail) {\n        int u = q[head++];\n        // Check A (odd -> index 2*u + 1)\n        if (est_flow[2*u + 1] > 0) {\n            int v = adj[2*u + 1];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n        // Check B (even -> index 2*u)\n        if (est_flow[2*u] > 0) {\n            int v = adj[2*u];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n    }\n    \n    int unreached = 0;\n    for(int i=0; i<N; ++i) {\n        if (!visited[i]) unreached += T[i];\n    }\n    return err + (long long)unreached * 5000;\n}\n\n// Phase 2: Simulation\n// Runs the simulation for 'length' steps.\n// Returns sum of absolute errors |actual - target|.\n// Optimized for speed (minimal memory indirection).\nlong long run_simulation(int length, const int* targets) {\n    memset(sim_counts, 0, N * sizeof(int));\n    \n    int curr = 0;\n    sim_counts[0]++;\n    \n    // Local pointers for compiler optimization\n    const int* adj_ptr = adj;\n    int* counts_ptr = sim_counts;\n    \n    // Simulation Loop\n    // Week 1: curr=0. End of Week 1: sim_counts[0]=1.\n    // Week k: Check sim_counts[prev]. If odd -> A, even -> B.\n    // sim_counts[prev] & 1  => 1 if odd (A), 0 if even (B).\n    // Mapping: A is at index 2*curr+1, B is at index 2*curr.\n    // Formula: 2*curr + (count & 1) maps correctly.\n    \n    for (int k = 1; k < length; ++k) {\n        int cnt = counts_ptr[curr];\n        int type = cnt & 1; \n        int next_node = adj_ptr[2*curr + type];\n        counts_ptr[next_node]++;\n        curr = next_node;\n    }\n    \n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(counts_ptr[i] - targets[i]);\n    }\n    return err;\n}\n\n// Helper for Directed Move Candidates\nstruct Candidate {\n    int u;     // Source node\n    int type;  // 0 for B, 1 for A\n    int prev_target;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, l_in;\n    if (cin >> n_in >> l_in) {}\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // Setup Flow Estimates for Phase 1\n    for(int i=0; i<N; ++i) {\n        est_flow[2*i + 1] = (T[i] + 1) / 2; // A (Odd)\n        est_flow[2*i]     = T[i] / 2;       // B (Even)\n    }\n\n    // --- Initial Construction: Greedy Bin Packing ---\n    // Assign outgoing edges (Plugs) to nodes with capacity (Sockets)\n    struct Plug { int u; int type; int val; };\n    vector<Plug> plugs; \n    plugs.reserve(2*N);\n    for(int i=0; i<N; ++i) {\n        if (est_flow[2*i + 1] > 0) plugs.push_back({i, 1, est_flow[2*i + 1]});\n        if (est_flow[2*i] > 0)     plugs.push_back({i, 0, est_flow[2*i]});\n    }\n    sort(plugs.begin(), plugs.end(), [](const Plug& a, const Plug& b){\n        return a.val > b.val;\n    });\n\n    // Default initialization\n    for(int i=0; i<N; ++i) {\n        adj[2*i] = (i + 1) % N;\n        adj[2*i+1] = (i + 1) % N;\n    }\n    \n    vector<int> cap(N);\n    for(int i=0; i<N; ++i) cap[i] = T[i];\n    if (cap[0] > 0) cap[0]--;\n    \n    memset(current_inflow, 0, sizeof(current_inflow));\n    \n    for(const auto& p : plugs) {\n        int best = -1, max_rem = -2e9;\n        // Random start index to distribute flow more evenly\n        int start = rng.next_int(N);\n        for(int k=0; k<N; ++k) {\n            int v = (start + k) % N;\n            if (cap[v] > max_rem) { max_rem = cap[v]; best = v; }\n        }\n        adj[2*p.u + p.type] = best;\n        cap[best] -= p.val;\n        current_inflow[best] += p.val;\n    }\n    \n    memcpy(best_adj, adj, sizeof(adj));\n\n    // --- Phase 1: Flow Proxy Optimization (0.0s - 0.15s) ---\n    // Heuristic optimization to establish topology and rough flow balance.\n    {\n        long long cur_err = calc_flow_error();\n        double temp = 100.0;\n        while(true) {\n            if (chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count() > 0.15) break;\n            \n            int u = rng.next_int(N);\n            if (T[u] == 0) continue;\n            int type = (est_flow[2*u] > 0) ? rng.next_int(2) : 1;\n            int idx = 2*u + type;\n            int val = est_flow[idx];\n            if (val == 0) continue;\n            \n            int old_v = adj[idx];\n            int new_v = rng.next_int(N);\n            if (old_v == new_v) continue;\n            \n            // Apply\n            current_inflow[old_v] -= val;\n            current_inflow[new_v] += val;\n            adj[idx] = new_v;\n            \n            long long next_err = calc_flow_error();\n            long long delta = next_err - cur_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_err = next_err;\n            } else {\n                // Revert\n                current_inflow[old_v] += val;\n                current_inflow[new_v] -= val;\n                adj[idx] = old_v;\n            }\n            temp *= 0.995;\n            if (temp < 0.5) temp = 0.5;\n        }\n    }\n    \n    memcpy(best_adj, adj, sizeof(adj));\n\n    // --- Phase 2: Multi-Stage Simulation ---\n    // Run simulations of increasing length to fine-tune the solution.\n    // Stage 1: 30k steps (Fast, coarse adjustment)\n    // Stage 2: 100k steps (Medium precision)\n    // Stage 3: 500k steps (Exact, final tuning)\n    struct Stage { int L; double end_t; };\n    vector<Stage> stages = { {30000, 0.4}, {100000, 0.8}, {L_TOTAL, TIME_LIMIT} };\n    \n    vector<int> current_T(N);\n    vector<int> surplus, deficit;\n    surplus.reserve(N); deficit.reserve(N);\n    vector<Candidate> candidates;\n    candidates.reserve(N);\n    \n    long long global_best_err = -1;\n    \n    for(const auto& stage : stages) {\n        // Scale Target T to current stage length\n        long long sT = 0;\n        for(int i=0; i<N; ++i) {\n            current_T[i] = (long long)T[i] * stage.L / L_TOTAL;\n            sT += current_T[i];\n        }\n        // Fix rounding errors\n        while(sT < stage.L) {\n            int i = rng.next_int(N);\n            if (T[i] > 0) { current_T[i]++; sT++; }\n        }\n        \n        long long cur_err = run_simulation(stage.L, current_T.data());\n        memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n        \n        if (stage.L == L_TOTAL) {\n            global_best_err = cur_err;\n            memcpy(best_adj, adj, sizeof(adj));\n        }\n        \n        double temp = 50.0;\n        int iter_mask = 255; // Check time every 256 iterations\n\n        int iter_cnt = 0;\n        while(true) {\n            iter_cnt++;\n            if ((iter_cnt & iter_mask) == 0) {\n                 if (chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count() > stage.end_t) break;\n            }\n            \n            // --- Move Selection ---\n            int u = -1, type = -1, old_v = -1, new_v = -1;\n            bool directed = false;\n            \n            // Strategy 1: Directed Redirect (Surplus -> Deficit)\n            // Try to relieve pressure from a surplus node by redirecting one of its incoming edges\n            // to a deficit node.\n            if (rng.next_double() < 0.75) {\n                surplus.clear(); deficit.clear();\n                for(int i=0; i<N; ++i) {\n                    if (sim_counts[i] > current_T[i]) surplus.push_back(i);\n                    else if (sim_counts[i] < current_T[i]) deficit.push_back(i);\n                }\n                \n                if (!surplus.empty() && !deficit.empty()) {\n                    // Pick a random Deficit node as destination\n                    int target_def = deficit[rng.next_int(deficit.size())];\n                    \n                    // Find incoming edges to ANY surplus node (sampling for efficiency)\n                    candidates.clear();\n                    int attempts = 20; \n                    while(attempts--) {\n                         int cand_u = rng.next_int(N);\n                         if (T[cand_u] == 0) continue;\n                         \n                         // Check A (type 1)\n                         int vA = adj[2*cand_u + 1];\n                         // Condition: edge is used at least once AND points to surplus\n                         if (sim_counts[cand_u] >= 1 && sim_counts[vA] > current_T[vA]) {\n                             candidates.push_back({cand_u, 1, vA});\n                         }\n                         // Check B (type 0)\n                         if (T[cand_u] > 1) {\n                             int vB = adj[2*cand_u];\n                             if (sim_counts[cand_u] >= 2 && sim_counts[vB] > current_T[vB]) {\n                                 candidates.push_back({cand_u, 0, vB});\n                             }\n                         }\n                    }\n                    \n                    if (!candidates.empty()) {\n                        const auto& c = candidates[rng.next_int(candidates.size())];\n                        u = c.u; type = c.type; old_v = c.prev_target;\n                        new_v = target_def;\n                        if (old_v != new_v) directed = true;\n                    }\n                }\n            }\n            \n            // Strategy 2 & 3: Swap or Random Redirect\n            if (!directed) {\n                // Strategy 2: Swap Targets (Exploration)\n                if (rng.next_double() < 0.2) { \n                    int u1 = rng.next_int(N);\n                    if (T[u1] == 0) continue;\n                    int t1 = (T[u1] > 1) ? rng.next_int(2) : 1;\n                    \n                    int u2 = rng.next_int(N);\n                    if (T[u2] == 0 || u1 == u2) continue;\n                    int t2 = (T[u2] > 1) ? rng.next_int(2) : 1;\n                    \n                    int v1 = adj[2*u1 + t1];\n                    int v2 = adj[2*u2 + t2];\n                    \n                    if (v1 != v2) {\n                        // Apply Swap\n                        adj[2*u1 + t1] = v2;\n                        adj[2*u2 + t2] = v1;\n                        \n                        long long next_err = run_simulation(stage.L, current_T.data());\n                        long long delta = next_err - cur_err;\n                        \n                        if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                            cur_err = next_err;\n                            memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n                            if (stage.L == L_TOTAL && cur_err < global_best_err) {\n                                global_best_err = cur_err;\n                                memcpy(best_adj, adj, sizeof(adj));\n                            }\n                        } else {\n                            // Revert\n                            adj[2*u1 + t1] = v1;\n                            adj[2*u2 + t2] = v2;\n                            memcpy(sim_counts, backup_counts, sizeof(sim_counts));\n                        }\n                        temp *= 0.9995;\n                        if (temp < 0.5) temp = 0.5;\n                        continue; // Skip standard revert logic below\n                    }\n                }\n                \n                // Strategy 3: Random Redirect (Fallback)\n                u = rng.next_int(N);\n                if (T[u] == 0) continue;\n                type = (T[u] > 1) ? rng.next_int(2) : 1;\n                old_v = adj[2*u + type];\n                new_v = rng.next_int(N);\n            }\n            \n            if (u == -1 || old_v == new_v) continue;\n            \n            // Apply Redirect\n            adj[2*u + type] = new_v;\n            \n            long long next_err = run_simulation(stage.L, current_T.data());\n            long long delta = next_err - cur_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_err = next_err;\n                memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n                if (stage.L == L_TOTAL && cur_err < global_best_err) {\n                    global_best_err = cur_err;\n                    memcpy(best_adj, adj, sizeof(adj));\n                }\n            } else {\n                // Revert\n                adj[2*u + type] = old_v;\n                // Restore sim_counts from backup (crucial for directed moves logic)\n                memcpy(sim_counts, backup_counts, sizeof(sim_counts));\n            }\n            \n            temp *= 0.9995;\n            if (temp < 0.5) temp = 0.5;\n        }\n    }\n\n    // Output Best Solution\n    for(int i=0; i<N; ++i) {\n        // Output format: A_i B_i\n        // adj stored as: adj[2*i] = B, adj[2*i+1] = A\n        cout << best_adj[2*i + 1] << \" \" << best_adj[2*i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#pragma GCC optimize(\"O3,unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// --------------------------------------------------------------------------\n// Global Variables\n// --------------------------------------------------------------------------\nint N, M, Q, L, W;\nvector<int> G;\nint pos_x[805];\nint pos_y[805];\nint dist_matrix[805][805]; \n\n// Group management\nvector<int> city_group; \nvector<vector<int>> groups;\nvector<long long> grp_sum_x, grp_sum_y; // Centroids\n\n// KNN\nconst int K_NN = 32; \nconst int DENSE_THRESHOLD = 55; \nconst int CANDIDATE_SAMPLE_SIZE = 12; \n\nstruct Neighbor {\n    int to;\n    int w_sq;\n};\nvector<vector<Neighbor>> knn_adj; \n\n// --------------------------------------------------------------------------\n// Utils\n// --------------------------------------------------------------------------\nstruct XorShift {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return next() * (1.0 / 4294967296.0);\n    }\n} rng;\n\nlong long hilbert(int x, int y, int pow, int rotate) {\n    if (pow == 0) return 0;\n    int hpow = 1 << (pow - 1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rotate) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rotate + rotateDelta[seg]) & 3;\n    long long subSquareSize = 1LL << (2 * pow - 2);\n    long long ans = seg * subSquareSize;\n    long long add = hilbert(nx, ny, pow - 1, nrot);\n    ans += (seg == 1 || seg == 2) ? add : (subSquareSize - 1 - add);\n    return ans;\n}\n\n// --------------------------------------------------------------------------\n// DSU\n// --------------------------------------------------------------------------\nstruct DSU {\n    int p[805];\n    void reset() { memset(p, -1, sizeof(p)); }\n    int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (p[x] > p[y]) swap(x, y);\n        p[x] += p[y];\n        p[y] = x;\n        return true;\n    }\n} dsu_calc;\n\n// --------------------------------------------------------------------------\n// Cost Calculation\n// --------------------------------------------------------------------------\n// Dense MST: O(K^2)\ndouble compute_dense_mst(const vector<int>& grp) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    static int min_dist[805];\n    static bool visited[805];\n    \n    for(int i=0; i<k; ++i) {\n        min_dist[i] = 2e9; \n        visited[i] = false;\n    }\n    \n    min_dist[0] = 0;\n    double total = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        int cur_min = 2e9;\n        \n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur_min) {\n                cur_min = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        if(i > 0) total += sqrt(cur_min);\n        \n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                int d = dist_matrix[city_u][grp[v]];\n                if(d < min_dist[v]) min_dist[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\n// Sparse MST: O(K * K_NN log(K*K_NN)) -> dominated by sort\nstruct LocalEdge {\n    int u, v;\n    int w_sq;\n    bool operator<(const LocalEdge& other) const { return w_sq < other.w_sq; }\n};\n\nvector<LocalEdge> edge_buffer;\n\ndouble compute_sparse_mst(const vector<int>& grp, int group_idx) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    edge_buffer.clear();\n    \n    for(int u : grp) {\n        const auto& neighbors = knn_adj[u];\n        for(const auto& nb : neighbors) {\n            int v = nb.to;\n            if (v > u && city_group[v] == group_idx) {\n                edge_buffer.push_back({u, v, nb.w_sq});\n            }\n        }\n    }\n    \n    if ((int)edge_buffer.size() < k - 1) return -1.0;\n    \n    sort(edge_buffer.begin(), edge_buffer.end());\n    \n    dsu_calc.reset();\n    int edges_count = 0;\n    double total = 0;\n    \n    for(const auto& e : edge_buffer) {\n        if(dsu_calc.unite(e.u, e.v)) {\n            total += sqrt(e.w_sq);\n            edges_count++;\n            if(edges_count == k - 1) return total;\n        }\n    }\n    \n    return -1.0;\n}\n\ndouble get_group_cost(const vector<int>& grp, int group_idx) {\n    if (grp.size() <= DENSE_THRESHOLD) {\n        return compute_dense_mst(grp);\n    } else {\n        double res = compute_sparse_mst(grp, group_idx);\n        if (res < 0) return compute_dense_mst(grp);\n        return res;\n    }\n}\n\n// --------------------------------------------------------------------------\n// Main Logic\n// --------------------------------------------------------------------------\n\nvector<pair<int, int>> get_mst_edges_final(const vector<int>& grp) {\n    if (grp.size() <= 1) return {};\n    int k = grp.size();\n    vector<int> min_dist(k, 2e9);\n    vector<int> parent(k, -1);\n    vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        int cur = 2e9;\n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur) {\n                cur = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        int city_u = grp[u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                int d = dist_matrix[city_u][grp[v]];\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    vector<pair<int, int>> result;\n    for(int i=1; i<k; ++i) {\n        if(parent[i] != -1) result.push_back({grp[i], grp[parent[i]]});\n    }\n    return result;\n}\n\nvector<int> rem_nodes;\nvector<vector<int>> planned_queries;\nvector<vector<int>> adj_tree;\n\nvoid dfs_query(int u, int p) {\n    int subtree_start = rem_nodes.size();\n    for (int v : adj_tree[u]) {\n        if (v == p) continue;\n        dfs_query(v, u);\n    }\n    rem_nodes.push_back(u);\n    \n    int count = rem_nodes.size() - subtree_start; \n    while (count >= L) {\n        vector<int> q;\n        q.reserve(L);\n        q.push_back(u);\n        for(int i=0; i<L-1; ++i) {\n            q.push_back(rem_nodes[subtree_start]);\n            rem_nodes.erase(rem_nodes.begin() + subtree_start);\n        }\n        planned_queries.push_back(q);\n        count -= (L - 1);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    edge_buffer.reserve(25000);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        pos_x[i] = (lx + rx) / 2;\n        pos_y[i] = (ly + ry) / 2;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    for(int i=0; i<N; ++i) {\n        dist_matrix[i][i] = 0;\n        for(int j=i+1; j<N; ++j) {\n            int dx = pos_x[i] - pos_x[j];\n            int dy = pos_y[i] - pos_y[j];\n            int d = dx*dx + dy*dy;\n            dist_matrix[i][j] = dist_matrix[j][i] = d;\n        }\n    }\n\n    knn_adj.resize(N);\n    vector<pair<int, int>> row_dists(N);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (i==j) row_dists[j] = {2e9, j}; \n            else row_dists[j] = {dist_matrix[i][j], j};\n        }\n        int k_target = min(N-1, K_NN + 5);\n        nth_element(row_dists.begin(), row_dists.begin() + k_target, row_dists.end());\n        \n        for(int k=0; k<k_target; ++k) {\n            knn_adj[i].push_back({row_dists[k].second, row_dists[k].first});\n        }\n    }\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int i, int j) {\n        return hilbert(pos_x[i], pos_y[i], 14, 0) < hilbert(pos_x[j], pos_y[j], 14, 0);\n    });\n\n    groups.resize(M);\n    city_group.resize(N);\n    grp_sum_x.assign(M, 0);\n    grp_sum_y.assign(M, 0);\n\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].reserve(G[i] + 16);\n        for (int k = 0; k < G[i]; ++k) {\n            int u = p[current_idx++];\n            groups[i].push_back(u);\n            city_group[u] = i;\n            grp_sum_x[i] += pos_x[u];\n            grp_sum_y[i] += pos_y[u];\n        }\n    }\n\n    vector<double> group_costs(M);\n    double total_cost = 0;\n    for(int i=0; i<M; ++i) {\n        group_costs[i] = get_group_cost(groups[i], i);\n        total_cost += group_costs[i];\n    }\n\n    double time_limit = 1.85;\n    double start_temp = 300.0;\n    double end_temp = 0.05;\n    \n    int iter = 0;\n    int nb_candidates[64]; \n\n    while(true) {\n        iter++;\n        if ((iter & 127) == 0) { \n            double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        int u = rng.next_int(N);\n        int g1 = city_group[u];\n        int g2 = -1;\n        int v = -1;\n\n        int nb_count = 0;\n        const auto& nbs = knn_adj[u];\n        int limit = min((int)nbs.size(), 20); \n        for(int k=0; k<limit; ++k) {\n            int nb = nbs[k].to;\n            if (city_group[nb] != g1) {\n                nb_candidates[nb_count++] = nb;\n            }\n        }\n\n        if (nb_count > 0 && rng.next_double() < 0.75) {\n            int neighbor = nb_candidates[rng.next_int(nb_count)];\n            g2 = city_group[neighbor];\n            \n            long long g1_cx = grp_sum_x[g1] / (long long)groups[g1].size();\n            long long g1_cy = grp_sum_y[g1] / (long long)groups[g1].size();\n            \n            long long best_dist = 9e18;\n            int g2_size = groups[g2].size();\n            int samples = min(g2_size, CANDIDATE_SAMPLE_SIZE);\n            \n            for(int k=0; k<samples; ++k) {\n                int cand;\n                if(g2_size <= CANDIDATE_SAMPLE_SIZE) cand = groups[g2][k];\n                else cand = groups[g2][rng.next_int(g2_size)];\n                \n                long long dx = pos_x[cand] - g1_cx;\n                long long dy = pos_y[cand] - g1_cy;\n                long long d = dx*dx + dy*dy;\n                if (d < best_dist) { best_dist = d; v = cand; }\n            }\n\n        } else {\n            g2 = rng.next_int(M);\n            if (g1 == g2) continue;\n            \n            long long g1_cx = grp_sum_x[g1] / (long long)groups[g1].size();\n            long long g1_cy = grp_sum_y[g1] / (long long)groups[g1].size();\n            \n            long long best_dist = 9e18;\n            int g2_size = groups[g2].size();\n            int samples = min(g2_size, CANDIDATE_SAMPLE_SIZE);\n            \n            for(int k=0; k<samples; ++k) {\n                int cand;\n                if(g2_size <= CANDIDATE_SAMPLE_SIZE) cand = groups[g2][k];\n                else cand = groups[g2][rng.next_int(g2_size)];\n                \n                long long dx = pos_x[cand] - g1_cx;\n                long long dy = pos_y[cand] - g1_cy;\n                long long d = dx*dx + dy*dy;\n                if (d < best_dist) { best_dist = d; v = cand; }\n            }\n        }\n        \n        if (v == -1) continue;\n\n        int idx_u = -1;\n        for(int k=0; k<(int)groups[g1].size(); ++k) if(groups[g1][k] == u) { idx_u = k; break; }\n        \n        int idx_v = -1;\n        for(int k=0; k<(int)groups[g2].size(); ++k) if(groups[g2][k] == v) { idx_v = k; break; }\n        \n        swap(groups[g1][idx_u], groups[g2][idx_v]);\n        city_group[u] = g2;\n        city_group[v] = g1;\n        \n        double new_cost_g1 = get_group_cost(groups[g1], g1);\n        double new_cost_g2 = get_group_cost(groups[g2], g2);\n        \n        double diff = (new_cost_g1 + new_cost_g2) - (group_costs[g1] + group_costs[g2]);\n        \n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n        double temp = start_temp * (1.0 - elapsed / time_limit);\n        if (temp < end_temp) temp = end_temp;\n        \n        if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n            total_cost += diff;\n            group_costs[g1] = new_cost_g1;\n            group_costs[g2] = new_cost_g2;\n            \n            grp_sum_x[g1] = grp_sum_x[g1] - pos_x[u] + pos_x[v];\n            grp_sum_y[g1] = grp_sum_y[g1] - pos_y[u] + pos_y[v];\n            grp_sum_x[g2] = grp_sum_x[g2] - pos_x[v] + pos_x[u];\n            grp_sum_y[g2] = grp_sum_y[g2] - pos_y[v] + pos_y[u];\n        } else {\n            swap(groups[g1][idx_u], groups[g2][idx_v]);\n            city_group[u] = g1;\n            city_group[v] = g2;\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if ((int)groups[i].size() <= L) {\n            planned_queries.push_back(groups[i]);\n            continue;\n        }\n        \n        vector<pair<int, int>> mst = get_mst_edges_final(groups[i]);\n        adj_tree.assign(N, {});\n        for (auto& e : mst) {\n            adj_tree[e.first].push_back(e.second);\n            adj_tree[e.second].push_back(e.first);\n        }\n        \n        rem_nodes.clear();\n        dfs_query(groups[i][0], -1);\n        \n        while (!rem_nodes.empty()) {\n            if ((int)rem_nodes.size() <= L) {\n                if (rem_nodes.size() > 1) planned_queries.push_back(rem_nodes);\n                rem_nodes.clear();\n            } else {\n                vector<int> q;\n                q.reserve(L);\n                for(int k=0; k<L; ++k) q.push_back(rem_nodes[k]);\n                planned_queries.push_back(q);\n                rem_nodes.erase(rem_nodes.begin(), rem_nodes.begin() + L - 1);\n            }\n        }\n    }\n    \n    shuffle(planned_queries.begin(), planned_queries.end(), mt19937(42));\n    int queries_to_run = min((int)planned_queries.size(), Q);\n    \n    vector<vector<pair<int, int>>> confirmed_edges(M);\n    \n    for(int i=0; i<queries_to_run; ++i) {\n        cout << \"? \" << planned_queries[i].size();\n        for(int c : planned_queries[i]) cout << \" \" << c;\n        cout << endl;\n        \n        for(size_t k=0; k<planned_queries[i].size()-1; ++k) {\n            int u, v;\n            cin >> u >> v;\n            confirmed_edges[city_group[u]].push_back({u, v});\n        }\n    }\n\n    cout << \"!\" << endl;\n    \n    struct FinEdge {\n        int u, v;\n        double w;\n        bool operator<(const FinEdge& o) const { return w < o.w; }\n    };\n    vector<FinEdge> cands;\n    cands.reserve(N);\n\n    for(int i=0; i<M; ++i) {\n        for(size_t k=0; k<groups[i].size(); ++k) {\n            cout << groups[i][k] << (k==groups[i].size()-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n        \n        cands.clear();\n        for(auto& e : confirmed_edges[i]) {\n            cands.push_back({e.first, e.second, -1.0});\n        }\n        \n        vector<pair<int, int>> est = get_mst_edges_final(groups[i]);\n        for(auto& e : est) {\n            double w = sqrt(dist_matrix[e.first][e.second]);\n            cands.push_back({e.first, e.second, w});\n        }\n        \n        sort(cands.begin(), cands.end());\n        \n        dsu_calc.reset();\n        int added = 0;\n        int needed = max(0, (int)groups[i].size() - 1);\n        \n        for(auto& e : cands) {\n            if(dsu_calc.unite(e.u, e.v)) {\n                cout << e.u << \" \" << e.v << \"\\n\";\n                added++;\n                if(added == needed) break;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n#include <memory>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int M = 40;\nconst int INF = 1e9;\n\n// Directions: U, D, L, R\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_chars[] = {'U', 'D', 'L', 'R'};\n\n// Types\nstruct Point {\n    int r, c;\n};\n\nstruct Action {\n    char type; // 'M', 'S', 'A'\n    char dir;  // 'U', 'D', 'L', 'R'\n};\n\nstruct NodeInfo {\n    int dist;\n    int parent_idx; \n    Action action_from_parent;\n    bool break_block;\n};\n\n// Globals\nNodeInfo nodes[N * N]; \n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\ninline int idx(int r, int c) {\n    return r * N + c;\n}\n\n// Dijkstra: returns distance to target\n// avoid_idx: treated as block (for investment planning)\nint run_dijkstra(int start_idx, int target_idx, const bitset<400>& grid, int avoid_idx = -1) {\n    for(int i=0; i<N*N; ++i) nodes[i].dist = INF;\n    \n    using P = pair<int, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    \n    nodes[start_idx] = {0, -1, {' ', ' '}, false};\n    pq.push({0, start_idx});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        \n        if (d > nodes[u].dist) continue;\n        if (u == target_idx && target_idx != -1) return d; \n\n        int r = u / N;\n        int c = u % N;\n        \n        // Move (1) & Break (2)\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k];\n            int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int v = idx(nr, nc);\n                if (v == avoid_idx) continue;\n                \n                bool is_blocked = grid[v];\n                int cost = is_blocked ? 2 : 1;\n                int new_dist = d + cost;\n                \n                if (new_dist < nodes[v].dist) {\n                    nodes[v] = {new_dist, u, {'M', dir_chars[k]}, is_blocked};\n                    pq.push({new_dist, v});\n                }\n            }\n        }\n        \n        // Slide (1)\n        for (int k = 0; k < 4; ++k) {\n            int cr = r, cc = c;\n            while (true) {\n                int nr = cr + dr[k];\n                int nc = cc + dc[k];\n                if (!is_valid(nr, nc)) break;\n                int v_next = idx(nr, nc);\n                if (grid[v_next]) break;\n                if (v_next == avoid_idx) break;\n                cr = nr;\n                cc = nc;\n            }\n            if (cr != r || cc != c) {\n                int v = idx(cr, cc);\n                int new_dist = d + 1;\n                if (new_dist < nodes[v].dist) {\n                    nodes[v] = {new_dist, u, {'S', dir_chars[k]}, false};\n                    pq.push({new_dist, v});\n                }\n            }\n        }\n    }\n    return (target_idx != -1) ? nodes[target_idx].dist : 0;\n}\n\nvector<Action> extract_path(int start_idx, int end_idx) {\n    vector<Action> path;\n    int cur = end_idx;\n    while (cur != start_idx && cur != -1) {\n        NodeInfo& info = nodes[cur];\n        if (info.dist == INF) break; \n        if (info.break_block) {\n            path.push_back({'M', info.action_from_parent.dir});\n            path.push_back({'A', info.action_from_parent.dir});\n        } else {\n            path.push_back(info.action_from_parent);\n        }\n        cur = info.parent_idx;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct BeamState {\n    int cost;\n    int heuristic;\n    int pos_idx;\n    bitset<400> grid;\n    vector<Action> history;\n    \n    bool operator<(const BeamState& other) const {\n        return (cost + heuristic) < (other.cost + other.heuristic);\n    }\n};\n\nint calc_heuristic(int next_target_idx, const bitset<400>& grid, const vector<Point>& targets) {\n    int h = 0;\n    for (int i = next_target_idx; i < (int)targets.size(); ++i) {\n        int pr = targets[i-1].r, pc = targets[i-1].c;\n        int cr = targets[i].r, cc = targets[i].c;\n        int dist = abs(pr - cr) + abs(pc - cc);\n        \n        bool has_block = false;\n        for(int k=0; k<4; ++k) {\n            int nr = cr + dr[k];\n            int nc = cc + dc[k];\n            if (is_valid(nr, nc) && grid[idx(nr, nc)]) {\n                has_block = true; \n                break;\n            }\n        }\n        if (has_block) h += max(1, dist - 5);\n        else h += dist;\n    }\n    return h;\n}\n\nbool apply_action(BeamState& s, Action a) {\n    s.history.push_back(a);\n    s.cost += 1;\n    int r = s.pos_idx / N;\n    int c = s.pos_idx % N;\n    \n    if(a.type == 'A') {\n        int nr = r, nc = c;\n        if (a.dir == 'U') nr--; else if (a.dir == 'D') nr++; else if (a.dir == 'L') nc--; else if (a.dir == 'R') nc++;\n        if (!is_valid(nr, nc)) return false;\n        s.grid.flip(idx(nr, nc));\n    } else if (a.type == 'M') {\n        int nr = r, nc = c;\n        if (a.dir == 'U') nr--; else if (a.dir == 'D') nr++; else if (a.dir == 'L') nc--; else if (a.dir == 'R') nc++;\n        if (!is_valid(nr, nc)) return false;\n        if (s.grid[idx(nr, nc)]) return false;\n        s.pos_idx = idx(nr, nc);\n    } else if (a.type == 'S') {\n        int d_idx = (a.dir=='U'?0:(a.dir=='D'?1:(a.dir=='L'?2:3)));\n        int cr = r, cc = c;\n        while(true) {\n            int nr = cr + dr[d_idx];\n            int nc = cc + dc[d_idx];\n            if (!is_valid(nr, nc) || s.grid[idx(nr, nc)]) break;\n            cr = nr; cc = nc;\n        }\n        s.pos_idx = idx(cr, cc);\n    }\n    return true;\n}\n\nbool apply_path(BeamState& s, const vector<Action>& path) {\n    for(const auto& a : path) {\n        if(!apply_action(s, a)) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n\n    int _n, _m;\n    if (!(cin >> _n >> _m)) return 0;\n    \n    Point start_pos;\n    cin >> start_pos.r >> start_pos.c;\n    \n    vector<Point> targets(M);\n    targets[0] = start_pos;\n    for(int k=1; k<M; ++k) cin >> targets[k].r >> targets[k].c;\n\n    vector<BeamState> beam;\n    bitset<400> initial_grid; \n    beam.reserve(200);\n    beam.push_back({0, calc_heuristic(1, initial_grid, targets), idx(start_pos.r, start_pos.c), initial_grid, {}});\n\n    int BEAM_WIDTH = 40; \n\n    for (int k = 0; k < M - 1; ++k) {\n        auto now = chrono::high_resolution_clock::now();\n        auto dur = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (dur > 1800) BEAM_WIDTH = 5; \n        else if (dur > 1500) BEAM_WIDTH = 15;\n\n        int target_idx = idx(targets[k+1].r, targets[k+1].c);\n        vector<BeamState> next_beam;\n        next_beam.reserve(BEAM_WIDTH * 5);\n        \n        // Buffers to store baseline distances\n        static int dist_from_start[400];\n\n        for (const auto& s : beam) {\n            // Baseline Dijkstra\n            run_dijkstra(s.pos_idx, -1, s.grid); \n            \n            if (nodes[target_idx].dist != INF) {\n                BeamState next_s = s; \n                vector<Action> path = extract_path(s.pos_idx, target_idx);\n                if (apply_path(next_s, path)) {\n                    next_s.heuristic = calc_heuristic(k + 2, next_s.grid, targets);\n                    next_beam.push_back(next_s);\n                }\n            }\n            \n            // Save distances\n            for(int i=0; i<400; ++i) dist_from_start[i] = nodes[i].dist;\n\n            // Investment candidates\n            if (k + 2 < M) {\n                Point ft = targets[k+2];\n                for (int d = 0; d < 4; ++d) {\n                    int br = ft.r + dr[d];\n                    int bc = ft.c + dc[d];\n                    if (!is_valid(br, bc)) continue;\n                    int b_idx = idx(br, bc);\n                    if (s.grid[b_idx]) continue; \n\n                    int best_dist = INF;\n                    int best_nb_idx = -1;\n                    \n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int nbr = br + dr[d2];\n                        int nbc = bc + dc[d2];\n                        if (!is_valid(nbr, nbc)) continue;\n                        int nb = idx(nbr, nbc);\n                        if (dist_from_start[nb] < best_dist) {\n                            best_dist = dist_from_start[nb];\n                            best_nb_idx = nb;\n                        }\n                    }\n                    \n                    if (best_dist > 20) continue; \n\n                    int est_leg2 = abs(br - targets[k+1].r) + abs(bc - targets[k+1].c); \n                    if (best_dist + 1 + est_leg2 > dist_from_start[target_idx] + 8) continue;\n\n                    int leg2_dist = run_dijkstra(best_nb_idx, target_idx, s.grid, b_idx);\n                    \n                    if (leg2_dist != INF) {\n                        int total_cost = best_dist + 1 + leg2_dist;\n                        if (total_cost > dist_from_start[target_idx] + 6) continue; \n\n                        vector<Action> path2 = extract_path(best_nb_idx, target_idx);\n                        \n                        run_dijkstra(s.pos_idx, best_nb_idx, s.grid);\n                        vector<Action> path1 = extract_path(s.pos_idx, best_nb_idx);\n                        \n                        BeamState next_s = s;\n                        if (apply_path(next_s, path1)) {\n                            int d_alter = -1;\n                            int nbr = best_nb_idx / N;\n                            int nbc = best_nb_idx % N;\n                            for(int dd=0; dd<4; ++dd) \n                                if(nbr + dr[dd] == br && nbc + dc[dd] == bc) d_alter = dd;\n                            \n                            if (d_alter != -1 && apply_action(next_s, {'A', dir_chars[d_alter]})) {\n                                if (apply_path(next_s, path2)) {\n                                    next_s.heuristic = calc_heuristic(k + 2, next_s.grid, targets);\n                                    next_beam.push_back(next_s);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        sort(next_beam.begin(), next_beam.end());\n        \n        beam.clear();\n        if (!next_beam.empty()) {\n            beam.push_back(next_beam[0]);\n            for(size_t i=1; i<next_beam.size(); ++i) {\n                if (beam.size() >= BEAM_WIDTH) break;\n                if (next_beam[i].cost != next_beam[i-1].cost || next_beam[i].pos_idx != next_beam[i-1].pos_idx) {\n                    beam.push_back(next_beam[i]);\n                }\n            }\n        }\n        if (beam.empty()) break;\n    }\n    \n    if (!beam.empty()) {\n        for (const auto& a : beam[0].history) {\n            cout << a.type << \" \" << a.dir << \"\\n\";\n        }\n    }\n\n    return 0;\n}"},"16":{"ahc001":"/**\n * Solution for AtCoder Heuristic Contest 001\n * Algorithm: Randomized Recursive BSP with Fast Dependency-Based Coordinate Descent\n * \n * Improvements:\n * 1. Fast Optimization: Implemented a dependency tracking system (`dep_indices`) that maps each \n *    internal tree node to the exact set of leaf rectangles whose boundaries depend on it. \n *    This reduces the complexity of a coordinate descent move from O(N) to O(sqrt(N)) on average, \n *    allowing significantly more optimization passes and random restarts.\n * 2. Efficient Score Update: Instead of recalculating the entire tree's score, we only update the \n *    scores of the affected leaves.\n * 3. Robust Topology Construction: Uses a normalized cost function in the BSP build phase to \n *    better balance aspect ratios and area targets.\n * 4. Static Memory: Uses static arrays for tree nodes and dependency lists to minimize allocation overhead.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\n// --- Configuration ---\nconst int W = 10000;\nconst int H = 10000;\nconst double TIME_LIMIT = 4.95;\n\n// --- Structures ---\nstruct Point {\n    int id;\n    int x, y, r;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    inline long long area() const { return (long long)(x2 - x1) * (y2 - y1); }\n};\n\nstruct Node {\n    bool is_leaf;\n    int p_idx; // for leaf: index in points vector\n    int child_l, child_r; // for internal: index in pool\n    int axis; // 0:x, 1:y\n    int split_pos;\n    \n    // For optimization bounds (static given topology)\n    int valid_min, valid_max; \n    \n    // Optimization dependencies\n    // range in the flat `dep_indices` array\n    int dep_start_L, dep_count_L;\n    int dep_start_R, dep_count_R;\n};\n\n// --- Globals ---\nint N;\nvector<Point> points;\nNode pool[2000];\nint pool_ptr = 0;\n\n// Dependency arrays (flat buffers for cache efficiency)\nint dep_indices[40000]; \nint dep_ptr = 0;\n\n// Leaf current state during optimization\nRect leaf_rects[205]; \n\n// --- Random ---\nuint64_t xor_state[2] = {0x123456789LL, 0x987654321LL};\ninline uint64_t xorshift() {\n    uint64_t s1 = xor_state[0];\n    uint64_t s0 = xor_state[1];\n    xor_state[0] = s0;\n    s1 ^= s1 << 23;\n    xor_state[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);\n    return xor_state[1] + s0;\n}\ninline int rand_int(int n) { return xorshift() % n; }\ninline double rand_double() { return (xorshift() & 0xFFFFFFFFFFF) * (1.0 / 17592186044416.0); }\n\n// --- Scoring ---\n// Optimization score: penalized slightly for area > target to center the slack\ninline double calc_score_opt(int r, long long s) {\n    if (s >= r) return 1.0 - 1e-9 * ((double)(s - r) / r);\n    double ratio = (double)s / r;\n    double t = 1.0 - ratio;\n    return 1.0 - t * t;\n}\n\n// Final score metric\ninline double calc_score_final(int r, long long s) {\n    if (s >= r) return 1.0;\n    double ratio = (double)s / r;\n    double t = 1.0 - ratio;\n    return 1.0 - t * t;\n}\n\n// --- Solution Container ---\nstruct Solution {\n    Rect rects[205];\n    double score;\n};\nSolution best_sol;\n\n// --- Tree Building ---\ninline int new_node() { return pool_ptr++; }\n\nint build(const vector<int>& p_idxs, Rect r) {\n    int u = new_node();\n    \n    if (p_idxs.size() == 1) {\n        pool[u].is_leaf = true;\n        pool[u].p_idx = p_idxs[0];\n        leaf_rects[p_idxs[0]] = r; // Initial guess\n        return u;\n    }\n    pool[u].is_leaf = false;\n\n    long long total_r = 0;\n    for(int idx : p_idxs) total_r += points[idx].r;\n    \n    int w = r.x2 - r.x1;\n    int h = r.y2 - r.y1;\n    \n    struct Cand { int axis; int pos; double cost; };\n    static Cand cands[512];\n    int cand_cnt = 0;\n\n    auto analyze = [&](int axis) {\n        static vector<int> sorted;\n        if (sorted.capacity() < p_idxs.size()) sorted.reserve(p_idxs.size());\n        sorted = p_idxs;\n        \n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n\n        long long current_r = 0;\n        int start = (axis==0) ? r.x1 : r.y1;\n        int len = (axis==0) ? w : h;\n        int other_len = (axis==0) ? h : w;\n\n        for(size_t i=0; i<sorted.size()-1; ++i) {\n            current_r += points[sorted[i]].r;\n            int p1 = (axis==0) ? points[sorted[i]].x : points[sorted[i]].y;\n            int p2 = (axis==0) ? points[sorted[i+1]].x : points[sorted[i+1]].y;\n            \n            if (p1 >= p2) continue;\n            int mn = p1 + 1;\n            int mx = p2;\n            if (mn > mx) continue;\n\n            double ratio = (double)current_r / total_r;\n            int ideal = start + (int)(len * ratio);\n            int pos = std::clamp(ideal, mn, mx);\n            \n            double norm_cost = std::abs(pos - ideal) / (double)len;\n            if (len < other_len * 1.1) norm_cost *= 1.2; // bias towards cutting longer side\n\n            if (cand_cnt < 512) cands[cand_cnt++] = {axis, pos, norm_cost};\n        }\n    };\n\n    analyze(0);\n    analyze(1);\n\n    int axis, pos;\n    if (cand_cnt == 0) {\n        // Fallback split\n        axis = (w > h) ? 0 : 1;\n        static vector<int> sorted; sorted = p_idxs;\n        if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n        else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n        int mid = sorted.size() / 2;\n        int p1 = (axis==0) ? points[sorted[mid-1]].x : points[sorted[mid-1]].y;\n        int p2 = (axis==0) ? points[sorted[mid]].x : points[sorted[mid]].y;\n        pos = std::clamp((p1+p2+1)/2, (axis==0?r.x1:r.y1)+1, (axis==0?r.x2:r.y2)-1);\n    } else {\n        sort(cands, cands + cand_cnt, [](const Cand& a, const Cand& b){ return a.cost < b.cost; });\n        int k = min(cand_cnt, 4);\n        int idx = 0;\n        if (rand_double() < 0.5) idx = 0;\n        else idx = rand_int(k);\n        axis = cands[idx].axis;\n        pos = cands[idx].pos;\n    }\n\n    pool[u].axis = axis;\n    pool[u].split_pos = pos;\n\n    vector<int> L, R;\n    L.reserve(p_idxs.size());\n    R.reserve(p_idxs.size());\n    for(int idx : p_idxs) {\n        int v = (axis==0) ? points[idx].x : points[idx].y;\n        if (v < pos) L.push_back(idx);\n        else R.push_back(idx);\n    }\n    \n    // Fallback for degenerate splits\n    if (L.empty() || R.empty()) { \n         static vector<int> sorted; sorted = p_idxs;\n         if (axis == 0) sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].x < points[b].x; });\n         else           sort(sorted.begin(), sorted.end(), [](int a, int b){ return points[a].y < points[b].y; });\n         size_t mid = sorted.size()/2;\n         L.assign(sorted.begin(), sorted.begin()+mid);\n         R.assign(sorted.begin()+mid, sorted.end());\n    }\n\n    Rect rL = r, rR = r;\n    if (axis == 0) { rL.x2 = pos; rR.x1 = pos; }\n    else           { rL.y2 = pos; rR.y1 = pos; }\n\n    pool[u].child_l = build(L, rL);\n    pool[u].child_r = build(R, rR);\n    return u;\n}\n\n// --- Optimization Setup ---\nvoid analyze_topology(int root) {\n    dep_ptr = 0;\n    \n    vector<int> nodes; nodes.reserve(pool_ptr);\n    vector<int> q; q.push_back(root);\n    int head = 0;\n    while(head < q.size()) {\n        int u = q[head++];\n        if (!pool[u].is_leaf) {\n            nodes.push_back(u);\n            q.push_back(pool[u].child_l);\n            q.push_back(pool[u].child_r);\n        }\n    }\n    \n    // Setup Dependencies: find leaves \"touching\" each split\n    for(int u : nodes) {\n        // Left Dependents: leaves in Left child exposed to the split\n        pool[u].dep_start_L = dep_ptr;\n        auto dfs_L = [&](auto&& self, int v) -> void {\n            if (pool[v].is_leaf) {\n                dep_indices[dep_ptr++] = pool[v].p_idx;\n                return;\n            }\n            // If v splits same axis, only right child touches u's split\n            if (pool[v].axis == pool[u].axis) {\n                self(self, pool[v].child_r);\n            } else { // v splits perp axis, both children touch\n                self(self, pool[v].child_l);\n                self(self, pool[v].child_r);\n            }\n        };\n        dfs_L(dfs_L, pool[u].child_l);\n        pool[u].dep_count_L = dep_ptr - pool[u].dep_start_L;\n        \n        // Right Dependents: leaves in Right child exposed to the split\n        pool[u].dep_start_R = dep_ptr;\n        auto dfs_R = [&](auto&& self, int v) -> void {\n            if (pool[v].is_leaf) {\n                dep_indices[dep_ptr++] = pool[v].p_idx;\n                return;\n            }\n            if (pool[v].axis == pool[u].axis) {\n                self(self, pool[v].child_l);\n            } else {\n                self(self, pool[v].child_l);\n                self(self, pool[v].child_r);\n            }\n        };\n        dfs_R(dfs_R, pool[u].child_r);\n        pool[u].dep_count_R = dep_ptr - pool[u].dep_start_R;\n\n        // Compute valid range for u based on point constraints\n        int ax = pool[u].axis;\n        int mn = -2e9, mx = 2e9;\n        \n        // Max coord of points in left dependents + 1\n        // Note: we only check dependents because they are the ones bounding the cut?\n        // No, strictly speaking any point in Left subtree bounds the cut.\n        // But points deeper in Left subtree are bounded by other nodes.\n        // However, for safety and correctness with topology, checking all leaves in subtrees is safer.\n        // Let's just check all leaves in subtrees (slower setup but O(N) per node is ok for setup).\n        // Re-using a collector is messy. Let's just do recursive checks.\n        auto check_max = [&](auto&& self, int v) -> void {\n            if (pool[v].is_leaf) {\n                int val = (ax == 0) ? points[pool[v].p_idx].x : points[pool[v].p_idx].y;\n                if (val > mn) mn = val;\n                return;\n            }\n            self(self, pool[v].child_l);\n            self(self, pool[v].child_r);\n        };\n        check_max(check_max, pool[u].child_l);\n        \n        auto check_min = [&](auto&& self, int v) -> void {\n            if (pool[v].is_leaf) {\n                int val = (ax == 0) ? points[pool[v].p_idx].x : points[pool[v].p_idx].y;\n                if (val < mx) mx = val;\n                return;\n            }\n            self(self, pool[v].child_l);\n            self(self, pool[v].child_r);\n        };\n        check_min(check_min, pool[u].child_r);\n        \n        pool[u].valid_min = mn + 1;\n        pool[u].valid_max = mx;\n    }\n}\n\nvoid optimize(int root) {\n    analyze_topology(root);\n    \n    vector<int> nodes;\n    vector<int> q = {root};\n    int head=0;\n    while(head<q.size()){\n        int u = q[head++];\n        if(!pool[u].is_leaf){\n            nodes.push_back(u);\n            q.push_back(pool[u].child_l);\n            q.push_back(pool[u].child_r);\n        }\n    }\n    \n    // Precompute required area for ratio calc\n    static long long ra[4000];\n    auto calc_ra = [&](auto&& self, int u) -> void {\n        if(pool[u].is_leaf) {\n            ra[u] = points[pool[u].p_idx].r;\n            return;\n        }\n        self(self, pool[u].child_l);\n        self(self, pool[u].child_r);\n        ra[u] = ra[pool[u].child_l] + ra[pool[u].child_r];\n    };\n    calc_ra(calc_ra, root);\n\n    int MAX_PASS = 80;\n    for(int pass=0; pass<MAX_PASS; ++pass) {\n        bool changed = false;\n        for(int u : nodes) {\n            int mn = pool[u].valid_min;\n            int mx = pool[u].valid_max;\n            if(mn > mx) continue;\n\n            int cur = pool[u].split_pos;\n            int ax = pool[u].axis;\n            \n            double ratio = (double)ra[pool[u].child_l] / ra[u];\n            \n            // Calculate node span range to convert ratio to coordinate\n            int u_start = 2e9, u_end = -2e9;\n            \n            for(int k=0; k<pool[u].dep_count_L; ++k) {\n                int pid = dep_indices[pool[u].dep_start_L + k];\n                int val = (ax==0) ? leaf_rects[pid].x1 : leaf_rects[pid].y1;\n                if(val < u_start) u_start = val;\n            }\n            for(int k=0; k<pool[u].dep_count_R; ++k) {\n                int pid = dep_indices[pool[u].dep_start_R + k];\n                int val = (ax==0) ? leaf_rects[pid].x2 : leaf_rects[pid].y2;\n                if(val > u_end) u_end = val;\n            }\n            \n            int ideal = u_start + (int)((u_end - u_start) * ratio);\n            ideal = std::clamp(ideal, mn, mx);\n            \n            // Search Candidates\n            static int tests[20];\n            int n_tests = 0;\n            tests[n_tests++] = ideal;\n            if (cur != ideal) tests[n_tests++] = cur;\n            for(int d : {-2, -1, 1, 2}) {\n                int v = ideal + d;\n                if(v >= mn && v <= mx) tests[n_tests++] = v;\n            }\n            if (abs(cur - ideal) > 3) {\n                int mid = (cur + ideal)/2;\n                if(mid>=mn && mid<=mx) tests[n_tests++] = mid;\n            }\n            \n            double best_gain = 0;\n            int best_p = cur;\n            \n            // Fast Evaluation Lambda\n            auto get_local_score = [&](int p) {\n                double s = 0;\n                for(int k=0; k<pool[u].dep_count_L; ++k) {\n                    int pid = dep_indices[pool[u].dep_start_L + k];\n                    long long w, h;\n                    if (ax == 0) {\n                        w = p - leaf_rects[pid].x1;\n                        h = leaf_rects[pid].y2 - leaf_rects[pid].y1;\n                    } else {\n                        w = leaf_rects[pid].x2 - leaf_rects[pid].x1;\n                        h = p - leaf_rects[pid].y1;\n                    }\n                    s += calc_score_opt(points[pid].r, w*h);\n                }\n                for(int k=0; k<pool[u].dep_count_R; ++k) {\n                    int pid = dep_indices[pool[u].dep_start_R + k];\n                    long long w, h;\n                    if (ax == 0) {\n                        w = leaf_rects[pid].x2 - p;\n                        h = leaf_rects[pid].y2 - leaf_rects[pid].y1;\n                    } else {\n                        w = leaf_rects[pid].x2 - leaf_rects[pid].x1;\n                        h = leaf_rects[pid].y2 - p;\n                    }\n                    s += calc_score_opt(points[pid].r, w*h);\n                }\n                return s;\n            };\n            \n            double base_s = get_local_score(cur);\n            \n            for(int i=0; i<n_tests; ++i) {\n                int p = tests[i];\n                if(p == cur) continue;\n                double s = get_local_score(p);\n                if (s > base_s + 1e-9) {\n                    base_s = s;\n                    best_p = p;\n                }\n            }\n            \n            if (best_p != cur) {\n                // Update leaf_rects\n                for(int k=0; k<pool[u].dep_count_L; ++k) {\n                    int pid = dep_indices[pool[u].dep_start_L + k];\n                    if (ax == 0) leaf_rects[pid].x2 = best_p;\n                    else leaf_rects[pid].y2 = best_p;\n                }\n                for(int k=0; k<pool[u].dep_count_R; ++k) {\n                    int pid = dep_indices[pool[u].dep_start_R + k];\n                    if (ax == 0) leaf_rects[pid].x1 = best_p;\n                    else leaf_rects[pid].y1 = best_p;\n                }\n                pool[u].split_pos = best_p;\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N)) return 0;\n    points.resize(N);\n    vector<int> p_idxs(N);\n    for(int i=0; i<N; ++i) {\n        cin >> points[i].x >> points[i].y >> points[i].r;\n        points[i].id = i;\n        p_idxs[i] = i;\n    }\n    \n    best_sol.score = -1.0;\n    auto start_t = chrono::high_resolution_clock::now();\n    \n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start_t).count() > TIME_LIMIT) break;\n        \n        pool_ptr = 0;\n        dep_ptr = 0;\n        int root = build(p_idxs, {0, 0, W, H});\n        optimize(root);\n        \n        // Greedy shrink & Eval\n        double sc = 0;\n        static Rect sol[205];\n        for(int i=0; i<N; ++i) {\n            Rect r = leaf_rects[i];\n            int req = points[i].r;\n            if (r.area() > req) {\n                while (r.area() > req) {\n                    int dl = points[i].x - r.x1;\n                    int dr = r.x2 - 1 - points[i].x;\n                    int du = points[i].y - r.y1;\n                    int dd = r.y2 - 1 - points[i].y;\n                    \n                    int mv = -1, mx = -1;\n                    if (dl > 0 && dl > mx) { mx=dl; mv=0; }\n                    if (dr > 0 && dr > mx) { mx=dr; mv=1; }\n                    if (du > 0 && du > mx) { mx=du; mv=2; }\n                    if (dd > 0 && dd > mx) { mx=dd; mv=3; }\n                    \n                    if (mv == -1) break;\n                    if (mv==0) r.x1++; else if(mv==1) r.x2--;\n                    else if(mv==2) r.y1++; else r.y2--;\n                }\n            }\n            sol[i] = r;\n            sc += calc_score_final(req, r.area());\n        }\n        \n        double total = 1e9 * sc / N;\n        if (total > best_sol.score) {\n            best_sol.score = total;\n            for(int i=0; i<N; ++i) best_sol.rects[i] = sol[i];\n        }\n    }\n    \n    for(int i=0; i<N; ++i) {\n        cout << best_sol.rects[i].x1 << \" \" << best_sol.rects[i].y1 << \" \"\n             << best_sol.rects[i].x2 << \" \" << best_sol.rects[i].y2 << \"\\n\";\n    }\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <string>\n#include <bitset>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <array>\n#include <cstring>\n\nusing namespace std;\n\n// ==========================================\n// Constants & Configuration\n// ==========================================\nconst int N = 50;\nconst int NUM_CELLS = N * N;\nconst int MAX_TILES = 2500;\n// Time limit strictly set to leave margin for I/O and checks\nconst double TIME_LIMIT = 1.95; \n\n// Diversity constraint: Max candidates per cell per step\n// Increased to 4 to allow more distinct visited-sets to survive\nconst int MAX_PER_CELL = 4; \n// Beam Width increased to 6000 for maximum exploration\nconst int BEAM_WIDTH = 6000;    \n\n// ==========================================\n// Data Structures\n// ==========================================\n\n// Precomputed Adjacency for grid graph\nstruct Neighbors {\n    int count;\n    array<int, 4> to;\n    array<char, 4> dir;\n};\n\n// Tree node for efficient path reconstruction\nstruct TreeNode {\n    int parent;\n    char dir;\n};\n\n// Heavy State: Persists in Beam\nstruct State {\n    int u;              // Current cell index\n    int real_score;     // Actual accumulated score\n    int eval_score;     // Score with noise\n    int tree_idx;       // Index in global tree\n    uint64_t hash;      // Zobrist hash of visited set\n    bitset<MAX_TILES> visited; // Bitset copy is the main cost\n};\n\n// Lightweight Candidate: For Expansion & Pruning\nstruct Candidate {\n    int eval_score;\n    int real_score;\n    int parent_idx;     // Index in current_beam\n    int u;              // Target cell index\n    int new_tile;       // Target tile ID\n    char dir;           // Move direction\n    uint64_t hash;      // New Zobrist hash\n};\n\n// Flat Bucket for Pruning (Zero Allocation)\nstruct Bucket {\n    int count;\n    int scores[MAX_PER_CELL];\n    int indices[MAX_PER_CELL];\n    uint64_t hashes[MAX_PER_CELL]; // Store hash to detect duplicates\n};\n\n// ==========================================\n// Global Variables & Buffers\n// ==========================================\nint tile_id[NUM_CELLS];\nint base_score[NUM_CELLS];\nint iter_score[NUM_CELLS];\nNeighbors graph[NUM_CELLS];\nuint64_t zobrist[MAX_TILES]; // Zobrist keys for each tile\n\n// Pre-allocated buffers\nvector<TreeNode> tree;\nvector<State> beam_curr;\nvector<State> beam_next;\nvector<Candidate> candidates;\nvector<int> survivors;\n\n// Spatial pruning structures\nBucket buckets[NUM_CELLS];\nvector<int> touched_buckets;\n\nmt19937 rng(12345);\n\n// ==========================================\n// Main Implementation\n// ==========================================\nint main() {\n    // Fast I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::system_clock::now();\n\n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    int start_node = si * N + sj;\n\n    // Read Inputs\n    for (int i = 0; i < NUM_CELLS; ++i) cin >> tile_id[i];\n    for (int i = 0; i < NUM_CELLS; ++i) cin >> base_score[i];\n\n    // Initialize Zobrist Hashing Keys\n    mt19937_64 hash_rng(12345);\n    for(int i=0; i<MAX_TILES; ++i) zobrist[i] = hash_rng();\n\n    // Build Graph (Precompute neighbors)\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            int cnt = 0;\n            if (r > 0) { graph[u].to[cnt] = u - N; graph[u].dir[cnt] = 'U'; cnt++; }\n            if (r < N - 1) { graph[u].to[cnt] = u + N; graph[u].dir[cnt] = 'D'; cnt++; }\n            if (c > 0) { graph[u].to[cnt] = u - 1; graph[u].dir[cnt] = 'L'; cnt++; }\n            if (c < N - 1) { graph[u].to[cnt] = u + 1; graph[u].dir[cnt] = 'R'; cnt++; }\n            graph[u].count = cnt;\n        }\n    }\n\n    // Allocations\n    beam_curr.reserve(BEAM_WIDTH);\n    beam_next.reserve(BEAM_WIDTH);\n    candidates.reserve(BEAM_WIDTH * 4);\n    tree.reserve(8000000); \n    touched_buckets.reserve(NUM_CELLS);\n    survivors.reserve(BEAM_WIDTH + 1000);\n\n    // Init buckets\n    for(int i=0; i<NUM_CELLS; ++i) buckets[i].count = 0;\n\n    uniform_int_distribution<int> noise_dist(0, 25);\n\n    int best_score_final = -1;\n    string best_path_final = \"\";\n    \n    int iter = 0;\n\n    // Main Iterative Loop\n    while (true) {\n        // Global time check\n        auto now = chrono::system_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() / 1000.0 > TIME_LIMIT) break;\n\n        iter++;\n        // 1. Iteration Setup: Perturb scores with noise\n        if (iter == 1) {\n            for (int i = 0; i < NUM_CELLS; ++i) iter_score[i] = base_score[i];\n        } else {\n            for (int i = 0; i < NUM_CELLS; ++i) iter_score[i] = base_score[i] + noise_dist(rng);\n        }\n\n        // 2. Reset Search\n        beam_curr.clear();\n        tree.clear();\n        \n        State start_s;\n        start_s.u = start_node;\n        start_s.real_score = base_score[start_node];\n        start_s.eval_score = iter_score[start_node];\n        start_s.tree_idx = -1;\n        start_s.hash = zobrist[tile_id[start_node]];\n        start_s.visited.reset();\n        start_s.visited.set(tile_id[start_node]);\n        \n        beam_curr.push_back(start_s);\n\n        if (start_s.real_score > best_score_final) {\n            best_score_final = start_s.real_score;\n            best_path_final = \"\";\n        }\n\n        // 3. Beam Search Steps\n        for (int step = 0; step < MAX_TILES; ++step) {\n            if (beam_curr.empty()) break;\n            \n            // Periodic time check\n            if ((step & 31) == 0) {\n                 if (chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - start_time).count() / 1000.0 > TIME_LIMIT) goto finish;\n            }\n\n            candidates.clear();\n            touched_buckets.clear();\n\n            // 3a. Expansion\n            for (int i = 0; i < (int)beam_curr.size(); ++i) {\n                const auto& s = beam_curr[i];\n                const int u_tile = tile_id[s.u];\n                const auto& nbrs = graph[s.u];\n\n                for (int k = 0; k < nbrs.count; ++k) {\n                    int v = nbrs.to[k];\n                    int v_tile = tile_id[v];\n\n                    // Validity check: Must cross tile boundary & tile must be unvisited\n                    if (u_tile != v_tile && !s.visited.test(v_tile)) {\n                        candidates.push_back({\n                            s.eval_score + iter_score[v],\n                            s.real_score + base_score[v],\n                            i,\n                            v,\n                            v_tile,\n                            nbrs.dir[k],\n                            s.hash ^ zobrist[v_tile] // Incremental hash update\n                        });\n                    }\n                }\n            }\n\n            if (candidates.empty()) break;\n\n            // 3b. Spatial Pruning + Domination Check\n            for (int i = 0; i < (int)candidates.size(); ++i) {\n                const auto& c = candidates[i];\n                Bucket& b = buckets[c.u];\n                \n                if (b.count == 0) {\n                    touched_buckets.push_back(c.u);\n                    b.scores[0] = c.eval_score;\n                    b.indices[0] = i;\n                    b.hashes[0] = c.hash;\n                    b.count = 1;\n                } else {\n                    // Domination Check: Look for duplicate visited-set hash\n                    bool duplicate = false;\n                    for(int k=0; k<b.count; ++k) {\n                        if (b.hashes[k] == c.hash) {\n                            duplicate = true;\n                            if (c.eval_score > b.scores[k]) {\n                                // Replace dominated state with better one\n                                b.scores[k] = c.eval_score;\n                                b.indices[k] = i;\n                                // Maintain sorted order locally\n                                int p = k;\n                                while(p > 0 && b.scores[p] > b.scores[p-1]) {\n                                    swap(b.scores[p], b.scores[p-1]);\n                                    swap(b.indices[p], b.indices[p-1]);\n                                    swap(b.hashes[p], b.hashes[p-1]);\n                                    p--;\n                                }\n                            }\n                            break;\n                        }\n                    }\n                    if (duplicate) continue;\n\n                    // Standard Top-K Insertion (Unique state)\n                    if (b.count < MAX_PER_CELL) {\n                        int pos = b.count;\n                        while (pos > 0 && c.eval_score > b.scores[pos-1]) {\n                            b.scores[pos] = b.scores[pos-1];\n                            b.indices[pos] = b.indices[pos-1];\n                            b.hashes[pos] = b.hashes[pos-1];\n                            pos--;\n                        }\n                        b.scores[pos] = c.eval_score;\n                        b.indices[pos] = i;\n                        b.hashes[pos] = c.hash;\n                        b.count++;\n                    } else if (c.eval_score > b.scores[MAX_PER_CELL-1]) {\n                        int pos = MAX_PER_CELL - 1;\n                        while (pos > 0 && c.eval_score > b.scores[pos-1]) {\n                            b.scores[pos] = b.scores[pos-1];\n                            b.indices[pos] = b.indices[pos-1];\n                            b.hashes[pos] = b.hashes[pos-1];\n                            pos--;\n                        }\n                        b.scores[pos] = c.eval_score;\n                        b.indices[pos] = i;\n                        b.hashes[pos] = c.hash;\n                    }\n                }\n            }\n\n            // Collect Survivors\n            survivors.clear();\n            for (int u : touched_buckets) {\n                Bucket& b = buckets[u];\n                for(int k=0; k<b.count; ++k) {\n                    survivors.push_back(b.indices[k]);\n                }\n                b.count = 0; // Reset bucket\n            }\n\n            // 3c. Global Pruning\n            if ((int)survivors.size() > BEAM_WIDTH) {\n                nth_element(survivors.begin(), survivors.begin() + BEAM_WIDTH, survivors.end(),\n                    [&](int a, int b) {\n                        return candidates[a].eval_score > candidates[b].eval_score;\n                    });\n                survivors.resize(BEAM_WIDTH);\n            }\n\n            // 3d. State Construction (Heavy Operation)\n            beam_next.clear();\n            for (int idx : survivors) {\n                const auto& cand = candidates[idx];\n                const auto& parent = beam_curr[cand.parent_idx];\n                \n                tree.push_back({parent.tree_idx, cand.dir});\n                int new_tree_idx = (int)tree.size() - 1;\n\n                State ns;\n                ns.u = cand.u;\n                ns.real_score = cand.real_score;\n                ns.eval_score = cand.eval_score;\n                ns.tree_idx = new_tree_idx;\n                ns.hash = cand.hash;\n                ns.visited = parent.visited; // Heavy copy\n                ns.visited.set(cand.new_tile);\n\n                beam_next.push_back(ns);\n\n                // Update Global Best\n                if (ns.real_score > best_score_final) {\n                    best_score_final = ns.real_score;\n                    string p;\n                    p.reserve(step + 8);\n                    int curr = new_tree_idx;\n                    while (curr != -1) {\n                        p += tree[curr].dir;\n                        curr = tree[curr].parent;\n                    }\n                    reverse(p.begin(), p.end());\n                    best_path_final = p;\n                }\n            }\n            \n            swap(beam_curr, beam_next);\n        }\n    }\n\nfinish:;\n    cout << best_path_final << endl;\n    return 0;\n}","ahc003":"/**\n * AtCoder Heuristic Contest Solution\n * Problem: Shortest Path with Unknown Edge Lengths\n * \n * Algorithm & Strategy:\n * 1. Graph Modeling: Grid graph with weighted edges.\n * 2. Pathfinding: A* (A-Star) with Manhattan distance * 1000 heuristic.\n * 3. Learning: Online SGD (Adam optimizer) with Squared Relative Error loss.\n *    - Regularization: L1 Norm (Total Variation) to enforce row/column smoothness.\n * \n * Key Improvements:\n * - Optimistic Initialization: Initial weights set to 4000.0 (below mean 5000.0).\n *   This encourages the pathfinder to explore edges that haven't been visited yet,\n *   preventing the model from getting stuck in local optima with overestimated weights.\n * - Strict Clamping: Weights are clamped to [1000, 9000], matching the strict generation bounds.\n * - Adaptive Training: Learning rate anneals over time; batch sizes adjust dynamically.\n * - Time Management: Strict cutoff to ensure training maximizes CPU usage without TLE.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Grid dimensions\nconst int N = 30;\nconst int NUM_H = N * (N - 1); \nconst int NUM_V = (N - 1) * N; \nconst int NUM_EDGES = NUM_H + NUM_V; \n\n// Helper to get edge indices\ninline int get_h_idx(int r, int c) { return r * (N - 1) + c; }\ninline int get_v_idx(int r, int c) { return NUM_H + r * N + c; }\n\nstruct Query {\n    vector<int> path_edges;\n    int measured_dist;\n};\n\nclass Solver {\nprivate:\n    // Model State\n    vector<double> weights;\n    \n    // Optimizer State (Adam)\n    vector<double> m, v; \n    double beta1 = 0.9;\n    double beta2 = 0.999;\n    double epsilon = 1e-8;\n    \n    // Hyperparameters\n    double lr_start = 200.0; // Initial Learning Rate\n    double lr_end = 50.0;    // Final Learning Rate\n    double lambda_smooth = 2.0e-6; // L1 Regularization Strength\n    \n    long long updates_count = 0;\n    vector<Query> history;\n    mt19937 rng;\n\n    // Pre-allocated buffers\n    vector<double> dist;\n    vector<int> parent_edge;\n    vector<int> parent_node;\n    \n    // Time tracking\n    chrono::steady_clock::time_point start_time;\n\npublic:\n    Solver() {\n        // Optimistic Initialization: 4000.0 (True mean is 5000.0)\n        // Encourages exploration of edges not yet proven to be expensive.\n        weights.assign(NUM_EDGES, 4000.0);\n        m.assign(NUM_EDGES, 0.0);\n        v.assign(NUM_EDGES, 1e-12);\n        rng.seed(42);\n        \n        dist.resize(N * N);\n        parent_edge.resize(N * N);\n        parent_node.resize(N * N);\n        \n        start_time = chrono::steady_clock::now();\n    }\n\n    // Heuristic for A*: Manhattan distance * Min Possible Weight (1000)\n    inline double heuristic(int u, int target) {\n        int r1 = u / N, c1 = u % N;\n        int r2 = target / N, c2 = target % N;\n        // 1000 is the strict lower bound of edge weights\n        return (abs(r1 - r2) + abs(c1 - c2)) * 1000.0;\n    }\n\n    // A* Pathfinding\n    pair<string, vector<int>> find_path(int si, int sj, int ti, int tj) {\n        fill(dist.begin(), dist.end(), 1e18);\n        \n        int start_node = si * N + sj;\n        int target_node = ti * N + tj;\n        \n        dist[start_node] = 0;\n        \n        using State = pair<double, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({heuristic(start_node, target_node), start_node});\n        \n        while (!pq.empty()) {\n            auto [f, u] = pq.top();\n            pq.pop();\n            \n            if (f > dist[u] + heuristic(u, target_node) + 1e-9) continue;\n            if (u == target_node) break;\n            \n            int r = u / N;\n            int c = u % N;\n            double g_u = dist[u];\n            \n            // Explore Neighbors: Up, Down, Left, Right\n            \n            // Up\n            if (r > 0) {\n                int v_n = u - N; \n                int e_idx = NUM_H + (r - 1) * N + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_n]) {\n                    dist[v_n] = g_u + w;\n                    parent_node[v_n] = u;\n                    parent_edge[v_n] = e_idx;\n                    pq.push({dist[v_n] + heuristic(v_n, target_node), v_n});\n                }\n            }\n            // Down\n            if (r < N - 1) {\n                int v_n = u + N;\n                int e_idx = NUM_H + r * N + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_n]) {\n                    dist[v_n] = g_u + w;\n                    parent_node[v_n] = u;\n                    parent_edge[v_n] = e_idx;\n                    pq.push({dist[v_n] + heuristic(v_n, target_node), v_n});\n                }\n            }\n            // Left\n            if (c > 0) {\n                int v_n = u - 1;\n                int e_idx = r * (N - 1) + (c - 1); \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_n]) {\n                    dist[v_n] = g_u + w;\n                    parent_node[v_n] = u;\n                    parent_edge[v_n] = e_idx;\n                    pq.push({dist[v_n] + heuristic(v_n, target_node), v_n});\n                }\n            }\n            // Right\n            if (c < N - 1) {\n                int v_n = u + 1;\n                int e_idx = r * (N - 1) + c; \n                double w = weights[e_idx];\n                if (g_u + w < dist[v_n]) {\n                    dist[v_n] = g_u + w;\n                    parent_node[v_n] = u;\n                    parent_edge[v_n] = e_idx;\n                    pq.push({dist[v_n] + heuristic(v_n, target_node), v_n});\n                }\n            }\n        }\n        \n        // Reconstruct Path\n        string path = \"\";\n        vector<int> edges;\n        int curr = target_node;\n        while (curr != start_node) {\n            int prev = parent_node[curr];\n            int e_idx = parent_edge[curr];\n            edges.push_back(e_idx);\n            \n            int diff = curr - prev;\n            if (diff == N) path += 'D';\n            else if (diff == -N) path += 'U';\n            else if (diff == 1) path += 'R';\n            else path += 'L';\n            \n            curr = prev;\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges.begin(), edges.end());\n        return {path, edges};\n    }\n\n    // Online Training\n    void train(const vector<int>& path_edges, int measured, int query_idx) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        // Safety Cutoff\n        if (elapsed > 1.85) return; \n        \n        history.push_back({path_edges, measured});\n        \n        // Adaptive Training Schedule\n        int base_batch = 100; \n        int base_iter = 40; \n        \n        // Train harder on initial data\n        if (history.size() < 100) {\n            base_batch = 120;\n            base_iter = 60; \n        } else if (history.size() < 300) {\n            base_batch = 110;\n            base_iter = 45; \n        } else {\n            base_batch = 100;\n            base_iter = 30;\n        }\n\n        // Throttle if near time limit\n        if (elapsed > 1.6) {\n            base_iter = 15;\n            base_batch = 50;\n        }\n\n        int batch_size = base_batch;\n        int iterations = base_iter;\n        \n        // Annealing LR\n        double progress = (double)query_idx / 1000.0;\n        double current_lr = lr_start * (1.0 - progress) + lr_end * progress;\n        \n        static vector<double> grad(NUM_EDGES);\n        vector<int> indices;\n        indices.reserve(batch_size);\n\n        for (int iter = 0; iter < iterations; ++iter) {\n            fill(grad.begin(), grad.end(), 0.0);\n            updates_count++;\n            \n            indices.clear();\n            int hist_size = history.size();\n            \n            // Stratified Sampling: Recent + Random\n            int recent_count = min(hist_size, 30); \n            for(int i = 0; i < recent_count; ++i) indices.push_back(hist_size - 1 - i);\n            \n            int needed = batch_size - recent_count;\n            if (needed > 0 && hist_size > 0) {\n                 for(int i = 0; i < needed; ++i) {\n                    indices.push_back(rng() % hist_size);\n                }\n            }\n\n            // 1. Prediction Error Gradient\n            for (int idx : indices) {\n                const auto& q = history[idx];\n                double pred = 0;\n                for (int e : q.path_edges) pred += weights[e];\n                \n                double y = q.measured_dist;\n                double diff = pred - y;\n                double g_factor = 2.0 * diff / (y * y);\n                \n                for (int e : q.path_edges) {\n                    grad[e] += g_factor;\n                }\n            }\n            \n            // 2. L1 Regularization Gradient (Smoothness)\n            // Horizontal edges\n            for (int r = 0; r < N; ++r) {\n                int start = r * (N - 1);\n                for (int c = 0; c < N - 2; ++c) {\n                    int e1 = start + c;\n                    int e2 = e1 + 1;\n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // Vertical edges\n            int v_offset = NUM_H;\n            for (int r = 0; r < N - 2; ++r) { \n                int row_start = v_offset + r * N;\n                for (int c = 0; c < N; ++c) {\n                    int e1 = row_start + c;\n                    int e2 = e1 + N; \n                    double w1 = weights[e1];\n                    double w2 = weights[e2];\n                    if (w1 > w2) {\n                        grad[e1] += lambda_smooth;\n                        grad[e2] -= lambda_smooth;\n                    } else if (w1 < w2) {\n                        grad[e1] -= lambda_smooth;\n                        grad[e2] += lambda_smooth;\n                    }\n                }\n            }\n            \n            // Adam Update\n            double bias_corr1 = 1.0 - pow(beta1, updates_count);\n            double bias_corr2 = 1.0 - pow(beta2, updates_count);\n            \n            for (int i = 0; i < NUM_EDGES; ++i) {\n                double g = grad[i];\n                \n                m[i] = beta1 * m[i] + (1 - beta1) * g;\n                v[i] = beta2 * v[i] + (1 - beta2) * g * g;\n                \n                double m_hat = m[i] / bias_corr1;\n                double v_hat = v[i] / bias_corr2;\n                \n                weights[i] -= current_lr * m_hat / (sqrt(v_hat) + epsilon);\n                \n                // Strict Clamping to Problem Constraints\n                if (weights[i] < 1000.0) weights[i] = 1000.0;\n                if (weights[i] > 9000.0) weights[i] = 9000.0;\n            }\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    Solver solver;\n    \n    int query_count = 1000;\n    for (int k = 0; k < query_count; ++k) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n        \n        auto [path_str, path_edges] = solver.find_path(si, sj, ti, tj);\n        cout << path_str << endl;\n        \n        int measured;\n        cin >> measured;\n        \n        solver.train(path_edges, measured, k);\n    }\n    \n    return 0;\n}","ahc004":"/**\n * Problem: AHC004 - Genetic Information\n * Approach: Multi-start Simulated Annealing with Pointer-based Dependency Graph\n * \n * Optimization Strategy:\n * 1. Data Structure Optimization:\n *    - Use direct pointers in `Dependency` struct to access `grid_hashes`, `grid_ids`, and `maps`.\n *    - This avoids array indexing overhead in the critical inner loop of SA.\n *    - Precompute all dependencies for each cell (O(1) lookup during SA).\n * \n * 2. State Updates:\n *    - Use Base-16 Rolling Hash.\n *    - Update hashes using XOR logic: `new_hash = old_hash ^ (old_val << shift) ^ (new_val << shift)`.\n *    - Only check map if `new_val` is not a DOT.\n *    - Incremental score update.\n * \n * 3. Search Strategy:\n *    - Main SA allows 0-8 (A-H + Dot).\n *    - Primary objective: Satisfy Strings. Secondary: Maximize Dots.\n *    - Multi-start to escape local optima.\n *    - Greedy Dot Optimization pass after each SA run if coverage is perfect.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <random>\n#include <cmath>\n#include <map>\n\nusing namespace std;\n\n// -----------------------------------------------------------------------------\n// Constants\n// -----------------------------------------------------------------------------\nconstexpr int N = 20;\nconstexpr int TIMEOUT_MS = 2950;\nconstexpr int HASH_MAP_SIZE = 16384;\nconstexpr int HASH_MAP_MASK = HASH_MAP_SIZE - 1;\nconstexpr int DOT_VAL = 8;\nconstexpr int SCORE_BASE = 10000; \n\n// -----------------------------------------------------------------------------\n// Random Number Generator\n// -----------------------------------------------------------------------------\nstruct Xorshift {\n    uint64_t state = 0x123456789ABCDEF;\n    inline uint64_t next() {\n        uint64_t x = state;\n        x ^= x << 13; x ^= x >> 7; x ^= x << 17;\n        return state = x;\n    }\n    inline int next_int(int n) { return next() % n; }\n    inline int next_val() { return next_int(9); } \n    inline int next_char() { return next() & 7; }\n    inline double next_double() { return (next() & 0xFFFFFFFF) / 4294967296.0; }\n};\nXorshift rng;\n\n// -----------------------------------------------------------------------------\n// Data Structures\n// -----------------------------------------------------------------------------\nstruct Target {\n    int id;\n    int weight;\n};\n\nstruct FastHashMap {\n    uint64_t keys[HASH_MAP_SIZE];\n    int ids[HASH_MAP_SIZE]; \n    \n    FastHashMap() { memset(ids, 0, sizeof(ids)); }\n    void clear() { memset(ids, 0, sizeof(ids)); }\n    \n    inline void insert(uint64_t key, int id) {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        keys[idx] = key;\n        ids[idx] = id + 1;\n    }\n    \n    inline int get(uint64_t key) const {\n        int idx = key & HASH_MAP_MASK;\n        while (ids[idx] != 0) {\n            if (keys[idx] == key) return ids[idx] - 1;\n            idx = (idx + 1) & HASH_MAP_MASK;\n        }\n        return -1;\n    }\n};\n\n// Optimized Dependency Struct using Pointers\nstruct Dependency {\n    uint64_t* hash_ptr;\n    int* id_ptr;\n    const FastHashMap* map_ptr;\n    uint8_t shift;\n};\n\nstruct Solver {\n    int M;\n    int max_possible_weight;\n    \n    FastHashMap maps[13];\n    vector<Target> targets_info;\n    vector<int> active_lengths;\n    \n    int grid[N][N];\n    \n    // Caches\n    uint64_t grid_hashes[2][13][N][N]; \n    int grid_ids[2][13][N][N]; \n    \n    // Score State\n    int occ[1000]; \n    int current_satisfied_weight;\n    int current_dots;\n    \n    // Best Solution\n    int best_grid[N][N];\n    int best_satisfied_weight;\n    int best_dots;\n    \n    // Precomputed dependencies\n    vector<Dependency> cell_deps[N][N];\n    \n    // Temp buffers\n    struct Change { int id; int diff; };\n    Change changes[256];\n    int changes_count;\n\n    Solver() {\n        best_satisfied_weight = -1;\n        best_dots = -1;\n    }\n\n    void read_input() {\n        int n_dummy;\n        if (!(cin >> n_dummy >> M)) return;\n        \n        map<string, int> counts;\n        for (int i = 0; i < M; ++i) {\n            string s; cin >> s; counts[s]++;\n        }\n        \n        max_possible_weight = M;\n        int id_counter = 0;\n        targets_info.reserve(counts.size());\n        \n        vector<bool> len_active(13, false);\n        for (auto const& [s, count] : counts) {\n            int len = s.length();\n            uint64_t h = 0;\n            for (char c : s) h = (h << 4) | (c - 'A');\n            maps[len].insert(h, id_counter);\n            targets_info.push_back({id_counter, count});\n            len_active[len] = true;\n            id_counter++;\n        }\n        \n        for(int l=2; l<=12; ++l) if (len_active[l]) active_lengths.push_back(l);\n        \n        // Precompute dependencies using pointers\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cell_deps[r][c].reserve(80);\n                for (int l : active_lengths) {\n                    // Horizontal\n                    for (int k = 0; k < l; ++k) {\n                        int start_c = (c - k + N) % N;\n                        Dependency dep;\n                        dep.hash_ptr = &grid_hashes[0][l][r][start_c];\n                        dep.id_ptr = &grid_ids[0][l][r][start_c];\n                        dep.map_ptr = &maps[l];\n                        dep.shift = (l - 1 - k) * 4;\n                        cell_deps[r][c].push_back(dep);\n                    }\n                    // Vertical\n                    for (int k = 0; k < l; ++k) {\n                        int start_r = (r - k + N) % N;\n                        Dependency dep;\n                        dep.hash_ptr = &grid_hashes[1][l][start_r][c];\n                        dep.id_ptr = &grid_ids[1][l][start_r][c];\n                        dep.map_ptr = &maps[l];\n                        dep.shift = (l - 1 - k) * 4;\n                        cell_deps[r][c].push_back(dep);\n                    }\n                }\n            }\n        }\n    }\n    \n    void init_state() {\n        current_satisfied_weight = 0;\n        current_dots = 0;\n        memset(occ, 0, sizeof(occ));\n        \n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                if (grid[r][c] == DOT_VAL) current_dots++;\n            }\n        }\n        \n        for(int dir=0; dir<2; ++dir) {\n            for(int l : active_lengths) {\n                for(int r=0; r<N; ++r) {\n                    for(int c=0; c<N; ++c) {\n                        uint64_t h = 0;\n                        if (dir == 0) {\n                            for(int k=0; k<l; ++k) h = (h << 4) | grid[r][(c+k)%N];\n                        } else {\n                            for(int k=0; k<l; ++k) h = (h << 4) | grid[(r+k)%N][c];\n                        }\n                        grid_hashes[dir][l][r][c] = h;\n                        \n                        int id = maps[l].get(h);\n                        grid_ids[dir][l][r][c] = id;\n                        \n                        if (id != -1) {\n                            if (occ[id] == 0) current_satisfied_weight += targets_info[id].weight;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n        update_best();\n    }\n    \n    void update_best() {\n        bool update = false;\n        if (current_satisfied_weight > best_satisfied_weight) update = true;\n        else if (current_satisfied_weight == best_satisfied_weight && current_dots > best_dots) update = true;\n        \n        if (update) {\n            best_satisfied_weight = current_satisfied_weight;\n            best_dots = current_dots;\n            memcpy(best_grid, grid, sizeof(grid));\n        }\n    }\n    \n    // Phase 2: Greedy Dot Optimization\n    void optimize_dots() {\n        if (best_satisfied_weight < max_possible_weight) return;\n        \n        memcpy(grid, best_grid, sizeof(grid));\n        init_state();\n        \n        vector<pair<int, int>> pos;\n        pos.reserve(N*N);\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) pos.push_back({i, j});\n        \n        // Try multiple passes\n        for (int pass = 0; pass < 3; ++pass) {\n            for(int i=pos.size()-1; i>0; --i) swap(pos[i], pos[rng.next_int(i+1)]);\n            bool improved = false;\n            \n            for (auto [r, c] : pos) {\n                if (grid[r][c] == DOT_VAL) continue;\n                \n                int old_val = grid[r][c];\n                const auto& deps = cell_deps[r][c];\n                changes_count = 0;\n                int weight_loss = 0;\n                \n                // Simulate removal\n                for (const auto& dep : deps) {\n                    int id = *dep.id_ptr;\n                    if (id != -1) {\n                        if (occ[id] == 1) weight_loss += targets_info[id].weight;\n                        occ[id]--;\n                        changes[changes_count++] = {id, -1};\n                    }\n                }\n                \n                if (weight_loss == 0) {\n                    grid[r][c] = DOT_VAL;\n                    current_dots++;\n                    improved = true;\n                    // Apply changes to hash/id\n                    uint64_t xor_val = (uint64_t(old_val) ^ uint64_t(DOT_VAL));\n                    for (const auto& dep : deps) {\n                         uint64_t new_h = (*dep.hash_ptr) ^ (xor_val << dep.shift);\n                         *dep.hash_ptr = new_h;\n                         *dep.id_ptr = -1;\n                    }\n                } else {\n                    // Revert\n                    for (int i = 0; i < changes_count; ++i) occ[changes[i].id] -= changes[i].diff;\n                }\n            }\n            if (!improved) break;\n        }\n        update_best();\n    }\n\n    void run_sa(double duration_ms) {\n        auto start_time = chrono::steady_clock::now();\n        double t0 = 15.0; \n        double t1 = 0.05;\n        \n        int64_t steps = 0;\n        \n        while (true) {\n            steps++;\n            if ((steps & 8191) == 0) {\n                if (chrono::duration<double, milli>(chrono::steady_clock::now() - start_time).count() > duration_ms) break;\n            }\n            \n            int r = rng.next_int(N);\n            int c = rng.next_int(N);\n            int old_val = grid[r][c];\n            int new_val;\n            do { new_val = rng.next_val(); } while (new_val == old_val);\n            \n            int delta_weight = 0;\n            changes_count = 0;\n            \n            const auto& deps = cell_deps[r][c];\n            \n            // 1. Remove old value contributions\n            for (const auto& dep : deps) {\n                int id = *dep.id_ptr;\n                if (id != -1) {\n                    if (occ[id] == 1) delta_weight -= targets_info[id].weight;\n                    occ[id]--;\n                    changes[changes_count++] = {id, -1};\n                }\n            }\n            \n            // 2. Add new value contributions\n            if (new_val != DOT_VAL) {\n                uint64_t xor_val = (uint64_t(old_val) ^ uint64_t(new_val));\n                for (const auto& dep : deps) {\n                    uint64_t new_h = (*dep.hash_ptr) ^ (xor_val << dep.shift);\n                    \n                    int id = dep.map_ptr->get(new_h);\n                    if (id != -1) {\n                        if (occ[id] == 0) delta_weight += targets_info[id].weight;\n                        occ[id]++;\n                        changes[changes_count++] = {id, 1};\n                    }\n                }\n            }\n            \n            // Score Logic\n            int score_diff = delta_weight * SCORE_BASE;\n            if (delta_weight == 0) {\n                // Secondary Objective: Dots\n                if (new_val == DOT_VAL) score_diff += 1;\n                if (old_val == DOT_VAL) score_diff -= 1;\n            }\n            \n            bool accept = false;\n            if (score_diff >= 0) accept = true;\n            else {\n                 double elapsed = chrono::duration<double, milli>(chrono::steady_clock::now() - start_time).count();\n                 double temp = t0 + (t1 - t0) * (elapsed / duration_ms);\n                 if (rng.next_double() < exp(score_diff / temp)) accept = true;\n            }\n            \n            if (accept) {\n                grid[r][c] = new_val;\n                current_satisfied_weight += delta_weight;\n                if (old_val == DOT_VAL) current_dots--;\n                if (new_val == DOT_VAL) current_dots++;\n                \n                uint64_t xor_val = (uint64_t(old_val) ^ uint64_t(new_val));\n                for (const auto& dep : deps) {\n                    uint64_t new_h = (*dep.hash_ptr) ^ (xor_val << dep.shift);\n                    *dep.hash_ptr = new_h;\n                    if (new_val == DOT_VAL) *dep.id_ptr = -1;\n                    else *dep.id_ptr = dep.map_ptr->get(new_h);\n                }\n                \n                if (current_satisfied_weight >= best_satisfied_weight) {\n                     if (current_satisfied_weight > best_satisfied_weight || current_dots > best_dots) {\n                         update_best();\n                     }\n                }\n\n            } else {\n                // Rollback\n                for (int i = changes_count - 1; i >= 0; --i) {\n                    occ[changes[i].id] -= changes[i].diff;\n                }\n            }\n        }\n    }\n\n    void solve() {\n        auto global_start = chrono::steady_clock::now();\n        \n        // Phase 0: Random Init\n        // We want characters only initially to boost match prob\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = rng.next_char();\n        init_state();\n        \n        int run_count = 0;\n        while(true) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - global_start).count();\n            if (elapsed > TIMEOUT_MS - 200 && run_count > 0) break;\n            \n            double remaining = TIMEOUT_MS - elapsed - 50;\n            double run_duration = 600.0;\n            if (remaining < 600) run_duration = remaining;\n            if (run_duration < 50) break;\n            \n            // Re-randomize grid on restart (keep best_grid safe)\n            if (run_count > 0) {\n                 for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = rng.next_char();\n                 init_state();\n            }\n            \n            run_sa(run_duration);\n            optimize_dots();\n            \n            run_count++;\n        }\n        \n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                int val = best_grid[i][j];\n                if (val == DOT_VAL) cout << '.';\n                else cout << (char)('A' + val);\n            }\n            cout << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver s;\n    s.read_input();\n    s.solve();\n    return 0;\n}","ahc005":"/**\n * Solution Analysis & Improvement Strategy:\n *\n * 1. Core Logic: Iterative Greedy with Min-Weight Vertex Cover (MWVC)\n *    - We construct the path by repeatedly solving MWVC on the bipartite graph of uncovered cells.\n *    - MWVC identifies the set of segments (Targets) to visit next to minimize cost.\n *    - We score candidate cells based on Cost/Gain, favoring those that cover Targets or form useful clusters.\n *\n * 2. Key Improvements in this version:\n *    - Performance Optimization: Switched Dijkstra from using `double` to scaled `int` (Base 1000 + Noise 0-150).\n *      Integer arithmetic is faster and avoids floating point overhead in the hot loop, allowing more iterations within 3.0s.\n *    - Intersection Bonus: Introduced a specific bonus for cells that cover *two* Target segments simultaneously.\n *      This explicitly biases the search towards the \"vertices\" of the Vertex Cover.\n *    - Bias Tuning: Shifted the `global_bias` distribution slightly negative ([-0.08, 0.02]).\n *      Negative bias makes distant cells appear slightly \"cheaper\", encouraging outlier exploration first.\n *    - Refined Scoring: Retained the \"Cluster Bonus\" (useful non-targets) as it proved effective.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n\n// Use AtCoder Library for MaxFlow\n#include <atcoder/maxflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Constants\nconst int INF = 1e9;\nconst char DIR_CHAR[] = {'U', 'D', 'L', 'R'};\nconst int SCALE = 1000; // Scale factor for integer Dijkstra\n\n// Global Grid Info\nint N;\nint SI, SJ;\nvector<string> GRID;\nvector<int> COSTS; // 1D flattened\nvector<bool> IS_ROAD; // 1D flattened\nvector<pair<int,int>> ROAD_CELLS; // Coordinates\n\n// Precomputed Distance from Start\nvector<int> DIST_TO_START; // 1D flattened\n\n// Helper for 1D coordinates\ninline int idx(int r, int c) { return r * N + c; }\n\n// Neighbor offsets (U, D, L, R)\nint D_OFF[4]; \n\nstruct Segment {\n    int id;\n    int type; // 0: H, 1: V\n    vector<int> cells; // 1D indices\n};\n\nvector<Segment> H_SEGS, V_SEGS;\nvector<int> H_ID; // 1D\nvector<int> V_ID; // 1D\n\n// Static Memory Pools (1D) for Dijkstra\nvector<int> dist_matrix;\nvector<int> parent_matrix;\nvector<int> dist_f_matrix; // Scaled integer distances\n\nvoid parse_input() {\n    if (!(cin >> N >> SI >> SJ)) return;\n    GRID.resize(N);\n    COSTS.resize(N * N);\n    IS_ROAD.assign(N * N, false);\n    H_ID.assign(N * N, -1);\n    V_ID.assign(N * N, -1);\n    ROAD_CELLS.clear();\n\n    for (int i = 0; i < N; ++i) {\n        cin >> GRID[i];\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i, j);\n            if (GRID[i][j] != '#') {\n                COSTS[id] = GRID[i][j] - '0';\n                IS_ROAD[id] = true;\n                ROAD_CELLS.push_back({i, j});\n            } else {\n                COSTS[id] = 0;\n            }\n        }\n    }\n\n    // Precompute offsets\n    D_OFF[0] = -N; D_OFF[1] = N; D_OFF[2] = -1; D_OFF[3] = 1;\n\n    // Identify Horizontal Segments\n    H_SEGS.clear();\n    int h_count = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ) {\n            if (!IS_ROAD[idx(i, j)]) { j++; continue; }\n            int k = j;\n            while (k < N && IS_ROAD[idx(i, k)]) k++;\n            Segment seg; seg.id = h_count; seg.type = 0;\n            for (int c = j; c < k; ++c) {\n                int id = idx(i, c);\n                seg.cells.push_back(id);\n                H_ID[id] = h_count;\n            }\n            H_SEGS.push_back(seg);\n            h_count++;\n            j = k;\n        }\n    }\n\n    // Identify Vertical Segments\n    V_SEGS.clear();\n    int v_count = 0;\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ) {\n            if (!IS_ROAD[idx(i, j)]) { i++; continue; }\n            int k = i;\n            while (k < N && IS_ROAD[idx(k, j)]) k++;\n            Segment seg; seg.id = v_count; seg.type = 1;\n            for (int r = i; r < k; ++r) {\n                int id = idx(r, j);\n                seg.cells.push_back(id);\n                V_ID[id] = v_count;\n            }\n            V_SEGS.push_back(seg);\n            v_count++;\n            i = k;\n        }\n    }\n\n    dist_matrix.resize(N * N);\n    parent_matrix.resize(N * N);\n    dist_f_matrix.resize(N * N);\n    DIST_TO_START.resize(N * N);\n}\n\n// Optimized Integer Dijkstra\n// compute_static: true -> standard Dijkstra for static distance (no noise)\n// compute_static: false -> randomized scaled Dijkstra for pathfinding\nvoid get_dist_matrix(int start_id, mt19937* rng, bool compute_static = false) {\n    if (compute_static) {\n        fill(dist_matrix.begin(), dist_matrix.end(), INF);\n        dist_matrix[start_id] = 0;\n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        pq.push({0, start_id});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist_matrix[u]) continue;\n            \n            int r = u / N, c = u % N;\n            for (int k = 0; k < 4; ++k) {\n                int nr = r, nc = c;\n                if (k == 0) nr--; else if (k == 1) nr++;\n                else if (k == 2) nc--; else nc++;\n                \n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = u + D_OFF[k]; \n                \n                if (IS_ROAD[v]) {\n                    int w = COSTS[v];\n                    if (d + w < dist_matrix[v]) {\n                        dist_matrix[v] = d + w;\n                        pq.push({dist_matrix[v], v});\n                    }\n                }\n            }\n        }\n    } else {\n        fill(dist_f_matrix.begin(), dist_f_matrix.end(), 2000000000); \n        \n        using P = pair<int, int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        \n        dist_matrix[start_id] = 0;\n        dist_f_matrix[start_id] = 0;\n        pq.push({0, start_id});\n        \n        // Directions buffer\n        int dirs[4] = {0, 1, 2, 3};\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            \n            if (d > dist_f_matrix[u]) continue;\n            \n            if (rng) {\n                for(int k=0; k<4; ++k) {\n                    int r = (*rng)() % (4 - k) + k;\n                    swap(dirs[k], dirs[r]);\n                }\n            }\n\n            int r = u / N, c = u % N;\n            for (int k : dirs) {\n                int nr = r, nc = c;\n                if (k == 0) nr--; else if (k == 1) nr++;\n                else if (k == 2) nc--; else nc++;\n                \n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                int v = u + D_OFF[k]; \n                \n                if (IS_ROAD[v]) {\n                    int w = COSTS[v];\n                    // Scaled weight + integer noise\n                    int noise = rng ? ((*rng)() % 150) : 0;\n                    int scaled_w = w * SCALE + noise;\n                    int new_d = d + scaled_w;\n                    \n                    if (new_d < dist_f_matrix[v]) {\n                        dist_f_matrix[v] = new_d;\n                        dist_matrix[v] = dist_matrix[u] + w;\n                        parent_matrix[v] = k;\n                        pq.push({new_d, v});\n                    }\n                }\n            }\n        }\n    }\n}\n\nstring get_path_str(int start_id, int end_id) {\n    string path = \"\";\n    int curr = end_id;\n    while (curr != start_id) {\n        int dir = parent_matrix[curr];\n        path += DIR_CHAR[dir];\n        if (dir == 0) curr -= D_OFF[0];\n        else if (dir == 1) curr -= D_OFF[1];\n        else if (dir == 2) curr -= D_OFF[2];\n        else if (dir == 3) curr -= D_OFF[3];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Result {\n    string path;\n    long long score;\n    int time_cost;\n};\n\nResult solve(int seed) {\n    mt19937 rng(seed);\n    \n    // Heuristic Parameters\n    uniform_real_distribution<double> penalty_dist(20.0, 120.0);\n    uniform_real_distribution<double> useful_dist(0.0, 0.4);\n    uniform_real_distribution<double> useful_bonus_dist(0.0, 0.05);\n    uniform_real_distribution<double> overhead_factor_dist(0.5, 2.0);\n    uniform_real_distribution<double> weight_noise_dist(0.9, 1.1);\n    uniform_real_distribution<double> bias_dist(-0.08, 0.02);\n    uniform_real_distribution<double> intersect_bonus_dist(0.0, 0.5);\n\n    double move_penalty = penalty_dist(rng);\n    double useful_base = useful_dist(rng);\n    double useful_bonus = useful_bonus_dist(rng);\n    double mwvc_overhead = move_penalty * overhead_factor_dist(rng);\n    double global_bias = bias_dist(rng);\n    double intersect_bonus = intersect_bonus_dist(rng);\n\n    vector<bool> covered(N * N, false);\n    int covered_cnt = 0;\n    int total_cells = ROAD_CELLS.size();\n    \n    vector<int> h_rem_cnt(H_SEGS.size());\n    vector<int> v_rem_cnt(V_SEGS.size());\n    for(int i=0; i<(int)H_SEGS.size(); ++i) h_rem_cnt[i] = H_SEGS[i].cells.size();\n    for(int i=0; i<(int)V_SEGS.size(); ++i) v_rem_cnt[i] = V_SEGS[i].cells.size();\n\n    auto visit_cell = [&](int id) {\n        if (!covered[id]) {\n            covered[id] = true;\n            covered_cnt++;\n            int hid = H_ID[id];\n            if (hid != -1) h_rem_cnt[hid]--;\n            int vid = V_ID[id];\n            if (vid != -1) v_rem_cnt[vid]--;\n        }\n    };\n\n    auto visit_pos = [&](int id) {\n        int hid = H_ID[id];\n        if (hid != -1) {\n            for (int cid : H_SEGS[hid].cells) visit_cell(cid);\n        }\n        int vid = V_ID[id];\n        if (vid != -1) {\n            for (int cid : V_SEGS[vid].cells) visit_cell(cid);\n        }\n    };\n\n    int current = idx(SI, SJ);\n    visit_pos(current);\n\n    string full_path = \"\";\n    int total_cost = 0;\n\n    while (covered_cnt < total_cells) {\n        // 1. Pathfinding\n        get_dist_matrix(current, &rng);\n\n        // 2. Build MWVC Graph\n        int S = H_SEGS.size() + V_SEGS.size();\n        int T = S + 1;\n        mf_graph<long long> g(T + 1);\n\n        for (auto& seg : H_SEGS) {\n            if (h_rem_cnt[seg.id] > 0) {\n                int min_d = INF;\n                int best_cid = -1;\n                for (int cid : seg.cells) {\n                    if (dist_matrix[cid] < min_d) {\n                        min_d = dist_matrix[cid];\n                        best_cid = cid;\n                    }\n                }\n                // Bias: prefer covering segments far from start (if bias < 0)\n                double d_bias = (best_cid != -1) ? DIST_TO_START[best_cid] * global_bias : 0;\n                long long w = (long long)((min_d + mwvc_overhead + d_bias) * weight_noise_dist(rng));\n                if (w < 1) w = 1;\n                g.add_edge(S, seg.id, w);\n            }\n        }\n        for (auto& seg : V_SEGS) {\n            if (v_rem_cnt[seg.id] > 0) {\n                int min_d = INF;\n                int best_cid = -1;\n                for (int cid : seg.cells) {\n                    if (dist_matrix[cid] < min_d) {\n                        min_d = dist_matrix[cid];\n                        best_cid = cid;\n                    }\n                }\n                double d_bias = (best_cid != -1) ? DIST_TO_START[best_cid] * global_bias : 0;\n                long long w = (long long)((min_d + mwvc_overhead + d_bias) * weight_noise_dist(rng));\n                if (w < 1) w = 1;\n                g.add_edge(H_SEGS.size() + seg.id, T, w);\n            }\n        }\n\n        // Constraints\n        bool needed = false;\n        for (auto& p : ROAD_CELLS) {\n            int id = idx(p.first, p.second);\n            if (!covered[id]) {\n                g.add_edge(H_ID[id], H_SEGS.size() + V_ID[id], 1e16);\n                needed = true;\n            }\n        }\n        if (!needed) break;\n\n        // Solve Min-Cut\n        g.flow(S, T);\n        auto cut = g.min_cut(S);\n\n        vector<bool> is_target_h(H_SEGS.size(), false);\n        vector<bool> is_target_v(V_SEGS.size(), false);\n        for(int i=0; i<(int)H_SEGS.size(); ++i) if(h_rem_cnt[i] > 0 && !cut[i]) is_target_h[i]=true;\n        for(int i=0; i<(int)V_SEGS.size(); ++i) if(v_rem_cnt[i] > 0 && cut[H_SEGS.size()+i]) is_target_v[i]=true;\n\n        // 3. Score Candidates\n        int best_id = -1;\n        double best_score = 1e18;\n\n        for (auto& p : ROAD_CELLS) {\n            int id = idx(p.first, p.second);\n            if (dist_matrix[id] == INF) continue;\n\n            int h = H_ID[id];\n            int v = V_ID[id];\n            double gain = 0.0;\n\n            bool th = (h != -1 && h_rem_cnt[h] > 0 && is_target_h[h]);\n            bool tv = (v != -1 && v_rem_cnt[v] > 0 && is_target_v[v]);\n\n            if (h != -1 && h_rem_cnt[h] > 0) {\n                if (th) gain += 1.0;\n                else gain += (useful_base + useful_bonus * h_rem_cnt[h]);\n            }\n            if (v != -1 && v_rem_cnt[v] > 0) {\n                if (tv) gain += 1.0;\n                else gain += (useful_base + useful_bonus * v_rem_cnt[v]);\n            }\n\n            if (th && tv) gain += intersect_bonus; // Bonus for covering two targets\n\n            if (gain < 1e-5) continue;\n\n            double cost = dist_matrix[id] + move_penalty + DIST_TO_START[id] * global_bias;\n            if (cost < 0) cost = 1.0;\n\n            double score = cost / gain;\n            score *= weight_noise_dist(rng);\n\n            if (score < best_score) {\n                best_score = score;\n                best_id = id;\n            }\n        }\n\n        if (best_id == -1) break;\n\n        // 4. Move\n        string sub = get_path_str(current, best_id);\n        full_path += sub;\n        total_cost += dist_matrix[best_id];\n        \n        int temp = current;\n        for (char c : sub) {\n            if (c == 'U') temp -= N;\n            else if (c == 'D') temp += N;\n            else if (c == 'L') temp -= 1;\n            else if (c == 'R') temp += 1;\n            visit_pos(temp);\n        }\n        current = best_id;\n        visit_pos(current);\n    }\n\n    // Return to start\n    if (current != idx(SI, SJ)) {\n        get_dist_matrix(current, &rng);\n        string sub = get_path_str(current, idx(SI, SJ));\n        full_path += sub;\n        total_cost += dist_matrix[idx(SI, SJ)];\n    }\n\n    return {full_path, 10000 + (long long)(1e7 * N / max(1, total_cost)), total_cost};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    parse_input();\n\n    // Precompute static distances\n    get_dist_matrix(idx(SI, SJ), nullptr, true);\n    DIST_TO_START = dist_matrix;\n\n    auto start_clock = chrono::high_resolution_clock::now();\n    double time_limit = 2.95;\n\n    Result best_res;\n    best_res.score = -1;\n\n    int seed = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> elapsed = now - start_clock;\n        if (elapsed.count() > time_limit) break;\n\n        Result res = solve(seed++);\n        if (res.score > best_res.score) {\n            best_res = res;\n        }\n    }\n\n    cout << best_res.path << endl;\n\n    return 0;\n}","future-contest-2022-qual":"/*\n * Solution for F Corporation Project Leader\n * Approach: Weighted Min-Cost Flow (Exp Priority) + CPM + Relaxed Incremental Coordinate Descent\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <chrono>\n#include <atcoder/mincostflow>\n\nusing namespace std;\nusing namespace atcoder;\n\n// --------------------------------------------------------------------------\n// Constants & Structures\n// --------------------------------------------------------------------------\n\nstruct Task {\n    int id;\n    vector<int> d;          // Required skill levels\n    vector<int> children;   // Dependent tasks\n    int unresolved_deps;    // Count of unsatisfied dependencies\n    double est_duration;    // Estimated duration for CPM\n    double cpm_height;      // Critical Path Height\n};\n\nstruct HistoryItem {\n    int task_id;\n    int actual_duration;\n};\n\nstruct Member {\n    int id;\n    vector<int> s;          // Estimated skill levels\n    vector<HistoryItem> history; // Log of completed tasks\n    int current_task;       // Currently assigned task ID, -1 if free\n    int start_day;          // Day the current task started\n};\n\n// --------------------------------------------------------------------------\n// Globals\n// --------------------------------------------------------------------------\n\nint N, M, K, R;\nvector<Task> tasks;\nvector<Member> members;\nvector<int> task_status;    // 0: waiting, 1: running, 2: completed\nmt19937 rng(5489);\nauto start_time = chrono::high_resolution_clock::now();\n\n// --------------------------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------------------------\n\ninline int calc_w(const vector<int>& d, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; ++k) {\n        int diff = d[k] - s[k];\n        if (diff > 0) w += diff;\n    }\n    return w;\n}\n\n// Expected days:\n// w=0 -> 1.0\n// w=1 -> 1.857\n// w=2 -> 2.428\n// w=3 -> 3.143\ninline double get_expected_days(int w) {\n    if (w <= 0) return 1.0;\n    if (w == 1) return 1.857142857;\n    if (w == 2) return 2.428571429;\n    if (w == 3) return 3.142857143;\n    return (double)w;\n}\n\ninline double get_expected_days_continuous(double w) {\n    if (w <= 0) return 1.0;\n    if (w >= 4) return w;\n    int w_floor = (int)w;\n    double v1 = get_expected_days(w_floor);\n    double v2 = get_expected_days(w_floor + 1);\n    return v1 + (v2 - v1) * (w - w_floor);\n}\n\ninline double get_elapsed_time() {\n    return chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n}\n\n// --------------------------------------------------------------------------\n// Skill Estimation: Incremental Coordinate Descent\n// --------------------------------------------------------------------------\n\nvoid update_member_skills(int m_idx) {\n    Member& m = members[m_idx];\n    int H = m.history.size();\n    if (H == 0) return;\n\n    vector<int> cached_w(H);\n    for(int i=0; i<H; ++i) {\n        cached_w[i] = calc_w(tasks[m.history[i].task_id].d, m.s);\n    }\n\n    long long current_sum_s = 0;\n    for(int x : m.s) current_sum_s += x;\n\n    // Revised Cost Function:\n    // - Hard Bounds Penalty: Extreme (20000)\n    // - Centering Penalty: Reduced weight (1) to allow floating within valid range\n    // - Regularization: Small\n    auto calc_incremental_cost = [&](int w, int actual) -> long long {\n        long long c = 0;\n        int lb, ub;\n        if (actual == 1) { lb=0; ub=4; }\n        else { lb = max(0, actual - 3); ub = actual + 3; }\n        \n        if (w < lb) c += (long long)(lb - w)*(lb - w) * 20000;\n        else if (w > ub) c += (long long)(w - ub)*(w - ub) * 20000;\n        \n        // Relaxed centering: only penalize if far from center?\n        // Actually, keeping L2 is robust, but maybe smaller weight relative to hard bounds is key.\n        // Here we keep it simple L2.\n        int diff = abs(w - actual);\n        c += diff * diff; \n        return c;\n    };\n\n    long long current_cost = 0;\n    for(int i=0; i<H; ++i) {\n        current_cost += calc_incremental_cost(cached_w[i], m.history[i].actual_duration);\n    }\n\n    int iterations = 500;\n    if (H > 50) iterations = 250;\n    if (H > 200) iterations = 150;\n    if (H > 500) iterations = 80;\n    \n    if (get_elapsed_time() > 2.75) iterations = 10;\n    \n    vector<int> p(K);\n    iota(p.begin(), p.end(), 0);\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        int k = p[rng() % K];\n        int original = m.s[k];\n        int best_val = original;\n        long long best_cost = current_cost;\n        long long best_reg = current_sum_s;\n\n        for (int delta : {-1, 1, -2, 2}) {\n            int next_val = original + delta;\n            if (next_val < 0) continue;\n\n            long long temp_cost = 0;\n            long long temp_reg = current_sum_s - original + next_val;\n            bool possible = true;\n\n            for(int i=0; i<H; ++i) {\n                int d_k = tasks[m.history[i].task_id].d[k];\n                int old_term = (d_k > original) ? (d_k - original) : 0;\n                int new_term = (d_k > next_val) ? (d_k - next_val) : 0;\n                \n                int w_new = cached_w[i];\n                if (old_term != new_term) {\n                    w_new = cached_w[i] - old_term + new_term;\n                    temp_cost += calc_incremental_cost(w_new, m.history[i].actual_duration);\n                } else {\n                    temp_cost += calc_incremental_cost(cached_w[i], m.history[i].actual_duration);\n                }\n\n                if (temp_cost > best_cost) { possible = false; break; }\n            }\n\n            if (possible) {\n                if (temp_cost < best_cost) {\n                    best_cost = temp_cost;\n                    best_reg = temp_reg;\n                    best_val = next_val;\n                } else if (temp_cost == best_cost) {\n                    if (temp_reg < best_reg) {\n                        best_reg = temp_reg;\n                        best_val = next_val;\n                    }\n                }\n            }\n        }\n\n        if (best_val != original) {\n            for(int i=0; i<H; ++i) {\n                int d_k = tasks[m.history[i].task_id].d[k];\n                int old_term = max(0, d_k - original);\n                int new_term = max(0, d_k - best_val);\n                cached_w[i] += (new_term - old_term);\n            }\n            m.s[k] = best_val;\n            current_cost = best_cost;\n            current_sum_s = best_reg;\n        }\n    }\n}\n\n// --------------------------------------------------------------------------\n// CPM Logic\n// --------------------------------------------------------------------------\n\nvoid update_cpm() {\n    // Use top 30% to balance expert availability\n    int top_k = max(1, (int)(M * 0.30));\n    vector<int> w_values(M);\n    \n    for (int i = 0; i < N; ++i) tasks[i].cpm_height = 0;\n\n    for (int i = N - 1; i >= 0; --i) {\n        for (int j = 0; j < M; ++j) {\n            w_values[j] = calc_w(tasks[i].d, members[j].s);\n        }\n        nth_element(w_values.begin(), w_values.begin() + top_k, w_values.end());\n        \n        long long sum_w = 0;\n        for (int j = 0; j < top_k; ++j) sum_w += w_values[j];\n        double avg_w = (double)sum_w / top_k;\n        \n        double duration = get_expected_days_continuous(avg_w);\n        tasks[i].est_duration = duration;\n        \n        double max_child_h = 0;\n        for (int v : tasks[i].children) {\n            if (v < N) max_child_h = max(max_child_h, tasks[v].cpm_height);\n        }\n        tasks[i].cpm_height = duration + max_child_h;\n    }\n}\n\n// --------------------------------------------------------------------------\n// Main\n// --------------------------------------------------------------------------\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    tasks.resize(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].id = i;\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; ++k) cin >> tasks[i].d[k];\n    }\n\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v; \n        tasks[u].children.push_back(v);\n        tasks[v].unresolved_deps++;\n    }\n\n    members.resize(M);\n    for (int i = 0; i < M; ++i) {\n        members[i].id = i;\n        members[i].s.assign(K, 0);\n        members[i].current_task = -1;\n        members[i].start_day = -1;\n    }\n    \n    task_status.assign(N, 0);\n    update_cpm();\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> available_tasks;\n        available_tasks.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 0 && tasks[i].unresolved_deps == 0) {\n                available_tasks.push_back(i);\n            }\n        }\n\n        vector<int> free_members;\n        free_members.reserve(M);\n        for (int i = 0; i < M; ++i) {\n            if (members[i].current_task == -1) {\n                free_members.push_back(i);\n            }\n        }\n\n        vector<pair<int, int>> assignments;\n\n        if (!available_tasks.empty() && !free_members.empty()) {\n            update_cpm();\n            \n            // Sort descending by CPM Height\n            sort(available_tasks.begin(), available_tasks.end(), [&](int a, int b) {\n                if (abs(tasks[a].cpm_height - tasks[b].cpm_height) > 1e-6)\n                    return tasks[a].cpm_height > tasks[b].cpm_height;\n                return tasks[a].children.size() > tasks[b].children.size();\n            });\n\n            int k_assign = min((int)available_tasks.size(), (int)free_members.size());\n            int num_free = free_members.size();\n            \n            int S = 0;\n            int T = num_free + k_assign + 1;\n            mcf_graph<int, long long> g(T + 1);\n\n            for (int i = 0; i < num_free; ++i) g.add_edge(S, 1 + i, 1, 0);\n            for (int j = 0; j < k_assign; ++j) g.add_edge(num_free + 1 + j, T, 1, 0);\n\n            for (int i = 0; i < num_free; ++i) {\n                int m_id = free_members[i];\n                long long skill_sum = 0;\n                for(int s : members[m_id].s) skill_sum += s;\n\n                for (int j = 0; j < k_assign; ++j) {\n                    int t_id = available_tasks[j];\n                    int w = calc_w(tasks[t_id].d, members[m_id].s);\n                    double exp_days = get_expected_days(w);\n                    \n                    // Weighting Strategy:\n                    // We use an exponential-like boost for high priority tasks.\n                    // Base Multiplier = 10000.\n                    // Height Bonus = Height * 3000.\n                    // This scaling ensures that saving 1 day on a high-height task is worth\n                    // \"infinitely\" more than saving 1 day on a low-height task, \n                    // but for tasks with similar heights, it allows optimizing the sum of durations.\n                    \n                    double h = tasks[t_id].cpm_height;\n                    long long priority_weight = 10000 + (long long)(h * 3000.0);\n                    \n                    long long cost = (long long)(exp_days * priority_weight) + skill_sum;\n                    g.add_edge(1 + i, num_free + 1 + j, 1, cost);\n                }\n            }\n\n            auto result = g.flow(S, T, k_assign);\n            auto edges = g.edges();\n            for (const auto& e : edges) {\n                if (e.from >= 1 && e.from <= num_free && \n                    e.to >= num_free + 1 && e.to <= num_free + k_assign && \n                    e.flow == 1) {\n                    \n                    int m_idx = e.from - 1;\n                    int t_idx = e.to - (num_free + 1);\n                    assignments.push_back({free_members[m_idx], available_tasks[t_idx]});\n                }\n            }\n        }\n\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first + 1 << \" \" << p.second + 1;\n            members[p.first].current_task = p.second;\n            members[p.first].start_day = day;\n            task_status[p.second] = 1;\n        }\n        cout << endl;\n\n        int n_finished;\n        cin >> n_finished;\n        if (n_finished == -1) break;\n\n        for (int i = 0; i < n_finished; ++i) {\n            int m_id_in; cin >> m_id_in;\n            int m_id = m_id_in - 1;\n            \n            int t_id = members[m_id].current_task;\n            int duration = day - members[m_id].start_day + 1;\n            \n            members[m_id].history.push_back({t_id, duration});\n            members[m_id].current_task = -1;\n            task_status[t_id] = 2;\n            for (int child : tasks[t_id].children) tasks[child].unresolved_deps--;\n            \n            update_member_skills(m_id);\n        }\n    }\n\n    return 0;\n}","ahc006":"#pragma GCC optimize(\"O3,unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <array>\n#include <cstring>\n\nusing namespace std;\n\n// ---------------------------------------------------------\n// Constants & Globals\n// ---------------------------------------------------------\nconstexpr int NUM_ORDERS = 1000;\nconstexpr int TARGET_ORDERS = 50;\nconstexpr int OFFICE_X = 400;\nconstexpr int OFFICE_Y = 400;\nconstexpr int TIME_LIMIT_MS = 1980;\nconstexpr int NEIGHBOR_COUNT = 40;\n\nalignas(64) int node_x[2001];\nalignas(64) int node_y[2001];\nalignas(64) uint16_t dist_mat[2001][2001]; // Precomputed distance matrix\n\nstruct OrderRaw {\n    int a, b, c, d;\n};\nOrderRaw orders_raw[NUM_ORDERS];\n\n// Precomputed neighbors for guided swap\nint neighbors[NUM_ORDERS][NEIGHBOR_COUNT];\n\n// ---------------------------------------------------------\n// Utils\n// ---------------------------------------------------------\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return next() / 4294967295.0;\n    }\n} rng;\n\ninline int get_dist_fast(int u, int v) {\n    int idx_u = (u == -1) ? 2000 : u;\n    int idx_v = (v == -1) ? 2000 : v;\n    return dist_mat[idx_u][idx_v];\n}\n\n// ---------------------------------------------------------\n// Solution State\n// ---------------------------------------------------------\nstruct Solution {\n    vector<int> route; \n    bitset<NUM_ORDERS> selected;\n    int total_dist;\n\n    void calc_dist() {\n        total_dist = 0;\n        if (route.empty()) return;\n        total_dist += get_dist_fast(-1, route[0]);\n        for (size_t i = 0; i < route.size() - 1; ++i) {\n            total_dist += get_dist_fast(route[i], route[i+1]);\n        }\n        total_dist += get_dist_fast(route.back(), -1);\n    }\n};\n\nstruct InsertInfo {\n    int delta;\n    int p_pos;\n    int d_pos;\n};\n\n// ---------------------------------------------------------\n// O(N) Insertion Logic\n// ---------------------------------------------------------\nstatic int cost_p[105];\nstatic int cost_d[105];\nstatic pair<int, int> suffix_min[105];\n\nInsertInfo find_best_insertion_fast(const vector<int>& route, int ord_idx) {\n    int P = ord_idx;\n    int D = ord_idx + 1000;\n    int n = route.size();\n    \n    for(int k=0; k<=n; ++k) {\n        int prev = (k==0) ? -1 : route[k-1];\n        int next = (k==n) ? -1 : route[k];\n        int base = get_dist_fast(prev, next);\n        cost_p[k] = get_dist_fast(prev, P) + get_dist_fast(P, next) - base;\n        cost_d[k] = get_dist_fast(prev, D) + get_dist_fast(D, next) - base;\n    }\n    \n    suffix_min[n] = {cost_d[n], n};\n    for(int k=n-1; k>=0; --k) {\n        if (cost_d[k] < suffix_min[k+1].first) {\n            suffix_min[k] = {cost_d[k], k};\n        } else {\n            suffix_min[k] = suffix_min[k+1];\n        }\n    }\n    \n    int best_val = 1e9;\n    int best_p = -1;\n    int best_d = -1;\n    \n    for(int i=0; i<=n; ++i) {\n        // Case 1: Insert P and D adjacently at i\n        {\n            int prev = (i==0) ? -1 : route[i-1];\n            int next = (i==n) ? -1 : route[i];\n            int base = get_dist_fast(prev, next);\n            int val = get_dist_fast(prev, P) + get_dist_fast(P, D) + get_dist_fast(D, next) - base;\n            if (val < best_val) { best_val = val; best_p = i; best_d = i; }\n        }\n        // Case 2: Insert P at i, D at some j > i\n        if (i < n) {\n            int val = cost_p[i] + suffix_min[i+1].first;\n            if (val < best_val) { best_val = val; best_p = i; best_d = suffix_min[i+1].second; }\n        }\n    }\n    return {best_val, best_p, best_d};\n}\n\nSolution build_solution_refined(const vector<int>& subset) {\n    Solution sol;\n    sol.selected.reset();\n    sol.route.reserve(2 * TARGET_ORDERS);\n    if (subset.empty()) return sol;\n\n    int first = subset[0];\n    sol.selected[first] = true;\n    sol.route.push_back(first);\n    sol.route.push_back(first + 1000);\n    sol.calc_dist(); \n\n    // Greedy Insertion\n    for (size_t k = 1; k < subset.size(); ++k) {\n        int ord = subset[k];\n        sol.selected[ord] = true;\n        InsertInfo info = find_best_insertion_fast(sol.route, ord);\n        sol.route.insert(sol.route.begin() + info.p_pos, ord);\n        sol.route.insert(sol.route.begin() + info.d_pos + 1, ord + 1000);\n        sol.total_dist += info.delta;\n    }\n    \n    // Refinement Pass\n    for(int ord : subset) {\n        vector<int> temp; \n        temp.reserve(sol.route.size());\n        for(int u : sol.route) {\n            int o = (u < 1000) ? u : u - 1000;\n            if(o != ord) temp.push_back(u);\n        }\n        InsertInfo info = find_best_insertion_fast(temp, ord);\n        temp.insert(temp.begin() + info.p_pos, ord);\n        temp.insert(temp.begin() + info.d_pos + 1, ord + 1000);\n        sol.route = temp;\n        sol.calc_dist();\n    }\n    return sol;\n}\n\nSolution generate_initial_solution() {\n    Solution best_init;\n    best_init.total_dist = 2e9;\n\n    vector<int> centers;\n    centers.reserve(NUM_ORDERS + 1);\n    centers.push_back(-1);\n    for(int i=0; i<NUM_ORDERS; ++i) centers.push_back(i);\n\n    static pair<int,int> dist_vec[NUM_ORDERS];\n\n    for (int c_idx : centers) {\n        int cx = (c_idx == -1) ? OFFICE_X : node_x[c_idx];\n        int cy = (c_idx == -1) ? OFFICE_Y : node_y[c_idx];\n\n        for(int i=0; i<NUM_ORDERS; ++i) {\n            int d_p = abs(node_x[i] - cx) + abs(node_y[i] - cy);\n            int d_d = abs(node_x[i+1000] - cx) + abs(node_y[i+1000] - cy);\n            int d_intr = abs(node_x[i] - node_x[i+1000]) + abs(node_y[i] - node_y[i+1000]);\n            dist_vec[i] = {d_p + d_d + d_intr, i};\n        }\n        \n        nth_element(dist_vec, dist_vec + TARGET_ORDERS, dist_vec + NUM_ORDERS);\n\n        vector<int> subset;\n        subset.reserve(TARGET_ORDERS);\n        for(int k=0; k<TARGET_ORDERS; ++k) subset.push_back(dist_vec[k].second);\n        \n        Solution s = build_solution_refined(subset);\n        if (s.total_dist < best_init.total_dist) {\n            best_init = s;\n        }\n    }\n    return best_init;\n}\n\nbool check_2opt_valid(const vector<int>& route, int l, int r) {\n    static int seen[NUM_ORDERS];\n    static int stamp = 0;\n    stamp++;\n    for (int i = l; i <= r; ++i) {\n        int u = route[i];\n        int oid = (u < 1000) ? u : u - 1000;\n        if (seen[oid] == stamp) return false;\n        seen[oid] = stamp;\n    }\n    return true;\n}\n\nvoid init_dist_mat() {\n    node_x[2000] = OFFICE_X;\n    node_y[2000] = OFFICE_Y;\n    for(int i=0; i<=2000; ++i) {\n        for(int j=0; j<=2000; ++j) {\n            dist_mat[i][j] = abs(node_x[i] - node_x[j]) + abs(node_y[i] - node_y[j]);\n        }\n    }\n}\n\nvoid init_neighbors() {\n    static pair<int,int> d[NUM_ORDERS];\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        for(int j=0; j<NUM_ORDERS; ++j) {\n            d[j] = {dist_mat[i][j], j};\n        }\n        d[i] = {2e9, i}; \n        partial_sort(d, d + NEIGHBOR_COUNT, d + NUM_ORDERS);\n        for(int k=0; k<NEIGHBOR_COUNT; ++k) neighbors[i][k] = d[k].second;\n    }\n}\n\n// Heuristic to select an order to remove based on approximated cost contribution\nint select_removal_candidate(const vector<int>& route, int trials) {\n    int best_ord = -1;\n    int max_saving = -1;\n    int sz = route.size();\n    \n    for(int t=0; t<trials; ++t) {\n        int idx = rng.next_int(sz);\n        int val = route[idx];\n        int ord = (val < 1000) ? val : val - 1000;\n        \n        int p_idx = -1, d_idx = -1;\n        for(int i=0; i<sz; ++i) {\n            if(route[i] == ord) p_idx = i;\n            else if(route[i] == ord + 1000) d_idx = i;\n        }\n        \n        int saving = 0;\n        int p_prev = (p_idx == 0) ? -1 : route[p_idx-1];\n        int p_next = (p_idx == sz-1) ? -1 : route[p_idx+1];\n        \n        if (d_idx == p_idx + 1) {\n            int d_next = (d_idx == sz-1) ? -1 : route[d_idx+1];\n            saving = get_dist_fast(p_prev, ord) + get_dist_fast(ord, ord+1000) + get_dist_fast(ord+1000, d_next) - get_dist_fast(p_prev, d_next);\n        } else {\n            int p_rem = get_dist_fast(p_prev, ord) + get_dist_fast(ord, p_next) - get_dist_fast(p_prev, p_next);\n            int d_prev = route[d_idx-1]; \n            int d_next = (d_idx == sz-1) ? -1 : route[d_idx+1];\n            int d_rem = get_dist_fast(d_prev, ord+1000) + get_dist_fast(ord+1000, d_next) - get_dist_fast(d_prev, d_next);\n            saving = p_rem + d_rem;\n        }\n        \n        if (saving > max_saving) {\n            max_saving = saving;\n            best_ord = ord;\n        }\n    }\n    return best_ord;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    auto start_t = chrono::high_resolution_clock::now();\n\n    for(int i=0; i<NUM_ORDERS; ++i) {\n        cin >> orders_raw[i].a >> orders_raw[i].b >> orders_raw[i].c >> orders_raw[i].d;\n        node_x[i] = orders_raw[i].a; node_y[i] = orders_raw[i].b;\n        node_x[i+1000] = orders_raw[i].c; node_y[i+1000] = orders_raw[i].d;\n    }\n    \n    init_dist_mat();\n    init_neighbors();\n\n    Solution curr_sol = generate_initial_solution();\n    Solution best_sol = curr_sol;\n\n    double t_start = 250.0; \n    double t_end = 0.1;\n    double temp = t_start;\n\n    vector<int> temp_route; \n    temp_route.reserve(105);\n    vector<int> candidates;\n    candidates.reserve(4);\n\n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 127) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            double elapsed = chrono::duration<double>(now - start_t).count() * 1000.0;\n            if (elapsed > TIME_LIMIT_MS) break;\n            double ratio = elapsed / TIME_LIMIT_MS;\n            temp = t_start * pow(t_end / t_start, ratio);\n        }\n\n        int type = rng.next_int(100);\n        \n        // Dynamic Probabilities: Favor exploration (Swap) early, optimization late.\n        bool do_swap = type < (temp > 20.0 ? 45 : 25);\n        \n        if (do_swap) { \n            // SWAP: Biased Removal + Best-of-3 Guided Insertion\n            int ord_rem = select_removal_candidate(curr_sol.route, 5); \n            \n            temp_route.clear();\n            for (int u : curr_sol.route) {\n                int o = (u < 1000) ? u : u - 1000;\n                if (o != ord_rem) temp_route.push_back(u);\n            }\n            \n            int base_dist = 0;\n            if (!temp_route.empty()) {\n                base_dist += get_dist_fast(-1, temp_route[0]);\n                for(size_t i=0; i<temp_route.size()-1; ++i) base_dist += get_dist_fast(temp_route[i], temp_route[i+1]);\n                base_dist += get_dist_fast(temp_route.back(), -1);\n            }\n\n            candidates.clear();\n            // 1. Guided Candidates\n            if (!temp_route.empty()) {\n                int anchor = temp_route[rng.next_int(temp_route.size())];\n                int anchor_ord = (anchor < 1000) ? anchor : anchor - 1000;\n                for(int k=0; k<20 && candidates.size() < 2; ++k) {\n                    int cand = neighbors[anchor_ord][rng.next_int(NEIGHBOR_COUNT)];\n                    if (!curr_sol.selected[cand]) {\n                        bool exists = false;\n                        for(int c : candidates) if(c==cand) exists=true;\n                        if(!exists) candidates.push_back(cand);\n                    }\n                }\n            }\n            // 2. Random Candidates\n            while(candidates.size() < 3) {\n                int cand = rng.next_int(NUM_ORDERS);\n                if (!curr_sol.selected[cand]) {\n                    bool exists = false;\n                    for(int c : candidates) if(c==cand) exists=true;\n                    if(!exists) candidates.push_back(cand);\n                }\n            }\n\n            // Evaluate candidates\n            int best_cand = -1;\n            InsertInfo best_info = { (int)1e9, -1, -1 };\n            \n            for (int cand : candidates) {\n                InsertInfo info = find_best_insertion_fast(temp_route, cand);\n                if (info.delta < best_info.delta) {\n                    best_info = info;\n                    best_cand = cand;\n                }\n            }\n\n            int new_dist = base_dist + best_info.delta;\n            int diff = new_dist - curr_sol.total_dist;\n\n            if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                curr_sol.selected[ord_rem] = false;\n                curr_sol.selected[best_cand] = true;\n                curr_sol.route = temp_route;\n                curr_sol.route.insert(curr_sol.route.begin() + best_info.p_pos, best_cand);\n                curr_sol.route.insert(curr_sol.route.begin() + best_info.d_pos + 1, best_cand + 1000);\n                curr_sol.total_dist = new_dist;\n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 70) { // REINSERT\n            int ord_rem = select_removal_candidate(curr_sol.route, 3); \n            \n            temp_route.clear();\n            for (int u : curr_sol.route) {\n                int o = (u < 1000) ? u : u - 1000;\n                if (o != ord_rem) temp_route.push_back(u);\n            }\n            \n            int base_dist = 0;\n            if (!temp_route.empty()) {\n                base_dist += get_dist_fast(-1, temp_route[0]);\n                for(size_t i=0; i<temp_route.size()-1; ++i) base_dist += get_dist_fast(temp_route[i], temp_route[i+1]);\n                base_dist += get_dist_fast(temp_route.back(), -1);\n            }\n\n            InsertInfo info = find_best_insertion_fast(temp_route, ord_rem);\n            int new_dist = base_dist + info.delta;\n            int diff = new_dist - curr_sol.total_dist;\n\n            if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                curr_sol.route = temp_route;\n                curr_sol.route.insert(curr_sol.route.begin() + info.p_pos, ord_rem);\n                curr_sol.route.insert(curr_sol.route.begin() + info.d_pos + 1, ord_rem + 1000);\n                curr_sol.total_dist = new_dist;\n                if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n            }\n\n        } else if (type < 85) { // GREEDY RELOCATE\n            int sz = curr_sol.route.size();\n            int u_idx = rng.next_int(sz);\n            int val = curr_sol.route[u_idx];\n            \n            temp_route = curr_sol.route;\n            temp_route.erase(temp_route.begin() + u_idx);\n            \n            int partner = (val < 1000) ? val + 1000 : val - 1000;\n            int p_idx = -1;\n            for(int i=0; i<(int)temp_route.size(); ++i) if(temp_route[i] == partner) { p_idx = i; break; }\n\n            int min_ins = (val < 1000) ? 0 : p_idx + 1;\n            int max_ins = (val < 1000) ? p_idx : (int)temp_route.size();\n            \n            if (min_ins <= max_ins) {\n                int u_prev = (u_idx==0) ? -1 : curr_sol.route[u_idx-1];\n                int u_next = (u_idx==sz-1) ? -1 : curr_sol.route[u_idx+1];\n                int rem_cost = get_dist_fast(u_prev, val) + get_dist_fast(val, u_next) - get_dist_fast(u_prev, u_next);\n                \n                int best_delta = 1e9, best_pos = -1;\n                for(int k=min_ins; k<=max_ins; ++k) {\n                    int t_prev = (k==0) ? -1 : temp_route[k-1];\n                    int t_next = (k==(int)temp_route.size()) ? -1 : temp_route[k];\n                    int add_cost = get_dist_fast(t_prev, val) + get_dist_fast(val, t_next) - get_dist_fast(t_prev, t_next);\n                    int delta = add_cost - rem_cost;\n                    if(delta < best_delta) { best_delta = delta; best_pos = k; }\n                }\n                \n                if (best_delta < 1e9 && (best_delta < 0 || rng.next_double() < exp(-best_delta / temp))) {\n                    temp_route.insert(temp_route.begin() + best_pos, val);\n                    curr_sol.route = temp_route;\n                    curr_sol.total_dist += best_delta;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n\n        } else { // 2-OPT\n            int sz = curr_sol.route.size();\n            int l = rng.next_int(sz - 1);\n            int r = rng.next_int(sz - l - 1) + l + 1;\n            if (check_2opt_valid(curr_sol.route, l, r)) {\n                int u_prev = (l==0) ? -1 : curr_sol.route[l-1];\n                int u_curr = curr_sol.route[l];\n                int v_curr = curr_sol.route[r];\n                int v_next = (r==sz-1) ? -1 : curr_sol.route[r+1];\n                int old_delta = get_dist_fast(u_prev, u_curr) + get_dist_fast(v_curr, v_next);\n                int new_delta = get_dist_fast(u_prev, v_curr) + get_dist_fast(u_curr, v_next);\n                int diff = new_delta - old_delta;\n                if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n                    reverse(curr_sol.route.begin() + l, curr_sol.route.begin() + r + 1);\n                    curr_sol.total_dist += diff;\n                    if (curr_sol.total_dist < best_sol.total_dist) best_sol = curr_sol;\n                }\n            }\n        }\n    }\n\n    vector<int> out_ids;\n    for(int i=0; i<NUM_ORDERS; ++i) if(best_sol.selected[i]) out_ids.push_back(i+1);\n    cout << out_ids.size();\n    for(int id : out_ids) cout << \" \" << id;\n    cout << \"\\n\";\n    cout << best_sol.route.size() + 2 << \" \" << OFFICE_X << \" \" << OFFICE_Y;\n    for(int u : best_sol.route) cout << \" \" << node_x[u] << \" \" << node_y[u];\n    cout << \" \" << OFFICE_X << \" \" << OFFICE_Y << \"\\n\";\n\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\n\nusing namespace std;\n\n// --- Constants & Tuning ---\nconst double TIME_LIMIT_SEC = 1.90; // Safety margin for 2.0s limit\nconst int MAX_W = 4000;             // Upper bound for edge weights (approx 800*sqrt(2)*3)\n\n// --- Data Structures ---\nstruct Point {\n    int x, y;\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n    int id;\n};\n\nstruct SimEdge {\n    int u_c, v_c;  // Component indices\n    int d_val;     // Min possible weight\n    int w_val;     // Current simulated weight\n    int range_len; // range of random weight (3d - d + 1)\n};\n\n// Optimized Disjoint Set Union\nstruct DSU {\n    vector<int> parent;\n    \n    DSU(int n) {\n        parent.resize(n);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    // Fast reset\n    inline void reset(int n) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int i) {\n        int root = i;\n        while (root != parent[root]) root = parent[root];\n        // Path compression\n        while (i != root) {\n            int next = parent[i];\n            parent[i] = root;\n            i = next;\n        }\n        return root;\n    }\n    \n    inline bool unite(int i, int j) {\n        int root_i = find(i);\n        int root_j = find(j);\n        if (root_i != root_j) {\n            parent[root_i] = root_j;\n            return true;\n        }\n        return false;\n    }\n    \n    inline bool same(int i, int j) {\n        return find(i) == find(j);\n    }\n};\n\n// Fast Xorshift Random Number Generator\nstruct Xorshift {\n    uint32_t state;\n    Xorshift(uint32_t seed = 123456789) : state(seed) {}\n    \n    inline uint32_t next() {\n        uint32_t x = state;\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return state = x;\n    }\n};\n\n// --- Globals ---\nint N, M;\nvector<Point> points;\nvector<Edge> all_edges;\nXorshift rng;\nauto start_time = chrono::high_resolution_clock::now();\n\n// Buffers for Counting Sort to avoid allocation in loop\nint cnt[MAX_W + 1];\nvector<SimEdge> sorted_buffer;\n\n// --- Helper Functions ---\ninline double get_elapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    chrono::duration<double> diff = now - start_time;\n    return diff.count();\n}\n\nint calc_dist(int i, int j) {\n    long long dx = points[i].x - points[j].x;\n    long long dy = points[i].y - points[j].y;\n    return (int)round(sqrt(dx*dx + dy*dy));\n}\n\n// O(N) Counting Sort for simulation edges\n// Much faster than std::sort for small integer keys\nvoid count_sort(vector<SimEdge>& edges, int n) {\n    memset(cnt, 0, sizeof(cnt));\n\n    for(int i=0; i<n; ++i) {\n        cnt[edges[i].w_val]++;\n    }\n\n    // Prefix sums\n    int current = 0;\n    for(int i=0; i<=MAX_W; ++i) {\n        int tmp = cnt[i];\n        cnt[i] = current;\n        current += tmp;\n    }\n\n    for(int i=0; i<n; ++i) {\n        sorted_buffer[cnt[edges[i].w_val]++] = edges[i];\n    }\n    \n    for(int i=0; i<n; ++i) edges[i] = sorted_buffer[i];\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // --- Input Parsing ---\n    int a, b;\n    if (!(cin >> a >> b)) return 0;\n    \n    if (b > 800) {\n        N = a; M = b;\n        points.resize(N);\n        for(int i=0; i<N; ++i) cin >> points[i].x >> points[i].y;\n    } else {\n        N = 400; M = 1995;\n        points.resize(N);\n        points[0].x = a; points[0].y = b;\n        for(int i=1; i<N; ++i) cin >> points[i].x >> points[i].y;\n    }\n\n    all_edges.resize(M);\n    for(int i=0; i<M; ++i) {\n        cin >> all_edges[i].u >> all_edges[i].v;\n        all_edges[i].d = calc_dist(all_edges[i].u, all_edges[i].v);\n        all_edges[i].id = i;\n    }\n\n    // --- Initialization ---\n    DSU main_dsu(N);\n    DSU sim_dsu(N);\n    \n    vector<SimEdge> candidates; candidates.reserve(M);\n    vector<SimEdge> active_sim_edges; active_sim_edges.reserve(M);\n    sorted_buffer.resize(M);\n    \n    int current_components = N;\n\n    // --- Main Interaction Loop ---\n    for (int i = 0; i < M; ++i) {\n        int l_i;\n        cin >> l_i;\n\n        int u = all_edges[i].u;\n        int v = all_edges[i].v;\n        \n        // 1. Cycle Check\n        if (main_dsu.same(u, v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int root_u = main_dsu.find(u);\n        int root_v = main_dsu.find(v);\n\n        // 2. Gather Candidates\n        // Collect all future edges that connect distinct components\n        candidates.clear();\n        for (int j = i + 1; j < M; ++j) {\n            int ru = main_dsu.find(all_edges[j].u);\n            int rv = main_dsu.find(all_edges[j].v);\n            if (ru != rv) {\n                candidates.push_back({ru, rv, all_edges[j].d, 0, 2 * all_edges[j].d + 1});\n            }\n        }\n\n        // 3. Bridge Check\n        // Check if connectivity is possible using all available candidates\n        sim_dsu.reset(N);\n        for (const auto& e : candidates) {\n            sim_dsu.unite(e.u_c, e.v_c);\n        }\n        if (!sim_dsu.same(root_u, root_v)) {\n            // Bridge detected: Must accept\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            current_components--;\n            continue;\n        }\n\n        // 4. Filter Simulation Set\n        // Heuristic: Sort by minimum length d. \n        // We only need the best edges to form the MST. \n        // K = 2*Components is usually sufficient for Euclidean graphs.\n        sort(candidates.begin(), candidates.end(), [](const SimEdge& a, const SimEdge& b){\n            return a.d_val < b.d_val;\n        });\n        \n        active_sim_edges.clear();\n        int target_size = max(current_components * 2, 400); // Keep a healthy buffer\n        if (target_size > (int)candidates.size()) target_size = (int)candidates.size();\n        \n        for(int k=0; k<target_size; ++k) {\n            active_sim_edges.push_back(candidates[k]);\n        }\n        \n        // 5. Monte Carlo Simulation\n        double elapsed = get_elapsed();\n        double budget = (TIME_LIMIT_SEC - elapsed) / (M - i + 5);\n        if (budget < 0.0002) budget = 0.0002; // Min time slice\n\n        long long sum_bottleneck = 0;\n        int sims = 0;\n        int n_active = active_sim_edges.size();\n        \n        auto step_start = chrono::high_resolution_clock::now();\n        \n        while(true) {\n            // Generate random weights\n            for (int k=0; k<n_active; ++k) {\n                 uint32_t r = rng.next();\n                 // Fast mapping to range [0, range_len-1]\n                 uint32_t offset = ((uint64_t)r * active_sim_edges[k].range_len) >> 32;\n                 active_sim_edges[k].w_val = active_sim_edges[k].d_val + offset;\n            }\n\n            // Sort (Counting Sort)\n            count_sort(active_sim_edges, n_active);\n\n            // Kruskal's Algorithm (Early Exit)\n            sim_dsu.reset(N);\n            int bottleneck = -1;\n            \n            for (int k=0; k<n_active; ++k) {\n                const auto& e = active_sim_edges[k];\n                if (sim_dsu.unite(e.u_c, e.v_c)) {\n                    // Stop as soon as our specific components are connected\n                    if (sim_dsu.same(root_u, root_v)) {\n                        bottleneck = e.w_val;\n                        break;\n                    }\n                }\n            }\n            \n            // Penalty if not connected (should not happen if bridge check passed and K is large enough)\n            if (bottleneck == -1) bottleneck = 5000;\n            sum_bottleneck += bottleneck;\n            sims++;\n\n            // Budget check (every 64 iterations to minimize overhead)\n            if ((sims & 63) == 0) {\n                auto curr = chrono::high_resolution_clock::now();\n                if ((curr - step_start).count() > budget) break;\n            }\n        }\n\n        // 6. Make Decision\n        double threshold = (sims > 0) ? (double)sum_bottleneck / sims : 1e9;\n\n        if (l_i < threshold) {\n            cout << 1 << endl;\n            main_dsu.unite(u, v);\n            current_components--;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"/**\n * AtCoder Heuristic Contest 008\n * Solution: Robust Honeycomb Trap with Strict Conflict Resolution\n * \n * Strategy:\n * 1. Layout: We overlay a skeleton of \"rooms\" (approx 5x5 size) on the 30x30 grid.\n *    - Walls are planned at specific rows/cols.\n *    - Gates are planned at the centers of these wall segments.\n * 2. Dynamic Logic:\n *    - We detect \"Dirty\" components (containing pets) and \"Clean\" components.\n *    - We assign priorities: \n *      a. ESCAPE: Humans in dirty rooms must leave.\n *      b. TRAP: Close gates connecting dirty rooms to clean rooms.\n *      c. BUILD: Construct the skeleton.\n * 3. Safety & Conflict Resolution:\n *    - Strict checks to ensure no two humans move to the same square.\n *    - Strict checks to ensure no human moves into a wall being built in the same turn.\n *    - A conservative reservation system ensures that high-priority movers do not displace \n *      low-priority waiters (preventing the \"moving to occupied square\" error).\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cmath>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --- Constants & Utils ---\nconst int N_ROWS = 30;\nconst int N_COLS = 30;\nconst int MAX_TURNS = 300;\n\nconst int DR[] = {-1, 1, 0, 0};\nconst int DC[] = {0, 0, -1, 1};\nconst char MOVE_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char BLOCK_CHARS[] = {'u', 'd', 'l', 'r'}; \n\nstruct Pet {\n    int id;\n    int r, c; \n    int type;\n};\n\nstruct Human {\n    int id;\n    int r, c;\n};\n\nstruct State {\n    vector<Pet> pets;\n    vector<Human> humans;\n    bool walls[N_ROWS][N_COLS];\n};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N_ROWS && c >= 0 && c < N_COLS;\n}\n\n// --- Strategic Plan ---\nbool plan_skeleton[N_ROWS][N_COLS];\nbool plan_gate[N_ROWS][N_COLS]; // True if this wall part is a gate (initially open)\n\nvoid init_plan() {\n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c) {\n            plan_skeleton[r][c] = false;\n            plan_gate[r][c] = false;\n        }\n\n    // Create a grid of walls. \n    // Lines at indices: 5, 11, 17, 23. \n    // This creates 5x5 and 4x5 sized regions.\n    vector<int> lines = {5, 11, 17, 23};\n    \n    for (int r : lines) {\n        for (int c = 0; c < N_COLS; ++c) plan_skeleton[r][c] = true;\n    }\n    for (int c : lines) {\n        for (int r = 0; r < N_ROWS; ++r) plan_skeleton[r][c] = true;\n    }\n    \n    // Define Gates at midpoints of wall segments\n    // Segments: 0-4, 6-10, 12-16, 18-22, 24-29\n    // Mids: 2, 8, 14, 20, 27\n    vector<int> mids = {2, 8, 14, 20, 27};\n    \n    for(int r : lines) {\n        for(int m : mids) plan_gate[r][m] = true;\n    }\n    for(int c : lines) {\n        for(int m : mids) plan_gate[m][c] = true;\n    }\n    \n    // Intersections are always solid walls\n    for(int r : lines) {\n        for(int c : lines) plan_gate[r][c] = false;\n    }\n}\n\n// --- Analysis Helpers ---\n\nstruct Component {\n    int id;\n    bool has_pet = false;\n    vector<pair<int,int>> cells;\n};\n\nvoid get_components(const State& st, vector<vector<int>>& id_map, vector<Component>& comps) {\n    id_map.assign(N_ROWS, vector<int>(N_COLS, -1));\n    comps.clear();\n    \n    for(int r=0; r<N_ROWS; ++r){\n        for(int c=0; c<N_COLS; ++c){\n            if(!st.walls[r][c] && id_map[r][c] == -1){\n                int cid = comps.size();\n                Component comp;\n                comp.id = cid;\n                \n                queue<pair<int,int>> q;\n                q.push({r,c});\n                id_map[r][c] = cid;\n                \n                while(!q.empty()){\n                    auto [cr, cc] = q.front();\n                    q.pop();\n                    comp.cells.push_back({cr, cc});\n                    \n                    for(int i=0; i<4; ++i){\n                        int nr = cr + DR[i];\n                        int nc = cc + DC[i];\n                        if(is_valid(nr, nc) && !st.walls[nr][nc] && id_map[nr][nc] == -1){\n                            id_map[nr][nc] = cid;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n                comps.push_back(comp);\n            }\n        }\n    }\n    \n    for(const auto& p : st.pets) {\n        if(id_map[p.r][p.c] != -1) comps[id_map[p.r][p.c]].has_pet = true;\n    }\n}\n\n// BFS pathfinding with strict reservation checks\n// Returns direction index (0-3) or -1\nint bfs_move(int sr, int sc, const vector<pair<int,int>>& targets, \n             const State& st, \n             const vector<vector<bool>>& reserved_next_pos, \n             const vector<vector<bool>>& reserved_new_wall,\n             const vector<bool>& processed_agents) {\n    \n    if(targets.empty()) return -1;\n\n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    \n    vector<vector<int>> dist(N_ROWS, vector<int>(N_COLS, 1e9));\n    vector<vector<pair<int,int>>> parent(N_ROWS, vector<pair<int,int>>(N_COLS, {-1,-1}));\n    \n    dist[sr][sc] = 0;\n    bool found = false;\n    int er = -1, ec = -1;\n    \n    // Optimization: Check targets quickly\n    static int target_mark[N_ROWS][N_COLS];\n    static int mark_counter = 0;\n    mark_counter++;\n    for(auto& t : targets) target_mark[t.first][t.second] = mark_counter;\n    \n    while(!q.empty()){\n        auto [cr, cc] = q.front();\n        q.pop();\n        \n        if(target_mark[cr][cc] == mark_counter){\n            found = true;\n            er = cr; ec = cc;\n            break;\n        }\n        \n        for(int i=0; i<4; ++i){\n            int nr = cr + DR[i];\n            int nc = cc + DC[i];\n            \n            if(!is_valid(nr, nc)) continue;\n            if(st.walls[nr][nc]) continue;\n            \n            // Check dynamic obstacles only for the immediate next step (t+1)\n            if(dist[cr][cc] == 0) {\n                // Cannot move into a new wall\n                if(reserved_new_wall[nr][nc]) continue;\n                // Cannot move into a spot reserved by a processed agent\n                if(reserved_next_pos[nr][nc]) continue;\n                \n                // Conservative Check: Cannot move into a spot occupied by an unprocessed agent\n                // (Because that agent might stay)\n                bool collision = false;\n                for(const auto& h : st.humans){\n                    if(!processed_agents[h.id] && h.r == nr && h.c == nc) collision = true;\n                }\n                if(collision) continue;\n            }\n            \n            if(dist[nr][nc] > dist[cr][cc] + 1){\n                dist[nr][nc] = dist[cr][cc] + 1;\n                parent[nr][nc] = {cr, cc};\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if(!found) return -1;\n    if(er == sr && ec == sc) return -1;\n    \n    // Backtrack\n    int cur_r = er, cur_c = ec;\n    while(parent[cur_r][cur_c].first != sr || parent[cur_r][cur_c].second != sc){\n        auto p = parent[cur_r][cur_c];\n        cur_r = p.first;\n        cur_c = p.second;\n    }\n    \n    for(int i=0; i<4; ++i){\n        if(sr + DR[i] == cur_r && sc + DC[i] == cur_c) return i;\n    }\n    return -1;\n}\n\n// --- Main Logic ---\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_plan();\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    \n    State state;\n    state.pets.resize(N);\n    for(int i=0; i<N; ++i){\n        state.pets[i].id = i;\n        cin >> state.pets[i].r >> state.pets[i].c >> state.pets[i].type;\n        state.pets[i].r--; state.pets[i].c--; \n    }\n    \n    int M;\n    cin >> M;\n    state.humans.resize(M);\n    for(int i=0; i<M; ++i){\n        state.humans[i].id = i;\n        cin >> state.humans[i].r >> state.humans[i].c;\n        state.humans[i].r--; state.humans[i].c--;\n    }\n    \n    for(int r=0; r<N_ROWS; ++r)\n        for(int c=0; c<N_COLS; ++c)\n            state.walls[r][c] = false;\n            \n    for(int turn=0; turn<MAX_TURNS; ++turn){\n        // 1. Component Analysis\n        vector<vector<int>> comp_map;\n        vector<Component> comps;\n        get_components(state, comp_map, comps);\n        \n        // Identify humans in danger\n        vector<bool> in_danger(M, false);\n        for(int i=0; i<M; ++i){\n            int cid = comp_map[state.humans[i].r][state.humans[i].c];\n            if(cid != -1 && comps[cid].has_pet) in_danger[i] = true;\n        }\n        \n        // 2. Generate Build Tasks\n        struct Task {\n            int r, c; // Wall location\n            int priority;\n        };\n        vector<Task> tasks;\n        \n        for(int r=0; r<N_ROWS; ++r){\n            for(int c=0; c<N_COLS; ++c){\n                if(state.walls[r][c]) continue;\n                if(!plan_skeleton[r][c]) continue;\n                \n                int prio = 0;\n                bool is_gate = plan_gate[r][c];\n                \n                // Check connectivity of this potential wall\n                set<int> adj_comps;\n                for(int k=0; k<4; ++k){\n                    int nr = r + DR[k];\n                    int nc = c + DC[k];\n                    if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                        if(comp_map[nr][nc] != -1) adj_comps.insert(comp_map[nr][nc]);\n                    }\n                }\n                \n                bool connects_dirty = false;\n                bool connects_clean = false;\n                for(int cid : adj_comps){\n                    if(comps[cid].has_pet) connects_dirty = true;\n                    else connects_clean = true;\n                }\n                \n                if(!is_gate) {\n                    prio = 50; \n                    if(connects_dirty) prio += 200; \n                } else {\n                    // Gate logic\n                    if(connects_dirty && connects_clean) prio = 1000; // MUST CLOSE\n                    else if(connects_dirty) prio = 500; // Contain dirty\n                    else prio = 10; // Clean area, keep low priority\n                }\n                \n                if(prio > 0) tasks.push_back({r, c, prio});\n            }\n        }\n        \n        // 3. Assign Agents to Plans\n        struct AgentPlan {\n            int h_idx;\n            int type; // 0: Wait, 1: Build, 2: Escape/Move\n            int target_r, target_c; \n            double score;\n        };\n        vector<AgentPlan> agents;\n        \n        auto get_dist = [&](int r1, int c1, int r2, int c2) {\n            return abs(r1 - r2) + abs(c1 - c2);\n        };\n        \n        for(int i=0; i<M; ++i){\n            AgentPlan p;\n            p.h_idx = i;\n            p.type = 0; \n            p.score = -1e9;\n            \n            if(in_danger[i]){\n                p.type = 2; \n                p.score = 100000; \n                p.target_r = -1; // Generic \"Safe Place\"\n            } else {\n                // Find best build task\n                for(const auto& t : tasks){\n                    // Verify safety (adjacent to pet rule)\n                    bool pet_adj = false;\n                    for(const auto& pt : state.pets) if(get_dist(t.r, t.c, pt.r, pt.c) <= 1) pet_adj = true;\n                    if(pet_adj) continue;\n                    \n                    // Verify no human stands on the wall site (current pos)\n                    bool human_on_site = false;\n                    for(const auto& h : state.humans) if(h.r == t.r && h.c == t.c) human_on_site = true;\n                    if(human_on_site) continue;\n                    \n                    int d = 1e9;\n                    for(int k=0; k<4; ++k){\n                        int nr = t.r + DR[k];\n                        int nc = t.c + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc]){\n                            d = min(d, get_dist(state.humans[i].r, state.humans[i].c, nr, nc));\n                        }\n                    }\n                    \n                    if(d < 1e9){\n                        double s = t.priority * 100.0 - d;\n                        if(s > p.score){\n                            p.score = s;\n                            p.target_r = t.r;\n                            p.target_c = t.c;\n                            p.type = 1; // Build\n                        }\n                    }\n                }\n            }\n            agents.push_back(p);\n        }\n        \n        // Sort by score descending\n        sort(agents.begin(), agents.end(), [](const AgentPlan& a, const AgentPlan& b){\n            return a.score > b.score;\n        });\n        \n        // 4. Execute Plans with strict conflict checks\n        vector<string> res_actions(M, \".\");\n        vector<vector<bool>> reserved_next(N_ROWS, vector<bool>(N_COLS, false));\n        vector<vector<bool>> reserved_wall(N_ROWS, vector<bool>(N_COLS, false));\n        vector<bool> processed(M, false);\n        \n        // Note: reserved_next tracks FINALIZED positions.\n        // processed[id] tracks if human `id` has moved.\n        // Unprocessed humans are treated as obstacles at their current pos.\n        \n        for(const auto& ag : agents){\n            int i = ag.h_idx;\n            processed[i] = true; // Mark as processed\n            \n            int r = state.humans[i].r;\n            int c = state.humans[i].c;\n            bool done = false;\n            \n            // -- Type 2: Escape --\n            if(ag.type == 2){\n                vector<pair<int,int>> clean_targets;\n                for(const auto& comp : comps){\n                    if(!comp.has_pet) {\n                        for(auto cell : comp.cells) clean_targets.push_back(cell);\n                    }\n                }\n                \n                int dir = bfs_move(r, c, clean_targets, state, reserved_next, reserved_wall, processed);\n                if(dir != -1){\n                    int nr = r + DR[dir];\n                    int nc = c + DC[dir];\n                    res_actions[i] = string(1, MOVE_CHARS[dir]);\n                    reserved_next[nr][nc] = true;\n                    done = true;\n                }\n            }\n            // -- Type 1: Build --\n            else if(ag.type == 1){\n                int tr = ag.target_r;\n                int tc = ag.target_c;\n                \n                // Can build?\n                if(get_dist(r, c, tr, tc) == 1){\n                    bool ok = true;\n                    if(state.walls[tr][tc] || reserved_wall[tr][tc]) ok = false;\n                    // Pet adjacency check\n                    for(const auto& pt : state.pets) if(get_dist(tr, tc, pt.r, pt.c) <= 1) ok = false;\n                    // Human occupancy (processed)\n                    if(reserved_next[tr][tc]) ok = false;\n                    // Human occupancy (unprocessed)\n                    for(const auto& h : state.humans) if(!processed[h.id] && h.r == tr && h.c == tc) ok = false;\n                    \n                    if(ok){\n                        int b_dir = -1;\n                        for(int k=0; k<4; ++k) if(r+DR[k]==tr && c+DC[k]==tc) b_dir = k;\n                        \n                        res_actions[i] = string(1, BLOCK_CHARS[b_dir]);\n                        reserved_wall[tr][tc] = true;\n                        reserved_next[r][c] = true; // Stay\n                        done = true;\n                    }\n                }\n                \n                // Move to build spot\n                if(!done){\n                    vector<pair<int,int>> spots;\n                    for(int k=0; k<4; ++k){\n                        int nr = tr + DR[k];\n                        int nc = tc + DC[k];\n                        if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc]){\n                            spots.push_back({nr, nc});\n                        }\n                    }\n                    int dir = bfs_move(r, c, spots, state, reserved_next, reserved_wall, processed);\n                    if(dir != -1){\n                        int nr = r + DR[dir];\n                        int nc = c + DC[dir];\n                        res_actions[i] = string(1, MOVE_CHARS[dir]);\n                        reserved_next[nr][nc] = true;\n                        done = true;\n                    }\n                }\n            }\n            \n            // -- Default: Stay --\n            if(!done){\n                // Try to stay\n                if(!reserved_next[r][c]){\n                    // Double check nobody claimed it (should be covered by reserved_next)\n                    // Check new wall\n                    if(!reserved_wall[r][c]) {\n                        res_actions[i] = \".\";\n                        reserved_next[r][c] = true;\n                    } else {\n                        // Emergency: Someone built a wall on us (should be prevented by build checks, but just in case)\n                        // Try to move any adjacent free\n                        for(int k=0; k<4; ++k){\n                            int nr = r+DR[k];\n                            int nc = c+DC[k];\n                            if(is_valid(nr, nc) && !state.walls[nr][nc] && !reserved_wall[nr][nc] && !reserved_next[nr][nc]){\n                                // And check unprocessed\n                                bool coll = false;\n                                for(const auto& h : state.humans) if(!processed[h.id] && h.r==nr && h.c==nc) coll = true;\n                                if(!coll){\n                                    res_actions[i] = string(1, MOVE_CHARS[k]);\n                                    reserved_next[nr][nc] = true;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output\n        string out_s = \"\";\n        for(const auto& s : res_actions) out_s += s;\n        cout << out_s << endl;\n        \n        // Update State\n        for(int i=0; i<M; ++i){\n            char c = res_actions[i][0];\n            if(c >= 'A' && c <= 'Z'){ \n                for(int k=0; k<4; ++k){\n                    if(MOVE_CHARS[k] == c){\n                        state.humans[i].r += DR[k];\n                        state.humans[i].c += DC[k];\n                    }\n                }\n            } else if(c >= 'a' && c <= 'z'){\n                 for(int k=0; k<4; ++k){\n                    if(BLOCK_CHARS[k] == c){\n                        state.walls[state.humans[i].r + DR[k]][state.humans[i].c + DC[k]] = true;\n                    }\n                }\n            }\n        }\n        \n        if(turn < MAX_TURNS){\n            string p_s;\n            for(int i=0; i<N; ++i){\n                cin >> p_s;\n                for(char c : p_s){\n                     for(int k=0; k<4; ++k){\n                        if(MOVE_CHARS[k] == c){\n                            state.pets[i].r += DR[k];\n                            state.pets[i].c += DC[k];\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <iomanip>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_STEPS = 200;\nconst double EPS = 1e-5; \nconst double TIME_LIMIT = 1.96; \n\n// Globals\nint Si, Sj, Ti, Tj;\ndouble P;\nint H[N][N-1]; \nint V[N-1][N]; \ndouble flat_dist[N*N]; \ndouble move_dist_cache[N*N][4]; \nint next_pos_cache[N*N][4]; \n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dchar[4] = {'U', 'D', 'L', 'R'};\n\n// State with Structure of Arrays (SoA) for better cache locality\nstruct State {\n    vector<int> us;\n    vector<double> ps;\n    double score; \n    double mass; \n    double heuristic; \n    string path;\n    double weighted_dist_sum; \n};\n\nstruct Candidate {\n    double heuristic;\n    int parent_idx;\n    int move_k;\n};\n\n// Memory Pool to minimize allocation overhead\nvector<vector<int>> int_vec_pool;\nvector<vector<double>> double_vec_pool;\n\nvoid acquire_vecs(vector<int>& iv, vector<double>& dv) {\n    if (!int_vec_pool.empty()) {\n        iv = std::move(int_vec_pool.back());\n        int_vec_pool.pop_back();\n        dv = std::move(double_vec_pool.back());\n        double_vec_pool.pop_back();\n    }\n}\n\nvoid release_vecs(vector<int>& iv, vector<double>& dv) {\n    iv.clear();\n    dv.clear();\n    int_vec_pool.push_back(std::move(iv));\n    double_vec_pool.push_back(std::move(dv));\n}\n\n// Timing\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_elapsed() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Non-linear wall penalty to strongly discourage dead ends/traps\ndouble get_wall_penalty(int r, int c) {\n    int w = 0;\n    if(r == 0 || V[r-1][c] == 1) w++;\n    if(r == N-1 || V[r][c] == 1) w++;\n    if(c == 0 || H[r][c-1] == 1) w++;\n    if(c == N-1 || H[r][c] == 1) w++;\n    \n    if (w == 0) return 0.0;\n    if (w == 1) return 0.02; // Single wall (room edge) - low penalty\n    if (w == 2) return 0.06; // Corridor/Corner - moderate penalty\n    if (w == 3) return 0.20; // Dead end - high penalty\n    return 1.0; // Trapped (4 walls)\n}\n\n// Dijkstra to compute weighted distances\nvoid compute_distances() {\n    for(int i=0; i<N*N; ++i) flat_dist[i] = 1e18;\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n    \n    int target = Ti*N + Tj;\n    flat_dist[target] = 0;\n    pq.push({0, target});\n    \n    while(!pq.empty()){\n        auto [d, u] = pq.top();\n        pq.pop();\n        \n        if(d > flat_dist[u]) continue;\n        \n        int r = u / N;\n        int c = u % N;\n        \n        auto try_push = [&](int nr, int nc) {\n            int v = nr*N + nc;\n            double weight = 1.0 + get_wall_penalty(nr, nc);\n            if (flat_dist[v] > d + weight) {\n                flat_dist[v] = d + weight;\n                pq.push({flat_dist[v], v});\n            }\n        };\n\n        if (r > 0 && V[r-1][c] == 0) try_push(r-1, c);\n        if (r < N-1 && V[r][c] == 0) try_push(r+1, c);\n        if (c > 0 && H[r][c-1] == 0) try_push(r, c-1);\n        if (c < N-1 && H[r][c] == 0) try_push(r, c+1);\n    }\n}\n\nvoid precompute_moves() {\n    for(int r=0; r<N; ++r){\n        for(int c=0; c<N; ++c){\n            int u = r*N + c;\n            for(int k=0; k<4; ++k){\n                bool blocked = false;\n                if(k == 0){ if(r == 0 || V[r-1][c] == 1) blocked = true; }\n                else if(k == 1){ if(r == N-1 || V[r][c] == 1) blocked = true; }\n                else if(k == 2){ if(c == 0 || H[r][c-1] == 1) blocked = true; }\n                else if(k == 3){ if(c == N-1 || H[r][c] == 1) blocked = true; }\n                \n                if(blocked) next_pos_cache[u][k] = u;\n                else next_pos_cache[u][k] = (r + dr[k])*N + (c + dc[k]);\n                \n                move_dist_cache[u][k] = flat_dist[next_pos_cache[u][k]];\n            }\n        }\n    }\n}\n\ndouble temp_probs[N*N];\nint touched_list[N*N]; \nint touched_cnt = 0;\n\nint main(){\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = chrono::high_resolution_clock::now();\n\n    if (!(cin >> Si >> Sj >> Ti >> Tj >> P)) return 0;\n\n    for(int i=0; i<N; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N-1; ++j) H[i][j] = s[j] - '0';\n    }\n    for(int i=0; i<N-1; ++i){\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) V[i][j] = s[j] - '0';\n    }\n    \n    compute_distances();\n    precompute_moves();\n    \n    fill(temp_probs, temp_probs + N*N, 0.0);\n    int_vec_pool.reserve(60000);\n    double_vec_pool.reserve(60000);\n\n    double inv_prob_move = 1.0 / (1.0 - P);\n    int target_u = Ti*N + Tj;\n\n    State initial;\n    initial.path = \"\";\n    initial.score = 0.0;\n    initial.us.push_back(Si*N + Sj);\n    initial.ps.push_back(1.0);\n    initial.mass = 1.0;\n    initial.weighted_dist_sum = flat_dist[Si*N + Sj];\n    initial.heuristic = 401.0 - (initial.weighted_dist_sum * inv_prob_move);\n    \n    if(Si == Ti && Sj == Tj) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    int current_beam_width = 3000; \n    vector<State> beam;\n    beam.reserve(60000);\n    beam.push_back(std::move(initial));\n    \n    vector<Candidate> candidates;\n    candidates.reserve(250000);\n\n    double stay_factor = P;\n    double move_factor = 1.0 - P;\n\n    for(int t=0; t<MAX_STEPS; ++t){\n        auto step_start = chrono::high_resolution_clock::now();\n\n        candidates.clear();\n        double time_term = 401.0 - (t + 1);\n        \n        // Step 1: Fast Heuristic Evaluation\n        for(int i=0; i < (int)beam.size(); ++i){\n            const auto& st = beam[i];\n            \n            if(st.us.empty()) {\n                candidates.push_back({st.score, i, -1});\n                continue;\n            }\n\n            double base_val = st.score + st.mass * time_term;\n            double stay_cost_term = stay_factor * st.weighted_dist_sum;\n            double common_part = base_val - stay_cost_term * inv_prob_move;\n\n            const int* u_ptr = st.us.data();\n            const double* p_ptr = st.ps.data();\n            int count = st.us.size();\n\n            for(int k=0; k<4; ++k){\n                double move_cost_sum = 0.0;\n                for(int j=0; j<count; ++j){\n                    move_cost_sum += p_ptr[j] * move_dist_cache[u_ptr[j]][k];\n                }\n                move_cost_sum *= move_factor;\n                \n                double h = common_part - move_cost_sum * inv_prob_move;\n                candidates.push_back({h, i, k});\n            }\n        }\n\n        // Step 2: Selection\n        int K = min((int)candidates.size(), current_beam_width);\n        if((int)candidates.size() > K){\n            nth_element(candidates.begin(), candidates.begin() + K, candidates.end(),\n                [](const Candidate& a, const Candidate& b){\n                    return a.heuristic > b.heuristic;\n                });\n        }\n        \n        // Step 3: State Construction\n        vector<State> next_beam;\n        next_beam.reserve(K);\n        \n        for(int k=0; k<K; ++k){\n            const auto& cand = candidates[k];\n            const auto& parent = beam[cand.parent_idx];\n            \n            if(cand.move_k == -1){\n                State nst;\n                nst.score = parent.score;\n                nst.mass = 0;\n                nst.heuristic = parent.heuristic;\n                nst.path = parent.path;\n                next_beam.push_back(std::move(nst));\n                continue;\n            }\n            \n            State nst;\n            nst.heuristic = cand.heuristic;\n            nst.path = parent.path + dchar[cand.move_k];\n            nst.score = parent.score;\n            \n            touched_cnt = 0;\n            int p_count = parent.us.size();\n            const int* pu_ptr = parent.us.data();\n            const double* pp_ptr = parent.ps.data();\n\n            for(int j=0; j<p_count; ++j){\n                int u = pu_ptr[j];\n                double val = pp_ptr[j];\n                \n                // Stay\n                if(temp_probs[u] == 0.0) touched_list[touched_cnt++] = u;\n                temp_probs[u] += val * stay_factor;\n                \n                // Move\n                int v = next_pos_cache[u][cand.move_k];\n                if(temp_probs[v] == 0.0) touched_list[touched_cnt++] = v;\n                temp_probs[v] += val * move_factor;\n            }\n            \n            nst.mass = 0.0;\n            nst.weighted_dist_sum = 0.0;\n            \n            acquire_vecs(nst.us, nst.ps);\n            nst.us.reserve(touched_cnt);\n            nst.ps.reserve(touched_cnt);\n            \n            for(int j=0; j<touched_cnt; ++j){\n                int idx = touched_list[j];\n                double prob = temp_probs[idx];\n                temp_probs[idx] = 0.0; \n                \n                if(prob < EPS) continue;\n                \n                if(idx == target_u){\n                    nst.score += prob * time_term;\n                } else {\n                    nst.us.push_back(idx);\n                    nst.ps.push_back(prob);\n                    nst.mass += prob;\n                    nst.weighted_dist_sum += prob * flat_dist[idx];\n                }\n            }\n            \n            next_beam.push_back(std::move(nst));\n        }\n        \n        for(auto& st : beam){\n            release_vecs(st.us, st.ps);\n        }\n        beam = std::move(next_beam);\n        \n        bool active = false;\n        for(const auto& s : beam) if(!s.us.empty()) { active = true; break; }\n        if(!active) break;\n\n        // Dynamic Beam Width Adjustment\n        auto step_end = chrono::high_resolution_clock::now();\n        double step_duration = chrono::duration<double>(step_end - step_start).count();\n        double total_elapsed = get_elapsed();\n        \n        if(total_elapsed > TIME_LIMIT) break;\n\n        double remaining_time = TIME_LIMIT - total_elapsed;\n        int remaining_steps = MAX_STEPS - (t + 1);\n        if(remaining_steps > 0){\n            double target_duration = remaining_time / remaining_steps;\n            double ratio = target_duration / (step_duration + 1e-9);\n            ratio = max(0.5, min(2.0, ratio)); \n            \n            current_beam_width = (int)(current_beam_width * ratio);\n            current_beam_width = max(100, min(50000, current_beam_width));\n        }\n    }\n    \n    double best_score = -1.0;\n    string best_s = \"\";\n    for(const auto& st : beam){\n        if(st.score > best_score){\n            best_score = st.score;\n            best_s = st.path;\n        }\n    }\n    \n    cout << best_s << endl;\n    \n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconst int N = 30;\nconst int N2 = N * N;\n\n// Global lookup tables\nint to_tbl[8][4];\nint rotated_type_tbl[8][4];\nint adj[N2][4]; // [cell_idx][dir] -> neighbor_idx (-1 if none)\n\n// Precompute connectivity and adjacency\nvoid init_tables() {\n    // Connectivity\n    memset(to_tbl, -1, sizeof(to_tbl));\n    to_tbl[0][0] = 1; to_tbl[0][1] = 0;\n    to_tbl[1][0] = 3; to_tbl[1][3] = 0;\n    to_tbl[2][2] = 3; to_tbl[2][3] = 2;\n    to_tbl[3][2] = 1; to_tbl[3][1] = 2;\n    to_tbl[4][0] = 1; to_tbl[4][1] = 0; to_tbl[4][2] = 3; to_tbl[4][3] = 2;\n    to_tbl[5][0] = 3; to_tbl[5][3] = 0; to_tbl[5][2] = 1; to_tbl[5][1] = 2;\n    to_tbl[6][1] = 3; to_tbl[6][3] = 1;\n    to_tbl[7][0] = 2; to_tbl[7][2] = 0;\n\n    // Rotations\n    for(int t=0; t<8; ++t) {\n        for(int r=0; r<4; ++r) {\n            int curr = t;\n            for(int k=0; k<r; ++k) {\n                if (curr >= 0 && curr <= 3) curr = (curr + 1) % 4;\n                else if (curr == 4) curr = 5;\n                else if (curr == 5) curr = 4;\n                else if (curr == 6) curr = 7;\n                else if (curr == 7) curr = 6;\n            }\n            rotated_type_tbl[t][r] = curr;\n        }\n    }\n\n    // Adjacency\n    // Directions: 0: Left, 1: Up, 2: Right, 3: Down\n    const int di[] = {0, -1, 0, 1};\n    const int dj[] = {-1, 0, 1, 0};\n    \n    memset(adj, -1, sizeof(adj));\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int idx = r * N + c;\n            for(int d=0; d<4; ++d) {\n                int nr = r + di[d];\n                int nc = c + dj[d];\n                if(nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    adj[idx][d] = nr * N + nc;\n                }\n            }\n        }\n    }\n}\n\nstruct State {\n    int8_t rots[N2];\n    int8_t types[N2];\n};\n\nint initial_types[N2];\nint visited[3600]; // 900 * 4\nint gen = 0;\n\nmt19937 rng(12345);\n\nlong long evaluate(const State& st, long long& out_real_score) {\n    gen++;\n    if (gen <= 0) {\n        memset(visited, 0, sizeof(visited));\n        gen = 1;\n    }\n\n    int max_loop1 = 0;\n    int max_loop2 = 0;\n    long long sum_sq_loops = 0;\n    long long sum_sq_paths = 0;\n    int loop_count = 0;\n\n    // Iterate linearly\n    for(int idx = 0; idx < N2; ++idx) {\n        int t = st.types[idx];\n        \n        for(int d = 0; d < 4; ++d) {\n            int v_idx = (idx << 2) + d; // idx * 4 + d\n            \n            if(visited[v_idx] == gen) continue;\n            if(to_tbl[t][d] == -1) continue;\n\n            int curr_idx = idx;\n            int curr_d = d;\n            int start_idx = idx;\n            int start_d = d;\n            \n            int len = 0;\n            bool is_loop = false;\n\n            while(true) {\n                // Mark Entry\n                visited[(curr_idx << 2) + curr_d] = gen;\n                \n                int curr_t = st.types[curr_idx];\n                int out_d = to_tbl[curr_t][curr_d];\n                \n                // Mark Exit\n                visited[(curr_idx << 2) + out_d] = gen;\n                \n                len++;\n                \n                // Move using precomputed adjacency\n                int next_idx = adj[curr_idx][out_d];\n                if(next_idx == -1) {\n                    is_loop = false;\n                    break;\n                }\n                \n                // Next entry direction is opposite of out_d: (out_d + 2) % 4\n                // 0<->2, 1<->3. XOR with 2 does this.\n                int next_d = (out_d ^ 2); \n                \n                // Check connection compatibility\n                if(to_tbl[st.types[next_idx]][next_d] == -1) {\n                    is_loop = false;\n                    break;\n                }\n                \n                // Check visited\n                if(visited[(next_idx << 2) + next_d] == gen) {\n                    if(next_idx == start_idx && next_d == start_d) {\n                        is_loop = true;\n                    } else {\n                        is_loop = false;\n                    }\n                    break;\n                }\n                \n                curr_idx = next_idx;\n                curr_d = next_d;\n            }\n\n            if(is_loop) {\n                loop_count++;\n                long long l2 = (long long)len * len;\n                sum_sq_loops += l2;\n                if(len > max_loop1) {\n                    max_loop2 = max_loop1;\n                    max_loop1 = len;\n                } else if(len > max_loop2) {\n                    max_loop2 = len;\n                }\n            } else {\n                sum_sq_paths += (long long)len * len;\n            }\n        }\n    }\n\n    out_real_score = 0;\n    if(loop_count >= 2) {\n        out_real_score = (long long)max_loop1 * max_loop2;\n    }\n\n    // Scoring\n    long long score = 0;\n    if (out_real_score > 0) {\n        score += out_real_score * 1000000LL;\n    }\n    // Weight for loops restored to 50 to heavily favor loop formation\n    score += sum_sq_loops * 50; \n    score += sum_sq_paths;\n\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    init_tables();\n\n    for(int i=0; i<N2; ++i) {\n        char c; cin >> c;\n        initial_types[i] = c - '0';\n    }\n\n    State best_global_state;\n    memset(best_global_state.rots, 0, sizeof(best_global_state.rots));\n    \n    long long best_global_score_real = -1;\n    long long best_global_raw_score = -1;\n\n    auto start_time = chrono::steady_clock::now();\n    double total_time_limit = 1.98;\n\n    int num_runs = 2;\n    \n    for(int run=0; run < num_runs; ++run) {\n        State current_state;\n        // Random Init\n        for(int i=0; i<N2; ++i) {\n            current_state.rots[i] = rng() % 4;\n            current_state.types[i] = rotated_type_tbl[initial_types[i]][current_state.rots[i]];\n        }\n\n        long long current_real_score = 0;\n        long long current_score = evaluate(current_state, current_real_score);\n\n        State best_local_state = current_state;\n        long long best_local_score_real = current_real_score;\n        long long best_local_raw_score = current_score;\n\n        double t0 = 10000.0;\n        double t1 = 0.1;\n        double temp = t0;\n\n        double run_end_time = (run + 1) * (total_time_limit / num_runs);\n        auto run_start_t = chrono::steady_clock::now();\n        int iter = 0;\n\n        while(true) {\n            iter++;\n            // Batch time check every 2048 iterations for low overhead\n            if((iter & 2047) == 0) {\n                auto now = chrono::steady_clock::now();\n                double total_elapsed = chrono::duration<double>(now - start_time).count();\n                if(total_elapsed > run_end_time) break;\n\n                double run_elapsed = chrono::duration<double>(now - run_start_t).count();\n                double expected_duration = total_time_limit / num_runs; \n                double progress = run_elapsed / expected_duration;\n                if(progress > 1.0) progress = 1.0;\n                temp = t0 * pow(t1/t0, progress);\n            }\n\n            // Mutation\n            int idx1 = rng() % N2;\n            int old_rot1 = current_state.rots[idx1];\n            int old_type1 = current_state.types[idx1];\n\n            int new_rot1 = (old_rot1 + 1 + (rng() % 3)) % 4;\n            current_state.rots[idx1] = new_rot1;\n            current_state.types[idx1] = rotated_type_tbl[initial_types[idx1]][new_rot1];\n            \n            int idx2 = -1, old_rot2, old_type2;\n            \n            // Pair mutation with ~6.25% probability (1/16)\n            // Using bitwise check for speed\n            if((rng() & 15) == 0) { \n                 int d = rng() % 4;\n                 int neighbor = adj[idx1][d];\n                 if(neighbor != -1) {\n                     idx2 = neighbor;\n                     old_rot2 = current_state.rots[idx2];\n                     old_type2 = current_state.types[idx2];\n                     \n                     int new_rot2 = (old_rot2 + 1 + (rng() % 3)) % 4;\n                     current_state.rots[idx2] = new_rot2;\n                     current_state.types[idx2] = rotated_type_tbl[initial_types[idx2]][new_rot2];\n                 }\n            }\n\n            long long new_real_score = 0;\n            long long new_score = evaluate(current_state, new_real_score);\n\n            double delta = new_score - current_score;\n\n            bool accept = false;\n            if(delta >= 0) {\n                accept = true;\n            } else if (temp > 1e-5) {\n                if(bernoulli_distribution(exp(delta/temp))(rng)) {\n                    accept = true;\n                }\n            }\n\n            if(accept) {\n                current_score = new_score;\n                current_real_score = new_real_score;\n\n                if(current_real_score > best_local_score_real) {\n                    best_local_score_real = current_real_score;\n                    best_local_raw_score = current_score;\n                    best_local_state = current_state;\n                } else if(current_real_score == best_local_score_real && current_score > best_local_raw_score) {\n                    best_local_raw_score = current_score;\n                    best_local_state = current_state;\n                }\n            } else {\n                // Revert\n                current_state.rots[idx1] = old_rot1;\n                current_state.types[idx1] = old_type1;\n                if(idx2 != -1) {\n                    current_state.rots[idx2] = old_rot2;\n                    current_state.types[idx2] = old_type2;\n                }\n            }\n        }\n\n        // Update global\n        bool update = false;\n        if(best_local_score_real > best_global_score_real) update = true;\n        else if(best_local_score_real == best_global_score_real && best_local_raw_score > best_global_raw_score) update = true;\n\n        if(update) {\n            best_global_score_real = best_local_score_real;\n            best_global_raw_score = best_local_raw_score;\n            best_global_state = best_local_state;\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cout << (int)best_global_state.rots[i*N+j];\n        }\n    }\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <map>\n#include <iomanip>\n#include <cstring>\n#include <tuple>\n#include <numeric>\n#include <set>\n\nusing namespace std;\n\n// --- Constants ---\nconst int UP = 2;\nconst int DOWN = 8;\nconst int LEFT = 1;\nconst int RIGHT = 4;\nconst int DIR[4] = {UP, DOWN, LEFT, RIGHT};\nconst int DR[4] = {-1, 1, 0, 0};\nconst int DC[4] = {0, 0, -1, 1};\nconst char DIR_CHAR[4] = {'U', 'D', 'L', 'R'};\n\n// --- Globals ---\nint N, T;\nvector<vector<int>> initial_board;\nvector<vector<int>> target_board;\nvector<vector<int>> tile_ids; \npair<int, int> empty_pos;\nstring moves_str = \"\";\n\n// --- Timing ---\nauto start_time = chrono::high_resolution_clock::now();\ndouble get_time() {\n    return chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n}\n\n// --- Utils ---\ninline bool has_dir(int tile, int dir) { return (tile & dir) != 0; }\ninline int reverse_dir(int dir) {\n    if (dir == UP) return DOWN;\n    if (dir == DOWN) return UP;\n    if (dir == LEFT) return RIGHT;\n    if (dir == RIGHT) return LEFT;\n    return 0;\n}\n\nmt19937 rng(5489);\n\n// --- DSU ---\nstruct DSU {\n    int parent[100];\n    int sz[100];\n    int edges[100];\n    void init(int n) {\n        for(int i=0; i<n; ++i) { parent[i]=i; sz[i]=1; edges[i]=0; }\n    }\n    int find(int x) {\n        int root = x;\n        while(root != parent[root]) root = parent[root];\n        while(x != root) { int nxt = parent[x]; parent[x] = root; x = nxt; }\n        return root;\n    }\n    void unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x != y) {\n            if (sz[x] < sz[y]) swap(x, y);\n            parent[y] = x;\n            sz[x] += sz[y];\n            edges[x] += edges[y] + 1;\n        } else {\n            edges[x]++;\n        }\n    }\n} dsu;\n\n// --- Evaluation ---\nstruct BoardScore {\n    int max_tree_size; \n    long long total_score;\n    vector<pair<int,int>> defects;\n};\n\nBoardScore evaluate(const vector<vector<int>>& board) {\n    int n2 = N*N;\n    dsu.init(n2);\n    int mismatches = 0;\n    int boundary_penalty = 0;\n    vector<pair<int,int>> defects;\n    defects.reserve(n2);\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int tile = board[r][c];\n            if (tile == 0) continue;\n            \n            int u = r*N + c;\n            bool bad = false;\n\n            if (has_dir(tile, UP)) {\n                if (r == 0) { boundary_penalty++; bad=true; }\n                else {\n                    int n = board[r-1][c];\n                    if (n == 0) { boundary_penalty++; bad=true; }\n                    else if (!has_dir(n, DOWN)) { mismatches++; bad=true; }\n                }\n            }\n            if (has_dir(tile, DOWN)) {\n                if (r == N-1) { boundary_penalty++; bad=true; }\n                else {\n                    int n = board[r+1][c];\n                    if (n == 0) { boundary_penalty++; bad=true; }\n                    else if (has_dir(n, UP)) dsu.unite(u, (r+1)*N + c);\n                    else { mismatches++; bad=true; }\n                }\n            }\n            if (has_dir(tile, LEFT)) {\n                if (c == 0) { boundary_penalty++; bad=true; }\n                else {\n                    int n = board[r][c-1];\n                    if (n == 0) { boundary_penalty++; bad=true; }\n                    else if (!has_dir(n, RIGHT)) { mismatches++; bad=true; }\n                }\n            }\n            if (has_dir(tile, RIGHT)) {\n                if (c == N-1) { boundary_penalty++; bad=true; }\n                else {\n                    int n = board[r][c+1];\n                    if (n == 0) { boundary_penalty++; bad=true; }\n                    else if (has_dir(n, LEFT)) dsu.unite(u, r*N + c + 1);\n                    else { mismatches++; bad=true; }\n                }\n            }\n            if (bad) defects.push_back({r,c});\n        }\n    }\n    \n    int max_tree = 0;\n    int total_cycles = 0;\n    \n    for(int i=0; i<n2; ++i) {\n        if (dsu.parent[i] == i) {\n            if (board[i/N][i%N] == 0 && dsu.sz[i] == 1) continue;\n            int v = dsu.sz[i];\n            int e = dsu.edges[i];\n            if (e == v - 1) {\n                if (v > max_tree) max_tree = v;\n            } else if (e >= v) {\n                total_cycles += (e - v + 1);\n                int reduced = max(1, v - (e - v + 1) * 3); \n                if (reduced > max_tree) max_tree = reduced;\n            }\n        }\n    }\n    \n    long long score = (long long)max_tree * 100000 \n                    - (long long)(mismatches + boundary_penalty) * 5000\n                    - (long long)total_cycles * 25000;\n                    \n    return {max_tree, score, defects};\n}\n\nvoid find_target_configuration() {\n    vector<int> tiles;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tiles.push_back(initial_board[r][c]);\n    auto it = find(tiles.begin(), tiles.end(), 0);\n    if(it != tiles.end()) iter_swap(it, tiles.end() - 1);\n\n    target_board.assign(N, vector<int>(N));\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) target_board[r][c] = tiles[r*N + c];\n    \n    BoardScore current_eval = evaluate(target_board);\n    vector<vector<int>> best_board = target_board;\n    long long best_score = current_eval.total_score;\n    \n    double time_limit = 2.5; \n    double start_temp = 8000.0;\n    double end_temp = 0.5;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 127) == 0) if (get_time() > time_limit) break;\n        \n        double temp = start_temp * pow(end_temp / start_temp, get_time() / time_limit);\n        \n        int r1, c1, r2, c2;\n        if (!current_eval.defects.empty() && (rng() % 100 < 60)) {\n            int idx = rng() % current_eval.defects.size();\n            r1 = current_eval.defects[idx].first; c1 = current_eval.defects[idx].second;\n        } else {\n            r1 = rng() % N; c1 = rng() % N;\n        }\n        \n        if (r1 == N-1 && c1 == N-1) { do { r1 = rng() % N; c1 = rng() % N; } while(r1 == N-1 && c1 == N-1); }\n        do { r2 = rng() % N; c2 = rng() % N; } while(r2 == N-1 && c2 == N-1);\n        \n        if (r1 == r2 && c1 == c2) continue;\n        if (target_board[r1][c1] == target_board[r2][c2]) continue;\n        \n        swap(target_board[r1][c1], target_board[r2][c2]);\n        BoardScore next_eval = evaluate(target_board);\n        \n        if (next_eval.total_score >= current_eval.total_score) {\n            current_eval = next_eval;\n            if (current_eval.total_score > best_score) { best_score = current_eval.total_score; best_board = target_board; }\n        } else {\n            if (uniform_real_distribution<>(0,1)(rng) < exp((next_eval.total_score - current_eval.total_score) / temp)) {\n                current_eval = next_eval;\n            } else {\n                swap(target_board[r1][c1], target_board[r2][c2]);\n            }\n        }\n    }\n    target_board = best_board;\n}\n\nvoid apply_move(char c) {\n    int dr = 0, dc = 0;\n    if (c == 'U') dr = -1; else if (c == 'D') dr = 1; else if (c == 'L') dc = -1; else if (c == 'R') dc = 1;\n    int nr = empty_pos.first + dr;\n    int nc = empty_pos.second + dc;\n    if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n        swap(initial_board[empty_pos.first][empty_pos.second], initial_board[nr][nc]);\n        swap(tile_ids[empty_pos.first][empty_pos.second], tile_ids[nr][nc]);\n        empty_pos = {nr, nc};\n        moves_str += c;\n    }\n}\n\nvoid execute_moves(const string& moves) {\n    for (char c : moves) apply_move(c);\n}\n\nstatic int dist_bfs[10][10][10][10];\nstatic char move_bfs[10][10][10][10];\n\nstring get_path_for_tile(int tr, int tc, int dest_r, int dest_c, const vector<vector<bool>>& loc) {\n    if (tr == dest_r && tc == dest_c) return \"\";\n    memset(dist_bfs, -1, sizeof(dist_bfs));\n    static tuple<int,int,int,int> q[10005];\n    int head = 0, tail = 0;\n    dist_bfs[tr][tc][empty_pos.first][empty_pos.second] = 0;\n    q[tail++] = {tr, tc, empty_pos.first, empty_pos.second};\n    \n    int final_er = -1, final_ec = -1;\n    bool found = false;\n    while(head < tail) {\n        auto [ctr, ctc, cer, cec] = q[head++];\n        if (ctr == dest_r && ctc == dest_c) { final_er = cer; final_ec = cec; found = true; break; }\n        int d = dist_bfs[ctr][ctc][cer][cec];\n        for (int i=0; i<4; ++i) {\n            int ner = cer + DR[i], nec = cec + DC[i];\n            if (ner >= 0 && ner < N && nec >= 0 && nec < N && !loc[ner][nec]) {\n                if (ner == ctr && nec == ctc) {\n                    int ntr = cer, ntc = cec;\n                    if (dist_bfs[ntr][ntc][ner][nec] == -1) {\n                        dist_bfs[ntr][ntc][ner][nec] = d + 1;\n                        move_bfs[ntr][ntc][ner][nec] = 'S'; \n                        q[tail++] = {ntr, ntc, ner, nec};\n                    }\n                } else {\n                    if (dist_bfs[ctr][ctc][ner][nec] == -1) {\n                        dist_bfs[ctr][ctc][ner][nec] = d + 1;\n                        move_bfs[ctr][ctc][ner][nec] = DIR_CHAR[i];\n                        q[tail++] = {ctr, ctc, ner, nec};\n                    }\n                }\n            }\n        }\n    }\n    if (!found) return \"\";\n    string path = \"\";\n    int ctr = dest_r, ctc = dest_c, cer = final_er, cec = final_ec;\n    int start_er = empty_pos.first, start_ec = empty_pos.second;\n    while (ctr != tr || ctc != tc || cer != start_er || cec != start_ec) {\n        char m = move_bfs[ctr][ctc][cer][cec];\n        if (m == 'S') {\n            int prev_er = ctr, prev_ec = ctc;\n            int dr = cer - prev_er, dc = cec - prev_ec;\n            char c = (dr == -1) ? 'U' : (dr == 1) ? 'D' : (dc == -1) ? 'L' : 'R';\n            path += c;\n            ctr = cer; ctc = cec; cer = prev_er; cec = prev_ec;\n        } else {\n            path += m;\n            int dr=0, dc=0;\n            if(m=='U') dr=-1; else if(m=='D') dr=1; else if(m=='L') dc=-1; else if(m=='R') dc=1;\n            cer -= dr; cec -= dc;\n        }\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstring safe_bfs_empty(int tr, int tc, const vector<vector<bool>>& loc) {\n    if (empty_pos.first == tr && empty_pos.second == tc) return \"\";\n    static int d[10][10]; static char m[10][10];\n    memset(d, -1, sizeof(d));\n    static pair<int,int> q[105];\n    int head = 0, tail = 0;\n    q[tail++] = empty_pos; d[empty_pos.first][empty_pos.second] = 0;\n    bool found = false;\n    while(head < tail) {\n        auto [r, c] = q[head++];\n        if (r == tr && c == tc) { found = true; break; }\n        for (int i=0; i<4; ++i) {\n            int nr=r+DR[i], nc=c+DC[i];\n            if(nr>=0 && nr<N && nc>=0 && nc<N && !loc[nr][nc] && d[nr][nc]==-1) {\n                d[nr][nc] = d[r][c]+1; m[nr][nc] = DIR_CHAR[i]; q[tail++] = {nr, nc};\n            }\n        }\n    }\n    if(!found) return \"\";\n    string p=\"\"; int r=tr, c=tc;\n    while(r!=empty_pos.first || c!=empty_pos.second) {\n        char c_move = m[r][c]; p+=c_move;\n        int dr=0, dc=0;\n        if(c_move=='U') dr=-1; else if(c_move=='D') dr=1; else if(c_move=='L') dc=-1; else if(c_move=='R') dc=1;\n        r-=dr; c-=dc;\n    }\n    reverse(p.begin(), p.end());\n    return p;\n}\n\nvoid solve_puzzle() {\n    tile_ids.assign(N, vector<int>(N));\n    int id_counter = 0;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) tile_ids[r][c] = id_counter++;\n    for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c] == 0) empty_pos = {r,c};\n\n    vector<int> target_assignment(N*N, -1);\n    vector<bool> id_used(N*N, false);\n\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int type = target_board[r][c];\n            int best_id = -1; int min_dist = 10000;\n            for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n                int id = tile_ids[i][j];\n                if (!id_used[id] && initial_board[i][j] == type) {\n                    int dist = abs(r - i) + abs(c - j);\n                    if (dist < min_dist) { min_dist = dist; best_id = id; }\n                }\n            }\n            target_assignment[r*N + c] = best_id;\n            id_used[best_id] = true;\n        }\n    }\n\n    vector<int> pos_map(N*N);\n    for(int i=0; i<N*N; ++i) pos_map[target_assignment[i]] = i;\n    int swaps = 0;\n    vector<bool> visited(N*N, false);\n    for(int i=0; i<N*N; ++i) {\n        if (!visited[i]) {\n            int curr = i;\n            while (!visited[curr]) { visited[curr] = true; curr = pos_map[tile_ids[curr/N][curr%N]]; }\n            swaps++;\n        }\n    }\n    int total_swaps = N*N - swaps;\n    int empty_id = -1; for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) if(initial_board[r][c]==0) empty_id = tile_ids[r][c];\n    int t_empty = pos_map[empty_id];\n    int dist = abs(empty_pos.first - t_empty/N) + abs(empty_pos.second - t_empty%N);\n    \n    if ((total_swaps + dist) % 2 != 0) {\n        bool swapped = false;\n        for(int i=0; i<N*N && !swapped; ++i) for(int j=i+1; j<N*N && !swapped; ++j) {\n            int id1 = target_assignment[i], id2 = target_assignment[j];\n            if (id1==empty_id || id2==empty_id) continue;\n            int t1=-1, t2=-2;\n            for(int r=0;r<N;++r)for(int c=0;c<N;++c) if(tile_ids[r][c]==id1) t1=initial_board[r][c];\n            for(int r=0;r<N;++r)for(int c=0;c<N;++c) if(tile_ids[r][c]==id2) t2=initial_board[r][c];\n            if(t1 == t2) { swap(target_assignment[i], target_assignment[j]); swapped=true; }\n        }\n        if(!swapped) {\n             for(int i=0; i<N*N && !swapped; ++i) for(int j=i+1; j<N*N && !swapped; ++j) {\n                if (target_assignment[i] != empty_id && target_assignment[j] != empty_id) {\n                    swap(target_assignment[i], target_assignment[j]); swapped=true;\n                }\n             }\n        }\n    }\n\n    vector<vector<int>> target_ids_map(N, vector<int>(N));\n    for(int i=0; i<N*N; ++i) target_ids_map[i/N][i%N] = target_assignment[i];\n    vector<vector<bool>> locked(N, vector<bool>(N, false));\n\n    auto get_pos = [&](int id) {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) if(tile_ids[i][j] == id) return make_pair(i,j);\n        return make_pair(-1,-1);\n    };\n    auto run_moves = [&](const string& p) { execute_moves(p); };\n\n    for (int r = 0; r <= N - 3; ++r) {\n        for (int c = 0; c < N; ++c) {\n            if (c < N - 2) {\n                int id = target_ids_map[r][c];\n                pair<int,int> curr = get_pos(id);\n                run_moves(get_path_for_tile(curr.first, curr.second, r, c, locked));\n                locked[r][c] = true;\n            } else {\n                int t1 = target_ids_map[r][N-2], t2 = target_ids_map[r][N-1];\n                pair<int,int> curr = get_pos(t2);\n                run_moves(get_path_for_tile(curr.first, curr.second, r+1, N-1, locked));\n                pair<int,int> p2 = get_pos(t2); locked[p2.first][p2.second] = true;\n                curr = get_pos(t1);\n                run_moves(get_path_for_tile(curr.first, curr.second, r, N-1, locked));\n                locked[p2.first][p2.second] = false;\n                pair<int,int> p1 = get_pos(t1); locked[p1.first][p1.second] = true;\n                p2 = get_pos(t2); locked[p2.first][p2.second] = true;\n                run_moves(safe_bfs_empty(r, N-2, locked));\n                run_moves(\"RD\");\n                locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n                locked[r][N-2] = true; locked[r][N-1] = true;\n                break;\n            }\n        }\n    }\n    for(int c=0; c <= N-3; ++c) {\n        int t1 = target_ids_map[N-2][c], t2 = target_ids_map[N-1][c];\n        pair<int,int> curr = get_pos(t2);\n        run_moves(get_path_for_tile(curr.first, curr.second, N-1, c+1, locked));\n        pair<int,int> p2 = get_pos(t2); locked[p2.first][p2.second] = true;\n        curr = get_pos(t1);\n        run_moves(get_path_for_tile(curr.first, curr.second, N-1, c, locked));\n        locked[p2.first][p2.second] = false;\n        pair<int,int> p1 = get_pos(t1); locked[p1.first][p1.second] = true;\n        p2 = get_pos(t2); locked[p2.first][p2.second] = true;\n        run_moves(safe_bfs_empty(N-2, c, locked));\n        run_moves(\"DR\");\n        locked[p1.first][p1.second] = false; locked[p2.first][p2.second] = false;\n        locked[N-2][c] = true; locked[N-1][c] = true;\n    }\n\n    locked[N-2][N-3] = false; locked[N-1][N-3] = false; \n    vector<pair<int,int>> pm = {{N-2, N-3}, {N-2, N-2}, {N-2, N-1}, {N-1, N-3}, {N-1, N-2}, {N-1, N-1}};\n    map<int,int> lmap;\n    for(int i=0; i<6; ++i) lmap[target_ids_map[pm[i].first][pm[i].second]] = i;\n    \n    int tgt_enc = 0; for(int i=0; i<6; ++i) tgt_enc = (tgt_enc << 3) | i;\n    int start_enc = 0; for(int i=0; i<6; ++i) start_enc = (start_enc << 3) | lmap[tile_ids[pm[i].first][pm[i].second]];\n    \n    if (start_enc != tgt_enc) {\n        static int parent[300000]; static char move_c[300000]; static bool vis[300000];\n        memset(vis, 0, sizeof(vis));\n        queue<int> q; q.push(start_enc); vis[start_enc] = true;\n        bool solved = false; int steps = 0;\n        while(!q.empty()) {\n            int curr = q.front(); q.pop();\n            if (curr == tgt_enc) { solved = true; break; }\n            if (++steps > 280000) break;\n            int s[6]; int tmp = curr; int z = -1;\n            for(int i=5; i>=0; --i) { s[i] = tmp & 7; if(s[i] == lmap[empty_id]) z = i; tmp >>= 3; }\n            int r = pm[z].first, c = pm[z].second;\n            for(int d=0; d<4; ++d) {\n                int nr = r + DR[d], nc = c + DC[d];\n                int nz = -1; for(int k=0; k<6; ++k) if(pm[k].first == nr && pm[k].second == nc) nz = k;\n                if (nz != -1) {\n                    swap(s[z], s[nz]); int nxt = 0; for(int i=0; i<6; ++i) nxt = (nxt << 3) | s[i];\n                    if (!vis[nxt]) { vis[nxt] = true; parent[nxt] = curr; move_c[nxt] = DIR_CHAR[d]; q.push(nxt); }\n                }\n            }\n        }\n        if (solved) {\n            string path = \"\"; int curr = tgt_enc;\n            while (curr != start_enc) { path += move_c[curr]; curr = parent[curr]; }\n            reverse(path.begin(), path.end()); run_moves(path);\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    if(!(cin >> N >> T)) return 0;\n    initial_board.resize(N, vector<int>(N));\n    for(int i=0; i<N; ++i) {\n        string s; cin >> s;\n        for(int j=0; j<N; ++j) initial_board[i][j] = (s[j]>='0' && s[j]<='9') ? (s[j]-'0') : (s[j]-'a'+10);\n    }\n    find_target_configuration();\n    solve_puzzle();\n    cout << moves_str << endl;\n    return 0;\n}","ahc012":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n#include <numeric>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst double PI = std::acos(-1.0);\nconst int MAX_K = 105;\nconst int MAX_N = 6000;\n\nstruct Point {\n    int id;\n    long long x, y;\n};\n\n// Global inputs\nint N;\nint K_limit;\nint A[11];\nvector<Point> points;\n\n// Random engine\nmt19937 rng(42);\n\n// Buffers for fast evaluation\n// Using flattened grid for potentially slightly faster access\nunsigned short counts_grid_flat[MAX_K * MAX_K];\n\n// Timer\nclass Timer {\n    chrono::high_resolution_clock::time_point start;\npublic:\n    Timer() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::duration<double>>(now - start).count();\n    }\n};\n\n// Helper: Unique coordinates with tolerance\nvector<double> get_unique_coords(const vector<double>& coords) {\n    if (coords.empty()) return {};\n    vector<double> sorted = coords;\n    sort(sorted.begin(), sorted.end());\n    vector<double> uniq;\n    uniq.push_back(sorted[0]);\n    for (size_t i = 1; i < sorted.size(); ++i) {\n        if (sorted[i] - uniq.back() > 1e-3) {\n            uniq.push_back(sorted[i]);\n        }\n    }\n    return uniq;\n}\n\n// Data structures for a specific angle pair configuration\nstruct AngleConfig {\n    double theta1, theta2; // degrees\n    vector<double> uniq_1, uniq_2;\n    vector<unsigned short> rank_1, rank_2; \n    \n    // Best solution found for this config\n    vector<int> best_c1, best_c2;\n    long long best_score = -1;\n};\n\n// Solver class\nclass Solver {\n    // Internal state for incremental updates\n    vector<unsigned short> current_Lx;\n    vector<unsigned short> current_Ly;\n    vector<int> current_c1;\n    vector<int> current_c2;\n    long long current_score;\n    \npublic:\n    Solver() {\n        current_Lx.resize(MAX_N);\n        current_Ly.resize(MAX_N);\n    }\n\n    // Build lookup table for a given set of cuts\n    // rank_to_bin maps: unique_coord_rank -> bin_index\n    // out_L maps: point_index -> bin_index\n    void build_lookup(const vector<int>& cuts, int num_uniq, const vector<unsigned short>& ranks, vector<unsigned short>& out_L) {\n        static unsigned short rank_to_bin[MAX_N]; // static to reuse memory\n        \n        int current_bin = 0;\n        int cut_idx = 0;\n        int num_cuts = cuts.size();\n        \n        for(int r=0; r<num_uniq; ++r) {\n            if(cut_idx < num_cuts && r == cuts[cut_idx]) {\n                current_bin++;\n                cut_idx++;\n            }\n            rank_to_bin[r] = (unsigned short)current_bin;\n        }\n        \n        for(int i=0; i<N; ++i) {\n            out_L[i] = rank_to_bin[ranks[i]];\n        }\n    }\n\n    // Fast eval using provided L tables\n    long long eval_core(int n1, int n2, const vector<unsigned short>& L1, const vector<unsigned short>& L2) {\n        // Clear grid (only used rows)\n        // We use MAX_K stride to avoid re-calculating offsets too much\n        for(int i=0; i<n1; ++i) {\n             memset(counts_grid_flat + i * MAX_K, 0, n2 * sizeof(unsigned short));\n        }\n\n        // Fill grid\n        for(int i=0; i<N; ++i) {\n            counts_grid_flat[L1[i] * MAX_K + L2[i]]++;\n        }\n\n        // Score\n        int piece_b[11] = {0};\n        for(int i=0; i<n1; ++i) {\n            unsigned short* row = counts_grid_flat + i * MAX_K;\n            for(int j=0; j<n2; ++j) {\n                int c = row[j];\n                if(c <= 10 && c >= 1) piece_b[c]++;\n            }\n        }\n\n        long long num = 0;\n        for(int d=1; d<=10; ++d) {\n            num += min(A[d], piece_b[d]);\n        }\n        return num;\n    }\n    \n    // Initial full evaluation\n    long long eval_init(const AngleConfig& config, const vector<int>& c1, const vector<int>& c2) {\n        build_lookup(c1, config.uniq_1.size(), config.rank_1, current_Lx);\n        build_lookup(c2, config.uniq_2.size(), config.rank_2, current_Ly);\n        current_c1 = c1;\n        current_c2 = c2;\n        return eval_core(c1.size()+1, c2.size()+1, current_Lx, current_Ly);\n    }\n\n    void run_sa(AngleConfig& config, double max_duration, int max_iters, bool warm_start) {\n        Timer t;\n        \n        auto gen_quantile_cuts = [&](int n, int max_v) {\n             vector<int> res;\n             if (max_v <= 1) return res;\n             if (n > max_v - 1) n = max_v - 1;\n             for (int i = 1; i <= n; ++i) {\n                 int idx = (int)(1.0 * i * max_v / (n + 1));\n                 if (idx < 1) idx = 1;\n                 if (idx >= max_v) idx = max_v - 1;\n                 res.push_back(idx);\n             }\n             sort(res.begin(), res.end());\n             res.erase(unique(res.begin(), res.end()), res.end());\n             return res;\n        };\n\n        vector<int> init_c1, init_c2;\n        if (warm_start && config.best_score != -1) {\n            init_c1 = config.best_c1;\n            init_c2 = config.best_c2;\n        } else {\n            int k1 = K_limit / 2;\n            int k2 = K_limit - k1;\n            init_c1 = gen_quantile_cuts(k1, config.uniq_1.size());\n            init_c2 = gen_quantile_cuts(k2, config.uniq_2.size());\n        }\n        \n        current_score = eval_init(config, init_c1, init_c2);\n        \n        if (current_score > config.best_score) {\n            config.best_score = current_score;\n            config.best_c1 = current_c1;\n            config.best_c2 = current_c2;\n        }\n\n        double start_temp = 2.5; \n        if (warm_start) start_temp = 0.5;\n        \n        // Temp buffers\n        vector<unsigned short> temp_L(MAX_N);\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if (max_iters > 0) {\n                if (iter >= max_iters) break;\n            } else {\n                if ((iter & 127) == 0) {\n                    if (t.elapsed() > max_duration) break;\n                }\n            }\n\n            double progress = 0;\n            if (max_iters > 0) progress = (double)iter / max_iters;\n            else progress = t.elapsed() / max_duration;\n            if (progress > 1.0) progress = 1.0;\n\n            double temp = start_temp * (1.0 - progress);\n            if(temp < 1e-9) temp = 1e-9;\n\n            int op_dim = rng() % 2; \n            \n            vector<int> next_cuts;\n            const vector<int>& curr_cuts = (op_dim == 0) ? current_c1 : current_c2;\n            int max_val = (op_dim == 0) ? config.uniq_1.size() : config.uniq_2.size();\n            int other_size = (op_dim == 0) ? current_c2.size() : current_c1.size();\n            \n            if (max_val <= 1) continue;\n\n            next_cuts = curr_cuts;\n            int type = rng() % 3; \n\n            bool valid_move = false;\n            \n            if (type == 0 && !next_cuts.empty()) { // Shift\n                int idx = rng() % next_cuts.size();\n                int old_v = next_cuts[idx];\n                int shift = (rng() % 7) - 3; \n                int val = old_v + shift;\n                if (val < 1) val = 1;\n                if (val >= max_val) val = max_val - 1;\n                \n                bool exists = false;\n                for(int v : next_cuts) if(v == val && v != old_v) { exists = true; break; }\n                \n                if(!exists) {\n                    next_cuts[idx] = val;\n                    sort(next_cuts.begin(), next_cuts.end());\n                    valid_move = true;\n                }\n            } else if (type == 1) { // Add\n                if (next_cuts.size() + other_size < K_limit) {\n                    int val = (rng() % (max_val - 1)) + 1;\n                    bool exists = false;\n                    for(int v : next_cuts) if(v == val) { exists = true; break; }\n                    if(!exists) {\n                        next_cuts.push_back(val);\n                        sort(next_cuts.begin(), next_cuts.end());\n                        valid_move = true;\n                    }\n                }\n            } else if (type == 2 && !next_cuts.empty()) { // Delete\n                int idx = rng() % next_cuts.size();\n                next_cuts.erase(next_cuts.begin() + idx);\n                valid_move = true;\n            }\n\n            if (!valid_move) continue;\n\n            // Optimized evaluation: only rebuild L for changed dimension\n            if (op_dim == 0) {\n                build_lookup(next_cuts, config.uniq_1.size(), config.rank_1, temp_L);\n                long long new_score = eval_core(next_cuts.size()+1, current_c2.size()+1, temp_L, current_Ly);\n                \n                long long diff = new_score - current_score;\n                if (diff >= 0 || exp(diff / temp) > (double(rng())/mt19937::max())) {\n                    current_c1 = next_cuts;\n                    current_Lx = temp_L;\n                    current_score = new_score;\n                    if (current_score > config.best_score) {\n                        config.best_score = current_score;\n                        config.best_c1 = current_c1;\n                        config.best_c2 = current_c2;\n                    }\n                }\n            } else {\n                build_lookup(next_cuts, config.uniq_2.size(), config.rank_2, temp_L);\n                long long new_score = eval_core(current_c1.size()+1, next_cuts.size()+1, current_Lx, temp_L);\n                \n                long long diff = new_score - current_score;\n                if (diff >= 0 || exp(diff / temp) > (double(rng())/mt19937::max())) {\n                    current_c2 = next_cuts;\n                    current_Ly = temp_L;\n                    current_score = new_score;\n                    if (current_score > config.best_score) {\n                        config.best_score = current_score;\n                        config.best_c1 = current_c1;\n                        config.best_c2 = current_c2;\n                    }\n                }\n            }\n        }\n    }\n};\n\nAngleConfig make_config(double t1, double t2) {\n    AngleConfig cfg;\n    cfg.theta1 = t1;\n    cfg.theta2 = t2;\n    \n    vector<double> raw_vals(N);\n    \n    double rad1 = t1 * PI / 180.0;\n    double c1 = cos(rad1), s1 = sin(rad1);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c1 + points[j].y * s1;\n    \n    cfg.uniq_1 = get_unique_coords(raw_vals);\n    cfg.rank_1.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_1.begin(), cfg.uniq_1.end(), raw_vals[j] - 1e-4);\n        cfg.rank_1[j] = (unsigned short)distance(cfg.uniq_1.begin(), it);\n    }\n    \n    double rad2 = t2 * PI / 180.0;\n    double c2 = cos(rad2), s2 = sin(rad2);\n    for(int j=0; j<N; ++j) raw_vals[j] = points[j].x * c2 + points[j].y * s2;\n    \n    cfg.uniq_2 = get_unique_coords(raw_vals);\n    cfg.rank_2.resize(N);\n    for(int j=0; j<N; ++j) {\n        auto it = lower_bound(cfg.uniq_2.begin(), cfg.uniq_2.end(), raw_vals[j] - 1e-4);\n        cfg.rank_2[j] = (unsigned short)distance(cfg.uniq_2.begin(), it);\n    }\n    \n    return cfg;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> K_limit)) return 0;\n    for(int i=1; i<=10; ++i) cin >> A[i];\n    points.resize(N);\n    for(int i=0; i<N; ++i) {\n        points[i].id = i;\n        cin >> points[i].x >> points[i].y;\n    }\n\n    Timer total_timer;\n    Solver solver;\n    \n    vector<AngleConfig> configs;\n    configs.reserve(300);\n    \n    // Phase 1: Broad Screening with Optimization\n    // Orthogonal\n    for(int i=0; i<90; i += 2) { \n        configs.push_back(make_config(i, i + 90.0));\n        configs.push_back(make_config(i + 0.5, i + 90.5));\n    }\n    \n    // Random\n    for(int i=0; i<100; ++i) {\n        double t1 = uniform_real_distribution<double>(0, 180)(rng);\n        double t2 = uniform_real_distribution<double>(0, 180)(rng);\n        double diff = abs(t1 - t2);\n        while(diff > 180) diff -= 180;\n        if(abs(diff) < 10 || abs(diff) > 170) continue;\n        configs.push_back(make_config(t1, t2));\n    }\n    \n    // With faster eval, we can screen slightly longer\n    for(auto& cfg : configs) {\n        solver.run_sa(cfg, 0, 200, false); \n    }\n    \n    vector<int> indices(configs.size());\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b){\n        return configs[a].best_score > configs[b].best_score;\n    });\n    \n    // Phase 2: Local Angle Refinement (Pattern Search)\n    int keep_top = 5;\n    vector<AngleConfig> final_candidates;\n    \n    for(int k=0; k<keep_top && k<(int)indices.size(); ++k) {\n        AngleConfig current = configs[indices[k]];\n        \n        // Attempt to improve angles using a deterministic pattern search\n        double delta = 1.0;\n        for(int step=0; step<3; ++step) {\n            bool improved = false;\n            double offsets[4][2] = {{delta, 0}, {-delta, 0}, {0, delta}, {0, -delta}};\n            \n            AngleConfig best_neighbor = current;\n            for(auto& off : offsets) {\n                AngleConfig neighbor = make_config(current.theta1 + off[0], current.theta2 + off[1]);\n                solver.run_sa(neighbor, 0, 300, false);\n                if (neighbor.best_score > best_neighbor.best_score) {\n                    best_neighbor = neighbor;\n                    improved = true;\n                }\n            }\n            if (improved) current = best_neighbor;\n            else delta *= 0.5;\n        }\n        final_candidates.push_back(current);\n    }\n    \n    // Phase 3: Deep Optimization\n    int best_idx = 0;\n    for(size_t i=1; i<final_candidates.size(); ++i) {\n        if(final_candidates[i].best_score > final_candidates[best_idx].best_score) {\n            best_idx = i;\n        }\n    }\n    \n    double remaining = 2.95 - total_timer.elapsed();\n    if (remaining < 0.1) remaining = 0.1;\n    \n    solver.run_sa(final_candidates[best_idx], remaining, -1, true);\n    \n    // Output\n    const auto& S = final_candidates[best_idx];\n    cout << S.best_c1.size() + S.best_c2.size() << endl;\n    \n    auto print_line = [&](double ang, double val) {\n        double rad = ang * PI / 180.0;\n        double A = cos(rad);\n        double B = sin(rad);\n        double C = val;\n        double Mx = C * A;\n        double My = C * B;\n        double Dx = -B;\n        double Dy = A;\n        long long scale = 400000000LL;\n        long long x1 = round(Mx - scale * Dx);\n        long long y1 = round(My - scale * Dy);\n        long long x2 = round(Mx + scale * Dx);\n        long long y2 = round(My + scale * Dy);\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    };\n    \n    for(int idx : S.best_c1) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_1.size())\n            val = (S.uniq_1[idx-1] + S.uniq_1[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_1[0] - 10.0;\n        else val = S.uniq_1.back() + 10.0;\n        print_line(S.theta1, val);\n    }\n    for(int idx : S.best_c2) {\n        double val;\n        if (idx > 0 && idx < (int)S.uniq_2.size())\n            val = (S.uniq_2[idx-1] + S.uniq_2[idx]) / 2.0;\n        else if (idx == 0) val = S.uniq_2[0] - 10.0;\n        else val = S.uniq_2.back() + 10.0;\n        print_line(S.theta2, val);\n    }\n\n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <iomanip>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// Time limit management\nconst double TIME_LIMIT = 4.95; \n\nint N, M;\nint C;\nlong long weights[65][65];\nuint64_t zobrist[65][65];\n\nusing Mask = unsigned long long;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const { return x == other.x && y == other.y; }\n};\n\nstruct Move {\n    Point p1, p2, p3, p4;\n};\n\nstruct State {\n    Mask row_dots[65];\n    Mask col_dots[65];\n    Mask d1_dots[130]; // x + y\n    Mask d2_dots[130]; // x - y + N\n\n    Mask h_edges[65];\n    Mask v_edges[65];\n    Mask d1_edges[130];\n    Mask d2_edges[130];\n\n    long long current_score_w;\n    uint64_t hash;\n    int move_count;\n\n    State() : current_score_w(0), hash(0), move_count(0) {\n        memset(row_dots, 0, sizeof(row_dots));\n        memset(col_dots, 0, sizeof(col_dots));\n        memset(d1_dots, 0, sizeof(d1_dots));\n        memset(d2_dots, 0, sizeof(d2_dots));\n        memset(h_edges, 0, sizeof(h_edges));\n        memset(v_edges, 0, sizeof(v_edges));\n        memset(d1_edges, 0, sizeof(d1_edges));\n        memset(d2_edges, 0, sizeof(d2_edges));\n    }\n\n    bool has_dot(int x, int y) const {\n        return (row_dots[y] >> x) & 1;\n    }\n\n    void add_dot(int x, int y) {\n        row_dots[y] |= (1ULL << x);\n        col_dots[x] |= (1ULL << y);\n        d1_dots[x + y] |= (1ULL << x);\n        d2_dots[x - y + N] |= (1ULL << x);\n        current_score_w += weights[x][y];\n        hash ^= zobrist[x][y];\n    }\n    \n    void add_edge(Point a, Point b) {\n        int l, r;\n        Mask mask;\n        if (a.y == b.y) { \n            if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n            mask = (1ULL << r) - (1ULL << l); \n            h_edges[a.y] |= mask;\n        } else if (a.x == b.x) { \n            if (a.y < b.y) { l = a.y; r = b.y; } else { l = b.y; r = a.y; }\n            mask = (1ULL << r) - (1ULL << l); \n            v_edges[a.x] |= mask;\n        } else if ((a.x + a.y) == (b.x + b.y)) { \n            if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n            mask = (1ULL << r) - (1ULL << l); \n            d1_edges[a.x + a.y] |= mask;\n        } else { \n            if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n            mask = (1ULL << r) - (1ULL << l); \n            d2_edges[a.x - a.y + N] |= mask;\n        }\n    }\n\n    void add_rect(const Move& m) {\n        add_edge(m.p1, m.p2);\n        add_edge(m.p2, m.p3);\n        add_edge(m.p3, m.p4);\n        add_edge(m.p4, m.p1);\n        move_count++;\n    }\n};\n\nstruct Node {\n    int parent_idx; \n    Move move;\n};\n\n// Compile-time neighbor finding optimization\ntemplate <int DIR>\ninline Point find_neighbor_t(const State& s, int x, int y) {\n    Mask m;\n    if constexpr (DIR == 0) { // R\n        m = s.row_dots[y] & (~0ULL << (x + 1)); \n        if (!m) return {-1, -1};\n        return {__builtin_ctzll(m), y};\n    } else if constexpr (DIR == 2) { // L\n        m = s.row_dots[y] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        return {63 - __builtin_clzll(m), y};\n    } else if constexpr (DIR == 1) { // U\n        m = s.col_dots[x] & (~0ULL << (y + 1));\n        if (!m) return {-1, -1};\n        return {x, __builtin_ctzll(m)};\n    } else if constexpr (DIR == 3) { // D\n        m = s.col_dots[x] & ((1ULL << y) - 1);\n        if (!m) return {-1, -1};\n        return {x, 63 - __builtin_clzll(m)};\n    } else if constexpr (DIR == 4) { // NE\n        int k = x - y + N;\n        m = s.d2_dots[k] & (~0ULL << (x + 1));\n        if (!m) return {-1, -1};\n        int nx = __builtin_ctzll(m);\n        return {nx, nx - k + N};\n    } else if constexpr (DIR == 6) { // SW\n        int k = x - y + N;\n        m = s.d2_dots[k] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        int nx = 63 - __builtin_clzll(m);\n        return {nx, nx - k + N};\n    } else if constexpr (DIR == 5) { // NW\n        int k = x + y;\n        m = s.d1_dots[k] & ((1ULL << x) - 1);\n        if (!m) return {-1, -1};\n        int nx = 63 - __builtin_clzll(m);\n        return {nx, k - nx};\n    } else if constexpr (DIR == 7) { // SE\n        int k = x + y;\n        m = s.d1_dots[k] & (~0ULL << (x + 1));\n        if (!m) return {-1, -1};\n        int nx = __builtin_ctzll(m);\n        return {nx, k - nx};\n    }\n    return {-1, -1};\n}\n\ninline bool check_segment_empty_fast(const State& s, Point p1, Point p2) {\n    int l, r;\n    Mask mask;\n    if (p1.y == p2.y) {\n        if (p1.x < p2.x) { l = p1.x + 1; r = p2.x; } else { l = p2.x + 1; r = p1.x; }\n        if (l >= r) return true;\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.row_dots[p1.y] & mask) == 0;\n    } else if (p1.x == p2.x) {\n        if (p1.y < p2.y) { l = p1.y + 1; r = p2.y; } else { l = p2.y + 1; r = p1.y; }\n        if (l >= r) return true;\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.col_dots[p1.x] & mask) == 0;\n    } else if ((p1.x + p1.y) == (p2.x + p2.y)) {\n        if (p1.x < p2.x) { l = p1.x + 1; r = p2.x; } else { l = p2.x + 1; r = p1.x; }\n        if (l >= r) return true;\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.d1_dots[p1.x + p1.y] & mask) == 0;\n    } else {\n        if (p1.x < p2.x) { l = p1.x + 1; r = p2.x; } else { l = p2.x + 1; r = p1.x; }\n        if (l >= r) return true;\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.d2_dots[p1.x - p1.y + N] & mask) == 0;\n    }\n}\n\ninline bool check_edge_overlap(const State& s, Point a, Point b) {\n    int l, r;\n    Mask mask;\n    if (a.y == b.y) {\n        if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.h_edges[a.y] & mask) != 0;\n    } else if (a.x == b.x) {\n        if (a.y < b.y) { l = a.y; r = b.y; } else { l = b.y; r = a.y; }\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.v_edges[a.x] & mask) != 0;\n    } else if ((a.x + a.y) == (b.x + b.y)) {\n        if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.d1_edges[a.x + a.y] & mask) != 0;\n    } else {\n        if (a.x < b.x) { l = a.x; r = b.x; } else { l = b.x; r = a.x; }\n        mask = (1ULL << r) - (1ULL << l);\n        return (s.d2_edges[a.x - a.y + N] & mask) != 0;\n    }\n}\n\ninline bool check_all_edges_free(const State& s, const Move& m) {\n    if (check_edge_overlap(s, m.p1, m.p2)) return false;\n    if (check_edge_overlap(s, m.p2, m.p3)) return false;\n    if (check_edge_overlap(s, m.p3, m.p4)) return false;\n    if (check_edge_overlap(s, m.p4, m.p1)) return false;\n    return true;\n}\n\nstruct Candidate {\n    int parent_local_idx; \n    Move move;\n    uint64_t new_hash;\n    double eval;\n};\n\nuint64_t rng_state = 123456789;\ninline uint64_t my_rand() {\n    rng_state ^= (rng_state << 13);\n    rng_state ^= (rng_state >> 7);\n    rng_state ^= (rng_state << 17);\n    return rng_state;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if (!(cin >> N >> M)) return 0;\n    C = (N - 1) / 2;\n\n    mt19937_64 rng(123);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            weights[x][y] = 1LL * (x - C) * (x - C) + 1LL * (y - C) * (y - C) + 1;\n            zobrist[x][y] = rng();\n        }\n    }\n\n    State s0;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        s0.add_dot(x, y);\n    }\n\n    vector<Node> all_nodes; \n    all_nodes.reserve(1000000); \n    all_nodes.push_back({-1, {}}); \n\n    vector<State> beam_states;\n    beam_states.reserve(3000);\n    beam_states.push_back(s0);\n    \n    vector<int> beam_node_indices;\n    beam_node_indices.reserve(3000);\n    beam_node_indices.push_back(0);\n\n    // Aggressive Beam Widths with Local Filtering optimization\n    int BASE_BEAM_WIDTH = 2600; \n    if (N > 35) BASE_BEAM_WIDTH = 1400;\n    if (N > 45) BASE_BEAM_WIDTH = 800; \n    if (N > 55) BASE_BEAM_WIDTH = 500; \n\n    int DIVERSITY_LIMIT = 6;\n\n    auto start_time = chrono::high_resolution_clock::now();\n    vector<Candidate> candidates;\n    candidates.reserve(200000);\n    \n    // Local buffer to avoid global sorting of massive candidate lists\n    vector<Candidate> local_candidates;\n    local_candidates.reserve(256);\n\n    vector<uint64_t> seen_hashes;\n    seen_hashes.reserve(BASE_BEAM_WIDTH * 4);\n    vector<int> parent_counts;\n    parent_counts.reserve(BASE_BEAM_WIDTH);\n\n    long long max_score = s0.current_score_w;\n    int best_final_node_idx = 0;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        // Dynamic Beam Width\n        int current_beam_width = BASE_BEAM_WIDTH;\n        if (elapsed > 4.2) current_beam_width = min(current_beam_width, 150);\n        else if (elapsed > 3.0) current_beam_width = min(current_beam_width, current_beam_width / 2);\n\n        candidates.clear();\n\n        for (size_t i = 0; i < beam_states.size(); ++i) {\n            const State& s = beam_states[i];\n            local_candidates.clear();\n            \n            for(int y=0; y<N; ++y) {\n                Mask m = s.row_dots[y];\n                while(m) {\n                    int x = __builtin_ctzll(m);\n                    \n                    // Template lambda for processing direction pairs\n                    auto try_rect = [&]<int d2, int d4>() {\n                        Point p2 = find_neighbor_t<d2>(s, x, y);\n                        if (p2.x == -1) return;\n\n                        Point p4 = find_neighbor_t<d4>(s, x, y);\n                        if (p4.x == -1) return;\n\n                        Point p1 = {p2.x + p4.x - x, p2.y + p4.y - y};\n                        \n                        if (p1.x < 0 || p1.x >= N || p1.y < 0 || p1.y >= N) return;\n                        if (s.has_dot(p1.x, p1.y)) return;\n\n                        if (!check_segment_empty_fast(s, p1, p2)) return;\n                        if (!check_segment_empty_fast(s, p1, p4)) return;\n                        \n                        Move move = {p1, p2, {x, y}, p4};\n                        if (!check_all_edges_free(s, move)) return;\n\n                        long long gain = weights[p1.x][p1.y];\n                        int perim = (abs(p1.x - p2.x) + abs(p1.y - p2.y)) + \n                                    (abs(p2.x - x) + abs(p2.y - y)) +\n                                    (abs(x - p4.x) + abs(y - p4.y)) +\n                                    (abs(p4.x - p1.x) + abs(p4.y - p1.y));\n                        \n                        double center_dist = abs((p1.x + x)/2.0 - C) + abs((p1.y + y)/2.0 - C);\n                        \n                        double scale_factor = (double)N / 30.0;\n                        double decay_factor = 1.0 + 20.0 / (s.move_count + 20.0);\n                        double penalty_coeff = (0.2 + 0.6 * max(0.0, 1.0 - center_dist / N)) * scale_factor * decay_factor;\n\n                        uint64_t nhash = s.hash ^ zobrist[p1.x][p1.y];\n                        double h_val = (double)gain - (double)perim * penalty_coeff + ((double)(my_rand() % 1000) / 2000.0);\n                        \n                        local_candidates.push_back({(int)i, move, nhash, h_val});\n                    };\n\n                    try_rect.operator()<0, 1>();\n                    try_rect.operator()<1, 2>();\n                    try_rect.operator()<2, 3>();\n                    try_rect.operator()<3, 0>();\n                    try_rect.operator()<4, 5>();\n                    try_rect.operator()<5, 6>();\n                    try_rect.operator()<6, 7>();\n                    try_rect.operator()<7, 4>();\n\n                    m &= (m - 1);\n                }\n            }\n            \n            // Local filtering: keep only best K from this parent\n            if (local_candidates.size() > DIVERSITY_LIMIT) {\n                std::nth_element(local_candidates.begin(), \n                                 local_candidates.begin() + DIVERSITY_LIMIT, \n                                 local_candidates.end(), \n                                 [](const Candidate& a, const Candidate& b) { return a.eval > b.eval; });\n                local_candidates.resize(DIVERSITY_LIMIT);\n            }\n            candidates.insert(candidates.end(), local_candidates.begin(), local_candidates.end());\n        }\n\n        if (candidates.empty()) break;\n\n        // Global selection\n        if (candidates.size() > current_beam_width * 4) {\n             nth_element(candidates.begin(), candidates.begin() + current_beam_width * 4, candidates.end(),\n                [](const Candidate& a, const Candidate& b) { return a.eval > b.eval; });\n             candidates.resize(current_beam_width * 4);\n        }\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.eval > b.eval;\n        });\n\n        vector<State> next_states;\n        vector<int> next_indices;\n        next_states.reserve(current_beam_width);\n        next_indices.reserve(current_beam_width);\n        seen_hashes.clear();\n        parent_counts.assign(beam_states.size(), 0);\n\n        int accepted = 0;\n        for (const auto& cand : candidates) {\n            if (accepted >= current_beam_width) break;\n            if (parent_counts[cand.parent_local_idx] >= DIVERSITY_LIMIT) continue;\n\n            bool dup = false;\n            for (uint64_t h : seen_hashes) {\n                if (h == cand.new_hash) { dup = true; break; }\n            }\n            if (dup) continue;\n\n            parent_counts[cand.parent_local_idx]++;\n            all_nodes.push_back({beam_node_indices[cand.parent_local_idx], cand.move});\n            int new_node_idx = (int)all_nodes.size() - 1;\n            \n            next_states.emplace_back(beam_states[cand.parent_local_idx]);\n            State& ns = next_states.back();\n            ns.add_dot(cand.move.p1.x, cand.move.p1.y);\n            ns.add_rect(cand.move);\n            \n            if (ns.current_score_w > max_score) {\n                max_score = ns.current_score_w;\n                best_final_node_idx = new_node_idx;\n            }\n\n            next_indices.push_back(new_node_idx);\n            seen_hashes.push_back(cand.new_hash);\n            accepted++;\n        }\n        \n        if (next_states.empty()) break;\n        beam_states = move(next_states);\n        beam_node_indices = move(next_indices);\n    }\n\n    vector<Move> result;\n    int curr = best_final_node_idx;\n    while (curr != 0) {\n        result.push_back(all_nodes[curr].move);\n        curr = all_nodes[curr].parent_idx;\n    }\n    reverse(result.begin(), result.end());\n\n    cout << result.size() << \"\\n\";\n    for (const auto& m : result) {\n        cout << m.p1.x << \" \" << m.p1.y << \" \" \n             << m.p2.x << \" \" << m.p2.y << \" \" \n             << m.p3.x << \" \" << m.p3.y << \" \" \n             << m.p4.x << \" \" << m.p4.y << \"\\n\";\n    }\n\n    return 0;\n}","ahc015":"/**\n * Final Optimized Solution for AtCoder Heuristic Contest (AHC015) - Halloween Candy\n * \n * Improvements:\n * - Reverted to the cleaner, lambda-based simulation loop which achieved the highest score (29.9M).\n * - Maintained the Bitwise Flood Fill (__int128) for fast exact scoring.\n * - Tuned time limit to 1.90s for maximum search depth.\n * - Removed manual loop unrolling which likely caused register spilling and performance degradation.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <array>\n#include <bit>\n\nusing namespace std;\n\n// --- Constants ---\nconstexpr int N = 10;\nconstexpr int MAX_T = 100;\nconstexpr char DIR_CHARS[] = {'F', 'B', 'L', 'R'}; \n\n// LUT Sizes\nconstexpr int LUT_SIZE = 1 << (2 * N); \nconstexpr int MASK_LUT_SIZE = 1 << N; \n\n// --- Global LUTs ---\nstatic uint32_t lut_move_L[LUT_SIZE];\nstatic uint32_t lut_move_R[LUT_SIZE];\nstatic uint16_t lut_row_score[LUT_SIZE]; \nstatic uint8_t lut_empty_cnt[LUT_SIZE];\nstatic uint16_t lut_row_to_mask[LUT_SIZE]; \nstatic int8_t lut_mask_kth_index[MASK_LUT_SIZE][11]; \n\nint flavors[MAX_T];\n\n// --- Fast RNG ---\nstruct XorShift128 {\n    unsigned int x = 123456789, y = 362436069, z = 521288629, w = 88675123;\n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return (uint64_t(next()) * n) >> 32;\n    }\n} rng;\n\n// --- Initialization ---\nvoid init_lut() {\n    for (int i = 0; i < LUT_SIZE; ++i) {\n        int cells[N];\n        int temp = i;\n        int empty = 0;\n        uint16_t mask = 0;\n        for (int k = 0; k < N; ++k) {\n            cells[k] = temp & 3;\n            temp >>= 2;\n            if (cells[k] == 0) { empty++; mask |= (1 << k); }\n        }\n        lut_empty_cnt[i] = empty;\n        lut_row_to_mask[i] = mask;\n        \n        // Move Left\n        int p = 0;\n        int new_cells_L[N] = {0};\n        for (int k = 0; k < N; ++k) if (cells[k] != 0) new_cells_L[p++] = cells[k];\n        uint32_t res_L = 0;\n        for (int k = 0; k < N; ++k) res_L |= (uint32_t(new_cells_L[k]) << (2 * k));\n        lut_move_L[i] = res_L;\n        \n        // Move Right\n        p = N - 1;\n        int new_cells_R[N] = {0};\n        for (int k = N - 1; k >= 0; --k) if (cells[k] != 0) new_cells_R[p--] = cells[k];\n        uint32_t res_R = 0;\n        for (int k = 0; k < N; ++k) res_R |= (uint32_t(new_cells_R[k]) << (2 * k));\n        lut_move_R[i] = res_R;\n        \n        // Score (Sum of squares of runs)\n        int current_run = 0, last_val = -1, score = 0;\n        for (int k = 0; k < N; ++k) {\n            if (cells[k] == 0) {\n                if (current_run > 0) score += current_run * current_run;\n                current_run = 0; last_val = -1;\n            } else {\n                if (cells[k] == last_val) current_run++;\n                else {\n                    if (current_run > 0) score += current_run * current_run;\n                    current_run = 1; last_val = cells[k];\n                }\n            }\n        }\n        if (current_run > 0) score += current_run * current_run;\n        lut_row_score[i] = score;\n    }\n    \n    for (int m = 0; m < MASK_LUT_SIZE; ++m) {\n        int count = 0;\n        for (int k = 0; k < N; ++k) {\n            if ((m >> k) & 1) {\n                count++;\n                lut_mask_kth_index[m][count] = k;\n            }\n        }\n    }\n}\n\n// Masks for bitwise flood fill\nconst unsigned __int128 COL_0_MASK = []{\n    unsigned __int128 m = 0;\n    for(int r=0; r<N; ++r) m |= ((unsigned __int128)1 << (r*10));\n    return m;\n}();\nconst unsigned __int128 COL_9_MASK = []{\n    unsigned __int128 m = 0;\n    for(int r=0; r<N; ++r) m |= ((unsigned __int128)1 << (r*10 + 9));\n    return m;\n}();\n\n// Helper to calculate orthogonal score (transpose + sum scores) from an array of 10 rows/cols\n// marked always_inline to allow compiler to optimize away array overhead\n__attribute__((always_inline)) \ninline int eval_ortho_score(const uint32_t* data) {\n    uint32_t r0=0, r1=0, r2=0, r3=0, r4=0, r5=0, r6=0, r7=0, r8=0, r9=0;\n    // Unrolling this loop helps the compiler schedule instructions better\n    auto ACC = [&](uint32_t v, int s) {\n        r0 |= (v & 3) << s;\n        r1 |= ((v >> 2) & 3) << s;\n        r2 |= ((v >> 4) & 3) << s;\n        r3 |= ((v >> 6) & 3) << s;\n        r4 |= ((v >> 8) & 3) << s;\n        r5 |= ((v >> 10) & 3) << s;\n        r6 |= ((v >> 12) & 3) << s;\n        r7 |= ((v >> 14) & 3) << s;\n        r8 |= ((v >> 16) & 3) << s;\n        r9 |= ((v >> 18) & 3) << s;\n    };\n\n    ACC(data[0], 0); ACC(data[1], 2); ACC(data[2], 4); ACC(data[3], 6); ACC(data[4], 8);\n    ACC(data[5], 10); ACC(data[6], 12); ACC(data[7], 14); ACC(data[8], 16); ACC(data[9], 18);\n\n    return lut_row_score[r0] + lut_row_score[r1] + lut_row_score[r2] + lut_row_score[r3] + \n           lut_row_score[r4] + lut_row_score[r5] + lut_row_score[r6] + lut_row_score[r7] + \n           lut_row_score[r8] + lut_row_score[r9];\n}\n\n// --- State Structure ---\nstruct State {\n    uint32_t rows[N];\n\n    void init() { memset(rows, 0, sizeof(rows)); }\n    \n    inline void place(int r, int c, int f) {\n        rows[r] |= (uint32_t(f) << (2 * c));\n    }\n    \n    inline void transpose(uint32_t* dst) const {\n        uint32_t c0=0, c1=0, c2=0, c3=0, c4=0, c5=0, c6=0, c7=0, c8=0, c9=0;\n        auto ACC = [&](uint32_t v, int s) {\n            c0 |= (v & 3) << s; c1 |= ((v >> 2) & 3) << s; c2 |= ((v >> 4) & 3) << s;\n            c3 |= ((v >> 6) & 3) << s; c4 |= ((v >> 8) & 3) << s; c5 |= ((v >> 10) & 3) << s;\n            c6 |= ((v >> 12) & 3) << s; c7 |= ((v >> 14) & 3) << s; c8 |= ((v >> 16) & 3) << s;\n            c9 |= ((v >> 18) & 3) << s;\n        };\n        ACC(rows[0], 0); ACC(rows[1], 2); ACC(rows[2], 4); ACC(rows[3], 6); ACC(rows[4], 8);\n        ACC(rows[5], 10); ACC(rows[6], 12); ACC(rows[7], 14); ACC(rows[8], 16); ACC(rows[9], 18);\n        \n        dst[0]=c0; dst[1]=c1; dst[2]=c2; dst[3]=c3; dst[4]=c4;\n        dst[5]=c5; dst[6]=c6; dst[7]=c7; dst[8]=c8; dst[9]=c9;\n    }\n    \n    inline void from_cols(const uint32_t* cols) {\n        uint32_t r0=0, r1=0, r2=0, r3=0, r4=0, r5=0, r6=0, r7=0, r8=0, r9=0;\n        auto ACC = [&](uint32_t v, int s) {\n            r0 |= (v & 3) << s; r1 |= ((v >> 2) & 3) << s; r2 |= ((v >> 4) & 3) << s;\n            r3 |= ((v >> 6) & 3) << s; r4 |= ((v >> 8) & 3) << s; r5 |= ((v >> 10) & 3) << s;\n            r6 |= ((v >> 12) & 3) << s; r7 |= ((v >> 14) & 3) << s; r8 |= ((v >> 16) & 3) << s;\n            r9 |= ((v >> 18) & 3) << s;\n        };\n        ACC(cols[0], 0); ACC(cols[1], 2); ACC(cols[2], 4); ACC(cols[3], 6); ACC(cols[4], 8);\n        ACC(cols[5], 10); ACC(cols[6], 12); ACC(cols[7], 14); ACC(cols[8], 16); ACC(cols[9], 18);\n\n        rows[0]=r0; rows[1]=r1; rows[2]=r2; rows[3]=r3; rows[4]=r4;\n        rows[5]=r5; rows[6]=r6; rows[7]=r7; rows[8]=r8; rows[9]=r9;\n    }\n\n    void tilt(int dir) {\n        if (dir == 2) { // Left\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_L[rows[i]];\n        } else if (dir == 3) { // Right\n            for (int i = 0; i < N; ++i) rows[i] = lut_move_R[rows[i]];\n        } else {\n            uint32_t cols[N];\n            transpose(cols);\n            if (dir == 0) { // Fwd/Up\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_L[cols[i]];\n            } else { // Bwd/Down\n                for (int i = 0; i < N; ++i) cols[i] = lut_move_R[cols[i]];\n            }\n            from_cols(cols);\n        }\n    }\n    \n    pair<int,int> get_kth_empty(int k) const {\n        for (int r = 0; r < N; ++r) {\n            int emp = lut_empty_cnt[rows[r]];\n            if (k <= emp) {\n                return {r, lut_mask_kth_index[lut_row_to_mask[rows[r]]][k]};\n            }\n            k -= emp;\n        }\n        return {-1, -1};\n    }\n\n    // Exact Score using Bitwise Flood Fill (__int128)\n    long long eval_full() const {\n        unsigned __int128 flavors_bb[4] = {0}; \n        for(int r=0; r<N; ++r){\n            uint32_t v = rows[r];\n            if (v == 0) continue;\n            for(int c=0; c<N; ++c) {\n                int f = (v >> (2*c)) & 3;\n                if(f) flavors_bb[f] |= ((unsigned __int128)1 << (r*10 + c));\n            }\n        }\n        \n        long long total_sq = 0;\n        for(int f=1; f<=3; ++f) {\n            unsigned __int128 bb = flavors_bb[f];\n            while(bb) {\n                int lsb_idx;\n                unsigned long long lo = (unsigned long long)bb;\n                if (lo) lsb_idx = __builtin_ctzll(lo);\n                else lsb_idx = 64 + __builtin_ctzll((unsigned long long)(bb >> 64));\n                \n                unsigned __int128 new_comp = (unsigned __int128)1 << lsb_idx;\n                \n                while(true) {\n                    unsigned __int128 left = (new_comp & ~COL_0_MASK) >> 1;\n                    unsigned __int128 right = (new_comp & ~COL_9_MASK) << 1;\n                    unsigned __int128 up = new_comp >> 10;\n                    unsigned __int128 down = new_comp << 10;\n                    unsigned __int128 expanded = (new_comp | left | right | up | down) & bb;\n                    if (expanded == new_comp) break;\n                    new_comp = expanded;\n                }\n                \n                int size = std::popcount((unsigned long long)new_comp) + \n                           std::popcount((unsigned long long)(new_comp >> 64));\n                total_sq += (long long)size * size;\n                bb &= ~new_comp;\n            }\n        }\n        return total_sq;\n    }\n};\n\nint main() {\n    auto start_time = chrono::high_resolution_clock::now();\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    init_lut();\n    \n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n    \n    State current_state;\n    current_state.init();\n    \n    const double TIME_LIMIT = 1.90;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        auto [pr, pc] = current_state.get_kth_empty(p);\n        current_state.place(pr, pc, flavors[t]);\n        \n        int best_dir = 0;\n        \n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        \n        if (t == 99 || remaining < 0.015) {\n            long long max_s = -1;\n            for (int d = 0; d < 4; ++d) {\n                State nxt = current_state;\n                nxt.tilt(d);\n                long long s = nxt.eval_full();\n                if (s > max_s) { max_s = s; best_dir = d; }\n            }\n        } else {\n            long long sum_scores[4] = {0};\n            int counts[4] = {0};\n            double budget = remaining / (100 - t);\n            \n            int iter = 0;\n            auto move_start = chrono::high_resolution_clock::now();\n            \n            while (true) {\n                if ((iter & 127) == 0) {\n                    auto curr = chrono::high_resolution_clock::now();\n                    if (chrono::duration<double>(curr - move_start).count() > budget ||\n                        chrono::duration<double>(curr - start_time).count() > TIME_LIMIT) break;\n                }\n                \n                int start_d = iter % 4;\n                iter++;\n                \n                State sim = current_state;\n                sim.tilt(start_d);\n                \n                for (int k = t + 1; k < 100; ++k) {\n                    int empty_cnt = 100 - k;\n                    int rnd = rng.next_int(empty_cnt) + 1;\n                    auto [r, c] = sim.get_kth_empty(rnd);\n                    sim.place(r, c, flavors[k]);\n                    \n                    int best_h = -1;\n                    int cands[4];\n                    int n_cands = 0;\n                    \n                    // --- Vertical Moves Evaluation ---\n                    uint32_t curr_cols[N];\n                    sim.transpose(curr_cols);\n                    \n                    for(int d=0; d<2; ++d) {\n                        const uint32_t* lut = (d==0) ? lut_move_L : lut_move_R;\n                        uint32_t next_cols[N];\n                        int score = 0;\n                        for(int i=0; i<N; ++i) {\n                            next_cols[i] = lut[curr_cols[i]];\n                            score += lut_row_score[next_cols[i]];\n                        }\n                        score += eval_ortho_score(next_cols); // Calculate Row score from Cols\n                        \n                        if(score > best_h) { best_h = score; n_cands = 1; cands[0] = d; }\n                        else if(score == best_h) { cands[n_cands++] = d; }\n                    }\n                    \n                    // --- Horizontal Moves Evaluation ---\n                    for(int d=2; d<4; ++d) {\n                        const uint32_t* lut = (d==2) ? lut_move_L : lut_move_R;\n                        uint32_t next_rows[N];\n                        int score = 0;\n                        for(int i=0; i<N; ++i) {\n                            next_rows[i] = lut[sim.rows[i]];\n                            score += lut_row_score[next_rows[i]];\n                        }\n                        score += eval_ortho_score(next_rows); // Calculate Col score from Rows\n                        \n                        if(score > best_h) { best_h = score; n_cands = 1; cands[0] = d; }\n                        else if(score == best_h) { cands[n_cands++] = d; }\n                    }\n                    \n                    if(n_cands == 1) sim.tilt(cands[0]);\n                    else sim.tilt(cands[rng.next_int(n_cands)]);\n                }\n                \n                sum_scores[start_d] += sim.eval_full();\n                counts[start_d]++;\n            }\n            \n            double best_avg = -1.0;\n            for(int d=0; d<4; ++d) {\n                if(counts[d]) {\n                    double avg = (double)sum_scores[d] / counts[d];\n                    if(avg > best_avg) { best_avg = avg; best_dir = d; }\n                }\n            }\n        }\n        \n        cout << DIR_CHARS[best_dir] << endl;\n        current_state.tilt(best_dir);\n    }\n    \n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nmt19937 rng(12345);\n\n// Helper for random numbers\nint rand_int(int l, int r) {\n    if (l > r) return l;\n    return uniform_int_distribution<int>(l, r)(rng);\n}\n\ndouble rand_double() {\n    return uniform_real_distribution<double>(0.0, 1.0)(rng);\n}\n\n// Type for Sorted Degree Sequence\ntypedef vector<int> SDS;\n\n// Compute Sorted Degree Sequence from adjacency matrix\nSDS get_sds(const vector<string>& adj, int N) {\n    SDS degs(N, 0);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (i != j && adj[i][j] == '1') {\n                degs[i]++;\n            }\n        }\n    }\n    sort(degs.begin(), degs.end());\n    return degs;\n}\n\n// Generate a random graph using Randomized Stochastic Block Model\n// This creates graphs with diverse degree structures\nvector<string> generate_sbm_graph(int N) {\n    // Random number of blocks from 1 to 10\n    int K = rand_int(1, 10);\n    \n    // Random vertex assignment\n    vector<int> assign(N);\n    for(int i=0; i<N; ++i) assign[i] = rand_int(0, K-1);\n    \n    // Random block interaction probabilities\n    // We bias probabilities towards 0 or 1 to create stronger signals\n    vector<vector<double>> probs(K, vector<double>(K));\n    for(int i=0; i<K; ++i) {\n        for(int j=i; j<K; ++j) {\n            double p = rand_double();\n            // Polarize p to increase variance\n            if (rand_double() < 0.6) {\n                p = (p < 0.5) ? 0.05 : 0.95; \n            }\n            probs[i][j] = probs[j][i] = p;\n        }\n    }\n    \n    // Generate adjacency matrix\n    vector<string> adj(N, string(N, '0'));\n    for(int i=0; i<N; ++i) {\n        for(int j=i+1; j<N; ++j) {\n            if (rand_double() < probs[assign[i]][assign[j]]) {\n                adj[i][j] = adj[j][i] = '1';\n            }\n        }\n    }\n    return adj;\n}\n\n// Calculate squared Euclidean distance between two SDS vectors\ndouble calc_sq_dist(const SDS& a, const SDS& b) {\n    double d = 0;\n    for(size_t i=0; i<a.size(); ++i) {\n        double diff = a[i] - b[i];\n        d += diff * diff;\n    }\n    return d;\n}\n\nstruct Candidate {\n    vector<string> adj;\n    SDS sds;\n};\n\nvoid solve() {\n    int M;\n    double eps;\n    if (!(cin >> M >> eps)) return;\n\n    // Strategy 1: Low Epsilon -> Compact encoding\n    // If noise is negligible, minimize N using simple edge count encoding\n    if (eps < 0.0001) { \n         for(int n=4; n<=100; ++n) {\n            if (n*(n-1)/2 + 1 >= M) {\n                cout << n << endl;\n                for(int i=0; i<M; ++i) {\n                    string s(n*(n-1)/2, '0');\n                    for(int k=0; k<i; ++k) s[k] = '1';\n                    cout << s << endl;\n                }\n                cout << flush;\n                for(int q=0; q<100; ++q) {\n                    string s; cin >> s;\n                    int cnt=0; for(char c:s) if(c=='1') cnt++;\n                    cout << min(cnt, M-1) << endl << flush;\n                }\n                return;\n            }\n        }\n    }\n    \n    // Strategy 2: General Case -> Robust SDS Encoding\n    // For significant noise, we prioritize E=0 by using N=100.\n    // For mild noise, we can reduce N slightly to improve score.\n    int N = 100;\n    if (eps <= 0.15) {\n        // Heuristic reduction of N for lower noise levels\n        // Needs to be large enough to support M distinct degree profiles\n        N = max(12, (int)(sqrt(M)*2.5)); \n        if (N > 100) N = 100;\n    }\n\n    // Generate a pool of candidate graphs\n    vector<Candidate> pool;\n    // We can generate fewer candidates if N is small to save time, \n    // but for N=100 we want good diversity.\n    int pool_size = 2500; \n    auto start_time = chrono::high_resolution_clock::now();\n    \n    while((int)pool.size() < pool_size) {\n        Candidate c;\n        c.adj = generate_sbm_graph(N);\n        c.sds = get_sds(c.adj, N);\n        pool.push_back(c);\n        \n        // Time safety check (2.0 sec limit for generation)\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_time).count() > 2000) break;\n    }\n    \n    // Fallback if generation was too slow\n    if ((int)pool.size() < M) {\n        while((int)pool.size() < M) {\n             Candidate c;\n             c.adj = vector<string>(N, string(N, '0'));\n             c.sds = vector<int>(N, 0);\n             pool.push_back(c);\n        }\n    }\n\n    // Greedy Selection: Select M graphs that maximize Minimum Distance (MaxMin)\n    vector<int> selected_indices;\n    vector<double> min_dists(pool.size(), 1e18);\n    \n    // Pick the first one (highest variance usually implies more information, or just random)\n    // Let's pick one with high variance in degrees? Or just random index 0.\n    selected_indices.push_back(0);\n    \n    // Initialize distances\n    for(size_t i=0; i<pool.size(); ++i) {\n        min_dists[i] = calc_sq_dist(pool[i].sds, pool[0].sds);\n    }\n    \n    while((int)selected_indices.size() < M) {\n        int best_idx = -1;\n        double max_val = -1.0;\n        \n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] > max_val) {\n                max_val = min_dists[i];\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) break;\n        \n        selected_indices.push_back(best_idx);\n        min_dists[best_idx] = -1.0; // Mark as used\n        \n        // Update distances\n        for(size_t i=0; i<pool.size(); ++i) {\n            if (min_dists[i] >= 0) {\n                double d = calc_sq_dist(pool[i].sds, pool[best_idx].sds);\n                if (d < min_dists[i]) min_dists[i] = d;\n            }\n        }\n    }\n    \n    // Output N and Graphs\n    cout << N << endl;\n    \n    // Prepare expected feature vectors for decoding\n    vector<vector<double>> code_expected_sds(M);\n    \n    for(int k=0; k<M; ++k) {\n        int idx = selected_indices[k];\n        const auto& cand = pool[idx];\n        \n        string s_out;\n        s_out.reserve(N*(N-1)/2);\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                s_out += cand.adj[i][j];\n            }\n        }\n        cout << s_out << endl;\n        \n        // Calculate Expected SDS under noise\n        // E[deg_new] = deg_old * (1 - epsilon) + (N - 1 - deg_old) * epsilon\n        //            = deg_old * (1 - 2*epsilon) + (N - 1) * epsilon\n        // We assume the sorted order is largely preserved or effectively approximated by transforming the sorted vector.\n        vector<double> exp_sds(N);\n        for(int i=0; i<N; ++i) {\n            exp_sds[i] = cand.sds[i] * (1.0 - 2.0 * eps) + (N - 1) * eps;\n        }\n        code_expected_sds[k] = exp_sds;\n    }\n    cout << flush;\n    \n    // Process Queries\n    for(int q=0; q<100; ++q) {\n        string s; cin >> s;\n        \n        // Compute observed SDS\n        SDS obs_sds(N, 0);\n        int p = 0;\n        for(int i=0; i<N; ++i) {\n            for(int j=i+1; j<N; ++j) {\n                if(s[p] == '1') {\n                    obs_sds[i]++;\n                    obs_sds[j]++;\n                }\n                p++;\n            }\n        }\n        sort(obs_sds.begin(), obs_sds.end());\n        \n        // Find nearest codeword in Euclidean space\n        int best_m = 0;\n        double min_dist = 1e18;\n        \n        for(int m=0; m<M; ++m) {\n            double d = 0;\n            const auto& target = code_expected_sds[m];\n            for(int i=0; i<N; ++i) {\n                double diff = obs_sds[i] - target[i];\n                d += diff * diff;\n            }\n            \n            if (d < min_dist) {\n                min_dist = d;\n                best_m = m;\n            }\n        }\n        cout << best_m << endl << flush;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    solve();\n    return 0;\n}","ahc017":"/*\n    Final Optimized Solution for AHC017\n    \n    Features:\n    1. Preprocessing: Edge Importance (Betweenness), Hop Distance, Pairwise Repulsion Costs.\n    2. Initialization: K-Means++ clustering on Hop Distance metric, Greedy Assignment, Bridge Repair.\n    3. Optimization: Simulated Annealing.\n       - Fast Edge Set operations (Swap-Remove).\n       - Leaf Optimization for Spanning Tree Connectivity Check: Checks leaf removal cases in O(deg(u)) instead of BFS.\n       - Interleaved BFS for general Connectivity Check.\n       - Precomputed float costs for O(1) scoring.\n*/\n\n#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Constants ---\nconst int INF = 1e9;\nconst int MAX_N = 1005;\nconst int MAX_M = 3005;\nconst int MAX_D = 32;\n\n// --- Structures ---\nstruct Edge {\n    int u, v, w, id;\n    double mid_x, mid_y;\n};\n\n// --- Globals ---\nint N, M, D, K;\nEdge edges[MAX_M];\npair<int,int> coords[MAX_N];\n\n// Compact Adjacency List\nint head[MAX_N], next_edge[MAX_M * 2], to_node[MAX_M * 2], edge_id_map[MAX_M * 2];\nint ecnt = 0;\n\nvoid add_edge(int u, int v, int id) {\n    to_node[ecnt] = v; edge_id_map[ecnt] = id; next_edge[ecnt] = head[u]; head[u] = ecnt++;\n    to_node[ecnt] = u; edge_id_map[ecnt] = id; next_edge[ecnt] = head[v]; head[v] = ecnt++;\n}\n\n// Precomputed info\nint16_t hop_dist[MAX_N][MAX_N];\ndouble edge_importance[MAX_M];\nfloat edge_pair_cost[MAX_M][MAX_M]; // Precomputed costs for speed\n\n// Solution State\nint assignment[MAX_M];\n// Using vector is fine if we do swap-remove, overhead is minimal compared to BFS\nvector<int> day_edges[MAX_D]; \ndouble day_scores[MAX_D];\n\n// Spanning Tree Structure\n// tree_adj is heavy to maintain as vector.\n// We can use a fixed size pool or just vectors. N is small.\nvector<int> tree_adj[MAX_D][MAX_N];\nint tree_deg[MAX_D][MAX_N]; // Track degrees for leaf optimization\nbool in_tree[MAX_D][MAX_M];\n\n// BFS / Traversal Utils\nint vis[MAX_N];\nint vis_token = 0;\nint q_bfs[MAX_N];\n\nmt19937 rng(12345);\nauto start_time = chrono::steady_clock::now();\n\ndouble get_time() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\n// --- Preprocessing ---\nvoid preprocessing() {\n    fill(edge_importance, edge_importance + M, 0.0);\n    static int dist[MAX_N];\n    static int parent_edge[MAX_N];\n    \n    // 1. Edge Importance\n    for(int start=1; start<=N; ++start) {\n        for(int i=1; i<=N; ++i) dist[i] = INF;\n        for(int i=1; i<=N; ++i) parent_edge[i] = -1;\n        \n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[start] = 0;\n        pq.push({0, start});\n        \n        while(!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if(d > dist[u]) continue;\n            \n            for(int e=head[u]; e!=-1; e=next_edge[e]) {\n                int v = to_node[e];\n                int id = edge_id_map[e];\n                if(dist[u] + edges[id].w < dist[v]) {\n                    dist[v] = dist[u] + edges[id].w;\n                    parent_edge[v] = id;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n        \n        for(int i=1; i<=N; ++i) {\n            if(i == start) continue;\n            int cur = i;\n            while(cur != start && parent_edge[cur] != -1) {\n                edge_importance[parent_edge[cur]] += 1.0;\n                int id = parent_edge[cur];\n                int u = edges[id].u, v = edges[id].v;\n                if(dist[u] < dist[v]) cur = u; else cur = v;\n            }\n        }\n    }\n    double max_imp = 1.0;\n    for(int i=0; i<M; ++i) max_imp = max(max_imp, edge_importance[i]);\n    if(max_imp > 0) for(int i=0; i<M; ++i) edge_importance[i] /= max_imp;\n\n    // 2. Hop Distances\n    for(int start=1; start<=N; ++start) {\n        vis_token++;\n        int h=0, t=0;\n        q_bfs[t++] = start;\n        vis[start] = vis_token;\n        for(int i=1; i<=N; ++i) hop_dist[start][i] = 32000;\n        hop_dist[start][start] = 0;\n        \n        while(h < t) {\n            int u = q_bfs[h++];\n            for(int e=head[u]; e!=-1; e=next_edge[e]) {\n                int v = to_node[e];\n                if(vis[v] != vis_token) {\n                    vis[v] = vis_token;\n                    hop_dist[start][v] = (int16_t)(hop_dist[start][u] + 1);\n                    q_bfs[t++] = v;\n                }\n            }\n        }\n    }\n\n    // 3. Edge Pair Costs\n    for(int i=0; i<M; ++i) {\n        for(int j=i; j<M; ++j) {\n            if(i == j) {\n                edge_pair_cost[i][j] = 0;\n                continue;\n            }\n            int u1 = edges[i].u, v1 = edges[i].v;\n            int u2 = edges[j].u, v2 = edges[j].v;\n            int d = min({(int)hop_dist[u1][u2], (int)hop_dist[u1][v2], (int)hop_dist[v1][u2], (int)hop_dist[v1][v2]});\n            double dist = d + 1.0;\n            double w = (edge_importance[i] + 1.0) * (edge_importance[j] + 1.0);\n            edge_pair_cost[i][j] = edge_pair_cost[j][i] = (float)(w / (dist * dist));\n        }\n    }\n}\n\n// --- Tree & Connectivity ---\nvoid check_vis_reset() {\n    if (vis_token > 2000000000) {\n        memset(vis, 0, sizeof(vis));\n        vis_token = 1;\n    }\n}\n\nvoid build_tree(int d) {\n    for(int i=1; i<=N; ++i) { tree_adj[d][i].clear(); tree_deg[d][i] = 0; }\n    for(int i=0; i<M; ++i) in_tree[d][i] = false;\n    \n    check_vis_reset();\n    vis_token++;\n    int h=0, t=0;\n    q_bfs[t++] = 1;\n    vis[1] = vis_token;\n    \n    while(h < t) {\n        int u = q_bfs[h++];\n        for(int e=head[u]; e!=-1; e=next_edge[e]) {\n            int v = to_node[e];\n            if(vis[v] == vis_token) continue;\n            \n            int id = edge_id_map[e];\n            if(assignment[id] != d) { \n                vis[v] = vis_token;\n                q_bfs[t++] = v;\n                \n                tree_adj[d][u].push_back(id);\n                tree_adj[d][v].push_back(id);\n                tree_deg[d][u]++;\n                tree_deg[d][v]++;\n                in_tree[d][id] = true;\n            }\n        }\n    }\n}\n\nvoid add_to_tree_adj(int d, int u, int v, int id) {\n    tree_adj[d][u].push_back(id);\n    tree_adj[d][v].push_back(id);\n    tree_deg[d][u]++;\n    tree_deg[d][v]++;\n    in_tree[d][id] = true;\n}\n\nvoid remove_from_tree_adj(int d, int u, int v, int id) {\n    // u\n    auto& adj_u = tree_adj[d][u];\n    for(int i=0; i<(int)adj_u.size(); ++i) {\n        if(adj_u[i] == id) {\n            adj_u[i] = adj_u.back();\n            adj_u.pop_back();\n            break;\n        }\n    }\n    tree_deg[d][u]--;\n    \n    // v\n    auto& adj_v = tree_adj[d][v];\n    for(int i=0; i<(int)adj_v.size(); ++i) {\n        if(adj_v[i] == id) {\n            adj_v[i] = adj_v.back();\n            adj_v.pop_back();\n            break;\n        }\n    }\n    tree_deg[d][v]--;\n    \n    in_tree[d][id] = false;\n}\n\nbool try_update_tree(int d, int e_rem, int e_add) {\n    int u = edges[e_rem].u;\n    int v = edges[e_rem].v;\n    \n    int best_repl = -1;\n\n    // Leaf Optimization\n    if (tree_deg[d][u] == 1) {\n        // u is a leaf. We just need any active edge connected to u (except e_rem)\n        for(int e=head[u]; e!=-1; e=next_edge[e]) {\n            int id = edge_id_map[e];\n            if(id == e_rem) continue;\n            if(assignment[id] != d) {\n                best_repl = id;\n                goto found;\n            }\n        }\n        // If we are adding e_add and it connects to u, it's valid\n        if(e_add != -1 && (edges[e_add].u == u || edges[e_add].v == u)) {\n            best_repl = e_add;\n            goto found;\n        }\n    }\n    \n    if (tree_deg[d][v] == 1) {\n        for(int e=head[v]; e!=-1; e=next_edge[e]) {\n            int id = edge_id_map[e];\n            if(id == e_rem) continue;\n            if(assignment[id] != d) {\n                best_repl = id;\n                goto found;\n            }\n        }\n        if(e_add != -1 && (edges[e_add].u == v || edges[e_add].v == v)) {\n            best_repl = e_add;\n            goto found;\n        }\n    }\n\n    // General Case: Interleaved BFS\n    {\n        static int q1[MAX_N], q2[MAX_N];\n        check_vis_reset();\n        vis_token += 2;\n        int tok1 = vis_token - 1;\n        int tok2 = vis_token;\n        \n        int h1=0, t1=0, h2=0, t2=0;\n        q1[t1++] = u; vis[u] = tok1;\n        q2[t2++] = v; vis[v] = tok2;\n        \n        int* small_q = nullptr;\n        int small_cnt = 0;\n        int small_tok = 0;\n        \n        while(true) {\n            bool moved = false;\n            if(h1 < t1) {\n                moved = true;\n                int curr = q1[h1++];\n                for(int id : tree_adj[d][curr]) {\n                    if(id == e_rem) continue;\n                    int nxt = (edges[id].u == curr) ? edges[id].v : edges[id].u;\n                    if(vis[nxt] != tok1) {\n                        vis[nxt] = tok1;\n                        q1[t1++] = nxt;\n                    }\n                }\n            } else {\n                small_q = q1; small_cnt = t1; small_tok = tok1;\n                break;\n            }\n            if(h2 < t2) {\n                moved = true;\n                int curr = q2[h2++];\n                for(int id : tree_adj[d][curr]) {\n                    if(id == e_rem) continue;\n                    int nxt = (edges[id].u == curr) ? edges[id].v : edges[id].u;\n                    if(vis[nxt] != tok2) {\n                        vis[nxt] = tok2;\n                        q2[t2++] = nxt;\n                    }\n                }\n            } else {\n                small_q = q2; small_cnt = t2; small_tok = tok2;\n                break;\n            }\n            if(!moved) break;\n        }\n        \n        if(e_add != -1) {\n            int x = edges[e_add].u;\n            int y = edges[e_add].v;\n            if((vis[x] == small_tok) != (vis[y] == small_tok)) best_repl = e_add;\n        }\n        \n        if(best_repl == -1) {\n            for(int i=0; i<small_cnt; ++i) {\n                int curr = small_q[i];\n                for(int e = head[curr]; e != -1; e = next_edge[e]) {\n                    int nxt = to_node[e];\n                    if(vis[nxt] != small_tok) {\n                        int id = edge_id_map[e];\n                        if(id == e_rem) continue;\n                        if(assignment[id] != d) { \n                            best_repl = id;\n                            goto found;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    found:;\n    if(best_repl != -1) {\n        remove_from_tree_adj(d, u, v, e_rem);\n        add_to_tree_adj(d, edges[best_repl].u, edges[best_repl].v, best_repl);\n        return true;\n    }\n    return false;\n}\n\nbool check_and_update(int d, int e_out, int e_in) {\n    if(!in_tree[d][e_out]) return true;\n    return try_update_tree(d, e_out, e_in);\n}\n\nint count_components(int d, vector<int>& cid) {\n    cid.assign(N+1, 0);\n    int cc = 0;\n    check_vis_reset();\n    vis_token++;\n    for(int i=1; i<=N; ++i) {\n        if(vis[i] != vis_token) {\n            cc++;\n            int h=0, t=0; q_bfs[t++] = i; vis[i] = vis_token; cid[i] = cc;\n            while(h < t) {\n                int u = q_bfs[h++];\n                for(int e=head[u]; e!=-1; e=next_edge[e]) {\n                    int id = edge_id_map[e];\n                    if(assignment[id] != d) {\n                        int v = to_node[e];\n                        if(vis[v] != vis_token) {\n                            vis[v] = vis_token; cid[v] = cc; q_bfs[t++] = v;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return cc;\n}\n\ndouble calc_day_score_delta(int d, int e_add) {\n    double delta = 0;\n    for(int e : day_edges[d]) {\n        delta += edge_pair_cost[e][e_add];\n    }\n    return delta;\n}\n\ndouble calc_score(int d) {\n    double s = 0;\n    const auto& es = day_edges[d];\n    int sz = es.size();\n    for(int i=0; i<sz; ++i) for(int j=i+1; j<sz; ++j) s += edge_pair_cost[es[i]][es[j]];\n    return s;\n}\n\n// --- Initialization ---\nvoid init() {\n    int k_clusters = (M + D - 1) / D;\n    int num_c = (M + k_clusters - 1) / k_clusters; \n    \n    vector<int> centers; centers.reserve(num_c);\n    int first = uniform_int_distribution<int>(1, N)(rng);\n    centers.push_back(first);\n    \n    vector<int> min_dist(N+1, 32000);\n    for(int i=1; i<=N; ++i) min_dist[i] = hop_dist[i][first];\n    \n    for(int i=1; i<num_c; ++i) {\n        long long sum_sq = 0;\n        for(int u=1; u<=N; ++u) sum_sq += (long long)min_dist[u] * min_dist[u];\n        long long r = uniform_int_distribution<long long>(0, sum_sq)(rng);\n        int next_c = -1;\n        long long current_sum = 0;\n        for(int u=1; u<=N; ++u) {\n            current_sum += (long long)min_dist[u] * min_dist[u];\n            if(current_sum >= r) { next_c = u; break; }\n        }\n        if(next_c == -1) next_c = N;\n        centers.push_back(next_c);\n        for(int u=1; u<=N; ++u) min_dist[u] = min(min_dist[u], (int)hop_dist[u][next_c]);\n    }\n    \n    vector<vector<int>> clusters(num_c);\n    vector<int> node_cluster(N+1);\n    \n    for(int iter=0; iter<8; ++iter) {\n        for(auto& c : clusters) c.clear();\n        for(int u=1; u<=N; ++u) {\n            int best = -1, min_d = 32000;\n            for(int c_idx=0; c_idx<num_c; ++c_idx) {\n                int d = hop_dist[u][centers[c_idx]];\n                if(d < min_d) { min_d = d; best = c_idx; }\n            }\n            node_cluster[u] = best;\n        }\n        for(int i=0; i<M; ++i) {\n            int u = edges[i].u, v = edges[i].v;\n            int c_u = node_cluster[u];\n            int c_v = node_cluster[v];\n            if(hop_dist[u][centers[c_u]] < hop_dist[v][centers[c_v]]) clusters[c_u].push_back(i);\n            else clusters[c_v].push_back(i);\n        }\n        for(int c=0; c<num_c; ++c) {\n            if(clusters[c].empty()) continue;\n            int best_node = centers[c];\n            int e_idx = clusters[c][uniform_int_distribution<int>(0, clusters[c].size()-1)(rng)];\n            best_node = (uniform_int_distribution<int>(0,1)(rng)) ? edges[e_idx].u : edges[e_idx].v;\n            centers[c] = best_node;\n        }\n    }\n    \n    fill(assignment, assignment + M, 0);\n    for(int d=1; d<=D; ++d) day_edges[d].clear();\n    \n    vector<int> c_order(num_c); iota(c_order.begin(), c_order.end(), 0);\n    shuffle(c_order.begin(), c_order.end(), rng);\n    \n    for(int c : c_order) {\n        sort(clusters[c].begin(), clusters[c].end(), [&](int a, int b){\n            return edge_importance[a] > edge_importance[b];\n        });\n        for(int id : clusters[c]) {\n            int best_d = -1;\n            double min_cost = 1e18;\n            int start_d = uniform_int_distribution<int>(1, D)(rng);\n            for(int i=0; i<D; ++i) {\n                int d = (start_d + i - 1) % D + 1;\n                if(day_edges[d].size() < K) {\n                    double cost = calc_day_score_delta(d, id);\n                    if(cost < min_cost) { min_cost = cost; best_d = d; }\n                }\n            }\n            if(best_d == -1) {\n                 for(int i=0; i<D; ++i) {\n                    int d = (start_d + i - 1) % D + 1;\n                    if(day_edges[d].size() < K) { best_d=d; break; }\n                 }\n            }\n            assignment[id] = best_d;\n            day_edges[best_d].push_back(id);\n        }\n    }\n    \n    for(int d=1; d<=D; ++d) {\n        while(true) {\n            if(get_time() > 2.8) break;\n            vector<int> cid;\n            if(count_components(d, cid) == 1) break;\n            \n            int bridge = -1;\n            vector<int> cands = day_edges[d];\n            shuffle(cands.begin(), cands.end(), rng);\n            for(int e : cands) {\n                if(cid[edges[e].u] != cid[edges[e].v]) { bridge = e; break; }\n            }\n            if(bridge == -1) break;\n            \n            bool moved = false;\n            vector<int> targets(D); iota(targets.begin(), targets.end(), 1);\n            shuffle(targets.begin(), targets.end(), rng);\n            \n            for(int t : targets) {\n                if(t == d) continue;\n                build_tree(t);\n                if(day_edges[t].size() < K) {\n                    if(check_and_update(t, bridge, -1)) {\n                        auto& s = day_edges[d]; s.erase(find(s.begin(), s.end(), bridge));\n                        day_edges[t].push_back(bridge); assignment[bridge] = t;\n                        moved = true; break;\n                    }\n                } else {\n                    for(int swap_e : day_edges[t]) {\n                        if(check_and_update(t, bridge, swap_e)) {\n                            auto& sd = day_edges[d]; sd.erase(find(sd.begin(), sd.end(), bridge));\n                            sd.push_back(swap_e);\n                            auto& st = day_edges[t]; st.erase(find(st.begin(), st.end(), swap_e));\n                            st.push_back(bridge);\n                            assignment[bridge] = t; assignment[swap_e] = d;\n                            moved = true; goto done_move;\n                        }\n                    }\n                    done_move:;\n                    if(moved) break;\n                }\n            }\n            if(!moved) break;\n        }\n    }\n    for(int d=1; d<=D; ++d) build_tree(d);\n}\n\n// --- SA ---\nvoid solve() {\n    for(int d=1; d<=D; ++d) day_scores[d] = calc_score(d);\n    double T0 = 200.0, T1 = 0.02, limit = 5.85;\n    int iter = 0;\n    \n    // Main loop\n    while(true) {\n        iter++;\n        if((iter & 0xFF) == 0 && get_time() > limit) break;\n        double temp = T0 + (T1 - T0) * (get_time() / limit);\n        \n        int d1 = uniform_int_distribution<int>(1, D)(rng);\n        int d2 = uniform_int_distribution<int>(1, D)(rng);\n        if(d1 == d2) continue;\n        \n        bool swap = true;\n        if(day_edges[d1].empty()) continue;\n        if(day_edges[d2].size() < K) {\n            if(day_edges[d2].empty() || uniform_real_distribution<double>(0,1)(rng) < 0.5) swap = false;\n        }\n        if(swap && day_edges[d2].empty()) swap = false;\n        \n        int i1 = uniform_int_distribution<int>(0, day_edges[d1].size()-1)(rng);\n        int e1 = day_edges[d1][i1];\n        int i2 = -1, e2 = -1;\n        if(swap) {\n            i2 = uniform_int_distribution<int>(0, day_edges[d2].size()-1)(rng);\n            e2 = day_edges[d2][i2];\n        }\n        \n        double ns1 = day_scores[d1], ns2 = day_scores[d2];\n        for(int x : day_edges[d1]) if(x!=e1) { ns1 -= edge_pair_cost[e1][x]; if(swap) ns1 += edge_pair_cost[e2][x]; }\n        for(int x : day_edges[d2]) if(x!=e2) { if(swap) ns2 -= edge_pair_cost[e2][x]; ns2 += edge_pair_cost[e1][x]; }\n        \n        double delta = (ns1 + ns2) - (day_scores[d1] + day_scores[d2]);\n        if(delta < 0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n            bool ok = true;\n            if(swap) {\n                if(!check_and_update(d1, e2, e1)) ok = false;\n                else if(!check_and_update(d2, e1, e2)) { ok = false; check_and_update(d1, e1, e2); }\n            } else {\n                if(!check_and_update(d2, e1, -1)) ok = false;\n            }\n            \n            if(ok) {\n                if(swap) {\n                    day_edges[d1][i1] = e2; day_edges[d2][i2] = e1;\n                    assignment[e1] = d2; assignment[e2] = d1;\n                } else {\n                    day_edges[d1][i1] = day_edges[d1].back(); day_edges[d1].pop_back();\n                    day_edges[d2].push_back(e1);\n                    assignment[e1] = d2;\n                }\n                day_scores[d1] = ns1; day_scores[d2] = ns2;\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    if(!(cin >> N >> M >> D >> K)) return 0;\n    fill(head, head+N+1, -1);\n    for(int i=0; i<M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w; edges[i].id = i;\n        add_edge(edges[i].u, edges[i].v, i);\n    }\n    for(int i=0; i<N; ++i) cin >> coords[i].first >> coords[i].second;\n    for(int i=0; i<M; ++i) {\n        edges[i].mid_x = (coords[edges[i].u-1].first + coords[edges[i].v-1].first)*0.5;\n        edges[i].mid_y = (coords[edges[i].u-1].second + coords[edges[i].v-1].second)*0.5;\n    }\n    preprocessing();\n    init();\n    solve();\n    for(int i=0; i<M; ++i) cout << assignment[i] << (i==M-1?\"\":\" \");\n    cout << endl;\n    return 0;\n}","ahc019":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <set>\n#include <random>\n#include <chrono>\n#include <tuple>\n#include <cstring>\n#include <queue>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\n// Global Constants and Time\nconst int MAX_D = 14;\nint D;\nauto start_time = chrono::high_resolution_clock::now();\n\ndouble get_time() {\n    auto now = chrono::high_resolution_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\n// Data Structures\nstruct Point {\n    int x, y, z;\n    auto operator<=>(const Point&) const = default;\n    Point operator+(const Point& other) const { return {x + other.x, y + other.y, z + other.z}; }\n    Point operator-(const Point& other) const { return {x - other.x, y - other.y, z - other.z}; }\n};\n\nstruct Rotation {\n    int p[3];\n    int s[3];\n};\nvector<Rotation> rotations;\n\nvoid init_rotations() {\n    int perms[6][3] = {{0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}};\n    for (int i = 0; i < 6; ++i) {\n        for (int mask = 0; mask < 8; ++mask) {\n            Rotation r;\n            for (int j = 0; j < 3; ++j) {\n                r.p[j] = perms[i][j];\n                r.s[j] = (mask & (1 << j)) ? -1 : 1;\n            }\n            int mat[3][3] = {0};\n            for(int j=0; j<3; ++j) mat[j][r.p[j]] = r.s[j];\n            int det = mat[0][0]*(mat[1][1]*mat[2][2] - mat[1][2]*mat[2][1])\n                    - mat[0][1]*(mat[1][0]*mat[2][2] - mat[1][2]*mat[2][0])\n                    + mat[0][2]*(mat[1][0]*mat[2][1] - mat[1][1]*mat[2][0]);\n            if (det == 1) rotations.push_back(r);\n        }\n    }\n}\n\nPoint apply_rot(const Point& pt, int rot_idx) {\n    const Rotation& r = rotations[rot_idx];\n    int coords[3] = {pt.x, pt.y, pt.z};\n    return {\n        coords[r.p[0]] * r.s[0],\n        coords[r.p[1]] * r.s[1],\n        coords[r.p[2]] * r.s[2]\n    };\n}\n\n// Inputs\nvector<string> f1_in, r1_in, f2_in, r2_in;\n\n// Helpers\nbool is_set(const vector<string>& s, int r, int c) { return s[r][c] == '1'; }\n\n// Get all valid positions\nvector<Point> get_maximal_voxels(const vector<string>& f, const vector<string>& r_s) {\n    vector<Point> v;\n    for(int x=0; x<D; ++x)\n        for(int y=0; y<D; ++y)\n            for(int z=0; z<D; ++z)\n                if(is_set(f, z, x) && is_set(r_s, z, y))\n                    v.push_back({x,y,z});\n    return v;\n}\n\nstruct Solution {\n    vector<int> grid1;\n    vector<int> grid2;\n    int num_blocks;\n    double score;\n};\n\n// Solver State\nstruct SolverState {\n    vector<Point> M1, M2;\n    vector<bool> used1, used2;\n    vector<int> cover_f1, cover_r1, cover_f2, cover_r2; // counts of coverage\n    vector<int> grid1, grid2;\n    int block_counter;\n    \n    SolverState() : grid1(D*D*D, 0), grid2(D*D*D, 0), block_counter(1) {}\n\n    void init(const vector<Point>& m1, const vector<Point>& m2) {\n        M1 = m1; M2 = m2;\n        used1.assign(M1.size(), false);\n        used2.assign(M2.size(), false);\n        cover_f1.assign(D*D, 0); cover_r1.assign(D*D, 0);\n        cover_f2.assign(D*D, 0); cover_r2.assign(D*D, 0);\n    }\n\n    void add_block(const vector<Point>& shape, int rot, Point shift, const vector<int>& indices1, const vector<int>& indices2) {\n        int id = block_counter++;\n        for(int idx : indices1) {\n            used1[idx] = true;\n            Point p = M1[idx];\n            grid1[p.x*D*D + p.y*D + p.z] = id;\n            cover_f1[p.z*D + p.x]++;\n            cover_r1[p.z*D + p.y]++;\n        }\n        for(int idx : indices2) {\n            used2[idx] = true;\n            Point p = M2[idx];\n            grid2[p.x*D*D + p.y*D + p.z] = id;\n            cover_f2[p.z*D + p.x]++;\n            cover_r2[p.z*D + p.y]++;\n        }\n    }\n};\n\n// Compute weights dynamically\nvoid update_weights(SolverState& state, vector<double>& w1, vector<double>& w2, mt19937& rng) {\n    // Counts of available voxels for each pixel\n    vector<int> cnt_f1(D*D, 0), cnt_r1(D*D, 0);\n    vector<int> cnt_f2(D*D, 0), cnt_r2(D*D, 0);\n\n    int n1 = state.M1.size();\n    int n2 = state.M2.size();\n\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        Point p = state.M1[i];\n        cnt_f1[p.z*D + p.x]++;\n        cnt_r1[p.z*D + p.y]++;\n    }\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        Point p = state.M2[i];\n        cnt_f2[p.z*D + p.x]++;\n        cnt_r2[p.z*D + p.y]++;\n    }\n\n    auto calc_w = [&](const Point& p, const vector<int>& cnt_f, const vector<int>& cnt_r, \n                      const vector<int>& cov_f, const vector<int>& cov_r) {\n        double w = 1.0; // base volume weight\n        int zx = p.z*D + p.x;\n        int zy = p.z*D + p.y;\n        \n        // If pixel not covered yet, high value. Inversely proportional to availability.\n        if (cov_f[zx] == 0) w += 50.0 / (cnt_f[zx] + 1e-5);\n        if (cov_r[zy] == 0) w += 50.0 / (cnt_r[zy] + 1e-5);\n        \n        return w;\n    };\n\n    w1.assign(n1, 0);\n    for(int i=0; i<n1; ++i) {\n        if(state.used1[i]) continue;\n        w1[i] = calc_w(state.M1[i], cnt_f1, cnt_r1, state.cover_f1, state.cover_r1);\n        w1[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n\n    w2.assign(n2, 0);\n    for(int i=0; i<n2; ++i) {\n        if(state.used2[i]) continue;\n        w2[i] = calc_w(state.M2[i], cnt_f2, cnt_r2, state.cover_f2, state.cover_r2);\n        w2[i] *= uniform_real_distribution<>(0.9, 1.1)(rng);\n    }\n}\n\n// Voting grid\ndouble votes[30*30*30];\nint vote_dim = 0;\nint vote_dim_sq = 0;\nint vote_offset = 0;\n\nvoid reset_votes() {\n    vote_offset = D;\n    vote_dim = 2 * D + 1;\n    vote_dim_sq = vote_dim * vote_dim;\n    fill(votes, votes + vote_dim*vote_dim*vote_dim, 0.0);\n}\n\nstruct MatchResult {\n    vector<Point> shape;\n    vector<int> indices1;\n    vector<int> indices2;\n    double total_weight;\n    int rotation;\n    Point shift;\n};\n\nMatchResult find_best_block(SolverState& state, const vector<double>& w1, const vector<double>& w2) {\n    MatchResult best_res;\n    best_res.total_weight = -1.0;\n\n    // Collect available indices\n    vector<int> c1, c2;\n    for(size_t i=0; i<state.M1.size(); ++i) if(!state.used1[i]) c1.push_back(i);\n    for(size_t i=0; i<state.M2.size(); ++i) if(!state.used2[i]) c2.push_back(i);\n\n    if (c1.empty() || c2.empty()) return best_res;\n\n    // Subsample for voting to speed up\n    vector<int> vote_c1 = c1;\n    vector<int> vote_c2 = c2;\n    \n    // Heuristic: Vote only with highest weight voxels to find promising alignments\n    // This avoids O(N^2) in the voting loop\n    int limit = 300;\n    if (vote_c1.size() > limit) {\n        partial_sort(vote_c1.begin(), vote_c1.begin()+limit, vote_c1.end(), [&](int a, int b){ return w1[a] > w1[b]; });\n        vote_c1.resize(limit);\n    }\n    if (vote_c2.size() > limit) {\n        partial_sort(vote_c2.begin(), vote_c2.begin()+limit, vote_c2.end(), [&](int a, int b){ return w2[a] > w2[b]; });\n        vote_c2.resize(limit);\n    }\n\n    // Iterate Rotations\n    for(int rot=0; rot<24; ++rot) {\n        reset_votes();\n        \n        // Precompute rotated V2 subset\n        vector<Point> v2_rot(vote_c2.size());\n        for(size_t i=0; i<vote_c2.size(); ++i) v2_rot[i] = apply_rot(state.M2[vote_c2[i]], rot);\n\n        // Voting\n        for(size_t i=0; i<vote_c1.size(); ++i) {\n            Point p1 = state.M1[vote_c1[i]];\n            double val1 = w1[vote_c1[i]];\n            for(size_t j=0; j<vote_c2.size(); ++j) {\n                Point d = p1 - v2_rot[j];\n                if(abs(d.x) < D && abs(d.y) < D && abs(d.z) < D) {\n                    int idx = (d.x + vote_offset) * vote_dim_sq + (d.y + vote_offset) * vote_dim + (d.z + vote_offset);\n                    votes[idx] += val1 + w2[vote_c2[j]];\n                }\n            }\n        }\n\n        // Find top candidate shifts\n        priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n        for(int i=0; i<vote_dim*vote_dim*vote_dim; ++i) {\n            if(votes[i] > 1e-3) {\n                pq.push({votes[i], i});\n                if(pq.size() > 5) pq.pop();\n            }\n        }\n\n        vector<int> candidates;\n        while(!pq.empty()) {\n            candidates.push_back(pq.top().second);\n            pq.pop();\n        }\n\n        // Evaluate candidates with full sets\n        for(int cand_idx : candidates) {\n            int dz = cand_idx % vote_dim;\n            int dy = (cand_idx / vote_dim) % vote_dim;\n            int dx = (cand_idx / vote_dim_sq);\n            Point shift = {dx - vote_offset, dy - vote_offset, dz - vote_offset};\n\n            // Build map of V2 points (rotated and shifted) -> original index\n            map<Point, int> v2_map;\n            for(int idx : c2) {\n                Point p = apply_rot(state.M2[idx], rot) + shift;\n                if (p.x >= 0 && p.x < D && p.y >= 0 && p.y < D && p.z >= 0 && p.z < D) {\n                    v2_map[p] = idx;\n                }\n            }\n\n            // Intersection nodes\n            struct Node {\n                Point p;\n                int idx1;\n                int idx2;\n                double w;\n            };\n            vector<Node> intersection;\n            for(int idx1 : c1) {\n                Point p = state.M1[idx1];\n                if (v2_map.count(p)) {\n                    int idx2 = v2_map[p];\n                    intersection.push_back({p, idx1, idx2, w1[idx1] + w2[idx2]});\n                }\n            }\n\n            if (intersection.empty()) continue;\n\n            // Find largest weighted connected component\n            set<Point> int_pts;\n            for(const auto& node : intersection) int_pts.insert(node.p);\n            set<Point> visited;\n            map<Point, int> p_to_node;\n            for(size_t k=0; k<intersection.size(); ++k) p_to_node[intersection[k].p] = k;\n\n            for(const auto& node : intersection) {\n                if (visited.count(node.p)) continue;\n\n                vector<Point> comp_shape;\n                vector<int> comp_idx1, comp_idx2;\n                double comp_w = 0;\n                \n                queue<Point> q;\n                q.push(node.p);\n                visited.insert(node.p);\n                \n                while(!q.empty()){\n                    Point u = q.front(); q.pop();\n                    int u_node_idx = p_to_node[u];\n                    comp_shape.push_back(u);\n                    comp_idx1.push_back(intersection[u_node_idx].idx1);\n                    comp_idx2.push_back(intersection[u_node_idx].idx2);\n                    comp_w += intersection[u_node_idx].w;\n\n                    Point neighbors[6] = {\n                        {u.x+1, u.y, u.z}, {u.x-1, u.y, u.z},\n                        {u.x, u.y+1, u.z}, {u.x, u.y-1, u.z},\n                        {u.x, u.y, u.z+1}, {u.x, u.y, u.z-1}\n                    };\n\n                    for(const auto& v : neighbors) {\n                        if(int_pts.count(v) && !visited.count(v)) {\n                            visited.insert(v);\n                            q.push(v);\n                        }\n                    }\n                }\n\n                if (comp_w > best_res.total_weight) {\n                    best_res.total_weight = comp_w;\n                    best_res.shape = comp_shape;\n                    best_res.indices1 = comp_idx1;\n                    best_res.indices2 = comp_idx2;\n                    best_res.rotation = rot;\n                    best_res.shift = shift;\n                }\n            }\n        }\n    }\n    return best_res;\n}\n\nvoid fill_residuals(SolverState& state, const vector<string>& f, const vector<string>& r_s, bool is_second) {\n    vector<pair<int,int>> needed_f, needed_r;\n    const vector<int>& cov_f = (is_second ? state.cover_f2 : state.cover_f1);\n    const vector<int>& cov_r = (is_second ? state.cover_r2 : state.cover_r1);\n\n    for(int z=0; z<D; ++z) {\n        for(int x=0; x<D; ++x) \n            if(is_set(f, z, x) && cov_f[z*D+x] == 0) needed_f.push_back({x, z});\n        for(int y=0; y<D; ++y) \n            if(is_set(r_s, z, y) && cov_r[z*D+y] == 0) needed_r.push_back({y, z});\n    }\n\n    vector<Point> candidates;\n    const vector<Point>& M = (is_second ? state.M2 : state.M1);\n    const vector<bool>& used = (is_second ? state.used2 : state.used1);\n    \n    for(size_t i=0; i<M.size(); ++i) if(!used[i]) candidates.push_back(M[i]);\n\n    vector<bool> done_f(needed_f.size(), false);\n    vector<bool> done_r(needed_r.size(), false);\n    int rem_f = needed_f.size();\n    int rem_r = needed_r.size();\n\n    while(rem_f > 0 || rem_r > 0) {\n        int best_idx = -1;\n        int best_cnt = -1;\n        \n        int step = (candidates.size() > 500) ? 2 : 1;\n        for(size_t i=0; i<candidates.size(); i+=step) {\n            if(candidates[i].x == -1) continue;\n            int cnt = 0;\n            const Point& p = candidates[i];\n            for(size_t k=0; k<needed_f.size(); ++k) \n                if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) cnt++;\n            for(size_t k=0; k<needed_r.size(); ++k) \n                if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) cnt++;\n            \n            if(cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = i;\n            }\n        }\n\n        if(best_idx == -1 || best_cnt == 0) break;\n\n        Point p = candidates[best_idx];\n        candidates[best_idx].x = -1; \n        \n        int id = state.block_counter++;\n        if (is_second) state.grid2[p.x*D*D + p.y*D + p.z] = id;\n        else state.grid1[p.x*D*D + p.y*D + p.z] = id;\n\n        for(size_t k=0; k<needed_f.size(); ++k) \n            if(!done_f[k] && needed_f[k].first == p.x && needed_f[k].second == p.z) { done_f[k]=true; rem_f--; }\n        for(size_t k=0; k<needed_r.size(); ++k) \n            if(!done_r[k] && needed_r[k].first == p.y && needed_r[k].second == p.z) { done_r[k]=true; rem_r--; }\n    }\n}\n\ndouble calc_score(const SolverState& state) {\n    map<int, int> vol;\n    set<int> s1, s2;\n    \n    for(int x : state.grid1) if(x) { vol[x]++; s1.insert(x); }\n    for(int x : state.grid2) if(x) { vol[x]++; s2.insert(x); }\n    \n    double score = 0;\n    for(int id : s1) {\n        if(s2.count(id)) score += 1.0 / vol[id];\n        else score += vol[id];\n    }\n    for(int id : s2) {\n        if(!s1.count(id)) score += vol[id];\n    }\n    return round(1e9 * score);\n}\n\nvoid run_solve() {\n    cin >> D;\n    f1_in.resize(D); r1_in.resize(D);\n    f2_in.resize(D); r2_in.resize(D);\n    for(int i=0; i<D; ++i) cin >> f1_in[i];\n    for(int i=0; i<D; ++i) cin >> r1_in[i];\n    for(int i=0; i<D; ++i) cin >> f2_in[i];\n    for(int i=0; i<D; ++i) cin >> r2_in[i];\n\n    init_rotations();\n    vector<Point> M1 = get_maximal_voxels(f1_in, r1_in);\n    vector<Point> M2 = get_maximal_voxels(f2_in, r2_in);\n    \n    Solution best_sol;\n    best_sol.score = 1e18;\n\n    mt19937 rng(42);\n\n    while (get_time() < 5.8) {\n        SolverState state;\n        state.init(M1, M2);\n        \n        int consecutive_fails = 0;\n        while(consecutive_fails < 5) {\n            vector<double> w1, w2;\n            update_weights(state, w1, w2, rng);\n            \n            MatchResult res = find_best_block(state, w1, w2);\n            \n            // If the best block is empty or has very low value (meaning it probably contributes nothing to silhouettes)\n            if(res.shape.empty() || res.total_weight < 0.5) { \n                break;\n            }\n            \n            // Heuristic: if the block is just 1x1 and contributes only to volume (weight approx 2.0)\n            // and doesn't help cover new silhouette (which would add ~50 weight), \n            // it might be better to stop greedy matching and let residuals handle it,\n            // UNLESS we still have large unmatched chunks. \n            // But 1x1 common (cost 1) is better than 1x1 residual (cost 1) if we need it for both.\n            // If we need it for only one, 1x1 common is cost 1 (0 unmatched, 1 inv).\n            // 1x1 residual is cost 1 (1 unmatched).\n            // So common is never strictly worse.\n            \n            state.add_block(res.shape, res.rotation, res.shift, res.indices1, res.indices2);\n            \n            // Check if block was \"trivial\" (small volume, low weight)\n            if (res.total_weight < 20.0 && res.shape.size() < 2) {\n                 consecutive_fails++;\n            } else {\n                 consecutive_fails = 0;\n            }\n        }\n        \n        fill_residuals(state, f1_in, r1_in, false);\n        fill_residuals(state, f2_in, r2_in, true);\n        \n        double s = calc_score(state);\n        if (s < best_sol.score) {\n            best_sol.score = s;\n            best_sol.grid1 = state.grid1;\n            best_sol.grid2 = state.grid2;\n            best_sol.num_blocks = state.block_counter - 1;\n        }\n    }\n\n    cout << best_sol.num_blocks << endl;\n    for(int i=0; i<(int)best_sol.grid1.size(); ++i) cout << best_sol.grid1[i] << (i==best_sol.grid1.size()-1?\"\":\" \");\n    cout << endl;\n    for(int i=0; i<(int)best_sol.grid2.size(); ++i) cout << best_sol.grid2[i] << (i==best_sol.grid2.size()-1?\"\":\" \");\n    cout << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    run_solve();\n    return 0;\n}","ahc020":"/**\n * Problem: AHC020 - Broadcasting\n * Approach: Simulated Annealing with Hybrid Steiner Tree Construction\n *\n * Key Improvements:\n * 1. Optimized Primal Heuristic (Takahashi's Algorithm) for final construction:\n *    - The previous version ran Takahashi from every terminal node. This version runs it from *every* node in the graph (N=100) as the root.\n *    - Often, the optimal Steiner Tree root (or \"center\") is not one of the terminal nodes (broadcasting stations) but an intermediate node.\n *    - Since N is small (100), this O(N * N * Dijkstra) check is feasible and often yields better trees.\n *\n * 2. Refined Simulated Annealing:\n *    - State representation uses sorted vectors for efficient radius queries.\n *    - Move strategies:\n *      a. Shift: Move resident to nearby station, biasing towards zero-cost increases (clustering).\n *      b. Clear: Attempt to empty a station completely to prune network branches.\n *    - Proxy Cost: MST on Metric Closure is used during SA for speed.\n *\n * 3. Data Structures:\n *    - Uses `vector` with `lower_bound` instead of `multiset` for better cache locality and speed.\n *    - Fast `Xorshift` RNG.\n */\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <bitset>\n#include <queue>\n#include <numeric>\n#include <iomanip>\n#include <cstring>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 105;\nconst int MAX_K = 5005;\nconst int MAX_M = 305;\nconst long long INF = 1e18;\nconst int MAX_P = 5000;\n\n// Structures\nstruct Point { int x, y; };\nstruct Edge { int u, v, w, id; };\nstruct AdjEdge { int to; int w; int id; };\n\n// Global Inputs\nint N, M, K;\nPoint stations[MAX_N];\nEdge edges[MAX_M];\nPoint residents[MAX_K];\nvector<AdjEdge> adj_list[MAX_N];\n\n// Precomputed Data\nlong long adj_dist[MAX_N][MAX_N]; // Shortest path distances\nint dist_res_stat[MAX_K][MAX_N];  // Required P for resident k at station i\nvector<int> nearby_stations[MAX_K]; // Valid stations sorted by distance\n\n// Random number generator (Xorshift for speed)\nstruct Xorshift {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    int next_int(int n) {\n        return next() % n;\n    }\n    double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Helper Functions\nlong long distSq(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint get_P(long long sq_dist) {\n    if (sq_dist == 0) return 0;\n    return (int)ceil(sqrt((double)sq_dist));\n}\n\nvoid precompute_paths() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            adj_dist[i][j] = (i == j ? 0 : INF);\n        }\n    }\n    for(int i=0; i<M; ++i) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int w = edges[i].w;\n        if(w < adj_dist[u][v]) {\n            adj_dist[u][v] = adj_dist[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(adj_dist[i][k] != INF && adj_dist[k][j] != INF) {\n                    if(adj_dist[i][k] + adj_dist[k][j] < adj_dist[i][j]) {\n                        adj_dist[i][j] = adj_dist[i][k] + adj_dist[k][j];\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Proxy Cost: MST on Metric Closure\n// Calculates the cost to connect a set of terminals using direct shortest paths.\nlong long calc_mst_proxy(int T, const int* nodes) {\n    if(T <= 1) return 0;\n    \n    long long cost = 0;\n    static long long min_d[MAX_N];\n    static bool visited[MAX_N];\n    \n    for(int i=0; i<T; ++i) { min_d[i] = INF; visited[i] = false; }\n    min_d[0] = 0;\n    \n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_d[j] < best) {\n                best = min_d[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        cost += best;\n        \n        int idx_u = nodes[u];\n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[idx_u][nodes[v]];\n                if(d < min_d[v]) min_d[v] = d;\n            }\n        }\n    }\n    return cost;\n}\n\n// 1. Multi-root Takahashi Algorithm\n// Attempts to build a Steiner Tree starting from *every possible node* in the graph.\n// This often finds a better center for the star-like topology.\npair<long long, vector<int>> takahashi_steiner_full_scan(const vector<int>& terminals) {\n    static bool is_target[MAX_N];\n    for(int i=0; i<N; ++i) is_target[i] = false;\n    \n    int target_count = 0;\n    for(int t : terminals) {\n        if(!is_target[t]) {\n            is_target[t] = true;\n            target_count++;\n        }\n    }\n    // Always include station 0\n    if(!is_target[0]) {\n        is_target[0] = true;\n        target_count++;\n    }\n\n    if (target_count <= 1) return {0, {}};\n    \n    long long best_total_cost = INF;\n    vector<int> best_edges;\n\n    static long long dist[MAX_N];\n    static int parent_node[MAX_N];\n    static int parent_edge[MAX_N];\n    static bool connected[MAX_N];\n    static int current_edge_cost[MAX_M];\n\n    // Try every node as the root of the greedy construction\n    for(int root = 0; root < N; ++root) {\n        // If root is isolated (infinite distance to 0 or targets), skip if possible,\n        // but since graph is connected and we use adj_list, simple check is fine.\n        // Optimization: If root is far from all targets, likely bad. But N=100 allows full check.\n        \n        for(int i=0; i<M; ++i) current_edge_cost[i] = edges[i].w;\n        for(int i=0; i<N; ++i) connected[i] = false;\n        \n        connected[root] = true;\n        int connected_count = is_target[root] ? 1 : 0;\n        long long current_tree_cost = 0;\n        vector<int> current_tree_edges;\n        \n        while(connected_count < target_count) {\n            for(int i=0; i<N; ++i) dist[i] = INF;\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<N; ++i) {\n                if(connected[i]) {\n                    dist[i] = 0;\n                    pq.push({0, i});\n                }\n            }\n            \n            int best_node = -1;\n            while(!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if(d > dist[u]) continue;\n                \n                if(is_target[u] && !connected[u]) {\n                    best_node = u;\n                    break; \n                }\n                \n                for(auto& edge : adj_list[u]) {\n                    int v = edge.to;\n                    int w = current_edge_cost[edge.id];\n                    if(dist[u] + w < dist[v]) {\n                        dist[v] = dist[u] + w;\n                        parent_node[v] = u;\n                        parent_edge[v] = edge.id;\n                        pq.push({dist[v], v});\n                    }\n                }\n            }\n            \n            if(best_node == -1) {\n                // Should effectively not happen in a connected graph\n                current_tree_cost = INF;\n                break; \n            }\n            \n            // Trace back\n            int curr = best_node;\n            while(!connected[curr]) {\n                connected[curr] = true;\n                if(is_target[curr]) connected_count++;\n                int eid = parent_edge[curr];\n                current_tree_edges.push_back(eid);\n                current_tree_cost += edges[eid].w;\n                current_edge_cost[eid] = 0; \n                curr = parent_node[curr];\n            }\n        }\n        \n        if(current_tree_cost < best_total_cost) {\n            best_total_cost = current_tree_cost;\n            best_edges = current_tree_edges;\n        }\n    }\n    return {best_total_cost, best_edges};\n}\n\n// 2. Metric MST + Pruning\n// A standard approximation: MST on the complete graph of terminals (metric closure),\n// then mapping those virtual edges back to real paths and pruning leaves.\npair<long long, vector<int>> metric_mst_steiner(const vector<int>& terminals) {\n    vector<int> nodes = terminals;\n    bool has_root = false;\n    for(int t : nodes) if(t == 0) has_root = true;\n    if(!has_root) nodes.push_back(0);\n    \n    int T = nodes.size();\n    if(T <= 1) return {0, {}};\n\n    vector<long long> min_d(T, INF);\n    vector<int> parent(T, -1);\n    vector<bool> visited(T, false);\n    min_d[0] = 0;\n    \n    for(int i=0; i<T; ++i) {\n        int u = -1;\n        long long best = INF;\n        for(int j=0; j<T; ++j) {\n            if(!visited[j] && min_d[j] < best) {\n                best = min_d[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        for(int v=0; v<T; ++v) {\n            if(!visited[v]) {\n                long long d = adj_dist[nodes[u]][nodes[v]];\n                if(d < min_d[v]) {\n                    min_d[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n\n    static bool used_edges_bs[MAX_M];\n    memset(used_edges_bs, 0, sizeof(used_edges_bs));\n\n    // Reconstruct paths\n    for(int i=1; i<T; ++i) {\n        if(parent[i] == -1) continue;\n        int u = nodes[i];\n        int v = nodes[parent[i]];\n        int curr = u;\n        while(curr != v) {\n            int best_nxt = -1;\n            int best_edge_id = -1;\n            // Find the edge on the shortest path\n            for(auto& edge : adj_list[curr]) {\n                int w = edge.to;\n                if(edge.w + adj_dist[w][v] == adj_dist[curr][v]) {\n                    best_nxt = w;\n                    best_edge_id = edge.id;\n                    break;\n                }\n            }\n            if(best_nxt != -1) {\n                used_edges_bs[best_edge_id] = true;\n                curr = best_nxt;\n            } else break;\n        }\n    }\n\n    vector<int> sub_edges;\n    for(int i=0; i<M; ++i) if(used_edges_bs[i]) sub_edges.push_back(i);\n    \n    // Pruning\n    vector<vector<pair<int,int>>> adj(N);\n    vector<int> degree(N, 0);\n    long long current_cost = 0;\n    static bool final_edge_active[MAX_M];\n    memset(final_edge_active, 0, sizeof(final_edge_active));\n    \n    for(int id : sub_edges) {\n        final_edge_active[id] = true;\n        adj[edges[id].u].push_back({edges[id].v, id});\n        adj[edges[id].v].push_back({edges[id].u, id});\n        degree[edges[id].u]++;\n        degree[edges[id].v]++;\n        current_cost += edges[id].w;\n    }\n    \n    static bool is_term[MAX_N];\n    memset(is_term, 0, sizeof(is_term));\n    for(int t : terminals) is_term[t] = true;\n    is_term[0] = true;\n    \n    queue<int> q;\n    for(int i=0; i<N; ++i) {\n        if(degree[i] == 1 && !is_term[i]) q.push(i);\n    }\n    \n    while(!q.empty()) {\n        int u = q.front(); q.pop();\n        for(auto& p : adj[u]) {\n            int v = p.first;\n            int id = p.second;\n            if(final_edge_active[id]) {\n                final_edge_active[id] = false;\n                current_cost -= edges[id].w;\n                degree[u]--;\n                degree[v]--;\n                if(degree[v] == 1 && !is_term[v]) q.push(v);\n            }\n        }\n    }\n    \n    vector<int> out_edges;\n    for(int i=0; i<M; ++i) if(final_edge_active[i]) out_edges.push_back(i);\n    return {current_cost, out_edges};\n}\n\nstruct State {\n    vector<int> assignment; \n    vector<vector<int>> station_radii; // Sorted for efficiency\n    vector<int> active_counts;\n    vector<int> terminals; \n    long long power_cost;\n    long long network_cost;\n    long long total_cost;\n    \n    State() {\n        assignment.resize(MAX_K);\n        station_radii.resize(MAX_N);\n        active_counts.resize(MAX_N, 0);\n        terminals.reserve(MAX_N);\n        power_cost = 0;\n        network_cost = 0;\n        total_cost = 0;\n    }\n\n    void update_terminals() {\n        terminals.clear();\n        for(int i=1; i<N; ++i) if(active_counts[i] > 0) terminals.push_back(i);\n    }\n    \n    void sync_terminals() { update_terminals(); }\n\n    void recalc_network_cost() {\n        update_terminals();\n        static int nodes[MAX_N];\n        int T = 0;\n        for(int t : terminals) nodes[T++] = t;\n        if(active_counts[0] == 0) nodes[T++] = 0; \n        \n        network_cost = calc_mst_proxy(T, nodes);\n        total_cost = power_cost + network_cost;\n    }\n\n    void add_resident(int u, int r) {\n        auto it = lower_bound(station_radii[u].begin(), station_radii[u].end(), r);\n        station_radii[u].insert(it, r);\n    }\n    \n    void remove_resident(int u, int r) {\n        auto it = lower_bound(station_radii[u].begin(), station_radii[u].end(), r);\n        if (it != station_radii[u].end() && *it == r) {\n            station_radii[u].erase(it);\n        }\n    }\n    \n    int get_max_r(int u) const {\n        if(station_radii[u].empty()) return 0;\n        return station_radii[u].back();\n    }\n    \n    int get_second_max_r(int u) const {\n        if(station_radii[u].size() < 2) return 0;\n        return station_radii[u][station_radii[u].size() - 2];\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> K)) return 0;\n    for(int i=0; i<N; ++i) cin >> stations[i].x >> stations[i].y;\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_list[edges[i].u].push_back({edges[i].v, edges[i].w, i});\n        adj_list[edges[i].v].push_back({edges[i].u, edges[i].w, i});\n    }\n    for(int i=0; i<K; ++i) cin >> residents[i].x >> residents[i].y;\n\n    precompute_paths();\n\n    // Filter valid nearby stations\n    for(int k=0; k<K; ++k) {\n        vector<pair<int, int>> dists;\n        for(int i=0; i<N; ++i) {\n            long long sq = distSq(residents[k].x, residents[k].y, stations[i].x, stations[i].y);\n            int P = get_P(sq);\n            if (P <= MAX_P) {\n                dist_res_stat[k][i] = P;\n                dists.push_back({P, i});\n            } else {\n                dist_res_stat[k][i] = MAX_P + 1;\n            }\n        }\n        for(auto& p : dists) nearby_stations[k].push_back(p.second);\n    }\n\n    State cur;\n    // Initial Greedy Assignment\n    for(int k=0; k<K; ++k) {\n        int u = nearby_stations[k][0]; \n        cur.assignment[k] = u;\n        cur.add_resident(u, dist_res_stat[k][u]);\n        cur.active_counts[u]++;\n    }\n    for(int i=0; i<N; ++i) {\n        long long r = cur.get_max_r(i);\n        cur.power_cost += r*r;\n    }\n    cur.recalc_network_cost();\n    \n    State best = cur;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n    double start_temp = 2000000.0; \n    double end_temp = 100.0;\n    \n    static int temp_nodes[MAX_N];\n\n    int iter = 0;\n    while(true) {\n        iter++;\n        if((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n            if(elapsed > time_limit) break;\n        }\n\n        static double temp = start_temp;\n        if ((iter & 4095) == 0) {\n            double progress = chrono::duration_cast<chrono::duration<double>>(chrono::steady_clock::now() - start_time).count() / time_limit;\n            temp = start_temp + (end_temp - start_temp) * progress;\n        }\n\n        // 96% Shift, 4% Clear\n        int move_type = (rng.next_int(100) < 96) ? 0 : 1;\n\n        if (move_type == 0) { // === Shift Move ===\n            int k = rng.next_int(K);\n            int u = cur.assignment[k];\n            int v = -1;\n            \n            // Candidate Selection: Bias towards stations where r <= existing_max (Zero marginal cost)\n            int best_v_zero = -1;\n            int search_lim = min((int)nearby_stations[k].size(), 30);\n            for(int i=0; i<search_lim; ++i) {\n                int cand = nearby_stations[k][i];\n                if(cand != u && cur.active_counts[cand] > 0) {\n                    if(dist_res_stat[k][cand] <= cur.get_max_r(cand)) {\n                        best_v_zero = cand;\n                        break; // First found is likely best/close enough\n                    }\n                    v = cand; \n                }\n            }\n            \n            if(best_v_zero != -1 && rng.next_int(100) < 80) {\n                v = best_v_zero;\n            } else if(v == -1) {\n                int idx = rng.next_int(min((int)nearby_stations[k].size(), 10));\n                v = nearby_stations[k][idx];\n            }\n\n            if(v == -1 || v == u) continue;\n            if(dist_res_stat[k][v] > MAX_P) continue;\n\n            // Calculate Power Delta\n            int r_k_u = dist_res_stat[k][u];\n            int r_max_u = cur.get_max_r(u);\n            long long old_Pu = (long long)r_max_u * r_max_u;\n            long long new_Pu = old_Pu;\n            \n            bool u_empty = (cur.active_counts[u] == 1);\n            if(u_empty) {\n                new_Pu = 0;\n            } else {\n                if(r_k_u == r_max_u) {\n                    int sec = cur.get_second_max_r(u);\n                    new_Pu = (long long)sec * sec;\n                }\n            }\n\n            int r_k_v = dist_res_stat[k][v];\n            int r_max_v = cur.get_max_r(v);\n            long long old_Pv = (long long)r_max_v * r_max_v;\n            long long new_Pv;\n            \n            bool v_active = (cur.active_counts[v] == 0);\n            if(v_active) {\n                new_Pv = (long long)r_k_v * r_k_v;\n            } else {\n                int nm = max(r_max_v, r_k_v);\n                new_Pv = (long long)nm * nm;\n            }\n\n            long long power_delta = (new_Pu - old_Pu) + (new_Pv - old_Pv);\n            long long network_delta = 0;\n\n            if(u_empty || v_active) {\n                int t_idx = 0;\n                for(int t : cur.terminals) {\n                    if(u_empty && t == u) continue;\n                    temp_nodes[t_idx++] = t;\n                }\n                if(v_active && v != 0) temp_nodes[t_idx++] = v;\n                \n                // Ensure 0 is included for calculation\n                bool has_0 = false;\n                for(int i=0; i<t_idx; ++i) if(temp_nodes[i] == 0) has_0 = true;\n                if(!has_0 && cur.active_counts[0] == 0) temp_nodes[t_idx++] = 0;\n                \n                long long new_net = calc_mst_proxy(t_idx, temp_nodes);\n                network_delta = new_net - cur.network_cost;\n            }\n\n            long long total_delta = power_delta + network_delta;\n\n            if(total_delta <= 0 || rng.next_double() < exp(-total_delta/temp)) {\n                cur.assignment[k] = v;\n                cur.remove_resident(u, r_k_u);\n                cur.active_counts[u]--;\n                cur.add_resident(v, r_k_v);\n                cur.active_counts[v]++;\n                \n                cur.power_cost += power_delta;\n                cur.network_cost += network_delta;\n                cur.total_cost += total_delta;\n                if(u_empty || v_active) cur.sync_terminals();\n                \n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n\n        } else { // === Clear Move ===\n            if(cur.terminals.size() <= 1) continue;\n            int idx = rng.next_int(cur.terminals.size());\n            int u = cur.terminals[idx];\n            if(u == 0) continue; \n\n            // Prepare new terminal set (current - u + 0)\n            int t_idx = 0;\n            for(int t : cur.terminals) {\n                if(t != u) temp_nodes[t_idx++] = t;\n            }\n            bool has_0 = false;\n            for(int i=0; i<t_idx; ++i) if(temp_nodes[i] == 0) has_0 = true;\n            if(!has_0) temp_nodes[t_idx++] = 0;\n\n            long long power_delta = -(long long)cur.get_max_r(u) * cur.get_max_r(u);\n            \n            static int new_maxs[MAX_N];\n            static bool touched[MAX_N];\n            for(int i=0; i<t_idx; ++i) {\n                int t = temp_nodes[i];\n                new_maxs[t] = cur.get_max_r(t);\n                touched[t] = false;\n            }\n\n            // Reassign all residents of u to best available target\n            bool feasible = true;\n            vector<pair<int,int>> moves; \n            // Note: Iterating all K is slow, optimization: iterate residents of u if stored.\n            // Given constraints (K=5000), O(K) is acceptable for 4% move rate.\n            for(int k=0; k<K; ++k) {\n                if(cur.assignment[k] == u) {\n                    int best_v = -1;\n                    long long best_inc = INF;\n                    \n                    for(int i=0; i<t_idx; ++i) {\n                        int v = temp_nodes[i];\n                        int r = dist_res_stat[k][v];\n                        if(r > MAX_P) continue;\n                        \n                        long long inc = 0;\n                        if(r > new_maxs[v]) {\n                            inc = (long long)r*r - (long long)new_maxs[v]*new_maxs[v];\n                        }\n                        if(inc < best_inc) {\n                            best_inc = inc;\n                            best_v = v;\n                        }\n                    }\n                    if(best_v == -1) { feasible = false; break; }\n                    moves.push_back({k, best_v});\n                    \n                    if(dist_res_stat[k][best_v] > new_maxs[best_v]) {\n                        new_maxs[best_v] = dist_res_stat[k][best_v];\n                        touched[best_v] = true;\n                    }\n                }\n            }\n\n            if(!feasible) continue;\n\n            long long added_power = 0;\n            for(int i=0; i<t_idx; ++i) {\n                int t = temp_nodes[i];\n                if(touched[t]) {\n                    long long old_r = cur.get_max_r(t);\n                    added_power += ((long long)new_maxs[t]*new_maxs[t] - old_r*old_r);\n                }\n            }\n\n            long long net_delta = calc_mst_proxy(t_idx, temp_nodes) - cur.network_cost;\n            long long total_delta = power_delta + added_power + net_delta;\n\n            if(total_delta <= 0 || rng.next_double() < exp(-total_delta/temp)) {\n                cur.station_radii[u].clear();\n                cur.active_counts[u] = 0;\n                for(auto& mv : moves) {\n                    int k = mv.first;\n                    int v = mv.second;\n                    int r = dist_res_stat[k][v];\n                    cur.assignment[k] = v;\n                    cur.add_resident(v, r);\n                    cur.active_counts[v]++;\n                }\n                cur.power_cost += (power_delta + added_power);\n                cur.network_cost += net_delta;\n                cur.total_cost += total_delta;\n                cur.sync_terminals();\n\n                if(cur.total_cost < best.total_cost) best = cur;\n            }\n        }\n    }\n\n    // Final Output\n    vector<int> final_P(N, 0);\n    vector<int> terminals;\n    for(int i=0; i<N; ++i) {\n        if(best.active_counts[i] > 0) {\n            if(i != 0) terminals.push_back(i);\n            final_P[i] = best.get_max_r(i);\n        }\n    }\n\n    // Hybrid Construction: Pick the best of two heuristics\n    // 1. Takahashi with full root scan\n    auto res1 = takahashi_steiner_full_scan(terminals);\n    // 2. Metric MST + Pruning\n    auto res2 = metric_mst_steiner(terminals);\n    \n    vector<int> final_edges = (res1.first < res2.first) ? res1.second : res2.second;\n\n    vector<bool> edge_active(M, false);\n    for(int id : final_edges) edge_active[id] = true;\n\n    for(int i=0; i<N; ++i) cout << final_P[i] << (i == N-1 ? \"\" : \" \");\n    cout << \"\\n\";\n    for(int i=0; i<M; ++i) cout << (edge_active[i] ? 1 : 0) << (i == M-1 ? \"\" : \" \");\n    cout << \"\\n\";\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cstring>\n#include <cmath>\n#include <climits>\n\nusing namespace std;\n\n// ------------------------------\n// Constants & Configuration\n// ------------------------------\nconst int N = 30;\nconst int TOTAL_BALLS = 465; // N*(N+1)/2\nconst int MAX_OPS = 10000;\nconst int SAMPLE_SIZE = 150;    // Size of violation subset to check per step\nconst double TIME_LIMIT = 1.82; // Time limit in seconds\n\n// ------------------------------\n// Data Structures\n// ------------------------------\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nstruct Weights {\n    int w_val_p;      // Parent Value\n    int w_val_c;      // Child Value\n    int w_row;        // Row Index\n    int w_diff;       // Value Difference\n    int w_tier;       // Target Row Direction\n    int w_col;        // Target Column Proximity\n    int w_down;       // Downward Lookahead\n    int w_up;         // Upward Lookahead\n    int w_noise;      // Random Noise\n};\n\nstruct Violation {\n    int x, y;\n};\n\n// ------------------------------\n// Global State (Static)\n// ------------------------------\nint initial_board[N][N];\nint board[N][N];\nbool in_violation[N][N];\nViolation violations[2000]; // Sufficient buffer for active violations\nint v_count = 0;\n\nMove moves_buffer[MAX_OPS + 200];\nMove best_ops_buffer[MAX_OPS + 200];\nint best_ops_count = MAX_OPS + 1;\n\nint target_row[TOTAL_BALLS];\nint target_col[TOTAL_BALLS];\n\n// ------------------------------\n// Fast Random Number Generator\n// ------------------------------\nstruct FastRNG {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    \n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    \n    inline int next_range(int n) {\n        return next() % n;\n    }\n} fast_rng;\n\n// ------------------------------\n// Helper Functions\n// ------------------------------\ninline int abs_diff(int a, int b) {\n    int d = a - b;\n    return d < 0 ? -d : d;\n}\n\ninline bool is_violation(int x, int y) {\n    if (x >= N - 1) return false;\n    // A node violates if it is larger than either of its children\n    return (board[x][y] > board[x+1][y] || board[x][y] > board[x+1][y+1]);\n}\n\n// ------------------------------\n// Main Solver\n// ------------------------------\nvoid solve(const Weights& w, int limit_k) {\n    // 1. Fast Reset\n    for(int i=0; i<N; ++i) {\n        memcpy(board[i], initial_board[i], (i+1)*sizeof(int));\n        memset(in_violation[i], 0, (i+1)*sizeof(bool));\n    }\n    v_count = 0;\n    int move_count = 0;\n\n    auto add = [&](int x, int y) {\n        if (x < 0 || x >= N - 1 || y < 0 || y > x) return;\n        if (!in_violation[x][y] && is_violation(x, y)) {\n            in_violation[x][y] = true;\n            violations[v_count++] = {x, y};\n        }\n    };\n\n    // 2. Initial Scan\n    for(int x = 0; x < N - 1; ++x) {\n        for(int y = 0; y <= x; ++y) add(x, y);\n    }\n\n    // Pre-load weights into registers/stack\n    const int w_val_p = w.w_val_p;\n    const int w_val_c = w.w_val_c;\n    const int w_row = w.w_row;\n    const int w_diff = w.w_diff;\n    const int w_tier = w.w_tier;\n    const int w_col = w.w_col;\n    const int w_down = w.w_down;\n    const int w_up = w.w_up;\n    const int w_noise = w.w_noise;\n\n    // 3. Greedy Loop\n    while (v_count > 0) {\n        // Pruning: Abort if we've already exceeded the best known solution\n        if (move_count >= limit_k) return;\n\n        int best_idx = -1;\n        int best_score = INT_MIN;\n\n        // Sampling Strategy:\n        // If few violations, check all. If many, check a contiguous subset starting at random offset.\n        // This provides spatial locality (cache friendliness) while ensuring diversity over time.\n        int count_to_check = (v_count <= SAMPLE_SIZE) ? v_count : SAMPLE_SIZE;\n        int start_offset = (v_count <= SAMPLE_SIZE) ? 0 : fast_rng.next_range(v_count);\n\n        for (int k = 0; k < count_to_check; ++k) {\n            int idx = start_offset + k;\n            if (idx >= v_count) idx -= v_count; // Wrap around\n\n            int x = violations[idx].x;\n            int y = violations[idx].y;\n            int p = board[x][y];\n            int l = board[x+1][y];\n            int r = board[x+1][y+1];\n            \n            bool go_left = (l < r);\n            int c = go_left ? l : r;\n            int nx = x + 1;\n            int ny = go_left ? y : y + 1;\n\n            // Calculate Score (using int for speed, max score << INT_MAX)\n            int score = 0;\n            \n            if (w_val_p) score += w_val_p * p;\n            if (w_val_c) score += w_val_c * c;\n            if (w_row)   score += w_row * x;\n            if (w_diff)  score += w_diff * (p - c);\n            \n            if (w_tier) {\n                // Ideally: P moves down if its target is lower (target > x)\n                //          C moves up if its target is higher (target <= x)\n                int p_gain = (target_row[p] > x) ? 1 : -1;\n                int c_gain = (target_row[c] <= x) ? 1 : -1;\n                score += w_tier * (p_gain + c_gain);\n            }\n\n            if (w_col) {\n                // Ideally: minimize horizontal distance to target column\n                int p_tc = target_col[p];\n                int c_tc = target_col[c];\n                int p_imp = abs_diff(p_tc, y) - abs_diff(p_tc, ny);\n                int c_imp = abs_diff(c_tc, ny) - abs_diff(c_tc, y);\n                score += w_col * (p_imp + c_imp);\n            }\n\n            if (w_down) {\n                int vc = 0;\n                if (nx < N - 1) {\n                    if (p > board[nx+1][ny]) vc++;\n                    if (p > board[nx+1][ny+1]) vc++;\n                }\n                score += w_down * vc;\n            }\n\n            if (w_up) {\n                int vc = 0;\n                if (x > 0) {\n                    if (y > 0 && board[x-1][y-1] > c) vc++;\n                    if (y < x && board[x-1][y] > c) vc++;\n                }\n                score += w_up * vc;\n            }\n\n            if (w_noise) {\n                score += w_noise * (int)(fast_rng.next() & 0x3F); // 0-63\n            }\n\n            if (score > best_score) {\n                best_score = score;\n                best_idx = idx;\n            }\n        }\n\n        // 4. Execute Swap\n        int x = violations[best_idx].x;\n        int y = violations[best_idx].y;\n        \n        // Remove violation (swap with last for O(1))\n        in_violation[x][y] = false;\n        violations[best_idx] = violations[--v_count];\n\n        // Verify validity\n        if (!is_violation(x, y)) continue;\n\n        int l = board[x+1][y];\n        int r = board[x+1][y+1];\n        bool go_left = (l < r);\n        int nx = x + 1;\n        int ny = go_left ? y : y + 1;\n\n        // Perform Swap\n        int tmp = board[x][y];\n        board[x][y] = board[nx][ny];\n        board[nx][ny] = tmp;\n\n        moves_buffer[move_count++] = {x, y, nx, ny};\n\n        // 5. Update active violations\n        // Check parents of original position (x,y)\n        if (x > 0) {\n            if (y < x) add(x-1, y);\n            if (y > 0) add(x-1, y-1);\n        }\n        // Check new position (nx,ny) and its children\n        add(nx, ny);\n    }\n\n    // 6. Update Global Best\n    if (move_count < best_ops_count) {\n        best_ops_count = move_count;\n        for(int i=0; i<move_count; ++i) best_ops_buffer[i] = moves_buffer[i];\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    // Precompute Ideal Targets\n    int cnt = 0;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<=i; ++j) {\n            if (cnt < TOTAL_BALLS) {\n                target_row[cnt] = i;\n                target_col[cnt] = j;\n                cnt++;\n            }\n        }\n    }\n\n    // Input\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j <= i; ++j) {\n            cin >> initial_board[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    mt19937 rng(12345);\n    uniform_int_distribution<int> dist(-100, 100);\n    uniform_int_distribution<int> dist_noise(-20, 20);\n\n    // Seed Strategies (Hand-tuned + Found by previous runs)\n    vector<Weights> strategies = {\n        {0, 0, 0, 0, 100, 0, -50, -50, 0},      // Tier focus\n        {0, 0, 0, 0, 100, 20, -50, -50, 0},     // Tier+Col\n        {10, 0, 0, 10, 50, 0, -20, -20, 0},     // Mixed Value\n        {0, 0, 0, 0, 0, 0, -100, -100, 0},      // Safety\n        {0, 0, 20, 0, 80, 0, -40, -40, 10}      // Row+Tier\n    };\n\n    // Baseline Runs\n    for(const auto& w : strategies) {\n        solve(w, best_ops_count);\n    }\n\n    Weights best_w = strategies[0];\n    \n    // Genetic / Hill Climbing Loop\n    int iter = 0;\n    while (true) {\n        iter++;\n        // Time Check (every 16 iters ~ negligible overhead)\n        if ((iter & 15) == 0) {\n            auto now = chrono::high_resolution_clock::now();\n            if (chrono::duration<double>(now - start_time).count() > TIME_LIMIT) break;\n        }\n\n        Weights w;\n        int roll = rng() % 100;\n        \n        if (roll < 50) {\n            // 50%: Mutate Best (Exploitation)\n            w = best_w;\n            if (rng()%2) w.w_val_p += dist_noise(rng);\n            if (rng()%2) w.w_val_c += dist_noise(rng);\n            if (rng()%2) w.w_row   += dist_noise(rng);\n            if (rng()%2) w.w_diff  += dist_noise(rng);\n            if (rng()%2) w.w_tier  += dist_noise(rng);\n            if (rng()%2) w.w_col   += dist_noise(rng);\n            if (rng()%2) w.w_down  += dist_noise(rng);\n            if (rng()%2) w.w_up    += dist_noise(rng);\n            w.w_noise = abs(w.w_noise + dist_noise(rng));\n        } else if (roll < 80) {\n            // 30%: Mutate Seed Strategy (Exploration)\n            w = strategies[rng() % strategies.size()];\n            w.w_val_p += dist_noise(rng);\n            w.w_tier += dist_noise(rng);\n            w.w_noise = abs(w.w_noise + dist_noise(rng));\n        } else {\n            // 20%: Random Restart\n            w.w_val_p = dist(rng);\n            w.w_val_c = dist(rng);\n            w.w_row   = dist(rng);\n            w.w_diff  = dist(rng);\n            w.w_tier  = dist(rng);\n            w.w_col   = dist(rng);\n            w.w_down  = dist(rng);\n            w.w_up    = dist(rng);\n            w.w_noise = abs(dist(rng));\n        }\n\n        int prev_k = best_ops_count;\n        solve(w, best_ops_count);\n        \n        if (best_ops_count < prev_k) {\n            best_w = w;\n        }\n    }\n\n    // Output\n    cout << best_ops_count << \"\\n\";\n    for (int i = 0; i < best_ops_count; ++i) {\n        cout << best_ops_buffer[i].x1 << \" \" << best_ops_buffer[i].y1 << \" \" \n             << best_ops_buffer[i].x2 << \" \" << best_ops_buffer[i].y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <bitset>\n#include <array>\n\nusing namespace std;\n\n// Constants\nconst int D = 9;\nconst int TOTAL_CELLS = 81;\n\n// Heuristics Weights\n// Tuned for enforcing depth sorting while preserving topology\nconst double W_DIST = 45.0; \nconst double W_NEIGH_MIN = 4.0;\nconst double W_NEIGH_MAX = 22.0;\nconst double W_IMP_MIN = 8.0;\nconst double W_IMP_MAX = 20.0;\n\n// Globals\nint N;\nint grid_fixed[D][D]; // 0: empty, 1: obstacle\nint dist_map[D][D];\nint visited_token[D][D];\nint bfs_token = 0;\n\n// Precomputed Adjacency List for fast BFS\n// Stores indices 0..80\nint adj[TOTAL_CELLS][4];\nint adj_deg[TOTAL_CELLS];\n\nstruct Point {\n    int r, c;\n};\n\nconst int dr[] = {0, 0, 1, -1};\nconst int dc[] = {1, -1, 0, 0};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D;\n}\n\n// Initialize adjacency list avoiding obstacles and bounds\nvoid init_adjacency() {\n    for(int r=0; r<D; ++r) {\n        for(int c=0; c<D; ++c) {\n            int u = r*D + c;\n            int deg = 0;\n            if(grid_fixed[r][c] == 0) { // Only valid cells have neighbors\n                for(int k=0; k<4; ++k) {\n                    int nr = r + dr[k];\n                    int nc = c + dc[k];\n                    if(is_valid(nr, nc) && grid_fixed[nr][nc] == 0) {\n                        adj[u][deg++] = nr*D + nc;\n                    }\n                }\n            }\n            adj_deg[u] = deg;\n        }\n    }\n}\n\n// Fast BFS for distance and connectivity analysis (Placement Phase)\n// Returns {count, sum_dist} of reachable empty cells\npair<int, int> bfs_analysis(const int grid[D][D]) {\n    bfs_token++;\n    visited_token[0][4] = bfs_token;\n    dist_map[0][4] = 0;\n    \n    static Point q[TOTAL_CELLS];\n    int head = 0, tail = 0;\n    q[tail++] = {0, 4};\n    \n    int count = 0;\n    int sum = 0;\n    \n    while(head < tail) {\n        Point p = q[head++];\n        int d = dist_map[p.r][p.c];\n        \n        for(int i=0; i<4; ++i) {\n            int nr = p.r + dr[i];\n            int nc = p.c + dc[i];\n            \n            if(is_valid(nr, nc) && visited_token[nr][nc] != bfs_token && grid[nr][nc] == 0) {\n                visited_token[nr][nc] = bfs_token;\n                dist_map[nr][nc] = d + 1;\n                q[tail++] = {nr, nc};\n                \n                if(nr != 0 || nc != 4) {\n                    count++;\n                    sum += (d + 1);\n                }\n            }\n        }\n    }\n    return {count, sum};\n}\n\nint grid_place[D][D];\n\nstruct BeamNode {\n    bitset<TOTAL_CELLS> removed_mask;\n    int cost;\n    int parent_idx; \n    int move_id;    \n};\n\nvector<vector<BeamNode>> beam_layers;\nbitset<TOTAL_CELLS> smaller_than[TOTAL_CELLS];\n\nvoid solve_retrieval(int K, const vector<int>& pos_to_id, const vector<Point>& id_to_pos) {\n    // Precompute bitsets for O(1) cost calculation\n    for(int i=0; i<TOTAL_CELLS; ++i) {\n        smaller_than[i].reset();\n        if(pos_to_id[i] == -1) continue;\n        for(int j=0; j<TOTAL_CELLS; ++j) {\n            if(pos_to_id[j] != -1 && pos_to_id[j] < pos_to_id[i]) {\n                smaller_than[i].set(j);\n            }\n        }\n    }\n\n    // Beam Width reduced to avoid TLE\n    int BEAM_WIDTH = 12500; \n    \n    beam_layers.clear();\n    beam_layers.reserve(K + 1);\n    \n    beam_layers.push_back({});\n    beam_layers[0].reserve(BEAM_WIDTH);\n    beam_layers[0].push_back({bitset<TOTAL_CELLS>(), 0, -1, -1});\n    \n    struct Candidate {\n        int parent_idx;\n        int move_id;\n        int new_cost;\n        bitset<TOTAL_CELLS> mask;\n    };\n    \n    static vector<Candidate> candidates;\n    candidates.reserve(BEAM_WIDTH * 6);\n    \n    // Buffers for BFS inside retrieval\n    static int q[TOTAL_CELLS];\n    static int reachable_ids[TOTAL_CELLS];\n    \n    // Use bitset for visited to avoid clearing large arrays\n    // or use token. Token is fast for small array.\n    // Let's use token with flattened array to match adjacency list.\n    static int visited_flat[TOTAL_CELLS];\n    static int bfs_retrieval_token = 0;\n    \n    for(int step = 0; step < K; ++step) {\n        vector<BeamNode>& current_beam = beam_layers[step];\n        candidates.clear();\n        \n        if(current_beam.empty()) break;\n\n        for(int i=0; i < (int)current_beam.size(); ++i) {\n            const auto& node = current_beam[i];\n            \n            // Optimized BFS using Adjacency List\n            bfs_retrieval_token++;\n            int start_node = 4; // (0,4)\n            visited_flat[start_node] = bfs_retrieval_token;\n            int head = 0, tail = 0;\n            q[tail++] = start_node;\n            \n            int r_count = 0;\n            \n            while(head < tail) {\n                int u = q[head++];\n                \n                // Iterate precomputed neighbors\n                int deg = adj_deg[u];\n                for(int k=0; k<deg; ++k) {\n                    int v = adj[u][k];\n                    \n                    if(visited_flat[v] == bfs_retrieval_token) continue;\n                    \n                    int id = pos_to_id[v];\n                    bool is_removed = (id != -1) && node.removed_mask[v];\n                    bool is_empty_slot = (id == -1);\n                    \n                    visited_flat[v] = bfs_retrieval_token;\n                    \n                    if(id != -1 && !is_removed) {\n                        // Reachable container (blocker)\n                        reachable_ids[r_count++] = v; \n                    } else if(is_empty_slot || is_removed) {\n                        // Passable\n                        q[tail++] = v;\n                    }\n                }\n            }\n            \n            // Generate candidates\n            for(int k=0; k<r_count; ++k) {\n                int idx = reachable_ids[k];\n                int rid = pos_to_id[idx];\n                \n                // Cost: count of smaller items NOT removed\n                int cost_inc = (smaller_than[idx] & (~node.removed_mask)).count();\n                \n                Candidate cand;\n                cand.parent_idx = i;\n                cand.move_id = rid;\n                cand.new_cost = node.cost + cost_inc;\n                cand.mask = node.removed_mask;\n                cand.mask.set(idx);\n                \n                candidates.push_back(cand);\n            }\n        }\n        \n        if(candidates.empty()) break;\n\n        // Sort candidates\n        sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.new_cost < b.new_cost;\n        });\n        \n        beam_layers.push_back({});\n        auto& next_layer = beam_layers.back();\n        next_layer.reserve(BEAM_WIDTH);\n        \n        int taken = 0;\n        for(const auto& cand : candidates) {\n            if(taken >= BEAM_WIDTH) break;\n            \n            // Dedup\n            if(taken > 0) {\n                const auto& prev = next_layer.back();\n                if(prev.cost == cand.new_cost && prev.removed_mask == cand.mask) continue;\n            }\n            \n            next_layer.push_back({cand.mask, cand.new_cost, cand.parent_idx, cand.move_id});\n            taken++;\n        }\n    }\n    \n    // Reconstruct\n    if(beam_layers.size() <= K) return; \n    \n    const auto& last_layer = beam_layers[K];\n    int best_idx = 0;\n    int min_cost = 2e9;\n    for(int i=0; i<(int)last_layer.size(); ++i) {\n        if(last_layer[i].cost < min_cost) {\n            min_cost = last_layer[i].cost;\n            best_idx = i;\n        }\n    }\n    \n    vector<int> removal_order;\n    removal_order.reserve(K);\n    int curr_idx = best_idx;\n    for(int layer = K; layer > 0; --layer) {\n        const auto& node = beam_layers[layer][curr_idx];\n        removal_order.push_back(node.move_id);\n        curr_idx = node.parent_idx;\n    }\n    reverse(removal_order.begin(), removal_order.end());\n    \n    for(int id : removal_order) {\n        Point p = id_to_pos[id];\n        cout << p.r << \" \" << p.c << \"\\n\";\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int d_in;\n    if (!(cin >> d_in)) return 0;\n    cin >> N;\n    \n    for(int r=0; r<D; ++r) {\n        for(int c=0; c<D; ++c) {\n            grid_fixed[r][c] = 0;\n            grid_place[r][c] = 0;\n            visited_token[r][c] = 0;\n        }\n    }\n    \n    for(int i=0; i<N; ++i){\n        int r, c;\n        cin >> r >> c;\n        grid_fixed[r][c] = 1;\n        grid_place[r][c] = 1;\n    }\n    \n    // Init Adjacency List\n    init_adjacency();\n    \n    int K = D*D - 1 - N;\n    vector<bool> id_seen(D*D, false);\n    vector<int> pos_to_id(TOTAL_CELLS, -1);\n    vector<Point> id_to_pos(D*D);\n    \n    vector<Point> candidates; candidates.reserve(TOTAL_CELLS);\n    vector<int> cand_dists; cand_dists.reserve(TOTAL_CELLS);\n    vector<int> all_dists; all_dists.reserve(TOTAL_CELLS);\n\n    for(int step=0; step<K; ++step){\n        int t;\n        cin >> t;\n        \n        int rem_count = 0;\n        int rank_t = 0;\n        for(int i=0; i<K; ++i){\n            if(!id_seen[i] || i == t) {\n                rem_count++;\n                if(i < t) rank_t++;\n            }\n        }\n        id_seen[t] = true;\n        double P = (rem_count > 1) ? (double)rank_t / (rem_count - 1) : 0.5;\n        \n        pair<int, int> state = bfs_analysis(grid_place);\n        int reachable_cnt = state.first;\n        int current_sum_dist = state.second;\n        \n        candidates.clear();\n        cand_dists.clear();\n        all_dists.clear();\n        \n        for(int r=0; r<D; ++r){\n            for(int c=0; c<D; ++c){\n                if(grid_place[r][c] == 0 && (r!=0 || c!=4)){\n                    if(visited_token[r][c] == bfs_token) {\n                        int d = dist_map[r][c];\n                        candidates.push_back({r, c});\n                        cand_dists.push_back(d);\n                        all_dists.push_back(d);\n                    }\n                }\n            }\n        }\n        \n        sort(all_dists.begin(), all_dists.end());\n        double target_dist = 0;\n        if(!all_dists.empty()) {\n            target_dist = all_dists[(int)round(P * (all_dists.size()-1))];\n        }\n        \n        double best_score = -1e18;\n        Point best_p = candidates[0]; \n        bool found = false;\n        \n        double w_neigh = W_NEIGH_MIN + (W_NEIGH_MAX - W_NEIGH_MIN) * P;\n        double w_imp = W_IMP_MIN + (W_IMP_MAX - W_IMP_MIN) * P;\n\n        for(size_t i=0; i<candidates.size(); ++i) {\n            Point p = candidates[i];\n            int d = cand_dists[i];\n            \n            grid_place[p.r][p.c] = 2;\n            pair<int, int> res = bfs_analysis(grid_place);\n            grid_place[p.r][p.c] = 0;\n            \n            if(res.first != reachable_cnt - 1) continue; \n            found = true;\n            \n            double dist_err = (d - target_dist) * (d - target_dist);\n            \n            int expected_new_sum = current_sum_dist - d;\n            int impact = res.second - expected_new_sum;\n            if(impact < 0) impact = 0;\n            \n            // Use adj list for neighbor counting? \n            // Since grid_place changes, adj list (based on grid_fixed) is only static.\n            // Can use adj list but check grid_place for occupancy.\n            int u = p.r * D + p.c;\n            int empty_neighbors = 0;\n            int deg = adj_deg[u];\n            for(int k=0; k<deg; ++k) {\n                int v = adj[u][k];\n                int vr = v/D, vc = v%D;\n                if(grid_place[vr][vc] == 0 && v != 4) empty_neighbors++;\n            }\n            \n            double score = -W_DIST * dist_err - w_neigh * empty_neighbors - w_imp * impact;\n            \n            if(score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        \n        if(!found && !candidates.empty()) best_p = candidates[0];\n        \n        cout << best_p.r << \" \" << best_p.c << endl;\n        grid_place[best_p.r][best_p.c] = 2; \n        pos_to_id[best_p.r * D + best_p.c] = t;\n        id_to_pos[t] = best_p;\n    }\n    \n    solve_retrieval(K, pos_to_id, id_to_pos);\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <random>\n#include <chrono>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\nconst int TIME_LIMIT_MS = 1950;\n\nint grid[N][N];\nint best_grid[N][N];\nint current_score = 0;\nint best_score = 0;\n\n// Adjacency: Symmetric matrix tracking shared edge segments between colors\nint adj_count[M + 1][M + 1];\nbool is_required[M + 1][M + 1];\n\n// Directions: 0:Up, 1:Down, 2:Left, 3:Right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\n// BFS Structures\nint visited[N][N];\nint visited_token = 0;\nint q_r[N * N];\nint q_c[N * N];\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n} rng;\n\n// Global connectivity check\n// Verifies if the removal of (rem_r, rem_c) disconnects the region of 'color'.\nbool check_global_connectivity(int rem_r, int rem_c, int color) {\n    visited_token++;\n    \n    int neighbors_r[4], neighbors_c[4];\n    int k = 0;\n    \n    for (int i = 0; i < 4; ++i) {\n        int nr = rem_r + dr[i];\n        int nc = rem_c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) {\n                neighbors_r[k] = nr; neighbors_c[k] = nc; k++;\n            }\n        }\n    }\n\n    if (k == 0) return true; \n\n    if (color != 0) {\n        // For non-zero color, verify all neighbors belong to the same component\n        int head = 0, tail = 0;\n        q_r[tail] = neighbors_r[0]; q_c[tail] = neighbors_c[0]; tail++;\n        visited[neighbors_r[0]][neighbors_c[0]] = visited_token;\n        \n        int found_neighbors = 1;\n        while(head < tail) {\n            int r = q_r[head++]; int c = q_c[head-1];\n            for(int i=0; i<4; ++i) {\n                int nr = r + dr[i]; int nc = c + dc[i];\n                if(is_valid(nr, nc) && grid[nr][nc] == color && visited[nr][nc] != visited_token) {\n                    if(nr == rem_r && nc == rem_c) continue;\n                    visited[nr][nc] = visited_token;\n                    q_r[tail] = nr; q_c[tail] = nc; tail++;\n                    if (abs(nr - rem_r) + abs(nc - rem_c) == 1) found_neighbors++;\n                }\n            }\n        }\n        return found_neighbors == k;\n    } else {\n        // For color 0, verify every neighbor component can reach the boundary\n        for(int j=0; j<k; ++j) {\n            if(visited[neighbors_r[j]][neighbors_c[j]] == visited_token) continue;\n            \n            // BFS Init\n            int head = 0, tail = 0;\n            q_r[tail] = neighbors_r[j]; q_c[tail] = neighbors_c[j]; tail++;\n            visited[neighbors_r[j]][neighbors_c[j]] = visited_token;\n            \n            bool reached_boundary = false;\n            if (neighbors_r[j] == 0 || neighbors_r[j] == N-1 || neighbors_c[j] == 0 || neighbors_c[j] == N-1) \n                reached_boundary = true;\n            \n            while(head < tail) {\n                int r = q_r[head++]; int c = q_c[head-1];\n                \n                for(int i=0; i<4; ++i) {\n                    int nr = r + dr[i]; int nc = c + dc[i];\n                    \n                    if (!is_valid(nr, nc)) { reached_boundary = true; continue; }\n                    if (nr == rem_r && nc == rem_c) continue;\n                    \n                    if (grid[nr][nc] == 0 && visited[nr][nc] != visited_token) {\n                        visited[nr][nc] = visited_token;\n                        q_r[tail] = nr; q_c[tail] = nc; tail++;\n                        if (!reached_boundary) {\n                            if (nr == 0 || nr == N-1 || nc == 0 || nc == N-1) reached_boundary = true;\n                        }\n                    }\n                }\n            }\n            if (!reached_boundary) return false;\n        }\n        return true;\n    }\n}\n\n// Optimized Local Check (3x3 Window)\nbool check_local_connectivity(int r, int c, int color) {\n    int n_idx[4], k = 0;\n    for(int i=0; i<4; ++i) {\n        int nr = r + dr[i]; int nc = c + dc[i];\n        if (is_valid(nr, nc)) {\n            if (grid[nr][nc] == color) n_idx[k++] = i;\n        } else if (color == 0) {\n            n_idx[k++] = i;\n        }\n    }\n    \n    if (k <= 1) return true;\n\n    // Union-Find to check connectivity of neighbors via diagonals\n    int p[4] = {0, 1, 2, 3};\n    \n    // Check 4 diagonals (Up-Left, Up-Right, Down-Left, Down-Right)\n    // Neighbor indices: 0:Up, 1:Down, 2:Left, 3:Right\n    \n    // Mapping from neighbor direction to index in n_idx array\n    int map_dir[4]; memset(map_dir, -1, sizeof(map_dir));\n    for(int i=0; i<k; ++i) map_dir[n_idx[i]] = i;\n    \n    // Union logic\n    auto unite = [&](int a, int b) {\n        int ra = a; while(ra != p[ra]) ra = p[ra];\n        int rb = b; while(rb != p[rb]) rb = p[rb];\n        if (ra != rb) p[ra] = rb;\n    };\n    \n    auto check_diag = [&](int dir1, int dir2, int dr_off, int dc_off) {\n        if (map_dir[dir1] != -1 && map_dir[dir2] != -1) {\n            int nr = r + dr_off, nc = c + dc_off;\n            bool ok = false;\n            if (is_valid(nr, nc)) { if(grid[nr][nc] == color) ok = true; }\n            else if (color == 0) ok = true;\n            if (ok) unite(map_dir[dir1], map_dir[dir2]);\n        }\n    };\n    \n    check_diag(0, 2, -1, -1); // Up-Left\n    check_diag(0, 3, -1, 1);  // Up-Right\n    check_diag(1, 2, 1, -1);  // Down-Left\n    check_diag(1, 3, 1, 1);   // Down-Right\n\n    int root = 0; while(root != p[root]) root = p[root];\n    for(int i=1; i<k; ++i) {\n        int ri = i; while(ri != p[ri]) ri = p[ri];\n        if (ri != root) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    int n_in, m_in;\n    if (!(cin >> n_in >> m_in)) return 0;\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            cin >> grid[i][j];\n            best_grid[i][j] = grid[i][j];\n            if(grid[i][j] == 0) current_score++;\n        }\n    }\n    best_score = current_score;\n\n    // Init Adjacency\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            int u = grid[i][j];\n            for(int k=0; k<4; ++k) {\n                int nr = i + dr[k]; int nc = j + dc[k];\n                int v = 0; if (is_valid(nr, nc)) v = grid[nr][nc];\n                if (u != v) adj_count[u][v]++;\n            }\n        }\n    }\n    for(int i=1; i<=M; ++i) adj_count[0][i] = adj_count[i][0];\n\n    for(int i=0; i<=M; ++i) for(int j=0; j<=M; ++j) if(adj_count[i][j] > 0) is_required[i][j] = true;\n\n    auto start_time = chrono::steady_clock::now();\n    double start_temp = 2.0; \n    double end_temp = 0.0;\n    \n    int change_u[16], change_v[16], change_val[16];\n    int iter = 0;\n\n    while(true) {\n        iter++;\n        if ((iter & 0x3FF) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            if (elapsed > TIME_LIMIT_MS) break;\n        }\n\n        int r = rng.next_int(N);\n        int c = rng.next_int(N);\n        int current_color = grid[r][c];\n\n        // Pick a random neighbor to potentially copy\n        int k = rng.next_int(4);\n        int nr = r + dr[k];\n        int nc = c + dc[k];\n        int target_color = 0;\n        if (is_valid(nr, nc)) target_color = grid[nr][nc];\n\n        if (current_color == target_color) continue;\n\n        int score_diff = 0;\n        if (current_color == 0) score_diff--;\n        if (target_color == 0) score_diff++;\n\n        if (score_diff < 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double, milli>(now - start_time).count();\n            double temp = start_temp + (end_temp - start_temp) * (elapsed / TIME_LIMIT_MS);\n            if (rng.next_double() > exp(score_diff / temp)) continue;\n        }\n\n        // Calculate Adjacency Changes\n        int num_changes = 0;\n        \n        for(int i=0; i<4; ++i) {\n            int nnr = r + dr[i]; int nnc = c + dc[i];\n            int n_col = 0; if (is_valid(nnr, nnc)) n_col = grid[nnr][nnc];\n            \n            if (n_col != current_color) {\n                int u = current_color, v = n_col;\n                if (u > v) swap(u, v);\n                bool found = false;\n                for(int j=0; j<num_changes; ++j) {\n                    if (change_u[j] == u && change_v[j] == v) { change_val[j]--; found = true; break; }\n                }\n                if (!found) { change_u[num_changes] = u; change_v[num_changes] = v; change_val[num_changes] = -1; num_changes++; }\n            }\n            \n            if (n_col != target_color) {\n                int u = target_color, v = n_col;\n                if (u > v) swap(u, v);\n                bool found = false;\n                for(int j=0; j<num_changes; ++j) {\n                    if (change_u[j] == u && change_v[j] == v) { change_val[j]++; found = true; break; }\n                }\n                if (!found) { change_u[num_changes] = u; change_v[num_changes] = v; change_val[num_changes] = 1; num_changes++; }\n            }\n        }\n\n        // Validate Adjacency\n        bool adj_ok = true;\n        for(int i=0; i<num_changes; ++i) {\n            int u = change_u[i]; int v = change_v[i];\n            int final = adj_count[u][v] + change_val[i];\n            if (is_required[u][v]) {\n                if (final <= 0) { adj_ok = false; break; }\n            } else {\n                if (final > 0) { adj_ok = false; break; }\n            }\n        }\n        if (!adj_ok) continue;\n\n        // Validate Connectivity\n        if (!check_local_connectivity(r, c, current_color)) {\n            if (!check_global_connectivity(r, c, current_color)) continue;\n        }\n\n        // Apply\n        for(int i=0; i<num_changes; ++i) {\n            int u = change_u[i]; int v = change_v[i];\n            int val = change_val[i];\n            adj_count[u][v] += val;\n            adj_count[v][u] += val;\n        }\n        \n        grid[r][c] = target_color;\n        current_score += score_diff;\n        \n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) memcpy(best_grid[i], grid[i], N * sizeof(int));\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) cout << best_grid[i][j] << (j==N-1 ? \"\" : \" \");\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <cassert>\n\nusing namespace std;\n\n// Global variables\nint N, D, Q;\nint query_count = 0;\nvector<vector<int>> memo; // Memoization for item comparisons\n\n// Perform a query: Output L size, R size, then elements of L and R\nvoid ask(const vector<int>& L, const vector<int>& R) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    query_count++;\n}\n\n// Read the judge's response\nint get_response() {\n    string res;\n    cin >> res;\n    if (res == \"<\") return 1;\n    if (res == \">\") return -1;\n    if (res == \"=\") return 2;\n    return 0; \n}\n\n// Pad remaining queries with dummy operations to meet the exact Q requirement\nvoid pad_queries() {\n    while (query_count < Q) {\n        // Compare item 0 and item 1. They are always valid indices (N >= 30).\n        // This consumes a query without changing state.\n        ask({0}, {1});\n        get_response(); \n    }\n}\n\n// Compare items a and b using the balance scale.\n// Returns 1 if a < b, -1 if a > b, 0 if a == b.\n// Uses memoization to avoid redundant queries.\nint compare_items(int a, int b) {\n    if (a == b) return 0;\n    if (memo[a][b] != 0) return (memo[a][b] == 2 ? 0 : memo[a][b]);\n\n    ask({a}, {b});\n    int res = get_response();\n    \n    if (res == 1) {\n        memo[a][b] = 1;\n        memo[b][a] = -1;\n        return 1;\n    } else if (res == -1) {\n        memo[a][b] = -1;\n        memo[b][a] = 1;\n        return -1;\n    } else {\n        memo[a][b] = 2;\n        memo[b][a] = 2;\n        return 0;\n    }\n}\n\n// Compute expected values of order statistics for the Exponential Distribution\nvector<double> compute_expected_weights(int n) {\n    vector<double> w(n);\n    double current = 0;\n    for (int i = 0; i < n; ++i) {\n        current += 1.0 / (n - i);\n        w[i] = current;\n    }\n    return w;\n}\n\n// Isotonic Regression (Pool Adjacent Violators Algorithm)\n// Fits data to be monotonically non-decreasing minimizing MSE.\nvector<double> isotonic_regression(const vector<double>& y) {\n    vector<pair<double, double>> stack; \n    for (double val : y) {\n        double current_val = val;\n        double current_w = 1.0;\n        while (!stack.empty() && stack.back().first >= current_val) {\n            double prev_val = stack.back().first;\n            double prev_w = stack.back().second;\n            stack.pop_back();\n            current_val = (prev_val * prev_w + current_val * current_w) / (prev_w + current_w);\n            current_w += prev_w;\n        }\n        stack.push_back({current_val, current_w});\n    }\n    vector<double> res;\n    for (auto p : stack) {\n        for (int i = 0; i < (int)p.second; ++i) res.push_back(p.first);\n    }\n    return res;\n}\n\nint main() {\n    // IO setup\n    ios_base::sync_with_stdio(false);\n    if (!(cin >> N >> D >> Q)) return 0;\n\n    memo.assign(N, vector<int>(N, 0));\n    srand(123); \n\n    // Determine budget for initial sorting.\n    // We reserve queries for the refinement phase (sorting sets + adjusting).\n    // Sorting D sets takes approx D * log2(D) queries. We want a few rounds.\n    // Maximize sort budget but ensure we can do at least some refinement.\n    int refinement_budget = max(Q / 4, min(Q / 2, D * D * 2));\n    int sort_budget = Q - refinement_budget;\n    if (sort_budget < 0) sort_budget = 0;\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n\n    // 1. Sort items (partially if budget is tight)\n    // We use stable_sort. If we hit the query limit, we stop comparing, \n    // effectively leaving the remaining items in their original relative order.\n    try {\n        stable_sort(p.begin(), p.end(), [&](int a, int b) {\n            if (query_count >= sort_budget) return false; \n            int res = compare_items(a, b);\n            return res == 1; // a < b\n        });\n    } catch(...) {}\n\n    // 2. Assign Expected Weights based on rank\n    vector<double> exp_w_sorted = compute_expected_weights(N);\n    vector<double> item_w(N);\n    // The item at p[i] is the i-th smallest found.\n    for (int i = 0; i < N; ++i) {\n        item_w[p[i]] = exp_w_sorted[i];\n    }\n\n    // 3. Greedy Partitioning (Largest Items First)\n    // This heuristic generally works well for minimizing variance.\n    vector<int> p_desc = p;\n    reverse(p_desc.begin(), p_desc.end());\n\n    vector<vector<int>> sets(D);\n    vector<double> set_sums(D, 0.0);\n\n    for (int idx : p_desc) {\n        int best_s = -1;\n        double min_sum = 1e18;\n        for (int s = 0; s < D; ++s) {\n            if (set_sums[s] < min_sum) {\n                min_sum = set_sums[s];\n                best_s = s;\n            }\n        }\n        sets[best_s].push_back(idx);\n        set_sums[best_s] += item_w[idx];\n    }\n\n    // 4. Local Search (In Silico)\n    // Optimize the partition using the estimated weights before spending more queries.\n    int ls_iter = 0;\n    while (ls_iter < 20000) {\n        ls_iter++;\n        int s1 = rand() % D;\n        int s2 = rand() % D;\n        if (s1 == s2) continue;\n        if (sets[s1].empty()) continue;\n\n        int type = (sets[s2].empty() ? 0 : rand() % 2);\n        int idx1 = rand() % sets[s1].size();\n        int u = sets[s1][idx1];\n\n        if (type == 0) { // Move u from s1 to s2\n            double new_s1 = set_sums[s1] - item_w[u];\n            double new_s2 = set_sums[s2] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n            \n            if (new_sq < old_sq) {\n                sets[s1].erase(sets[s1].begin() + idx1);\n                sets[s2].push_back(u);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        } else { // Swap u (from s1) with v (from s2)\n            int idx2 = rand() % sets[s2].size();\n            int v = sets[s2][idx2];\n            \n            double new_s1 = set_sums[s1] - item_w[u] + item_w[v];\n            double new_s2 = set_sums[s2] - item_w[v] + item_w[u];\n            \n            double old_sq = set_sums[s1]*set_sums[s1] + set_sums[s2]*set_sums[s2];\n            double new_sq = new_s1*new_s1 + new_s2*new_s2;\n\n            if (new_sq < old_sq) {\n                swap(sets[s1][idx1], sets[s2][idx2]);\n                set_sums[s1] = new_s1;\n                set_sums[s2] = new_s2;\n            }\n        }\n    }\n\n    // 5. Refinement Phase with Physical Queries\n    // We sort the sets by weight using the scale, then update our belief (estimates)\n    // using Isotonic Regression, and finally try to balance the extremes.\n    while (true) {\n        // Check if we have enough queries to perform a set sort.\n        int needed = D * log2(D) + 2;\n        if (query_count + needed > Q) break;\n\n        // 5.1 Sort sets physically\n        vector<int> set_indices(D);\n        iota(set_indices.begin(), set_indices.end(), 0);\n        \n        bool possible = true;\n        stable_sort(set_indices.begin(), set_indices.end(), [&](int a, int b){\n            if (query_count >= Q) { possible = false; return false; }\n            ask(sets[a], sets[b]);\n            int res = get_response();\n            return res == 1; // a < b\n        });\n        if (!possible) break;\n\n        // 5.2 Correct estimates\n        // We extract the current estimates in the physical sorted order\n        vector<double> sorted_estimates;\n        for (int idx : set_indices) sorted_estimates.push_back(set_sums[idx]);\n        \n        // Apply PAVA to enforce monotonicity\n        vector<double> pav_res = isotonic_regression(sorted_estimates);\n        \n        // Slightly perturb to enforce strict inequality where PAVA flattens,\n        // to encourage movement.\n        for (int i = 1; i < D; ++i) {\n            if (pav_res[i] <= pav_res[i-1] + 1e-9) {\n                pav_res[i] = pav_res[i-1] + 1e-5;\n            }\n        }\n        // Update set_sums\n        for (int i = 0; i < D; ++i) set_sums[set_indices[i]] = pav_res[i];\n\n        // 5.3 Balance Heaviest and Lightest\n        int light_idx = set_indices[0];\n        int heavy_idx = set_indices.back();\n\n        double diff = set_sums[heavy_idx] - set_sums[light_idx];\n        if (diff < 1e-5) break; // Already balanced within estimate precision\n\n        double target = diff / 2.0; // Amount to transfer from Heavy to Light\n        int best_type = -1;\n        int best_u_idx = -1, best_v_idx = -1;\n        double min_err = 1e18;\n\n        // Try Move\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            int u = sets[heavy_idx][i];\n            double err = abs(item_w[u] - target);\n            if (err < min_err) {\n                min_err = err;\n                best_type = 0;\n                best_u_idx = i;\n            }\n        }\n        // Try Swap\n        for (int i = 0; i < (int)sets[heavy_idx].size(); ++i) {\n            for (int j = 0; j < (int)sets[light_idx].size(); ++j) {\n                int u = sets[heavy_idx][i];\n                int v = sets[light_idx][j];\n                double delta = item_w[u] - item_w[v];\n                if (delta <= 0) continue; // Must move mass from heavy to light\n                double err = abs(delta - target);\n                if (err < min_err) {\n                    min_err = err;\n                    best_type = 1;\n                    best_u_idx = i;\n                    best_v_idx = j;\n                }\n            }\n        }\n\n        // Apply best operation\n        if (best_type == 0) {\n            int u = sets[heavy_idx][best_u_idx];\n            sets[heavy_idx].erase(sets[heavy_idx].begin() + best_u_idx);\n            sets[light_idx].push_back(u);\n            set_sums[heavy_idx] -= item_w[u];\n            set_sums[light_idx] += item_w[u];\n        } else if (best_type == 1) {\n            int u = sets[heavy_idx][best_u_idx];\n            int v = sets[light_idx][best_v_idx];\n            swap(sets[heavy_idx][best_u_idx], sets[light_idx][best_v_idx]);\n            set_sums[heavy_idx] -= item_w[u] - item_w[v];\n            set_sums[light_idx] += item_w[u] - item_w[v];\n        } else {\n            break; // Cannot find a move/swap that matches target\n        }\n    }\n\n    // Ensure exactly Q queries are performed\n    pad_queries();\n\n    // Output final assignment\n    vector<int> ans(N);\n    for (int i = 0; i < D; ++i) {\n        for (int x : sets[i]) ans[x] = i;\n    }\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"/**\n * Highly Optimized Heuristic Solution for \"Stack of Boxes\" using Incremental Beam Search.\n * \n * Key Features & Improvements:\n * 1. Beam Search Optimization: \n *    - Reduced Beam Width to 50 to strictly satisfy the Time Limit.\n *    - Uses a custom `FixedVec` struct to minimize dynamic allocation overhead and ensure cache locality.\n *    - Fast state copying (~4KB per state via memcpy) enables efficient search.\n * \n * 2. Incremental Heuristic:\n *    - State evaluation is updated incrementally (O(StackHeight)) rather than fully recalculated.\n *    - Heuristic terms tuned for immediate impact (Energy) vs long-term structure (Bad Links, Urgency).\n * \n * 3. Heuristic Logic:\n *    - **Bad Link Penalty**: Heavily penalizes blocking \"urgent\" boxes (needed soon).\n *    - **Good Link Bonus**: Rewards placing smaller boxes on larger ones to maintain sorted order.\n *    - **Empty Stack Management**: Conserves empty stacks but uses them for large base values.\n *    - **Buried Urgency**: Discourages piling boxes onto stacks that contain deeply buried urgent items.\n * \n * 4. Search Constraints:\n *    - Only considers moving \"internally sorted\" chunks. This drastically reduces the branching factor\n *      and keeps stacks orderly.\n * \n * Complexity:\n * - Fits well within 2.0s with Beam Width = 50 and N = 200.\n */\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// --- Constants & Tuning ---\nconst int MAX_OPS = 5000;\nconst int BEAM_WIDTH = 50;   // Tuned for performance/score trade-off\nconst int MAX_DEPTH = 60;    // Safety limit for search depth\n\n// Heuristic Weights\nconst double W_ENERGY = 1.0;\nconst double W_BAD_LINK_BASE = 100.0;\nconst double W_BAD_LINK_URGENCY = 2500.0; \nconst double W_GAP = 1.0;                 \nconst double W_BURIED = 300.0;            \nconst double W_EMPTY_STACK = 500.0;       \nconst double W_EMPTY_VAL_FACTOR = 2.0;    \nconst double W_HEIGHT_SQR = 0.2; \n\nstruct Move {\n    short v; \n    short i; \n};\n\n// Optimized fixed-size vector to replace std::vector in tight loops\ntemplate<typename T, int Cap>\nstruct FixedVec {\n    T data[Cap];\n    int sz = 0;\n    \n    FixedVec() : sz(0) {}\n    \n    inline void push_back(T v) { data[sz++] = v; }\n    inline void pop_back() { sz--; }\n    inline T back() const { return data[sz-1]; }\n    inline bool empty() const { return sz == 0; }\n    inline int size() const { return sz; }\n    inline T operator[](int i) const { return data[i]; }\n    inline void resize(int n) { sz = n; }\n    inline void clear() { sz = 0; }\n    \n    // Fast bulk append\n    inline void append(const T* ptr, int count) {\n        if (count > 0) {\n            memcpy(data + sz, ptr, count * sizeof(T));\n            sz += count;\n        }\n    }\n};\n\n// State representation (approx 4KB)\nstruct State {\n    FixedVec<short, 200> stacks[10]; \n    double g_cost; \n    double h_val; \n    FixedVec<Move, 65> history; \n    int op_count;\n    \n    bool operator>(const State& other) const {\n        return (g_cost + h_val) > (other.g_cost + other.h_val);\n    }\n};\n\nint N, M;\nint global_ops = 0;\nvector<Move> global_result;\n\n// Calculate heuristic score for a single stack\ndouble get_stack_score(const FixedVec<short, 200>& s, int current_target) {\n    if (s.empty()) return 0.0;\n    \n    double score = 0.0;\n    int h = s.size();\n    \n    // Quadratic height penalty to keep stacks balanced\n    score += (double)(h * h) * W_HEIGHT_SQR;\n    \n    // Reward using empty stack for large base value\n    score -= (double)s[0] * W_EMPTY_VAL_FACTOR;\n\n    // Link Analysis\n    for (int i = 0; i < h - 1; ++i) {\n        int below = s[i];\n        int above = s[i+1];\n        \n        if (above > below) {\n            // Bad Link: Larger on Smaller\n            int dist = below - current_target;\n            if (dist < 1) dist = 1;\n            double urgency = 1.0 / (double)dist;\n            score += W_BAD_LINK_BASE + W_BAD_LINK_URGENCY * urgency;\n        } else {\n            // Good Link: Smaller on Larger\n            score += (double)(below - above) * W_GAP;\n        }\n    }\n    \n    // Buried Urgency\n    for (int i = 0; i < h; ++i) {\n        int val = s[i];\n        if (val >= current_target) {\n            int dist = val - current_target;\n            if (dist < 25) { \n                 double urgency = 1.0 / (double)(dist + 1);\n                 int height_above = h - 1 - i;\n                 score += height_above * W_BURIED * urgency;\n            }\n        }\n    }\n    \n    return score;\n}\n\n// Calculate total heuristic from scratch\ndouble calculate_full_heuristic(const State& s, int current_target) {\n    double score = 0;\n    int empty_count = 0;\n    for(int i=0; i<M; ++i) {\n        if(s.stacks[i].empty()) empty_count++;\n        else score += get_stack_score(s.stacks[i], current_target);\n    }\n    score += (M - empty_count) * W_EMPTY_STACK;\n    return score;\n}\n\n// Find position of box v\npair<int, int> get_pos(const State& s, int v) {\n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<s.stacks[i].size(); ++j) {\n            if(s.stacks[i][j] == v) return {i, j};\n        }\n    }\n    return {-1, -1};\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    State current_state;\n    current_state.g_cost = 0;\n    current_state.op_count = 0;\n    \n    for(int i=0; i<M; ++i) {\n        for(int j=0; j<N/M; ++j) {\n            int val; cin >> val;\n            current_state.stacks[i].push_back((short)val);\n        }\n    }\n\n    current_state.h_val = calculate_full_heuristic(current_state, 1);\n\n    for (int target = 1; target <= N; ++target) {\n        if (global_ops >= MAX_OPS) break;\n\n        while (true) {\n            pair<int, int> loc = get_pos(current_state, target);\n            int src = loc.first;\n            int idx = loc.second;\n\n            // If target is already at the top, carry it out\n            if (idx == current_state.stacks[src].size() - 1) {\n                global_result.push_back({(short)target, 0});\n                current_state.stacks[src].pop_back();\n                global_ops++;\n                \n                // Update heuristic for the next target\n                current_state.h_val = calculate_full_heuristic(current_state, target + 1);\n                break;\n            }\n            \n            // --- Beam Search Start ---\n            priority_queue<State, vector<State>, greater<State>> beam;\n            \n            State start = current_state;\n            start.history.clear();\n            start.g_cost = 0;\n            // h_val is kept\n            \n            beam.push(start);\n            \n            State best_state;\n            bool solved = false;\n            double best_f = 1e18;\n            \n            int depth = 0;\n            while(!beam.empty() && depth < MAX_DEPTH) {\n                // Collect best nodes for this level\n                vector<State> level;\n                level.reserve(BEAM_WIDTH);\n                int cnt = 0;\n                while(!beam.empty() && cnt < BEAM_WIDTH) {\n                    level.push_back(beam.top());\n                    beam.pop();\n                    cnt++;\n                }\n                \n                priority_queue<State, vector<State>, greater<State>> next_beam;\n                \n                for(const auto& s : level) {\n                    pair<int, int> sloc = get_pos(s, target);\n                    int s_src = sloc.first;\n                    int s_idx = sloc.second;\n                    \n                    // Check if target is exposed\n                    if(s_idx == s.stacks[s_src].size() - 1) {\n                        double f = s.g_cost + s.h_val;\n                        if(f < best_f) {\n                            best_f = f;\n                            best_state = s;\n                            solved = true;\n                        }\n                        continue;\n                    }\n                    \n                    // Pruning\n                    if(solved && (s.g_cost + s.h_val >= best_f)) continue;\n                    \n                    // Move Generation: Only from source stack\n                    int top = s.stacks[s_src].size() - 1;\n                    \n                    // Identify sorted chunks [sorted_start ... top]\n                    int sorted_start = top;\n                    while(sorted_start > s_idx + 1) {\n                        if(s.stacks[s_src][sorted_start-1] > s.stacks[s_src][sorted_start]) sorted_start--;\n                        else break;\n                    }\n                    \n                    // Cache source stack score before modification\n                    double score_src_old = get_stack_score(s.stacks[s_src], target);\n                    bool src_was_empty = s.stacks[s_src].empty();\n\n                    // Try all valid chunks\n                    for(int k = sorted_start; k <= top; ++k) {\n                        int chunk_sz = top - k + 1;\n                        double energy = chunk_sz + 1.0;\n                        short moved_v = s.stacks[s_src][k];\n                        \n                        for(int dst = 0; dst < M; ++dst) {\n                            if(dst == s_src) continue;\n                            \n                            State next_s = s;\n                            \n                            double score_dst_old = get_stack_score(next_s.stacks[dst], target);\n                            bool dst_was_empty = next_s.stacks[dst].empty();\n                            \n                            // Execute Move\n                            next_s.stacks[dst].append(&next_s.stacks[s_src].data[k], chunk_sz);\n                            next_s.stacks[s_src].resize(k);\n                            \n                            // Incremental Heuristic Update\n                            double h_new = next_s.h_val;\n                            h_new -= score_src_old;\n                            h_new -= score_dst_old;\n                            h_new += get_stack_score(next_s.stacks[s_src], target);\n                            h_new += get_stack_score(next_s.stacks[dst], target);\n                            \n                            // Update Empty Stack Penalties\n                            if(!src_was_empty && next_s.stacks[s_src].empty()) h_new -= W_EMPTY_STACK;\n                            if(dst_was_empty && !next_s.stacks[dst].empty()) h_new += W_EMPTY_STACK;\n                            \n                            next_s.h_val = h_new;\n                            next_s.g_cost += energy * W_ENERGY;\n                            next_s.history.push_back({moved_v, (short)(dst + 1)});\n                            next_s.op_count++;\n                            \n                            if(next_s.op_count <= MAX_OPS) {\n                                next_beam.push(next_s);\n                            }\n                        }\n                    }\n                }\n                beam = move(next_beam);\n                depth++;\n                if(solved && beam.empty()) break;\n            }\n            \n            if (solved) {\n                // Apply best sequence found\n                for(int i=0; i<best_state.history.size(); ++i) {\n                    global_result.push_back(best_state.history[i]);\n                }\n                current_state = best_state;\n                current_state.history.clear();\n                global_ops = current_state.op_count;\n            } else {\n                // Fallback: Greedy move if search fails or depth exceeded\n                int top = current_state.stacks[src].size() - 1;\n                int k = top;\n                // Greedy Logic: Pick best sorted chunk available\n                while(k > idx + 1 && current_state.stacks[src][k-1] > current_state.stacks[src][k]) k--;\n                \n                short moved_v = current_state.stacks[src][k];\n                int chunk_sz = top - k + 1;\n\n                int best_dst = -1;\n                double best_h = 1e18;\n                \n                // Evaluate all destinations for this greedy move\n                for(int dst=0; dst<M; ++dst) {\n                    if(dst == src) continue;\n                    State tmp = current_state;\n                    tmp.stacks[dst].append(&tmp.stacks[src].data[k], chunk_sz);\n                    tmp.stacks[src].resize(k);\n                    double h = calculate_full_heuristic(tmp, target);\n                    if(h < best_h) { best_h = h; best_dst = dst; }\n                }\n                \n                // Execute Fallback Move\n                current_state.stacks[best_dst].append(&current_state.stacks[src].data[k], chunk_sz);\n                current_state.stacks[src].resize(k);\n                global_result.push_back({moved_v, (short)(best_dst+1)});\n                global_ops++;\n                current_state.op_count++;\n                current_state.h_val = best_h;\n            }\n            \n            if(global_ops >= MAX_OPS) break;\n        }\n    }\n    \n    for(const auto& m : global_result) {\n        cout << m.v << \" \" << m.i << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n#include <cstring>\n\nusing namespace std;\n\n// Use float for heuristic calculations for speed (SIMD friendly)\n// The loss of precision compared to double is negligible for the heuristic ordering\ntypedef float Real;\n\n// Timer struct to manage execution time within 2.0s\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    Timer() { reset(); }\n    void reset() { start = chrono::high_resolution_clock::now(); }\n    double elapsed() {\n        auto end = chrono::high_resolution_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(end - start).count() / 1000.0;\n    }\n};\n\nint N;\nvector<int> D_vals; \nvector<Real> D_gen; // Weighted D for generation heuristic\nvector<int> dist_mat_flat; \n\nconst char dc_char[] = {'U', 'D', 'L', 'R'};\n\n// Precomputed adjacency table for O(1) neighbor lookup\n// Max N=40, so nodes <= 1600. \nint adj[1600][4];\nconst int INF = 1e9;\n\n// Read input and initialize graph adjacency\nvoid init_graph() {\n    if (!(cin >> N)) return;\n    vector<string> h_walls(N-1), v_walls(N);\n    for(int i=0; i<N-1; ++i) cin >> h_walls[i];\n    for(int i=0; i<N; ++i) cin >> v_walls[i];\n    \n    int num_nodes = N*N;\n    D_vals.resize(num_nodes);\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) cin >> D_vals[i*N + j];\n\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            int u = r*N + c;\n            if(r > 0 && h_walls[r-1][c] == '0') adj[u][0] = (r-1)*N + c; else adj[u][0] = -1;\n            if(r < N-1 && h_walls[r][c] == '0') adj[u][1] = (r+1)*N + c; else adj[u][1] = -1;\n            if(c > 0 && v_walls[r][c-1] == '0') adj[u][2] = r*N + (c-1); else adj[u][2] = -1;\n            if(c < N-1 && v_walls[r][c] == '0') adj[u][3] = r*N + (c+1); else adj[u][3] = -1;\n        }\n    }\n}\n\n// Compute All-Pairs Shortest Paths (BFS) and store in a flat array for cache efficiency\nvoid compute_apsp() {\n    int num_nodes = N * N;\n    dist_mat_flat.assign(num_nodes * num_nodes, INF);\n    static vector<int> q_vec(num_nodes);\n    static vector<int> d_local(num_nodes);\n    \n    for (int u = 0; u < num_nodes; ++u) {\n        fill(d_local.begin(), d_local.end(), INF);\n        int head = 0, tail = 0;\n        q_vec[tail++] = u;\n        d_local[u] = 0;\n        dist_mat_flat[u * num_nodes + u] = 0;\n        \n        while(head < tail){\n            int curr = q_vec[head++];\n            int d_c = d_local[curr];\n            dist_mat_flat[u * num_nodes + curr] = d_c;\n            \n            for(int k=0; k<4; ++k){\n                int v = adj[curr][k];\n                if(v != -1 && d_local[v] == INF){\n                    d_local[v] = d_c + 1;\n                    q_vec[tail++] = v;\n                }\n            }\n        }\n    }\n}\n\n// Helper: Reconstruct path string from u to v using BFS distances\nstring get_path_string(int u, int v) {\n    string res = \"\";\n    int curr = u;\n    int num_nodes = N * N;\n    while (curr != v) {\n        int best_next = -1;\n        int best_dist = INF;\n        for(int k=0; k<4; ++k) {\n            int next_node = adj[curr][k];\n            if(next_node != -1) {\n                int d = dist_mat_flat[next_node * num_nodes + v]; \n                if (d < best_dist) {\n                    best_dist = d;\n                    best_next = next_node;\n                }\n            }\n        }\n        if(best_next == curr - N) res += 'U';\n        else if(best_next == curr + N) res += 'D';\n        else if(best_next == curr - 1) res += 'L';\n        else res += 'R';\n        curr = best_next;\n    }\n    return res;\n}\n\n// Calculate the exact objective function score for a valid cycle\nlong long calculate_score_cycle(const string& path) {\n    if (path.empty()) return 2e18;\n    long long L = path.length();\n    int num_nodes = N * N;\n    vector<vector<int>> visits(num_nodes);\n    int r = 0, c = 0;\n    visits[0].push_back(0);\n    \n    for(int t=1; t<=L; ++t){\n        char m = path[t-1];\n        if(m=='U') r--; else if(m=='D') r++; else if(m=='L') c--; else if(m=='R') c++;\n        visits[r*N + c].push_back(t);\n    }\n    \n    double total_sum = 0;\n    for(int u=0; u<num_nodes; ++u){\n        if(visits[u].empty()) return 2e18; \n        long long s_sq = 0;\n        for(size_t i=0; i<visits[u].size()-1; ++i){\n            long long diff = visits[u][i+1] - visits[u][i];\n            s_sq += diff * (diff - 1);\n        }\n        long long diff = (visits[u][0] + L) - visits[u].back();\n        s_sq += diff * (diff - 1);\n        total_sum += (double)D_vals[u] * s_sq;\n    }\n    return (long long)round(total_sum / (2.0 * L));\n}\n\n// Ensure the path visits all nodes and returns to (0,0).\n// Uses greedy nearest-neighbor insertion for missing nodes.\nstring validate_and_fix(string path) {\n    int num_nodes = N * N;\n    vector<bool> visited(num_nodes, false);\n    visited[0] = true;\n    int r = 0, c = 0;\n    for(char m : path) {\n        if(m=='U') r--; else if(m=='D') r++; else if(m=='L') c--; else if(m=='R') c++;\n        visited[r*N + c] = true;\n    }\n    int curr = r*N + c;\n    vector<int> unvisited;\n    for(int i=0; i<num_nodes; ++i) if(!visited[i]) unvisited.push_back(i);\n    \n    if(unvisited.empty()) {\n        if(curr != 0) path += get_path_string(curr, 0);\n        return path;\n    }\n    \n    while(!unvisited.empty()) {\n        int best_idx = -1;\n        int min_dist = INF;\n        for(int i=0; i<unvisited.size(); ++i) {\n            int target = unvisited[i];\n            int d = dist_mat_flat[curr * num_nodes + target];\n            if(d < min_dist) {\n                min_dist = d;\n                best_idx = i;\n            }\n        }\n        int target = unvisited[best_idx];\n        string sub = get_path_string(curr, target);\n        path += sub;\n        for(char m : sub) {\n            if(m=='U') r--; else if(m=='D') r++; else if(m=='L') c--; else if(m=='R') c++;\n            int u = r*N + c;\n            for(int k=0; k<unvisited.size(); ++k) {\n                if(unvisited[k] == u) {\n                    unvisited.erase(unvisited.begin() + k);\n                    k--;\n                }\n            }\n        }\n        curr = target;\n    }\n    if(curr != 0) path += get_path_string(curr, 0);\n    return path;\n}\n\nint main() {\n    Timer timer;\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    init_graph();\n    compute_apsp();\n\n    int num_nodes = N*N;\n    vector<Real> W(num_nodes * num_nodes);\n    vector<Real> pow_lookup(2 * num_nodes + 5);\n\n    long long best_score = -1;\n    string best_path = \"\";\n    \n    struct Params {\n        double k_dist;\n        double tabu_val;\n        double noise;\n        double init_val;\n        double d_pow;\n        int length;\n        int tabu_len;\n    };\n    \n    mt19937 rng(123);\n    vector<Params> param_list;\n    \n    // Seed with known high-performing parameter sets\n    param_list.push_back({2.0, 10.0, 1e-4, -3000.0, 1.0, 40000, 1});\n    param_list.push_back({2.0, 10.0, 1e-4, -3000.0, 1.0, 40000, 2});\n    param_list.push_back({2.5, 10.0, 1e-4, -4000.0, 1.0, 45000, 1});\n    param_list.push_back({1.5, 20.0, 1e-4, -2500.0, 1.05, 50000, 2});\n    param_list.push_back({3.0, 5.0, 1e-4, -2000.0, 0.95, 35000, 1});\n    \n    // Fill the rest with random parameters to explore the search space\n    for(int i=0; i<300; ++i) {\n        uniform_real_distribution<double> dist_k(0.6, 4.5);\n        uniform_real_distribution<double> dist_tabu(0.0, 150.0);\n        uniform_real_distribution<double> dist_noise(1e-5, 0.5);\n        uniform_real_distribution<double> dist_init(-6000.0, -1000.0);\n        uniform_real_distribution<double> dist_dpow(0.9, 1.1);\n        uniform_int_distribution<int> dist_len(20000, 60000);\n        uniform_int_distribution<int> dist_tabulen(1, 3);\n        param_list.push_back({dist_k(rng), dist_tabu(rng), dist_noise(rng), dist_init(rng), dist_dpow(rng), dist_len(rng), dist_tabulen(rng)});\n    }\n\n    // Reused vectors for simulation to avoid reallocation\n    vector<Real> static_score(num_nodes);\n    vector<Real> dynamic_score(num_nodes);\n    vector<int> last_visit(num_nodes);\n    vector<bool> visited_map(num_nodes);\n    vector<int> tabu_list(10, -1); \n\n    // Generate a fallback valid solution using DFS\n    {\n        string dfs_path = \"\";\n        vector<bool> vis(num_nodes, false);\n        auto dfs = [&](auto&& self, int u) -> void {\n            vis[u] = true;\n            for(int k=0; k<4; ++k) {\n                int v = adj[u][k];\n                if(v != -1 && !vis[v]) {\n                    dfs_path += dc_char[k];\n                    self(self, v);\n                    if(k==0) dfs_path += 'D'; else if(k==1) dfs_path += 'U'; else if(k==2) dfs_path += 'R'; else dfs_path += 'L';\n                }\n            }\n        };\n        dfs(dfs, 0);\n        best_path = validate_and_fix(dfs_path);\n        best_score = calculate_score_cycle(best_path);\n    }\n\n    int p_idx = 0;\n    D_gen.resize(num_nodes);\n    \n    // Main loop: Random Restarts with Randomized Greedy\n    while(timer.elapsed() < 1.85) {\n        Params p;\n        if(p_idx < param_list.size()) p = param_list[p_idx++];\n        else {\n            // Default fallback\n            uniform_real_distribution<double> dist_k(0.5, 5.0);\n            p = {dist_k(rng), 0.0, 0.1, -3000.0, 1.0, 40000, 1}; \n        }\n\n        int TARGET_LEN = p.length;\n        int TABU_SIZE = p.tabu_len;\n        \n        // Set up weighted dirtiness for generation heuristic\n        if(abs(p.d_pow - 1.0) < 1e-3) {\n            for(int i=0; i<num_nodes; ++i) D_gen[i] = (Real)D_vals[i];\n        } else {\n            for(int i=0; i<num_nodes; ++i) D_gen[i] = pow((Real)D_vals[i], (Real)p.d_pow);\n        }\n\n        // Precompute Gravity Weights\n        for(int d=0; d<pow_lookup.size(); ++d) pow_lookup[d] = 1.0f / pow(1.0 + d, p.k_dist);\n        for(int i=0; i<num_nodes * num_nodes; ++i) {\n            int dist = dist_mat_flat[i];\n            W[i] = (dist == INF) ? 0.0f : pow_lookup[dist];\n        }\n        \n        // Initialize Static Scores: potential attraction of node v\n        for(int v=0; v<num_nodes; ++v) {\n            Real s = 0;\n            const Real* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) s += D_gen[u] * w_row[u];\n            static_score[v] = s;\n        }\n        \n        // Initialize State\n        int init_val = (int)p.init_val;\n        fill(last_visit.begin(), last_visit.end(), init_val);\n        last_visit[0] = 0; \n        \n        for(int v=0; v<num_nodes; ++v) {\n            Real d = 0;\n            const Real* w_row = &W[v * num_nodes];\n            for(int u=0; u<num_nodes; ++u) d += D_gen[u] * last_visit[u] * w_row[u];\n            dynamic_score[v] = d;\n        }\n\n        fill(visited_map.begin(), visited_map.end(), false);\n        visited_map[0] = true;\n        int visited_count = 1;\n        \n        fill(tabu_list.begin(), tabu_list.end(), -1);\n        int tabu_head = 0;\n\n        string path;\n        path.reserve(TARGET_LEN + 1000);\n        int curr = 0;\n        uniform_real_distribution<Real> noise_dist(0.0, 1.0);\n        bool early_exit = false;\n\n        for(int t=1; t<=TARGET_LEN; ++t) {\n            // Periodically check time limit\n            if((t & 1023) == 0 && timer.elapsed() > 1.95) {\n                early_exit = true; \n                break;\n            }\n            \n            int best_next = -1;\n            int dist_to_home = dist_mat_flat[curr * num_nodes + 0];\n            bool must_return = (t + dist_to_home >= TARGET_LEN);\n            \n            Real max_val = -1e18;\n            for(int k=0; k<4; ++k) {\n                int next_node = adj[curr][k];\n                if(next_node != -1) {\n                    // If forced to return, only consider moves that reduce distance\n                    if(must_return) {\n                        int d = dist_mat_flat[next_node * num_nodes + 0];\n                        if(d >= dist_to_home) continue; \n                    }\n                    \n                    // Heuristic Score = t * Static - Dynamic\n                    Real val = (Real)t * static_score[next_node] - dynamic_score[next_node];\n                    \n                    if(!must_return) {\n                         bool is_tabu = false;\n                         for(int ti=0; ti<TABU_SIZE; ++ti) if(tabu_list[ti] == next_node) is_tabu = true;\n                         if(is_tabu) val -= p.tabu_val;\n                         val += noise_dist(rng) * p.noise;\n                    }\n                    \n                    if(val > max_val) {\n                        max_val = val;\n                        best_next = next_node;\n                    }\n                }\n            }\n            \n            if(best_next == -1) break; \n            \n            // Append move\n            if(best_next == curr - N) path += 'U';\n            else if(best_next == curr + N) path += 'D';\n            else if(best_next == curr - 1) path += 'L';\n            else path += 'R';\n            \n            // Update Tabu\n            tabu_list[tabu_head] = curr; \n            tabu_head = (tabu_head + 1) % TABU_SIZE;\n\n            // Efficient Score Update (Bottleneck)\n            long long old_last = last_visit[best_next];\n            Real update_factor = D_gen[best_next] * (t - old_last);\n            const Real* w_vec = &W[best_next * num_nodes];\n            \n            // Manual Unrolling for speed\n            int v=0;\n            for(; v<=num_nodes-8; v+=8) {\n                dynamic_score[v]   += update_factor * w_vec[v];\n                dynamic_score[v+1] += update_factor * w_vec[v+1];\n                dynamic_score[v+2] += update_factor * w_vec[v+2];\n                dynamic_score[v+3] += update_factor * w_vec[v+3];\n                dynamic_score[v+4] += update_factor * w_vec[v+4];\n                dynamic_score[v+5] += update_factor * w_vec[v+5];\n                dynamic_score[v+6] += update_factor * w_vec[v+6];\n                dynamic_score[v+7] += update_factor * w_vec[v+7];\n            }\n            for(; v<num_nodes; ++v) dynamic_score[v] += update_factor * w_vec[v];\n            \n            last_visit[best_next] = t;\n            curr = best_next;\n            \n            if(!visited_map[curr]) {\n                visited_map[curr] = true;\n                visited_count++;\n            }\n\n            // Opportunistic Evaluation:\n            // If we returned to start and visited everyone, it's a valid cycle.\n            if(curr == 0 && visited_count == num_nodes && t > num_nodes) {\n                long long sc = calculate_score_cycle(path);\n                if(sc < best_score) {\n                    best_score = sc;\n                    best_path = path;\n                }\n            }\n            \n            if(curr == 0 && must_return) break;\n        }\n        \n        // Final check\n        if(!early_exit && curr == 0 && !path.empty()) {\n            string valid_path = validate_and_fix(path);\n            if(valid_path.length() <= 100000) {\n                long long sc = calculate_score_cycle(valid_path);\n                if(sc < best_score) {\n                    best_score = sc;\n                    best_path = valid_path;\n                }\n            }\n        }\n    }\n    \n    cout << best_path << endl;\n    return 0;\n}","ahc028":"/**\n * Solution for AtCoder Heuristic Contest 028\n * \n * Algorithm:\n * 1. Preprocessing:\n *    - Map character positions on grid.\n *    - Compute Overlaps between all pairs of strings t_k.\n *    - Compute ATSP (Asymmetric TSP) Heuristic Matrix:\n *      dist_matrix[i][j] = cost to type the extension of t_j immediately after t_i.\n *      This cost is minimized over all valid physical end positions of t_i to provide a tight lower bound.\n * \n * 2. Phase 1: Initialization (GRASP)\n *    - Run multiple Randomized Greedy constructions using the heuristic matrix.\n *    - Select the best initial solution.\n * \n * 3. Phase 2: Heuristic Simulated Annealing\n *    - Optimize the permutation of strings using the ATSP Heuristic cost.\n *    - O(1) delta updates allow high iteration count.\n *    - Periodically synchronize with the Exact Cost (calculated via DP) to update the global best.\n * \n * 4. Phase 3: Exact Cost Local Search\n *    - In the remaining time, perform a Randomized Local Search (Hill Climbing) using the EXACT cost function.\n *    - Moves: Swap, Insert, Short Reversal.\n *    - This phase refines the solution by considering the actual global path constraints that the heuristic might miss.\n * \n * 5. Output the reconstructed path of the best found permutation.\n */\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <cstring>\n\nusing namespace std;\n\n// -------------------- Constants & Globals --------------------\nint N, M;\nint start_r, start_c;\nvector<string> A;\nvector<string> T;\nvector<pair<int, int>> char_positions[26];\n\n// overlaps[i][j] = length of suffix of T[i] matching prefix of T[j]\nint overlaps[205][205];\n\n// ATSP Distance Matrix (Heuristic)\nint dist_matrix[205][205];\nint start_dist[205];\n\n// Global Best\nvector<int> global_best_p;\nint global_min_exact_cost = INT_MAX;\n\nmt19937 rng(12345);\n\n// -------------------- Helper Functions --------------------\ninline int c2i(char c) { return c - 'A'; }\ninline int dist(int r1, int c1, int r2, int c2) { return abs(r1 - r2) + abs(c1 - c2); }\n\nint calc_overlap(const string& s1, const string& s2) {\n    for (int len = 4; len >= 1; --len) {\n        bool match = true;\n        for (int k = 0; k < len; ++k) {\n            if (s1[5 - len + k] != s2[k]) {\n                match = false;\n                break;\n            }\n        }\n        if (match) return len;\n    }\n    return 0;\n}\n\n// Precompute heuristic cost: Min cost to type s starting from any of start_coords\nint calc_segment_cost_heuristic(const vector<pair<int,int>>& start_coords, const string& s) {\n    if (s.empty()) return 0;\n    int L = s.size();\n    vector<int> dp_prev(start_coords.size());\n    \n    // Initialize first char cost\n    int c0 = c2i(s[0]);\n    const auto& pos0 = char_positions[c0];\n    vector<int> next_dp(pos0.size());\n    \n    for(size_t j=0; j<pos0.size(); ++j) {\n        int min_d = 1000000;\n        for(const auto& sp : start_coords) {\n            int d = dist(sp.first, sp.second, pos0[j].first, pos0[j].second) + 1;\n            if(d < min_d) min_d = d;\n        }\n        next_dp[j] = min_d;\n    }\n    dp_prev = next_dp;\n    \n    // Iterate rest of string\n    for(int i=1; i<L; ++i) {\n        int cc = c2i(s[i]);\n        const auto& cpos = char_positions[cc];\n        const auto& ppos = char_positions[c2i(s[i-1])];\n        vector<int> curr_dp(cpos.size());\n        for(size_t j=0; j<cpos.size(); ++j) {\n            int min_val = 1000000;\n            for(size_t k=0; k<ppos.size(); ++k) {\n                int val = dp_prev[k] + dist(ppos[k].first, ppos[k].second, cpos[j].first, cpos[j].second) + 1;\n                if(val < min_val) min_val = val;\n            }\n            curr_dp[j] = min_val;\n        }\n        dp_prev = curr_dp;\n    }\n    int ans = 1000000;\n    for(int v : dp_prev) if(v < ans) ans = v;\n    return ans;\n}\n\n// Optimized Exact Cost Calculation using DP\n// Uses static arrays to minimize overhead\nint get_exact_cost(const vector<int>& p) {\n    static int dp_prev[300];\n    static int dp_curr[300];\n    \n    // Init with start position -> First char of first string\n    int s0_idx = p[0];\n    int c0 = c2i(T[s0_idx][0]);\n    const auto* pos0 = &char_positions[c0];\n    int sz0 = pos0->size();\n    \n    for(int j=0; j<sz0; ++j) {\n        dp_prev[j] = dist(start_r, start_c, (*pos0)[j].first, (*pos0)[j].second) + 1;\n    }\n    \n    int prev_c = c0;\n    int prev_sz = sz0;\n    const vector<pair<int,int>>* prev_pos_ptr = pos0;\n    \n    // Helper lambda or macro not needed, simplified loop\n    // Iterate through the logical sequence\n    \n    // 1. Rest of first string\n    for(int k=1; k<5; ++k) {\n        int cc = c2i(T[s0_idx][k]);\n        const auto& cpos = char_positions[cc];\n        int sz_curr = cpos.size();\n        \n        for(int j=0; j<sz_curr; ++j) {\n            int r = cpos[j].first;\n            int c = cpos[j].second;\n            int min_val = 100000000;\n            for(int m=0; m<prev_sz; ++m) {\n                int d = dist((*prev_pos_ptr)[m].first, (*prev_pos_ptr)[m].second, r, c);\n                int total = dp_prev[m] + d + 1;\n                if(total < min_val) min_val = total;\n            }\n            dp_curr[j] = min_val;\n        }\n        for(int j=0; j<sz_curr; ++j) dp_prev[j] = dp_curr[j];\n        prev_c = cc;\n        prev_sz = sz_curr;\n        prev_pos_ptr = &cpos;\n    }\n    \n    // 2. Rest of the strings (extensions only)\n    for(size_t i=1; i<p.size(); ++i) {\n        int u = p[i-1];\n        int v = p[i];\n        int ov = overlaps[u][v];\n        const string& t = T[v];\n        \n        for(int k=ov; k<5; ++k) {\n            int cc = c2i(t[k]);\n            const auto& cpos = char_positions[cc];\n            int sz_curr = cpos.size();\n            \n            for(int j=0; j<sz_curr; ++j) {\n                int r = cpos[j].first;\n                int c = cpos[j].second;\n                int min_val = 100000000;\n                for(int m=0; m<prev_sz; ++m) {\n                    int d = dist((*prev_pos_ptr)[m].first, (*prev_pos_ptr)[m].second, r, c);\n                    int total = dp_prev[m] + d + 1;\n                    if(total < min_val) min_val = total;\n                }\n                dp_curr[j] = min_val;\n            }\n            for(int j=0; j<sz_curr; ++j) dp_prev[j] = dp_curr[j];\n            prev_c = cc;\n            prev_sz = sz_curr;\n            prev_pos_ptr = &cpos;\n        }\n    }\n    \n    int ans = 100000000;\n    for(int j=0; j<prev_sz; ++j) {\n        if(dp_prev[j] < ans) ans = dp_prev[j];\n    }\n    return ans;\n}\n\nvoid check_candidate(const vector<int>& p) {\n    int cost = get_exact_cost(p);\n    if (cost < global_min_exact_cost) {\n        global_min_exact_cost = cost;\n        global_best_p = p;\n    }\n}\n\n// Final solution reconstruction\nvoid solve_final(const vector<int>& p) {\n    vector<int> S;\n    S.reserve(1200);\n    for(char c : T[p[0]]) S.push_back(c2i(c));\n    for(size_t i=1; i<p.size(); ++i) {\n        int ov = overlaps[p[i-1]][p[i]];\n        for(int k=ov; k<5; ++k) S.push_back(c2i(T[p[i]][k]));\n    }\n    \n    int L = S.size();\n    vector<vector<int>> dp(L), parent(L);\n    \n    int c0 = S[0];\n    const auto& pos0 = char_positions[c0];\n    dp[0].resize(pos0.size());\n    parent[0].resize(pos0.size(), -1);\n    \n    for(size_t j=0; j<pos0.size(); ++j) {\n        dp[0][j] = dist(start_r, start_c, pos0[j].first, pos0[j].second) + 1;\n    }\n    \n    for(int i=1; i<L; ++i) {\n        int cc = S[i];\n        int pc = S[i-1];\n        const auto& cpos = char_positions[cc];\n        const auto& ppos = char_positions[pc];\n        dp[i].resize(cpos.size());\n        parent[i].resize(cpos.size());\n        \n        for(size_t j=0; j<cpos.size(); ++j) {\n            int r = cpos[j].first;\n            int c = cpos[j].second;\n            int min_val = 1e9;\n            int best_p = -1;\n            for(size_t k=0; k<ppos.size(); ++k) {\n                int d = dist(ppos[k].first, ppos[k].second, r, c);\n                int val = dp[i-1][k] + d + 1;\n                if(val < min_val) { min_val = val; best_p = k; }\n            }\n            dp[i][j] = min_val;\n            parent[i][j] = best_p;\n        }\n    }\n    \n    int min_total = 1e9;\n    int idx = -1;\n    for(size_t j=0; j<dp[L-1].size(); ++j) {\n        if(dp[L-1][j] < min_total) { min_total = dp[L-1][j]; idx = j; }\n    }\n    \n    vector<pair<int,int>> path;\n    for(int i=L-1; i>=0; --i) {\n        path.push_back(char_positions[S[i]][idx]);\n        idx = parent[i][idx];\n    }\n    reverse(path.begin(), path.end());\n    for(auto& pt : path) cout << pt.first << \" \" << pt.second << \"\\n\";\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = chrono::high_resolution_clock::now();\n    \n    cin >> N >> M >> start_r >> start_c;\n    A.resize(N);\n    for(int i=0; i<N; ++i) cin >> A[i];\n    T.resize(M);\n    for(int i=0; i<M; ++i) cin >> T[i];\n    \n    // Preprocessing\n    for(int i=0; i<N; ++i)\n        for(int j=0; j<N; ++j)\n            char_positions[c2i(A[i][j])].push_back({i, j});\n            \n    for(int i=0; i<M; ++i)\n        for(int j=0; j<M; ++j)\n            overlaps[i][j] = (i==j ? 0 : calc_overlap(T[i], T[j]));\n            \n    vector<pair<int,int>> s_pos = {{start_r, start_c}};\n    for(int i=0; i<M; ++i) start_dist[i] = calc_segment_cost_heuristic(s_pos, T[i]);\n    \n    for(int i=0; i<M; ++i) {\n        int li = c2i(T[i].back());\n        const auto& ends = char_positions[li];\n        for(int j=0; j<M; ++j) {\n            if(i==j) { dist_matrix[i][j]=1e9; continue; }\n            dist_matrix[i][j] = calc_segment_cost_heuristic(ends, T[j].substr(overlaps[i][j]));\n        }\n    }\n    \n    // --- Phase 1: GRASP Initialization ---\n    int best_approx = 1e9;\n    vector<int> current_p;\n    // Generate diverse initial solutions\n    for(int iter=0; iter<400; ++iter) {\n        vector<int> p; p.reserve(M);\n        vector<bool> used(M, false);\n        int curr = rng()%M;\n        p.push_back(curr); used[curr]=true;\n        int c = start_dist[curr];\n        \n        for(int i=1; i<M; ++i) {\n            int min_d = 1e9;\n            for(int j=0; j<M; ++j) if(!used[j] && dist_matrix[curr][j] < min_d) min_d = dist_matrix[curr][j];\n            \n            vector<int> cands;\n            // Consider all candidates close to minimum\n            for(int j=0; j<M; ++j) if(!used[j] && dist_matrix[curr][j] <= min_d+2) cands.push_back(j);\n            \n            // Fail-safe\n            if(cands.empty()) for(int j=0; j<M; ++j) if(!used[j]) { cands.push_back(j); break; }\n            \n            int next = cands[rng()%cands.size()];\n            p.push_back(next); used[next]=true;\n            c += dist_matrix[curr][next]; \n            curr = next;\n        }\n        if(c < best_approx) { best_approx=c; current_p=p; }\n        if(iter % 20 == 0) check_candidate(p);\n    }\n    check_candidate(current_p);\n    \n    // --- Phase 2: Heuristic Simulated Annealing ---\n    vector<int> p = current_p;\n    int cur_h_cost = best_approx;\n    double T0=12.0, T1=0.1;\n    \n    int iters = 0;\n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        double el = chrono::duration<double>(now - start_time).count();\n        if(el > 1.50) break;\n        double temp = T0 + (T1-T0)*(el/1.50);\n        \n        // Batch moves to check time less frequently\n        for(int b=0; b<100; ++b) {\n             int type = rng()%100;\n             if(type < 40) { // SWAP\n                 int i = rng()%M, j = rng()%M;\n                 if(i==j) continue;\n                 if(i>j) swap(i,j);\n                 int u=p[i], v=p[j];\n                 int pi=(i>0)?p[i-1]:-1, ni=p[i+1];\n                 int pj=p[j-1], nj=(j<M-1)?p[j+1]:-1;\n                 int delta = 0;\n                 if(j==i+1) {\n                     delta += (pi!=-1 ? dist_matrix[pi][v] : start_dist[v]) - (pi!=-1 ? dist_matrix[pi][u] : start_dist[u]);\n                     delta += dist_matrix[v][u] - dist_matrix[u][v];\n                     if(nj!=-1) delta += dist_matrix[u][nj] - dist_matrix[v][nj];\n                 } else {\n                     delta += (pi!=-1 ? dist_matrix[pi][v] : start_dist[v]) - (pi!=-1 ? dist_matrix[pi][u] : start_dist[u]);\n                     delta += dist_matrix[v][ni] - dist_matrix[u][ni];\n                     delta += dist_matrix[pj][u] - dist_matrix[pj][v];\n                     if(nj!=-1) delta += dist_matrix[u][nj] - dist_matrix[v][nj];\n                 }\n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     swap(p[i], p[j]); cur_h_cost += delta;\n                 }\n             } else if(type < 70) { // BLOCK INSERT\n                 int len = (rng()%3)+1;\n                 if(M<len+1) len=1;\n                 int i = rng()%(M-len+1);\n                 int k = rng()%(M-len+1); // Index in remaining array\n                 if(k==i) continue;\n                 \n                 // Calculate delta using neighbors\n                 int bs = p[i], be = p[i+len-1];\n                 int pb = (i>0)?p[i-1]:-1, nb = (i+len<M)?p[i+len]:-1;\n                 \n                 int u_idx = (k < i) ? k-1 : k+len-1;\n                 int v_idx = (k < i) ? k : k+len;\n                 int u = (u_idx>=0)?p[u_idx]:-1;\n                 int v = (v_idx<M)?p[v_idx]:-1;\n                 \n                 int delta = 0;\n                 delta -= (pb!=-1?dist_matrix[pb][bs]:start_dist[bs]);\n                 if(nb!=-1) delta -= dist_matrix[be][nb];\n                 if(pb!=-1 && nb!=-1) delta += dist_matrix[pb][nb];\n                 else if(pb==-1 && nb!=-1) delta += start_dist[nb];\n                 \n                 if(u!=-1 && v!=-1) delta -= dist_matrix[u][v];\n                 else if(u==-1 && v!=-1) delta -= start_dist[v];\n                 \n                 if(u!=-1) delta += dist_matrix[u][bs];\n                 else delta += start_dist[bs];\n                 if(v!=-1) delta += dist_matrix[be][v];\n                 \n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     vector<int> blk(p.begin()+i, p.begin()+i+len);\n                     p.erase(p.begin()+i, p.begin()+i+len);\n                     p.insert(p.begin()+k, blk.begin(), blk.end());\n                     cur_h_cost += delta;\n                 }\n             } else { // 2-OPT (Reversal)\n                 int i = rng()%M, j = rng()%M;\n                 if(i>j) swap(i,j);\n                 if(j-i+1 > 20 || j==i) continue; // Limit size for speed\n                 int pi = (i>0)?p[i-1]:-1;\n                 int nj = (j<M-1)?p[j+1]:-1;\n                 int start_val = p[i], end_val = p[j];\n                 \n                 int d_old = 0;\n                 if(pi!=-1) d_old += dist_matrix[pi][start_val]; else d_old += start_dist[start_val];\n                 if(nj!=-1) d_old += dist_matrix[end_val][nj];\n                 for(int k=i; k<j; ++k) d_old += dist_matrix[p[k]][p[k+1]];\n                 \n                 int d_new = 0;\n                 if(pi!=-1) d_new += dist_matrix[pi][end_val]; else d_new += start_dist[end_val];\n                 if(nj!=-1) d_new += dist_matrix[start_val][nj];\n                 for(int k=j; k>i; --k) d_new += dist_matrix[p[k]][p[k-1]];\n                 \n                 int delta = d_new - d_old;\n                 if(delta<=0 || bernoulli_distribution(exp(-delta/temp))(rng)) {\n                     reverse(p.begin()+i, p.begin()+j+1);\n                     cur_h_cost += delta;\n                 }\n             }\n        }\n        iters += 100;\n        if((iters & 255) == 0) check_candidate(p);\n    }\n    check_candidate(p);\n    \n    // --- Phase 3: Exact Cost Randomized Local Search ---\n    // Start from best found solution\n    p = global_best_p;\n    int cur_exact = global_min_exact_cost;\n    \n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        if(chrono::duration<double>(now - start_time).count() > 1.97) break;\n        \n        // Try random move, accept if better or equal (to escape plateaus)\n        int type = rng()%3;\n        if(type == 0) { // Swap\n            int i = rng()%M, j = rng()%M;\n            if(i==j) continue;\n            swap(p[i], p[j]);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                swap(p[i], p[j]); // Revert\n            }\n        } else if(type == 1) { // Insert\n            int i = rng()%M;\n            int j = rng()%M;\n            if(i==j) continue;\n            int val = p[i];\n            p.erase(p.begin()+i);\n            p.insert(p.begin()+j, val);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                p.erase(p.begin()+j);\n                p.insert(p.begin()+i, val);\n            }\n        } else { // Short Reverse\n            int i = rng()%M, j = rng()%M;\n            if(i>j) swap(i,j);\n            if(i==j || j-i > 15) continue; \n            reverse(p.begin()+i, p.begin()+j+1);\n            int cost = get_exact_cost(p);\n            if(cost <= cur_exact) {\n                cur_exact = cost;\n                if(cost < global_min_exact_cost) { global_min_exact_cost=cost; global_best_p=p; }\n            } else {\n                reverse(p.begin()+i, p.begin()+j+1);\n            }\n        }\n    }\n    \n    solve_final(global_best_p);\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <iomanip>\n#include <numeric>\n#include <cassert>\n\nusing namespace std;\n\n// ---------------------- Utils ----------------------\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool is_time_over() {\n        return elapsed() > limit;\n    }\n};\n\nmt19937 rng(12345);\n\n// ---------------------- Globals ----------------------\n\nint N, M;\ndouble EPS;\nint op_count = 0;\nint max_ops;\n\nstruct Point { int r, c; };\n\nstruct Polyomino {\n    vector<Point> shape;\n};\nvector<Polyomino> fields;\n\nstruct Operation {\n    int type; // 0: drill, 1: divine\n    int r, c; // for drill\n    vector<Point> set_points; // for divine\n    int result_drill;\n    int result_divine;\n    \n    double divine_mean_base; \n    double divine_mean_coeff; \n    double divine_var_inv; \n};\nvector<Operation> history;\nvector<vector<vector<int>>> cell_to_ops;\n\nstruct ValidPos {\n    int r, c; // top-left\n    vector<Point> cells;\n};\nvector<vector<ValidPos>> possible_positions; // [field_id][pos_id]\nvector<vector<int>> active_indices; // [field_id] -> list of valid pos_ids\n\nvector<vector<int>> grid_known; // -1: unknown, >=0: exact value\n\n// ---------------------- Functions ----------------------\n\nvoid precompute_positions() {\n    possible_positions.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int max_r = 0, max_c = 0;\n        for (auto& p : fields[k].shape) {\n            max_r = max(max_r, p.r);\n            max_c = max(max_c, p.c);\n        }\n        for (int r = 0; r < N - max_r; ++r) {\n            for (int c = 0; c < N - max_c; ++c) {\n                ValidPos vp;\n                vp.r = r;\n                vp.c = c;\n                for (auto& p : fields[k].shape) {\n                    vp.cells.push_back({p.r + r, p.c + c});\n                }\n                possible_positions[k].push_back(vp);\n            }\n        }\n    }\n}\n\nvoid add_history(Operation op) {\n    int idx = history.size();\n    if (op.type == 1) {\n        int k_sz = op.set_points.size();\n        double var = k_sz * EPS * (1.0 - EPS);\n        op.divine_mean_base = k_sz * EPS;\n        op.divine_mean_coeff = 1.0 - 2.0 * EPS;\n        op.divine_var_inv = 0.5 / max(1e-9, var);\n    } \n    \n    history.push_back(op);\n    \n    if (op.type == 0) {\n        cell_to_ops[op.r][op.c].push_back(idx);\n        grid_known[op.r][op.c] = op.result_drill;\n    } else {\n        for (auto& p : op.set_points) {\n            cell_to_ops[p.r][p.c].push_back(idx);\n        }\n    }\n}\n\nvoid prune_positions() {\n    active_indices.assign(M, {});\n    for (int k = 0; k < M; ++k) {\n        for (int i = 0; i < (int)possible_positions[k].size(); ++i) {\n            bool ok = true;\n            const auto& cells = possible_positions[k][i].cells;\n            for (const auto& p : cells) {\n                if (grid_known[p.r][p.c] == 0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) {\n                active_indices[k].push_back(i);\n            }\n        }\n    }\n}\n\nstruct State {\n    vector<int> config; \n    vector<vector<int>> counts;\n    vector<int> op_preds; \n    double energy;\n};\n\ninline double get_op_energy(int op_idx, int pred_val) {\n    const auto& op = history[op_idx];\n    if (op.type == 0) { \n        return 100000.0 * abs(pred_val - op.result_drill);\n    } else { \n        double mean = op.divine_mean_base + pred_val * op.divine_mean_coeff;\n        double diff = op.result_divine - mean;\n        double sq = diff * diff * op.divine_var_inv;\n        // Robust loss to handle noisy Divine data\n        return min(sq, 15.0);\n    }\n}\n\nvector<vector<int>> run_sa(int num_solutions, double duration) {\n    vector<vector<int>> solutions;\n    Timer t(duration);\n    \n    for (int k = 0; k < M; ++k) {\n        if (active_indices[k].empty()) return {}; \n    }\n\n    while (solutions.size() < (size_t)num_solutions && !t.is_time_over()) {\n        State S;\n        S.config.resize(M);\n        S.counts.assign(N, vector<int>(N, 0));\n        S.op_preds.assign(history.size(), 0);\n        S.energy = 0;\n\n        for (int k = 0; k < M; ++k) {\n            int idx = active_indices[k][rng() % active_indices[k].size()];\n            S.config[k] = idx;\n            for (const auto& p : possible_positions[k][idx].cells) {\n                S.counts[p.r][p.c]++;\n                for (int op_idx : cell_to_ops[p.r][p.c]) {\n                    S.op_preds[op_idx]++;\n                }\n            }\n        }\n\n        for (int i = 0; i < (int)history.size(); ++i) {\n            S.energy += get_op_energy(i, S.op_preds[i]);\n        }\n        \n        State best_S = S;\n\n        double Temp = 5.0;\n        double decay = 0.92;\n        int iter = 0;\n        int max_iter = 1500;\n        \n        static vector<int> changed_ops;\n        changed_ops.reserve(history.size());\n\n        while (iter < max_iter) { \n            iter++;\n            int k = rng() % M;\n            if (active_indices[k].size() <= 1) continue;\n\n            int old_idx = S.config[k];\n            int new_idx = active_indices[k][rng() % active_indices[k].size()];\n            if (old_idx == new_idx) continue;\n\n            const auto& old_cells = possible_positions[k][old_idx].cells;\n            const auto& new_cells = possible_positions[k][new_idx].cells;\n\n            changed_ops.clear();\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) changed_ops.push_back(op_idx);\n            }\n            sort(changed_ops.begin(), changed_ops.end());\n            changed_ops.erase(unique(changed_ops.begin(), changed_ops.end()), changed_ops.end());\n\n            double delta = 0;\n            for (int op_idx : changed_ops) delta -= get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            for (const auto& p : old_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n            }\n            for (const auto& p : new_cells) {\n                for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n            }\n\n            for (int op_idx : changed_ops) delta += get_op_energy(op_idx, S.op_preds[op_idx]);\n\n            if (delta < 0 || exp(-delta / Temp) > (double)rng() / 4294967296.0) {\n                S.energy += delta;\n                S.config[k] = new_idx;\n                for (const auto& p : old_cells) S.counts[p.r][p.c]--;\n                for (const auto& p : new_cells) S.counts[p.r][p.c]++;\n                if(S.energy < best_S.energy) best_S = S;\n            } else {\n                for (const auto& p : new_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]--;\n                }\n                for (const auto& p : old_cells) {\n                    for (int op_idx : cell_to_ops[p.r][p.c]) S.op_preds[op_idx]++;\n                }\n            }\n            Temp *= decay;\n            if (Temp < 0.05) break;\n        }\n        solutions.push_back(best_S.config);\n    }\n    return solutions;\n}\n\nint main() {\n    cin.tie(nullptr);\n    ios_base::sync_with_stdio(false);\n\n    if (!(cin >> N >> M >> EPS)) return 0;\n    max_ops = 2 * N * N;\n\n    fields.resize(M);\n    for (int i = 0; i < M; ++i) {\n        int d; cin >> d;\n        fields[i].shape.resize(d);\n        for (int j = 0; j < d; ++j) {\n            cin >> fields[i].shape[j].r >> fields[i].shape[j].c;\n        }\n    }\n\n    precompute_positions();\n    grid_known.assign(N, vector<int>(N, -1));\n    cell_to_ops.assign(N, vector<vector<int>>(N));\n\n    // Initial Scan\n    int block_size = max(2, N / 5);\n    \n    for(int r=0; r<N; r+=block_size) {\n        for(int c=0; c<N; c+=block_size) {\n            if(op_count >= max_ops) break;\n            \n            vector<Point> pts;\n            for(int rr=r; rr<min(N, r+block_size); ++rr) {\n                for(int cc=c; cc<min(N, c+block_size); ++cc) {\n                    pts.push_back({rr, cc});\n                }\n            }\n            if(pts.size() >= 2) {\n                cout << \"q \" << pts.size();\n                for(auto& p : pts) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                op_count++;\n                int res; \n                if(!(cin >> res)) return 0;\n                add_history({1, 0, 0, pts, 0, res});\n            }\n        }\n    }\n\n    Timer global_timer(2.85);\n\n    while (!global_timer.is_time_over() && op_count < max_ops) {\n        prune_positions();\n\n        vector<vector<int>> solutions = run_sa(40, 0.05);\n\n        vector<vector<int>> pos_counts(N, vector<int>(N, 0));\n        int sol_cnt = solutions.size();\n        \n        if (sol_cnt > 0) {\n            for(const auto& cfg : solutions) {\n                for(int k=0; k<M; ++k) {\n                    int idx = cfg[k];\n                    for(auto& p : possible_positions[k][idx].cells) {\n                        pos_counts[p.r][p.c]++;\n                    }\n                }\n            }\n        }\n\n        vector<Point> answer_candidates;\n        bool confident = true;\n        if (sol_cnt == 0) confident = false;\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                bool cell_oil = false;\n                if (grid_known[r][c] != -1) {\n                    if (grid_known[r][c] > 0) cell_oil = true;\n                } else {\n                    if (sol_cnt > 0) {\n                        if (pos_counts[r][c] == sol_cnt) cell_oil = true;\n                        else if (pos_counts[r][c] == 0) cell_oil = false;\n                        else confident = false;\n                    } else {\n                        confident = false;\n                    }\n                }\n                if (cell_oil) answer_candidates.push_back({r, c});\n            }\n        }\n        \n        if (confident) {\n            bool consistent = true;\n            for (auto& p : answer_candidates) {\n                if (grid_known[p.r][p.c] == 0) consistent = false;\n            }\n            if (consistent) {\n                for(int r=0; r<N; ++r) {\n                    for(int c=0; c<N; ++c) {\n                        if (grid_known[r][c] > 0) {\n                            bool in_ans = false;\n                            for(auto& p : answer_candidates) if(p.r==r && p.c==c) in_ans=true;\n                            if(!in_ans) consistent = false;\n                        }\n                    }\n                }\n            }\n\n            if (consistent) {\n                cout << \"a \" << answer_candidates.size();\n                for(auto& p : answer_candidates) cout << \" \" << p.r << \" \" << p.c;\n                cout << endl;\n                op_count++;\n                int res; \n                if(!(cin >> res)) return 0;\n                if (res == 1) return 0;\n            }\n        }\n        \n        if (op_count >= max_ops) break;\n\n        int best_r = -1, best_c = -1;\n        \n        if (sol_cnt > 0) {\n            int max_ent = -1;\n            for(int r=0; r<N; ++r) {\n                for(int c=0; c<N; ++c) {\n                    if (grid_known[r][c] != -1) continue;\n                    int yes = pos_counts[r][c];\n                    int no = sol_cnt - yes;\n                    int score = min(yes, no);\n                    if (score > max_ent) {\n                        max_ent = score;\n                        best_r = r;\n                        best_c = c;\n                    }\n                }\n            }\n            if (max_ent == 0) best_r = -1;\n        }\n        \n        if (best_r == -1) {\n             vector<Point> unknowns;\n             for(int r=0; r<N; ++r)\n                 for(int c=0; c<N; ++c)\n                     if(grid_known[r][c] == -1) unknowns.push_back({r, c});\n             \n             if (unknowns.empty()) break; \n             \n             vector<Point> adj_candidates;\n             for(auto& u : unknowns) {\n                 bool adj = false;\n                 int dr[] = {0,0,1,-1};\n                 int dc[] = {1,-1,0,0};\n                 for(int i=0; i<4; ++i) {\n                     int nr=u.r+dr[i], nc=u.c+dc[i];\n                     if(nr>=0 && nr<N && nc>=0 && nc<N && grid_known[nr][nc]>0) adj=true;\n                 }\n                 if(adj) adj_candidates.push_back(u);\n             }\n             \n             if (!adj_candidates.empty()) {\n                 int idx = rng() % adj_candidates.size();\n                 best_r = adj_candidates[idx].r;\n                 best_c = adj_candidates[idx].c;\n             } else {\n                 vector<Point> checker;\n                 for(auto& u : unknowns) if((u.r+u.c)%2==0) checker.push_back(u);\n                 if (!checker.empty()) {\n                     int idx = rng() % checker.size();\n                     best_r = checker[idx].r;\n                     best_c = checker[idx].c;\n                 } else {\n                     int idx = rng() % unknowns.size();\n                     best_r = unknowns[idx].r;\n                     best_c = unknowns[idx].c;\n                 }\n             }\n        }\n        \n        cout << \"q 1 \" << best_r << \" \" << best_c << endl;\n        op_count++;\n        int val; \n        if(!(cin >> val)) return 0;\n        add_history({0, best_r, best_c, {}, val, 0});\n    }\n    \n    vector<Point> final_ans;\n    for(int r=0; r<N; ++r) {\n        for(int c=0; c<N; ++c) {\n            if(grid_known[r][c] > 0) final_ans.push_back({r, c});\n        }\n    }\n    if(final_ans.empty()) {\n        for(int r=0;r<N;++r)for(int c=0;c<N;++c) final_ans.push_back({r, c});\n    }\n    cout << \"a \" << final_ans.size();\n    for(auto& p : final_ans) cout << \" \" << p.r << \" \" << p.c;\n    cout << endl;\n    int res; cin >> res;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global Inputs\nint W_GRID;\nint D, N;\nvector<vector<int>> A;\n\nconst int SHORTAGE_PENALTY = 100;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct SolutionState {\n    vector<vector<int>> groups; // items assigned to each column\n    vector<int> widths;\n    long long score;\n};\n\nlong long get_time_ms() {\n    using namespace std::chrono;\n    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\nclass Solver {\npublic:\n    vector<int> needs;\n    vector<int> R;\n    vector<int> curr_cuts;\n    vector<int> prev_cuts;\n    vector<int> next_needs;\n\n    Solver() {\n        needs.resize(60); \n        R.resize(60); \n        curr_cuts.resize(60); \n        prev_cuts.resize(60);\n        next_needs.resize(60);\n    }\n\n    long long solve_column_cost(const vector<int>& items, int width, vector<vector<int>>* out_cuts = nullptr) {\n        if (items.empty()) return 0;\n        if (width <= 0) return 1e17; \n\n        int m = items.size();\n        long long total_cost = 0;\n        \n        fill(prev_cuts.begin(), prev_cuts.begin() + m, 0);\n        if (out_cuts) out_cuts->assign(D, vector<int>(m));\n\n        for (int d = 0; d < D; ++d) {\n            for(int i=0; i<m; ++i) {\n                needs[i] = (A[d][items[i]] + width - 1) / width;\n                if(needs[i] < 1) needs[i] = 1;\n            }\n            \n            R[m-1] = 0;\n            for(int i=m-2; i>=0; --i) R[i] = R[i+1] + max(1, needs[i+1]);\n\n            bool has_next = (d < D - 1);\n            if (has_next) {\n                for(int i=0; i<m; ++i) {\n                    next_needs[i] = (A[d+1][items[i]] + width - 1) / width;\n                    if(next_needs[i] < 1) next_needs[i] = 1;\n                }\n            }\n\n            int current_y = 0;\n            int next_day_y_acc = 0; \n\n            for(int i=0; i<m-1; ++i) {\n                int min_cut = current_y + 1;\n                int max_cut = W_GRID - (m - 1 - i);\n                int ideal_cut = current_y + needs[i]; \n                int future_limit = W_GRID - R[i];\n                \n                int safe_min = max(min_cut, ideal_cut);\n                int safe_max = min(max_cut, future_limit);\n                \n                int chosen = safe_min; \n\n                if (safe_min <= safe_max) {\n                    if (d > 0) {\n                        int p = prev_cuts[i];\n                        if (p >= safe_min && p <= safe_max) chosen = p; \n                        else {\n                            if (has_next) {\n                                int target = next_day_y_acc + next_needs[i];\n                                if (target < safe_min) chosen = safe_min;\n                                else if (target > safe_max) chosen = safe_max;\n                                else chosen = target;\n                            } else {\n                                if (p < safe_min) chosen = safe_min;\n                                else chosen = safe_max;\n                            }\n                        }\n                    } else {\n                        if (has_next) {\n                            int target = next_day_y_acc + next_needs[i];\n                            if (target < safe_min) chosen = safe_min;\n                            else if (target > safe_max) chosen = safe_max;\n                            else chosen = target;\n                        } else {\n                            chosen = safe_min;\n                        }\n                    }\n                } else {\n                    chosen = max(min_cut, min(ideal_cut, max_cut));\n                }\n\n                curr_cuts[i] = chosen;\n                current_y = chosen;\n                if (has_next) next_day_y_acc += next_needs[i];\n            }\n            curr_cuts[m-1] = W_GRID; \n            \n            long long d_cost = 0;\n            int prev_y = 0;\n            for(int i=0; i<m; ++i) {\n                int h = curr_cuts[i] - prev_y;\n                long long area = (long long)h * width;\n                long long req = A[d][items[i]];\n                if (area < req) d_cost += (req - area) * SHORTAGE_PENALTY;\n                prev_y = curr_cuts[i];\n            }\n            \n            if (d > 0) {\n                for(int i=0; i<m-1; ++i) {\n                    if (curr_cuts[i] != prev_cuts[i]) d_cost += (width << 1);\n                }\n            }\n            \n            total_cost += d_cost;\n            if (out_cuts) (*out_cuts)[d] = vector<int>(curr_cuts.begin(), curr_cuts.begin() + m);\n            for(int i=0; i<m; ++i) prev_cuts[i] = curr_cuts[i];\n        }\n        return total_cost;\n    }\n} solver;\n\nvoid optimize_widths(const vector<vector<int>>& groups, vector<int>& widths, long long& current_total_score) {\n    int K = groups.size();\n    vector<long long> col_scores(K);\n    \n    current_total_score = 0;\n    for(int c=0; c<K; ++c) {\n        col_scores[c] = solver.solve_column_cost(groups[c], widths[c]);\n        current_total_score += col_scores[c];\n    }\n\n    vector<long long> delta_minus(K);\n    vector<long long> delta_plus(K);\n\n    auto update_deltas = [&](int c) {\n        delta_minus[c] = 1e18;\n        delta_plus[c] = 1e18;\n        if (widths[c] > 1) {\n            delta_minus[c] = solver.solve_column_cost(groups[c], widths[c] - 1) - col_scores[c];\n        }\n        if (widths[c] < W_GRID - (K-1)) {\n            delta_plus[c] = solver.solve_column_cost(groups[c], widths[c] + 1) - col_scores[c];\n        }\n    };\n\n    for(int c=0; c<K; ++c) update_deltas(c);\n\n    int iter = 0;\n    while(iter < 80) { \n        iter++;\n        \n        int best_src = -1; long long min_d_minus = 1e18;\n        int second_src = -1; long long second_d_minus = 1e18;\n\n        for(int c=0; c<K; ++c) {\n            if (widths[c] <= 1) continue;\n            if (delta_minus[c] < min_d_minus) {\n                second_d_minus = min_d_minus; second_src = best_src;\n                min_d_minus = delta_minus[c]; best_src = c;\n            } else if (delta_minus[c] < second_d_minus) {\n                second_d_minus = delta_minus[c]; second_src = c;\n            }\n        }\n\n        int best_dst = -1; long long min_d_plus = 1e18;\n        int second_dst = -1; long long second_d_plus = 1e18;\n\n        for(int c=0; c<K; ++c) {\n            if (delta_plus[c] < min_d_plus) {\n                second_d_plus = min_d_plus; second_dst = best_dst;\n                min_d_plus = delta_plus[c]; best_dst = c;\n            } else if (delta_plus[c] < second_d_plus) {\n                second_d_plus = delta_plus[c]; second_dst = c;\n            }\n        }\n        \n        long long best_change = 0;\n        int final_src = -1, final_dst = -1;\n        \n        auto check = [&](int s, int d, long long dm, long long dp) {\n            if(s == -1 || d == -1) return;\n            long long ch = dm + dp;\n            if(ch < best_change) {\n                best_change = ch;\n                final_src = s;\n                final_dst = d;\n            }\n        };\n\n        if(best_src != best_dst) check(best_src, best_dst, min_d_minus, min_d_plus);\n        check(best_src, second_dst, min_d_minus, second_d_plus);\n        check(second_src, best_dst, second_d_minus, min_d_plus);\n\n        if (best_change < -1) { \n            widths[final_src]--;\n            widths[final_dst]++;\n            current_total_score += best_change;\n            col_scores[final_src] = solver.solve_column_cost(groups[final_src], widths[final_src]);\n            col_scores[final_dst] = solver.solve_column_cost(groups[final_dst], widths[final_dst]);\n            update_deltas(final_src);\n            update_deltas(final_dst);\n        } else {\n            break;\n        }\n    }\n}\n\nSolutionState evaluate_groups(const vector<vector<int>>& groups) {\n    int K = groups.size();\n    vector<long long> max_demands(K, 0);\n    long long total_demand = 0;\n    for(int c=0; c<K; ++c) {\n        for(int d=0; d<D; ++d) {\n            long long s = 0;\n            for(int idx : groups[c]) s += A[d][idx];\n            if (s > max_demands[c]) max_demands[c] = s;\n        }\n        total_demand += max_demands[c];\n    }\n    \n    vector<int> widths(K, 1);\n    int remaining = W_GRID - K;\n    if (remaining > 0 && total_demand > 0) {\n        vector<pair<long long, int>> rems(K);\n        for(int c=0; c<K; ++c) {\n            long long share = (long long)remaining * max_demands[c];\n            widths[c] += (int)(share / total_demand);\n            rems[c] = { share % total_demand, c };\n        }\n        int used = 0;\n        for(int w : widths) used += w;\n        int left = W_GRID - used;\n        sort(rems.rbegin(), rems.rend());\n        for(int i=0; i<left; ++i) widths[rems[i].second]++;\n    } else if (remaining > 0) {\n        widths[0] += remaining;\n    }\n\n    long long score = 0;\n    optimize_widths(groups, widths, score);\n    return {groups, widths, score};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> W_GRID >> D >> N)) return 0;\n    A.resize(D, vector<int>(N));\n    for(int d=0; d<D; ++d) for(int k=0; k<N; ++k) cin >> A[d][k];\n\n    long long start_time = get_time_ms();\n    mt19937 rng(42);\n\n    SolutionState best_sol;\n    best_sol.score = -1;\n\n    int max_k = min(N, 14); \n    \n    for(int K=1; K<=max_k; ++K) {\n        if (get_time_ms() - start_time > 2850) break;\n\n        // Initial Partition (Sorted)\n        vector<vector<int>> current_groups(K);\n        vector<int> cuts(K+1);\n        cuts[0] = 0; cuts[K] = N;\n        for(int i=1; i<K; ++i) cuts[i] = (N * i) / K;\n        \n        for(int c=0; c<K; ++c) {\n            for(int i=cuts[c]; i<cuts[c+1]; ++i) current_groups[c].push_back(i);\n        }\n\n        SolutionState current = evaluate_groups(current_groups);\n        if (best_sol.score == -1 || current.score < best_sol.score) best_sol = current;\n        \n        if (K == 1) continue;\n\n        double T0 = 5e5; \n        double T1 = 1e1; \n        int iter = 0;\n        double temp = T0;\n        \n        while(true) {\n            if ((iter & 31) == 0) {\n                if (get_time_ms() - start_time > 2850) break;\n            }\n            iter++;\n            \n            // Move: Pick a random item and move it to a random column\n            int src_col = uniform_int_distribution<int>(0, K-1)(rng);\n            if (current_groups[src_col].empty()) continue;\n\n            int item_idx_in_group = uniform_int_distribution<int>(0, current_groups[src_col].size()-1)(rng);\n            int item = current_groups[src_col][item_idx_in_group];\n            \n            int dst_col = uniform_int_distribution<int>(0, K-1)(rng);\n            if (src_col == dst_col) continue;\n\n            // Apply Move\n            vector<vector<int>> next_groups = current_groups;\n            next_groups[src_col].erase(next_groups[src_col].begin() + item_idx_in_group);\n            \n            // Insert into destination maintaining sorted order (heuristic for better packing)\n            auto pos = lower_bound(next_groups[dst_col].begin(), next_groups[dst_col].end(), item);\n            next_groups[dst_col].insert(pos, item);\n            \n            SolutionState next_sol = evaluate_groups(next_groups);\n            long long diff = next_sol.score - current.score;\n            \n            if (diff < 0 || uniform_real_distribution<double>(0,1)(rng) < exp(-diff / temp)) {\n                current = next_sol;\n                current_groups = next_groups; // Update tracking\n                if (current.score < best_sol.score) best_sol = current;\n            }\n            \n            temp *= 0.96;\n            if (temp < T1) temp = T1;\n        }\n    }\n\n    // Output\n    vector<vector<Rect>> final_rects(D, vector<Rect>(N));\n    int current_x = 0;\n    for(size_t c=0; c<best_sol.groups.size(); ++c) {\n        int w = best_sol.widths[c];\n        vector<vector<int>> cuts;\n        solver.solve_column_cost(best_sol.groups[c], w, &cuts);\n        for(int d=0; d<D; ++d) {\n            int prev_y = 0;\n            for(size_t i=0; i<best_sol.groups[c].size(); ++i) {\n                int idx = best_sol.groups[c][i];\n                int y = cuts[d][i];\n                int x0 = min(W_GRID, max(0, current_x));\n                int x1 = min(W_GRID, max(0, current_x + w));\n                int y0 = min(W_GRID, max(0, prev_y));\n                int y1 = min(W_GRID, max(0, y));\n                final_rects[d][idx] = {y0, x0, y1, x1};\n                prev_y = y;\n            }\n        }\n        current_x += w;\n    }\n    \n    for(int d=0; d<D; ++d) {\n        for(int k=0; k<N; ++k) {\n            cout << final_rects[d][k].r0 << \" \" << final_rects[d][k].c0 << \" \" \n                 << final_rects[d][k].r1 << \" \" << final_rects[d][k].c1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#pragma GCC optimize(\"Ofast\")\n#pragma GCC optimize(\"unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstdint>\n#include <cstring>\n#include <array>\n\nusing namespace std;\n\n// Problem Constants\nconstexpr int N = 9;\nconstexpr int TOTAL_CELLS = 81;\nconstexpr int MOD = 998244353;\n\n// Fast Xorshift Random Number Generator\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    \n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    }\n    \n    inline int next_int(int n) {\n        return (uint64_t)next() * n >> 32;\n    }\n    \n    inline double next_double() {\n        return (double)next() / 4294967296.0;\n    }\n} rng;\n\n// Compressed Move Structure (Fits in 64-byte cache line)\nstruct alignas(64) FastMove {\n    int values[9];       // 36 bytes\n    uint8_t indices[9];  // 9 bytes\n    uint8_t m, p, q;     // 3 bytes\n    // Padding handled by alignas\n};\n\n// Buffer for Delta Calculation\nstruct Change {\n    uint8_t idx;\n    int old_val;\n    int new_val;\n};\n\n// Global Data\nint N_in, M_in, K_in;\nint initial_board[TOTAL_CELLS];\nint board[TOTAL_CELLS]; \nint stamps[20][9];\n\nFastMove possible_moves[1000];\nint num_possible_moves = 0;\n\n// State\nint current_ops[81];\nlong long current_score;\n\n// Best State\nint best_ops[81];\nlong long best_score = -1;\n\n// Lookup table for delta calc (maps board index -> change buffer index)\nint8_t pos_in_buffer[TOTAL_CELLS];\n\n// --- Initialization ---\nvoid init_moves() {\n    num_possible_moves = 0;\n    for (int m = 0; m < M_in; ++m) {\n        for (int p = 0; p <= N - 3; ++p) {\n            for (int q = 0; q <= N - 3; ++q) {\n                FastMove& fm = possible_moves[num_possible_moves];\n                fm.m = m; fm.p = p; fm.q = q;\n                int idx = 0;\n                for (int i = 0; i < 3; ++i) {\n                    for (int j = 0; j < 3; ++j) {\n                        fm.indices[idx] = (uint8_t)((p + i) * N + (q + j));\n                        fm.values[idx] = stamps[m][i * 3 + j];\n                        idx++;\n                    }\n                }\n                num_possible_moves++;\n            }\n        }\n    }\n}\n\n// --- Core Logic ---\n\n// Apply a move permanently to `board` and `current_score`\ninline void apply_permanent(int move_idx, bool adding) {\n    if (move_idx == -1) return;\n    const auto& mv = possible_moves[move_idx];\n    for (int i = 0; i < 9; ++i) {\n        int idx = mv.indices[i];\n        int val = board[idx];\n        current_score -= val;\n        if (adding) {\n            val += mv.values[i];\n            if (val >= MOD) val -= MOD;\n        } else {\n            val -= mv.values[i];\n            if (val < 0) val += MOD;\n        }\n        board[idx] = val;\n        current_score += val;\n    }\n}\n\n// Evaluate adding a move without changing board (for Greedy/HC)\ninline long long eval_add_move(int move_idx) {\n    if (move_idx == -1) return 0;\n    long long d = 0;\n    const auto& m = possible_moves[move_idx];\n    for (int i = 0; i < 9; ++i) {\n        int idx = m.indices[i];\n        int v = board[idx] + m.values[i];\n        if (v >= MOD) v -= MOD;\n        d += (v - board[idx]);\n    }\n    return d;\n}\n\n// Run Hill Climbing on the current configuration\nvoid run_hill_climbing(int passes) {\n    for (int pass = 0; pass < passes; ++pass) {\n        bool improved = false;\n        for (int k = 0; k < K_in; ++k) {\n            int old_mv = current_ops[k];\n            apply_permanent(old_mv, false); // Remove\n            \n            long long current_base = current_score;\n            int best_mv = -1;\n            long long max_val = current_base;\n            \n            // Try all possible moves\n            for (int mv = 0; mv < num_possible_moves; ++mv) {\n                long long d = eval_add_move(mv);\n                if (current_base + d > max_val) {\n                    max_val = current_base + d;\n                    best_mv = mv;\n                }\n            }\n            \n            if (best_mv != -1) {\n                current_ops[k] = best_mv;\n                apply_permanent(best_mv, true);\n                if (best_mv != old_mv) improved = true;\n            } else {\n                current_ops[k] = -1;\n                if (old_mv != -1) improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nint main() {\n    // Setup Timer\n    auto start_clock = chrono::steady_clock::now();\n    \n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if (!(cin >> N_in >> M_in >> K_in)) return 0;\n    for (int i = 0; i < TOTAL_CELLS; ++i) cin >> initial_board[i];\n    for (int m = 0; m < M_in; ++m) {\n        for (int i = 0; i < 9; ++i) cin >> stamps[m][i];\n    }\n    \n    init_moves();\n    \n    // --- 1. Randomized Greedy Initialization (Best of N) ---\n    // Time budget: 0.25s max for init\n    \n    int global_best_init_ops[81];\n    long long global_best_init_score = -1;\n    \n    // Reduce init trials to avoid TLE\n    int init_trials = 40; \n    \n    for (int t = 0; t < init_trials; ++t) {\n        // Check time periodically\n        if ((t & 7) == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start_clock).count() > 0.25) break;\n        }\n\n        // Reset board\n        for (int i = 0; i < TOTAL_CELLS; ++i) board[i] = initial_board[i];\n        current_score = 0;\n        for (int i = 0; i < TOTAL_CELLS; ++i) current_score += board[i];\n        for (int k = 0; k < K_in; ++k) current_ops[k] = -1;\n        \n        // Randomized Greedy Construction\n        for (int k = 0; k < K_in; ++k) {\n            int best_mv = -1;\n            long long best_d = -1e18;\n            \n            for (int mv = 0; mv < num_possible_moves; ++mv) {\n                long long d = eval_add_move(mv);\n                // Noise ~ 2.5% of MOD\n                double noise = rng.next_double() * 25000000.0; \n                \n                if (d + noise > best_d) {\n                    best_d = d + noise;\n                    best_mv = mv;\n                }\n            }\n            \n            if (best_mv != -1) {\n                 long long real_d = eval_add_move(best_mv);\n                 if (real_d > -50000000) { \n                     current_ops[k] = best_mv;\n                     apply_permanent(best_mv, true);\n                 }\n            }\n        }\n        \n        // 1 Pass of Hill Climbing\n        run_hill_climbing(1);\n        \n        if (current_score > global_best_init_score) {\n            global_best_init_score = current_score;\n            for (int k = 0; k < K_in; ++k) global_best_init_ops[k] = current_ops[k];\n        }\n    }\n    \n    // Restore best initialization\n    for (int i = 0; i < TOTAL_CELLS; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < TOTAL_CELLS; ++i) current_score += board[i];\n    for (int k = 0; k < K_in; ++k) {\n        current_ops[k] = global_best_init_ops[k];\n        apply_permanent(current_ops[k], true);\n    }\n    \n    best_score = current_score;\n    for(int k=0; k<K_in; ++k) best_ops[k] = current_ops[k];\n    \n    // --- 2. Simulated Annealing ---\n    \n    double time_limit = 1.90; // Hard stop for SA\n    double t0 = 4e8;\n    double t1 = 1e-1;\n    \n    Change changes[18];\n    long long iter = 0;\n    double current_temp = t0;\n    memset(pos_in_buffer, -1, sizeof(pos_in_buffer));\n    \n    const int POSITIONS_PER_ROW = 7;\n    const int POSITIONS_TOTAL = 49;\n    \n    while (true) {\n        // Check time less frequently to save overhead\n        if ((iter & 2047) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_clock).count();\n            if (elapsed > time_limit) break;\n            current_temp = t0 * pow(t1 / t0, elapsed / time_limit);\n        }\n        iter++;\n        \n        int slot = rng.next_int(K_in);\n        int old_mv = current_ops[slot];\n        int new_mv = -1;\n        \n        if (old_mv == -1) {\n             // Slot empty: add random\n             new_mv = rng.next_int(num_possible_moves);\n        } else {\n            // Slot occupied\n            uint32_t r_val = rng.next();\n            int type = r_val % 100;\n            \n            if (type < 5) {\n                // 5% Remove\n                new_mv = -1;\n            } else if (type < 35) {\n                // 30% Random Replacement\n                new_mv = rng.next_int(num_possible_moves);\n            } else if (type < 55) {\n                // 20% Swap Stamp\n                const auto& om = possible_moves[old_mv];\n                int nm = rng.next_int(M_in);\n                if (nm != om.m) {\n                    new_mv = nm * POSITIONS_TOTAL + om.p * POSITIONS_PER_ROW + om.q;\n                } else {\n                    new_mv = rng.next_int(num_possible_moves);\n                }\n            } else {\n                // 45% Shift\n                const auto& om = possible_moves[old_mv];\n                int dir = (r_val >> 8) & 3;\n                int np = om.p; \n                int nq = om.q;\n                if (dir == 0) np++;\n                else if (dir == 1) np--;\n                else if (dir == 2) nq++;\n                else nq--;\n                \n                if (np >= 0 && np < 7 && nq >= 0 && nq < 7) {\n                    new_mv = om.m * POSITIONS_TOTAL + np * POSITIONS_PER_ROW + nq;\n                } else {\n                    new_mv = -1; // Shifted off\n                }\n            }\n        }\n        \n        if (old_mv == new_mv) continue;\n        \n        // Delta Calc\n        int change_cnt = 0;\n        \n        // 1. Remove Old\n        if (old_mv != -1) {\n            const auto& m = possible_moves[old_mv];\n            for (int i = 0; i < 9; ++i) {\n                int idx = m.indices[i];\n                int v = board[idx];\n                int nv = v - m.values[i];\n                if (nv < 0) nv += MOD;\n                changes[change_cnt] = {(uint8_t)idx, v, nv};\n                pos_in_buffer[idx] = (int8_t)change_cnt;\n                change_cnt++;\n            }\n        }\n        \n        // 2. Add New\n        if (new_mv != -1) {\n            const auto& m = possible_moves[new_mv];\n            for (int i = 0; i < 9; ++i) {\n                int idx = m.indices[i];\n                int val_add = m.values[i];\n                int8_t pos = pos_in_buffer[idx];\n                if (pos != -1) {\n                    int nv = changes[pos].new_val + val_add;\n                    if (nv >= MOD) nv -= MOD;\n                    changes[pos].new_val = nv;\n                } else {\n                    int v = board[idx];\n                    int nv = v + val_add;\n                    if (nv >= MOD) nv -= MOD;\n                    changes[change_cnt] = {(uint8_t)idx, v, nv};\n                    pos_in_buffer[idx] = (int8_t)change_cnt;\n                    change_cnt++;\n                }\n            }\n        }\n        \n        long long delta = 0;\n        for (int i = 0; i < change_cnt; ++i) {\n            delta += (changes[i].new_val - changes[i].old_val);\n        }\n        \n        bool accept = (delta >= 0);\n        if (!accept) {\n             if (delta > -current_temp * 10.0) {\n                 if (rng.next_double() < exp(delta / current_temp)) accept = true;\n             }\n        }\n        \n        if (accept) {\n            current_score += delta;\n            current_ops[slot] = new_mv;\n            for (int i = 0; i < change_cnt; ++i) {\n                board[changes[i].idx] = changes[i].new_val;\n                pos_in_buffer[changes[i].idx] = -1;\n            }\n            if (current_score > best_score) {\n                best_score = current_score;\n                for (int k = 0; k < K_in; ++k) best_ops[k] = current_ops[k];\n            }\n        } else {\n            for (int i = 0; i < change_cnt; ++i) {\n                pos_in_buffer[changes[i].idx] = -1;\n            }\n        }\n    }\n    \n    // --- 3. Final Polish ---\n    \n    // Reload best state\n    for (int i = 0; i < TOTAL_CELLS; ++i) board[i] = initial_board[i];\n    current_score = 0;\n    for (int i = 0; i < TOTAL_CELLS; ++i) current_score += board[i];\n    for (int k = 0; k < K_in; ++k) {\n        current_ops[k] = best_ops[k];\n        apply_permanent(current_ops[k], true);\n    }\n    \n    // Very brief Hill Climbing if time permits\n    auto now = chrono::steady_clock::now();\n    if (chrono::duration<double>(now - start_clock).count() < 1.98) {\n        run_hill_climbing(1);\n    }\n    \n    // Final check\n    if (current_score > best_score) {\n        for(int k=0; k<K_in; ++k) best_ops[k] = current_ops[k];\n    }\n    \n    // Output\n    vector<FastMove> res;\n    res.reserve(K_in);\n    for (int i = 0; i < K_in; ++i) {\n        if (best_ops[i] != -1) res.push_back(possible_moves[best_ops[i]]);\n    }\n    cout << res.size() << \"\\n\";\n    for (const auto& m : res) cout << (int)m.m << \" \" << (int)m.p << \" \" << (int)m.q << \"\\n\";\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <deque>\n#include <cmath>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Coord {\n    int r, c;\n    bool operator==(const Coord& other) const { return r == other.r && c == other.c; }\n    bool operator!=(const Coord& other) const { return !(*this == other); }\n};\n\nstruct Crane {\n    Coord pos;\n    bool holding;\n    int container_id;\n};\n\nstruct State {\n    int grid[N][N];\n    deque<int> queues[N];\n    Crane crane;\n    vector<int> next_needed_val; \n    vector<bool> dispatched;\n    int items_on_grid;\n    vector<string> history;\n    int last_dispatch_turn;\n    int total_dispatched;\n\n    State() {\n        for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) grid[i][j] = -1;\n        items_on_grid = 0;\n        history.resize(N);\n        next_needed_val.resize(N);\n        for(int i=0; i<N; ++i) next_needed_val[i] = i * N;\n        dispatched.assign(N*N, false);\n        crane = {{0,0}, false, -1};\n        last_dispatch_turn = 0;\n        total_dispatched = 0;\n    }\n};\n\nint dist(Coord a, Coord b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\n// Advance next_needed pointers past already dispatched items\nvoid update_next_needed(State& st, int row) {\n    while (st.next_needed_val[row] < (row + 1) * N) {\n        if (st.dispatched[st.next_needed_val[row]]) {\n            st.next_needed_val[row]++;\n        } else {\n            break;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in;\n    if (!(cin >> n_in)) return 0;\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    State st;\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) st.queues[i].push_back(A[i][j]);\n    }\n\n    for (int turn = 1; turn <= MAX_TURNS; ++turn) {\n        // Check Completion\n        bool all_done = true;\n        for(int i=0; i<N; ++i) {\n            update_next_needed(st, i);\n            if(st.next_needed_val[i] < (i+1)*N) all_done = false;\n        }\n        if (all_done && st.items_on_grid == 0 && !st.crane.holding) break;\n\n        int turns_stuck = turn - st.last_dispatch_turn;\n        \n        // Panic Levels\n        bool panic_mild = (turns_stuck > 60);\n        bool panic_severe = (turns_stuck > 120);\n\n        // Refill Strategy: Stop adding items if grid is getting full or stuck\n        int refill_cap = 18;\n        if (panic_mild) refill_cap = 10;\n        if (panic_severe) refill_cap = 0;\n\n        // --- STEP 1: REFILL ---\n        if (st.items_on_grid < refill_cap) {\n            for(int i=0; i<N; ++i) {\n                if (!st.queues[i].empty()) {\n                    bool cell_free = (st.grid[i][0] == -1);\n                    bool crane_blocking = (st.crane.pos.r == i && st.crane.pos.c == 0 && st.crane.holding);\n                    if (cell_free && !crane_blocking) {\n                        st.grid[i][0] = st.queues[i].front();\n                        st.queues[i].pop_front();\n                        st.items_on_grid++;\n                    }\n                }\n            }\n        }\n\n        // --- STEP 2: CRANE ACTIONS ---\n        for(int i=1; i<N; ++i) st.history[i] += (turn == 1 ? 'B' : '.');\n        \n        char act = '.';\n        if (turn == 1) {\n            act = '.'; \n        } else {\n            Crane& c = st.crane;\n            if (c.holding) {\n                int held = c.container_id;\n                int r_owner = held / N;\n                int needed_val = st.next_needed_val[r_owner];\n                bool is_strict_next = (held == needed_val);\n                \n                Coord gate_dest = {r_owner, N-1};\n                \n                bool attempt_store = false;\n                \n                // LOGIC: Store or Evict?\n                if (!is_strict_next && !panic_severe) {\n                    int urgency = held - needed_val; \n                    // Allowable urgency scales with free space.\n                    // Empty grid -> High urgency allowed (store for later).\n                    // Full grid -> Only low urgency allowed (needed soon).\n                    int free_space = 20 - st.items_on_grid;\n                    int allowed_urgency = max(0, free_space / 2);\n                    \n                    if (panic_mild) allowed_urgency = 1; // Restrict storage in mild panic\n\n                    if (urgency <= allowed_urgency && st.items_on_grid <= 19) {\n                        attempt_store = true;\n                    }\n                }\n\n                Coord best_spot = {-1, -1};\n                if (attempt_store) {\n                    int min_d = 9999;\n                    // Try columns 1, 2, 3\n                    for(int cc : {1, 2, 3}) {\n                        for(int rr=0; rr<N; ++rr) {\n                            if (st.grid[rr][cc] == -1) {\n                                int d = dist(c.pos, {rr, cc});\n                                if (d < min_d) { min_d = d; best_spot = {rr, cc}; }\n                            }\n                        }\n                    }\n                    // Fallback to col 0 if grid is sparse\n                    if (best_spot.r == -1 && st.items_on_grid < 10) {\n                        for(int rr=0; rr<N; ++rr) {\n                            if (st.grid[rr][0] == -1) {\n                                int d = dist(c.pos, {rr, 0});\n                                if (d < min_d) { min_d = d; best_spot = {rr, 0}; }\n                            }\n                        }\n                    }\n                }\n\n                if (attempt_store && best_spot.r != -1) {\n                    // Store\n                    if (c.pos == best_spot) act = 'Q';\n                    else {\n                         if (c.pos.r < best_spot.r) act = 'D';\n                         else if (c.pos.r > best_spot.r) act = 'U';\n                         else if (c.pos.c < best_spot.c) act = 'R';\n                         else act = 'L';\n                    }\n                } else {\n                    // Deliver / Evict\n                    if (c.pos == gate_dest) act = 'Q';\n                    else {\n                        if (c.pos.r < gate_dest.r) act = 'D';\n                        else if (c.pos.r > gate_dest.r) act = 'U';\n                        else if (c.pos.c < gate_dest.c) act = 'R';\n                        else act = 'L';\n                    }\n                }\n            } else {\n                // PICKING LOGIC\n                Coord target = {-1, -1};\n                double best_score = 1e18; \n                \n                // Priority 1: Strict Next on Grid\n                for(int r=0; r<N; ++r) {\n                    for(int cc=0; cc<N; ++cc) {\n                        int id = st.grid[r][cc];\n                        if (id != -1 && id == st.next_needed_val[id/N]) {\n                             if (cc == N-1 && r == id/N) continue; // Already at gate\n                             double d = dist(c.pos, {r, cc});\n                             double score = d; \n                             if (score < best_score) { best_score = score; target = {r, cc}; }\n                        }\n                    }\n                }\n                \n                // Priority 2: Strict Next in Queue (Digging)\n                if (st.items_on_grid < refill_cap + 2) {\n                    for(int r=0; r<N; ++r) {\n                        int needed = st.next_needed_val[r];\n                        if (needed >= (r+1)*N) continue;\n                        \n                        for(int k=0; k<(int)st.queues[r].size(); ++k) {\n                            if (st.queues[r][k] == needed) {\n                                int depth_limit = panic_mild ? 0 : 4;\n                                if (k <= depth_limit && st.items_on_grid + k <= 20) {\n                                    double d = dist(c.pos, {r, 0});\n                                    double score = 1000.0 + d + k * 10.0; \n                                    if (score < best_score) { best_score = score; target = {r, 0}; }\n                                }\n                                break;\n                            }\n                        }\n                    }\n                }\n                \n                // Priority 3: Junk / Eviction\n                if (target.r == -1) {\n                    for(int cc : {1, 2, 3, 0}) {\n                        for(int r=0; r<N; ++r) {\n                            if (st.grid[r][cc] != -1) {\n                                int id = st.grid[r][cc];\n                                int r_owner = id/N;\n                                int needed = st.next_needed_val[r_owner];\n                                if (id == needed) continue; \n                                \n                                int urgency = id - needed; \n                                double d = dist(c.pos, {r, cc});\n                                \n                                // If severe panic, ignore urgency (0 weight) to just pick closest.\n                                // Otherwise, prefer low urgency items (weight 100) to reduce M1.\n                                double urgency_w = panic_severe ? 0.0 : 100.0;\n                                \n                                double score = 2000.0 + urgency * urgency_w + d;\n                                \n                                if (score < best_score) { best_score = score; target = {r, cc}; }\n                            }\n                        }\n                    }\n                }\n                \n                if (target.r != -1) {\n                    if (c.pos == target) {\n                        if (st.grid[target.r][target.c] != -1) act = 'P';\n                        else act = '.'; \n                    } else {\n                        if (c.pos.r < target.r) act = 'D';\n                        else if (c.pos.r > target.r) act = 'U';\n                        else if (c.pos.c < target.c) act = 'R';\n                        else act = 'L';\n                    }\n                }\n            }\n\n            if (act == 'U') st.crane.pos.r--;\n            else if (act == 'D') st.crane.pos.r++;\n            else if (act == 'L') st.crane.pos.c--;\n            else if (act == 'R') st.crane.pos.c++;\n            else if (act == 'P') {\n                st.crane.holding = true;\n                st.crane.container_id = st.grid[st.crane.pos.r][st.crane.pos.c];\n                st.grid[st.crane.pos.r][st.crane.pos.c] = -1;\n                st.items_on_grid--;\n            } else if (act == 'Q') {\n                st.crane.holding = false;\n                st.grid[st.crane.pos.r][st.crane.pos.c] = st.crane.container_id;\n                st.crane.container_id = -1;\n                st.items_on_grid++;\n            }\n        }\n        st.history[0] += act;\n\n        for(int i=0; i<N; ++i) {\n            int id = st.grid[i][N-1];\n            if (id != -1) {\n                st.grid[i][N-1] = -1;\n                st.items_on_grid--;\n                st.dispatched[id] = true;\n                st.last_dispatch_turn = turn;\n                st.total_dispatched++;\n            }\n        }\n    }\n\n    for(int i=0; i<N; ++i) cout << st.history[i] << endl;\n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <atcoder/mincostflow>\n#include <chrono>\n#include <random>\n#include <map>\n\nusing namespace std;\nusing namespace atcoder;\n\n// Directions: 0:U, 1:D, 2:L, 3:R\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nint N = 20;\nlong long grid_h[20][20];\n\nstruct Job {\n    int id;\n    int start_node;\n    int end_node;\n    long long amount;\n    int dist_start_end; \n};\n\nstruct TinyOp {\n    uint8_t type; \n    int val;      \n};\n\nstruct Result {\n    long long cost;\n    vector<TinyOp> ops;\n};\n\nstruct SearchParams {\n    double mcf_noise_factor; \n    double drop_base;\n    double drop_mult;\n    double pick_base;\n    double pick_mult;\n    double source_activity_weight;\n    double sink_activity_weight;\n    double load_weight_factor; \n    double hysteresis;\n    double pickup_delivery_weight; \n    double region_bonus; \n    double carried_centroid_weight;\n};\n\nmt19937 rng(12345);\n\nstruct Point { int r, c; };\nPoint node_coords[405];\nint node_region[405];\n\nvoid init_coords() {\n    for(int i=0; i<N*N; ++i) {\n        node_coords[i] = {i/N, i%N};\n        int rr = (i/N) / 5;\n        int rc = (i%N) / 5;\n        node_region[i] = rr * 4 + rc;\n    }\n}\n\ninline int fast_dist(int u, int v) {\n    return abs(node_coords[u].r - node_coords[v].r) + abs(node_coords[u].c - node_coords[v].c);\n}\n\nstruct EdgeInfo {\n    int to;\n    long long flow;\n};\n\n// Global buffers\nvector<int> parent_buf;\nvector<int> edge_index_buf;\nvector<vector<EdgeInfo>> flow_adj_buf;\n// Dynamic activity tracking\nvector<long long> source_activity(405), sink_activity(405);\n\nvoid init_buffers() {\n    parent_buf.resize(N * N + 2);\n    edge_index_buf.resize(N * N + 2);\n    flow_adj_buf.resize(N * N + 2);\n}\n\nResult solve_iteration(const SearchParams& p, long long cost_cutoff) {\n    mcf_graph<int, long long> g(N * N + 2);\n    int S = N * N;\n    int T = N * N + 1;\n    long long BASE_COST = 1000; \n    \n    bool use_noise = (p.mcf_noise_factor > 1e-9);\n    long long max_noise = (long long)(p.mcf_noise_factor * 100);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = i * N + j;\n            long long val = grid_h[i][j];\n            if (val > 0) {\n                g.add_edge(S, u, val, 0);\n            } else if (val < 0) {\n                g.add_edge(u, T, -val, 0);\n            }\n            \n            for (int k = 0; k < 4; k++) {\n                int ni = i + dr[k];\n                int nj = j + dc[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int v = ni * N + nj;\n                    long long cost = BASE_COST;\n                    if (use_noise) {\n                        cost += (long long)(rng() % (max_noise + 1));\n                    }\n                    g.add_edge(u, v, 1000000, cost);\n                }\n            }\n        }\n    }\n\n    g.flow(S, T);\n    \n    for(auto &v : flow_adj_buf) v.clear();\n    auto edges = g.edges();\n    for(const auto& e : edges) {\n        if(e.flow > 0) {\n             if (e.from == S || e.to == T || (e.from < N*N && e.to < N*N)) {\n                 flow_adj_buf[e.from].push_back({e.to, e.flow});\n             }\n        }\n    }\n\n    vector<Job> jobs;\n    jobs.reserve(N * 20);\n    queue<int> q;\n    \n    while(true) {\n        fill(parent_buf.begin(), parent_buf.end(), -1);\n        queue<int> empty; swap(q, empty);\n        q.push(S);\n        parent_buf[S] = S;\n        bool found = false;\n        \n        while(!q.empty()){\n            int u = q.front(); q.pop();\n            if(u == T) { found = true; break; }\n            \n            if (!flow_adj_buf[u].empty()) {\n                if (flow_adj_buf[u].size() > 1) {\n                    for (int i = flow_adj_buf[u].size() - 1; i > 0; i--) {\n                         int j = rng() % (i + 1);\n                         swap(flow_adj_buf[u][i], flow_adj_buf[u][j]);\n                    }\n                }\n                for(int i=0; i<(int)flow_adj_buf[u].size(); ++i) {\n                    EdgeInfo &e = flow_adj_buf[u][i];\n                    if(e.flow > 0 && parent_buf[e.to] == -1) {\n                        parent_buf[e.to] = u;\n                        edge_index_buf[e.to] = i;\n                        q.push(e.to);\n                    }\n                }\n            }\n        }\n        \n        if(!found) break;\n        \n        long long path_cap = 1e18;\n        int curr = T;\n        while(curr != S) {\n            int pr = parent_buf[curr];\n            int idx = edge_index_buf[curr];\n            path_cap = min(path_cap, flow_adj_buf[pr][idx].flow);\n            curr = pr;\n        }\n        \n        int u_start = -1, u_end = -1;\n        curr = T;\n        while(curr != S) {\n            int pr = parent_buf[curr];\n            int idx = edge_index_buf[curr];\n            flow_adj_buf[pr][idx].flow -= path_cap;\n            if(curr == T) u_end = pr;\n            if(pr == S) u_start = curr;\n            curr = pr;\n        }\n        jobs.push_back({0, u_start, u_end, path_cap, 0});\n    }\n\n    map<pair<int,int>, long long> merged_map;\n    for(const auto& j : jobs){\n        merged_map[{j.start_node, j.end_node}] += j.amount;\n    }\n    \n    jobs.clear();\n    jobs.reserve(merged_map.size());\n    \n    fill(source_activity.begin(), source_activity.end(), 0);\n    fill(sink_activity.begin(), sink_activity.end(), 0);\n\n    int id_cnt = 0;\n    for(auto& kv : merged_map){\n        int dist_se = fast_dist(kv.first.first, kv.first.second);\n        jobs.push_back({id_cnt++, kv.first.first, kv.first.second, kv.second, dist_se});\n        \n        source_activity[kv.first.first] += kv.second;\n        sink_activity[kv.first.second] += kv.second;\n    }\n    \n    // Simulation State\n    int truck_r = 0, truck_c = 0;\n    long long truck_load = 0;\n    vector<TinyOp> ops;\n    ops.reserve(50000);\n    long long total_cost = 0;\n    \n    // Dynamic Centroid Tracking\n    long long carried_r_sum = 0;\n    long long carried_c_sum = 0;\n    long long carried_amount_total = 0;\n    \n    vector<bool> is_picked(jobs.size(), false);\n    vector<int> active_indices;\n    active_indices.reserve(jobs.size());\n    for(int i=0; i<(int)jobs.size(); ++i) active_indices.push_back(i);\n    \n    int prev_target = -1;\n\n    while(!active_indices.empty()) {\n        if(ops.size() > 80000) return {2000000000000000000LL, {}};\n        if(total_cost >= cost_cutoff) return {total_cost, {}};\n\n        int u = truck_r * N + truck_c;\n        int current_region = node_region[u];\n        \n        long long unload_amt = 0;\n        long long load_amt = 0;\n        \n        for (int i = 0; i < (int)active_indices.size(); ) {\n            int idx = active_indices[i];\n            Job &j = jobs[idx];\n            bool done_now = false;\n\n            if(is_picked[idx]) {\n                if (j.end_node == u) {\n                    unload_amt += j.amount;\n                    truck_load -= j.amount;\n                    \n                    // Update Centroid\n                    carried_r_sum -= j.amount * node_coords[j.end_node].r;\n                    carried_c_sum -= j.amount * node_coords[j.end_node].c;\n                    carried_amount_total -= j.amount;\n                    \n                    // Update Activity\n                    sink_activity[j.end_node] -= j.amount;\n                    \n                    done_now = true;\n                }\n            } else {\n                if (j.start_node == u) {\n                    load_amt += j.amount;\n                    is_picked[idx] = true;\n                    truck_load += j.amount;\n                    \n                    // Update Centroid\n                    carried_r_sum += j.amount * node_coords[j.end_node].r;\n                    carried_c_sum += j.amount * node_coords[j.end_node].c;\n                    carried_amount_total += j.amount;\n                    \n                    // Update Activity\n                    source_activity[j.start_node] -= j.amount;\n                }\n            }\n\n            if (done_now) {\n                active_indices[i] = active_indices.back();\n                active_indices.pop_back();\n            } else {\n                i++;\n            }\n        }\n        \n        if (unload_amt > 0) {\n            ops.push_back({5, (int)unload_amt});\n            total_cost += unload_amt;\n        }\n        if (load_amt > 0) {\n            ops.push_back({4, (int)load_amt});\n            total_cost += load_amt;\n        }\n        \n        if(active_indices.empty()) break;\n        \n        // Target Selection\n        int best_target = -1;\n        double best_score = 1e18;\n        \n        // Calc Centroid position\n        int cent_r = -1, cent_c = -1;\n        if (carried_amount_total > 0) {\n            cent_r = carried_r_sum / carried_amount_total;\n            cent_c = carried_c_sum / carried_amount_total;\n        }\n        \n        for(int idx : active_indices) {\n            const Job &j = jobs[idx];\n            int target = -1;\n            bool is_drop = false;\n            \n            if(is_picked[idx]) {\n                target = j.end_node;\n                is_drop = true;\n            } else {\n                target = j.start_node;\n                is_drop = false;\n            }\n            \n            int d = fast_dist(u, target);\n            \n            // Move Cost\n            double score = d * (100.0 + truck_load * p.load_weight_factor);\n            \n            // Activity / Base Bonuses (Dynamic)\n            if(is_drop) {\n                score -= p.sink_activity_weight * sink_activity[target];\n                score += p.drop_base;\n                score += p.drop_mult * j.amount;\n            } else {\n                score -= p.source_activity_weight * source_activity[target];\n                score += p.pick_base;\n                score += p.pick_mult * j.amount;\n                score += p.pickup_delivery_weight * j.dist_start_end;\n            }\n            \n            // Hysteresis\n            if (target == prev_target) {\n                score -= p.hysteresis;\n            }\n            \n            // Region Bonus\n            if (node_region[target] == current_region) {\n                score -= p.region_bonus;\n            }\n            \n            // Centroid Attraction (only if carrying)\n            if (truck_load > 0 && cent_r != -1) {\n                int d_cent = abs(node_coords[target].r - cent_r) + abs(node_coords[target].c - cent_c);\n                score += p.carried_centroid_weight * d_cent;\n            }\n            \n            if(score < best_score) {\n                best_score = score;\n                best_target = target;\n            }\n        }\n        \n        if(best_target != -1) {\n            prev_target = best_target;\n            int tr = node_coords[best_target].r;\n            int tc = node_coords[best_target].c;\n            \n            int move_dir = -1;\n            vector<int> dirs;\n            if(tr < truck_r) dirs.push_back(0);\n            else if(tr > truck_r) dirs.push_back(1);\n            if(tc < truck_c) dirs.push_back(2);\n            else if(tc > truck_c) dirs.push_back(3);\n            \n            if(!dirs.empty()) {\n                move_dir = dirs[0];\n                if(dirs.size() > 1 && (rng() & 1)) move_dir = dirs[1];\n                \n                ops.push_back({(uint8_t)move_dir, 0});\n                total_cost += (100 + truck_load);\n                truck_r += dr[move_dir];\n                truck_c += dc[move_dir];\n            }\n        } else { break; }\n    }\n    \n    return {total_cost, ops};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    init_coords();\n    init_buffers();\n\n    if (cin >> N) {}\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> grid_h[i][j];\n        }\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n    double time_limit = 1.85;\n    \n    long long best_cost = 4e18; \n    vector<TinyOp> best_ops;\n    \n    // Baseline\n    {\n        SearchParams b;\n        b.mcf_noise_factor = 0;\n        b.drop_base = -600; b.drop_mult = -20;\n        b.pick_base = 0; b.pick_mult = 5;\n        b.source_activity_weight = 10.0; b.sink_activity_weight = 10.0;\n        b.load_weight_factor = 1.0;\n        b.hysteresis = 100.0;\n        b.pickup_delivery_weight = 0.0;\n        b.region_bonus = 200.0;\n        b.carried_centroid_weight = 10.0;\n        \n        Result r = solve_iteration(b, best_cost);\n        best_cost = r.cost;\n        best_ops = r.ops;\n    }\n    \n    while(true) {\n        auto now = chrono::high_resolution_clock::now();\n        chrono::duration<double> diff = now - start_time;\n        if(diff.count() > time_limit) break;\n        \n        SearchParams p;\n        p.mcf_noise_factor = uniform_real_distribution<double>(0.0, 25.0)(rng);\n        p.drop_base = uniform_real_distribution<double>(-2000.0, 0.0)(rng);\n        p.drop_mult = uniform_real_distribution<double>(-100.0, -5.0)(rng);\n        p.pick_base = uniform_real_distribution<double>(-400.0, 400.0)(rng);\n        p.pick_mult = uniform_real_distribution<double>(-15.0, 30.0)(rng);\n        p.source_activity_weight = uniform_real_distribution<double>(0.0, 60.0)(rng);\n        p.sink_activity_weight = uniform_real_distribution<double>(0.0, 60.0)(rng);\n        p.load_weight_factor = uniform_real_distribution<double>(0.8, 4.0)(rng);\n        p.hysteresis = uniform_real_distribution<double>(0.0, 600.0)(rng);\n        p.pickup_delivery_weight = uniform_real_distribution<double>(-20.0, 80.0)(rng);\n        p.region_bonus = uniform_real_distribution<double>(0.0, 500.0)(rng);\n        p.carried_centroid_weight = uniform_real_distribution<double>(0.0, 30.0)(rng);\n        \n        Result r = solve_iteration(p, best_cost);\n        \n        if(r.cost < best_cost) {\n            best_cost = r.cost;\n            best_ops = r.ops;\n        }\n    }\n    \n    for(auto& op : best_ops) {\n        if(op.type < 4) cout << dir_char[op.type] << \"\\n\";\n        else if(op.type == 4) cout << \"+\" << op.val << \"\\n\";\n        else cout << \"-\" << op.val << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <queue>\n\nusing namespace std;\n\n// --- Global Constants ---\nint N, M, T;\nint SEED_COUNT;     // 2*N*(N-1)\nint GRID_SIZE;      // N*N\n\n// --- Tunable Parameters ---\n// K_MIN: Minimum copies of max-value gene to preserve.\n// 2 provides a safety buffer against probabilistic loss.\nconst int K_MIN = 2; \n// K_TARGET_BASE: Base target for redundancy during early/mid game.\nconst int K_TARGET_BASE = 5; \n\n// Bonuses for selection scoring:\nconst long long BONUS_CRITICAL = 1e16; // Vital for preservation\nconst long long BONUS_TARGET = 1e9;    // Important for diversity/redundancy\nconst long long BONUS_CARRY = 50000;   // Incentive for carrying max genes\n\n// --- Structures ---\nstruct Seed {\n    int id;\n    vector<int> x;\n    int total_val;\n};\n\n// --- Random Engine ---\nmt19937 rng(5489u);\n\n// --- Timer Helper ---\nstruct Timer {\n    chrono::high_resolution_clock::time_point start;\n    double limit;\n    Timer(double l) : limit(l) {\n        start = chrono::high_resolution_clock::now();\n    }\n    double elapsed() {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - start).count();\n    }\n    bool check() {\n        return elapsed() < limit;\n    }\n};\n\n// --- Grid & Adjacency ---\nvector<vector<int>> adj;\nvector<int> degrees;\n\nvoid init_grid() {\n    GRID_SIZE = N * N;\n    adj.assign(GRID_SIZE, vector<int>());\n    degrees.assign(GRID_SIZE, 0);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            // Neighbor Down\n            if (r + 1 < N) {\n                int v = (r + 1) * N + c;\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            // Neighbor Right\n            if (c + 1 < N) {\n                int v = r * N + (c + 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n        }\n    }\n    for(int i=0; i<GRID_SIZE; ++i) degrees[i] = adj[i].size();\n}\n\n// --- Potential Calculation ---\n// Returns the sum of max attributes for two seeds.\n// Represents the best possible offspring they can produce.\ninline int calc_potential(const Seed& a, const Seed& b) {\n    int score = 0;\n    for (int k = 0; k < M; ++k) {\n        score += (a.x[k] > b.x[k]) ? a.x[k] : b.x[k];\n    }\n    return score;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> T)) return 0;\n    SEED_COUNT = 2 * N * (N - 1);\n    init_grid();\n\n    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        seeds[i].id = i;\n        seeds[i].x.resize(M);\n        seeds[i].total_val = 0;\n        for (int j = 0; j < M; ++j) {\n            cin >> seeds[i].x[j];\n            seeds[i].total_val += seeds[i].x[j];\n        }\n    }\n\n    vector<int> global_max(M);\n    vector<Seed> selected_seeds;\n    selected_seeds.reserve(GRID_SIZE);\n    vector<bool> used(SEED_COUNT);\n    vector<int> current_counts(M);\n    \n    // Nodes sorted by degree descending (heuristics)\n    vector<pair<int, int>> node_degrees(GRID_SIZE);\n    for(int i=0; i<GRID_SIZE; ++i) node_degrees[i] = { degrees[i], i };\n    sort(node_degrees.rbegin(), node_degrees.rend());\n\n    // Time budget per turn (Total 2.0s / 10 turns ~ 0.2s)\n    const double TIME_PER_TURN = 0.195; \n    \n    for (int t = 0; t < T; ++t) {\n        Timer timer(TIME_PER_TURN);\n\n        // 1. Global Max Identification\n        fill(global_max.begin(), global_max.end(), -1);\n        for(const auto& s : seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] > global_max[j]) global_max[j] = s.x[j];\n            }\n        }\n\n        // 2. Dynamic Target Calculation (Gradual Elitism)\n        // Increases k_target in the final 4 turns to shift towards pure quality/consolidation\n        int k_target = K_TARGET_BASE;\n        int turns_left = T - 1 - t;\n        if (turns_left <= 3) {\n             // Interpolation factor: 0.25, 0.5, 0.75, 1.0\n             double alpha = 1.0 - (double)turns_left / 4.0; \n             k_target = K_TARGET_BASE + (int)((GRID_SIZE - K_TARGET_BASE) * alpha);\n        }\n\n        // 3. Greedy Selection\n        selected_seeds.clear();\n        fill(used.begin(), used.end(), false);\n        fill(current_counts.begin(), current_counts.end(), 0);\n\n        for(int step = 0; step < GRID_SIZE; ++step) {\n            int best_idx = -1;\n            long long best_score = -1;\n\n            for(int k = 0; k < SEED_COUNT; ++k) {\n                if(used[k]) continue;\n\n                long long score = seeds[k].total_val; \n                \n                for(int j = 0; j < M; ++j) {\n                    if(seeds[k].x[j] == global_max[j]) {\n                        score += BONUS_CARRY; \n                        if(current_counts[j] < K_MIN) {\n                            score += BONUS_CRITICAL;\n                        } else if(current_counts[j] < k_target) {\n                            score += BONUS_TARGET;\n                        }\n                    }\n                }\n\n                if(score > best_score) {\n                    best_score = score;\n                    best_idx = k;\n                }\n            }\n\n            used[best_idx] = true;\n            selected_seeds.push_back(seeds[best_idx]);\n            for(int j = 0; j < M; ++j) {\n                if(seeds[best_idx].x[j] == global_max[j]) {\n                    current_counts[j]++;\n                }\n            }\n        }\n\n        // 4. Initialization: Greedy Constructive Heuristic\n        // Instead of random or simple sort, we build the grid.\n        // Start with the best seed at the center, then fill neighbors with best compatible seeds.\n        \n        // Calculate generic quality for tie-breaking\n        vector<long long> quality(GRID_SIZE);\n        vector<int> subset_max_counts(M, 0);\n        for(const auto& s : selected_seeds) {\n            for(int j=0; j<M; ++j) {\n                if(s.x[j] == global_max[j]) subset_max_counts[j]++;\n            }\n        }\n        for(int i=0; i<GRID_SIZE; ++i) {\n            long long q = selected_seeds[i].total_val;\n            for(int j=0; j<M; ++j) {\n                if(selected_seeds[i].x[j] == global_max[j]) {\n                    // Scarcity bonus\n                    q += (1000000000LL / (subset_max_counts[j] + 1));\n                }\n            }\n            quality[i] = q;\n        }\n\n        vector<int> layout(GRID_SIZE, -1);\n        vector<bool> seed_placed(GRID_SIZE, false);\n        vector<bool> node_occupied(GRID_SIZE, false);\n        \n        // Place seed with highest quality at the node with max degree (center)\n        int start_node = node_degrees[0].second;\n        int best_seed = -1;\n        long long max_q = -1;\n        for(int i=0; i<GRID_SIZE; ++i) {\n            if(quality[i] > max_q) {\n                max_q = quality[i];\n                best_seed = i;\n            }\n        }\n        layout[start_node] = best_seed;\n        seed_placed[best_seed] = true;\n        node_occupied[start_node] = true;\n\n        // Frontier list for BFS-like expansion\n        vector<int> frontier;\n        vector<bool> in_frontier(GRID_SIZE, false);\n\n        auto add_neighbors = [&](int u) {\n            for(int v : adj[u]) {\n                if(!node_occupied[v] && !in_frontier[v]) {\n                    frontier.push_back(v);\n                    in_frontier[v] = true;\n                }\n            }\n        };\n        add_neighbors(start_node);\n\n        for(int step = 1; step < GRID_SIZE; ++step) {\n            // Pick best node from frontier to fill next\n            // Heuristic: Prioritize nodes with more occupied neighbors, then degree\n            int best_node_idx = -1;\n            int best_occ_count = -1;\n            int best_deg = -1;\n\n            for(int i=0; i<(int)frontier.size(); ++i) {\n                int u = frontier[i];\n                int occ = 0;\n                for(int v : adj[u]) if(node_occupied[v]) occ++;\n                \n                if(occ > best_occ_count || (occ == best_occ_count && degrees[u] > best_deg)) {\n                    best_occ_count = occ;\n                    best_deg = degrees[u];\n                    best_node_idx = i;\n                }\n            }\n\n            int u = frontier[best_node_idx];\n            // Efficient removal from vector\n            frontier[best_node_idx] = frontier.back();\n            frontier.pop_back();\n            in_frontier[u] = false; \n\n            // Identify occupied neighbors seeds\n            vector<int> neighbors_seeds;\n            for(int v : adj[u]) {\n                if(node_occupied[v]) neighbors_seeds.push_back(layout[v]);\n            }\n\n            // Find best unplaced seed for this node\n            int best_s = -1;\n            long long best_s_score = -1;\n\n            for(int s=0; s<GRID_SIZE; ++s) {\n                if(seed_placed[s]) continue;\n                \n                long long score = 0;\n                // Sum potential with occupied neighbors\n                for(int ns : neighbors_seeds) {\n                    score += calc_potential(selected_seeds[s], selected_seeds[ns]);\n                }\n                // Tie-break with intrinsic quality\n                score = score * 10000 + (quality[s] % 10000);\n\n                if(score > best_s_score) {\n                    best_s_score = score;\n                    best_s = s;\n                }\n            }\n\n            layout[u] = best_s;\n            seed_placed[best_s] = true;\n            node_occupied[u] = true;\n            add_neighbors(u);\n        }\n\n        // 5. Precompute Potentials for SA\n        vector<vector<int>> potentials(GRID_SIZE, vector<int>(GRID_SIZE));\n        for(int i=0; i<GRID_SIZE; ++i) {\n            for(int j=i+1; j<GRID_SIZE; ++j) {\n                potentials[i][j] = potentials[j][i] = calc_potential(selected_seeds[i], selected_seeds[j]);\n            }\n        }\n\n        long long current_score = 0;\n        for (int u = 0; u < GRID_SIZE; ++u) {\n            for (int v : adj[u]) {\n                if (u < v) {\n                    current_score += potentials[layout[u]][layout[v]];\n                }\n            }\n        }\n\n        long long best_score = current_score;\n        vector<int> best_layout = layout;\n\n        // 6. Simulated Annealing\n        double t0 = 1200.0; \n        double t1 = 0.1;\n        \n        int iter = 0;\n        while(true) {\n            iter++;\n            if ((iter & 255) == 0) {\n                if (!timer.check()) break;\n            }\n\n            double progress = timer.elapsed() / TIME_PER_TURN;\n            if(progress >= 1.0) break;\n            double temp = t0 * pow(t1/t0, progress);\n\n            int c1 = rng() % GRID_SIZE;\n            int c2 = rng() % GRID_SIZE;\n            while (c1 == c2) c2 = rng() % GRID_SIZE;\n\n            int s1 = layout[c1];\n            int s2 = layout[c2];\n\n            long long delta = 0;\n            \n            for (int u : adj[c1]) {\n                if (u == c2) continue;\n                delta += (potentials[s2][layout[u]] - potentials[s1][layout[u]]);\n            }\n            for (int u : adj[c2]) {\n                if (u == c1) continue;\n                delta += (potentials[s1][layout[u]] - potentials[s2][layout[u]]);\n            }\n            \n            if (delta >= 0 || bernoulli_distribution(exp(delta / temp))(rng)) {\n                layout[c1] = s2;\n                layout[c2] = s1;\n                current_score += delta;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_layout = layout;\n                }\n            }\n        }\n\n        // 7. Output\n        vector<vector<int>> output_grid(N, vector<int>(N));\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                int cell = r*N + c;\n                int seed_idx = best_layout[cell];\n                output_grid[r][c] = selected_seeds[seed_idx].id;\n            }\n        }\n\n        for(int r=0; r<N; ++r) {\n            for(int c=0; c<N; ++c) {\n                cout << output_grid[r][c] << (c == N-1 ? \"\" : \" \");\n            }\n            cout << endl;\n        }\n        cout.flush();\n\n        // 8. Input Next Generation\n        for(int i=0; i<SEED_COUNT; ++i) {\n            seeds[i].id = i;\n            seeds[i].total_val = 0;\n            for(int j=0; j<M; ++j) {\n                cin >> seeds[i].x[j];\n                seeds[i].total_val += seeds[i].x[j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <tuple>\n#include <set>\n#include <map>\n\nusing namespace std;\n\n// --------------------------------------------------------\n// Constants & Globals\n// --------------------------------------------------------\nconst int MAX_N = 35;\nconst int DR[] = {0, 1, 0, -1};\nconst int DC[] = {1, 0, -1, 0};\nconst char MOVE_CHARS[] = {'R', 'D', 'L', 'U'};\n\nint N, M, V;\nint s_grid[MAX_N][MAX_N]; // Source grid\nint t_grid[MAX_N][MAX_N]; // Target grid (drop locations)\nint t_original[MAX_N][MAX_N]; // Tracks if a cell is originally a target\n\nint root_r, root_c;\nint turns = 0;\nint delivered_count = 0;\n\nstruct Leaf {\n    int id;\n    int len;\n    int dir; // 0:R, 1:D, 2:L, 3:U\n    bool holding;\n};\nvector<Leaf> leaves;\n\nstruct LockedTask {\n    bool active;\n    int leaf_idx;\n    int r, c; // Target coordinates\n    int root_r, root_c; // Intended root position\n};\nLockedTask current_lock = {false, -1, -1, -1, -1, -1};\n\n// --------------------------------------------------------\n// Helper Functions\n// --------------------------------------------------------\n\ninline pair<int, int> get_leaf_pos(int rr, int rc, int len, int dir) {\n    return {rr + DR[dir] * len, rc + DC[dir] * len};\n}\n\ninline int get_rot_diff(int current, int target) {\n    return (target - current + 4) % 4;\n}\n\nchar get_rot_cmd(int diff) {\n    if (diff == 0) return '.';\n    if (diff == 1) return 'R';\n    if (diff == 3) return 'L';\n    if (diff == 2) return 'R'; \n    return '.';\n}\n\ninline int get_rot_cost(int diff) {\n    if (diff == 0) return 0;\n    if (diff == 1 || diff == 3) return 1;\n    return 2;\n}\n\n// --------------------------------------------------------\n// Main\n// --------------------------------------------------------\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> V)) return 0;\n    \n    vector<string> s_in(N), t_in(N);\n    for(int i=0; i<N; ++i) cin >> s_in[i];\n    for(int i=0; i<N; ++i) cin >> t_in[i];\n\n    // Initialize Grids\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            bool is_s = (s_in[i][j] == '1');\n            bool is_t = (t_in[i][j] == '1');\n            t_original[i][j] = is_t ? 1 : 0;\n            \n            if (is_s && is_t) {\n                delivered_count++;\n                s_grid[i][j] = 0;\n                t_grid[i][j] = 0;\n            } else {\n                s_grid[i][j] = is_s ? 1 : 0;\n                t_grid[i][j] = is_t ? 1 : 0;\n            }\n        }\n    }\n    \n    // 1. Arm Design\n    // Strategy: Cyclic lengths 1..~N/2. \n    // This proved superior to small-length bias in previous tests.\n    cout << V << endl;\n    int max_len = max(1, (N + 1) / 2); \n    for(int i=1; i<V; ++i) {\n        int len = (i - 1) % max_len + 1; \n        cout << \"0 \" << len << endl;\n    }\n    \n    // Initial position: Center\n    root_r = N/2; \n    root_c = N/2;\n    cout << root_r << \" \" << root_c << endl;\n\n    // Initialize Leaf State\n    leaves.resize(V-1);\n    for(int i=0; i<V-1; ++i) {\n        leaves[i].id = i;\n        leaves[i].len = (i) % max_len + 1;\n        leaves[i].dir = 0;\n        leaves[i].holding = false;\n    }\n\n    // Main Simulation Loop\n    while (delivered_count < M && turns < 100000) {\n        \n        // Collect Active Targets\n        vector<pair<int,int>> picks, drops;\n        picks.reserve(M);\n        drops.reserve(M);\n        for(int r=0; r<N; ++r) for(int c=0; c<N; ++c) {\n            if (s_grid[r][c]) picks.push_back({r, c});\n            if (t_grid[r][c]) drops.push_back({r, c});\n        }\n\n        if (picks.empty() && drops.empty()) break;\n\n        // -------------------------------------------------\n        // Candidate Generation\n        // -------------------------------------------------\n        \n        // Validate Lock\n        if (current_lock.active) {\n            // Check bounds & existence\n            if (current_lock.r < 0 || current_lock.r >= N || current_lock.c < 0 || current_lock.c >= N) {\n                current_lock.active = false;\n            } else if (leaves[current_lock.leaf_idx].holding) {\n                if (!t_grid[current_lock.r][current_lock.c]) current_lock.active = false;\n            } else {\n                if (!s_grid[current_lock.r][current_lock.c]) current_lock.active = false;\n            }\n        }\n\n        struct Candidate {\n            int leaf_idx;\n            int r, c; // Target\n            int rr, rc; // Root\n            int leaf_dir;\n            double score;\n        };\n\n        vector<Candidate> candidates;\n        // Only consider a subset of targets closest to current root to speed up\n        int K = 6; \n\n        for(int i=0; i<V-1; ++i) {\n            const auto& targets = leaves[i].holding ? drops : picks;\n            if (targets.empty()) continue;\n\n            // Find closest K targets by Manhattan distance\n            vector<pair<int, int>> dists;\n            dists.reserve(targets.size());\n            for(int k=0; k<targets.size(); ++k) {\n                int d = abs(targets[k].first - root_r) + abs(targets[k].second - root_c);\n                dists.push_back({d, k});\n            }\n            \n            // Partial sort to get top K\n            int count = min((int)dists.size(), K);\n            partial_sort(dists.begin(), dists.begin() + count, dists.end());\n            \n            for(int k=0; k<count; ++k) {\n                auto& t = targets[dists[k].second];\n                // Try 4 approach directions\n                for(int d=0; d<4; ++d) {\n                    int rr = t.first - DR[d] * leaves[i].len;\n                    int rc = t.second - DC[d] * leaves[i].len;\n                    if (rr < 0 || rr >= N || rc < 0 || rc >= N) continue;\n                    \n                    int move_cost = abs(rr - root_r) + abs(rc - root_c);\n                    int rot_cost = get_rot_cost(get_rot_diff(leaves[i].dir, d));\n                    \n                    // Base score is max turns needed\n                    candidates.push_back({i, t.first, t.second, rr, rc, d, (double)max(move_cost, rot_cost)});\n                }\n            }\n        }\n\n        // Sort candidates by base score\n        int cand_limit = min((int)candidates.size(), 60);\n        partial_sort(candidates.begin(), candidates.begin() + cand_limit, candidates.end(), [](const Candidate& a, const Candidate& b){\n            return a.score < b.score;\n        });\n        candidates.resize(cand_limit);\n\n        // -------------------------------------------------\n        // Scoring Refinement (Lookahead & Hysteresis)\n        // -------------------------------------------------\n        Candidate best_cand = {-1, -1, -1, -1, -1, -1, 1e18};\n\n        for(auto& cand : candidates) {\n            double bonus = 0;\n            int primary_turns = (int)cand.score;\n            \n            // Hysteresis: persist with current lock unless significantly better option appears\n            if (current_lock.active && cand.leaf_idx == current_lock.leaf_idx && \n                cand.r == current_lock.r && cand.c == current_lock.c) {\n                bonus += 3.0; \n            }\n            \n            // Bias: Prefer Drops to prevent filling up\n            if (leaves[cand.leaf_idx].holding) bonus += 1.0;\n\n            // Parallelism: Check if other leaves can do something useful at destination (cand.rr, cand.rc)\n            // We check the 4 reachable cells for each other leaf.\n            for(int j=0; j<V-1; ++j) {\n                if (j == cand.leaf_idx) continue;\n                \n                for(int d=0; d<4; ++d) {\n                    int tip_r = cand.rr + DR[d] * leaves[j].len;\n                    int tip_c = cand.rc + DC[d] * leaves[j].len;\n                    \n                    if (tip_r < 0 || tip_r >= N || tip_c < 0 || tip_c >= N) continue;\n                    \n                    bool useful = false;\n                    if (leaves[j].holding) {\n                        if (t_grid[tip_r][tip_c]) useful = true;\n                    } else {\n                        if (s_grid[tip_r][tip_c]) useful = true;\n                    }\n\n                    if (useful) {\n                        int rot_needed = get_rot_cost(get_rot_diff(leaves[j].dir, d));\n                        // Action is parallel if rotation fits within movement time\n                        if (rot_needed <= primary_turns + 1) {\n                            double val = 2.0; // Base parallelism bonus\n                            if (leaves[j].holding) val += 1.0; // Priority for drop\n                            // Penalize if it slightly extends time (should rarely happen due to check)\n                            if (rot_needed > primary_turns) val -= 0.5;\n                            \n                            bonus += val;\n                            break; // Only count one potential action per leaf to avoid overestimation\n                        }\n                    }\n                }\n            }\n            \n            cand.score -= bonus;\n            if (cand.score < best_cand.score) {\n                best_cand = cand;\n            }\n        }\n\n        // Update Lock\n        if (best_cand.leaf_idx != -1) {\n            current_lock = {true, best_cand.leaf_idx, best_cand.r, best_cand.c, best_cand.rr, best_cand.rc};\n        } else {\n            // Should not happen if targets exist, but safe break\n            break;\n        }\n\n        // -------------------------------------------------\n        // Execution Step\n        // -------------------------------------------------\n        \n        // 1. Determine Root Movement\n        int move_dir = -1;\n        if (current_lock.root_r > root_r) move_dir = 1;\n        else if (current_lock.root_r < root_r) move_dir = 3;\n        else if (current_lock.root_c > root_c) move_dir = 0;\n        else if (current_lock.root_c < root_c) move_dir = 2;\n        \n        int next_rr = root_r + (move_dir == -1 ? 0 : DR[move_dir]);\n        int next_rc = root_c + (move_dir == -1 ? 0 : DC[move_dir]);\n\n        vector<char> rot_cmds(V-1, '.');\n        vector<char> act_cmds(V, '.');\n        vector<bool> leaf_busy(V-1, false);\n        vector<pair<int,int>> used_locs;\n\n        // 2. Opportunistic Actions (Immediate P/D)\n        // Order: Leaves holding items first (to Drop), then empty (to Pick)\n        vector<int> order(V-1);\n        for(int i=0; i<V-1; ++i) order[i] = i;\n        sort(order.begin(), order.end(), [&](int a, int b){\n            if (leaves[a].holding != leaves[b].holding) return leaves[a].holding > leaves[b].holding;\n            return leaves[a].len < leaves[b].len;\n        });\n\n        for(int i : order) {\n            int best_d = -1;\n            for(int d=0; d<4; ++d) {\n                int diff = get_rot_diff(leaves[i].dir, d);\n                if (diff == 2) continue; // Cannot do 180 turn instantly\n\n                auto [tr, tc] = get_leaf_pos(next_rr, next_rc, leaves[i].len, d);\n                if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n                \n                // Collision Check\n                bool collision = false;\n                for(auto& u : used_locs) if(u.first == tr && u.second == tc) collision = true;\n                if(collision) continue;\n\n                if(leaves[i].holding) {\n                    if(t_grid[tr][tc]) { best_d = d; break; }\n                } else {\n                    if(s_grid[tr][tc]) { best_d = d; break; }\n                }\n            }\n            \n            if (best_d != -1) {\n                leaf_busy[i] = true;\n                rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, best_d));\n                act_cmds[i+1] = 'P';\n                used_locs.push_back(get_leaf_pos(next_rr, next_rc, leaves[i].len, best_d));\n            }\n        }\n\n        // 3. Rotate Primary Leaf (if not busy)\n        if (best_cand.leaf_idx != -1 && !leaf_busy[best_cand.leaf_idx]) {\n            rot_cmds[best_cand.leaf_idx] = get_rot_cmd(get_rot_diff(leaves[best_cand.leaf_idx].dir, best_cand.leaf_dir));\n            leaf_busy[best_cand.leaf_idx] = true;\n        }\n\n        // 4. Rotate Idle Leaves towards future utility\n        // They aim for useful targets relative to the DESTINATION root pos\n        if (best_cand.leaf_idx != -1) {\n            int dest_r = best_cand.rr;\n            int dest_c = best_cand.rc;\n            \n            for(int i=0; i<V-1; ++i) {\n                if (leaf_busy[i]) continue;\n                \n                int best_d = -1;\n                int min_cost = 10;\n\n                // Check all 4 directions for utility\n                for(int d=0; d<4; ++d) {\n                    int tr = dest_r + DR[d] * leaves[i].len;\n                    int tc = dest_c + DC[d] * leaves[i].len;\n                    \n                    if (tr < 0 || tr >= N || tc < 0 || tc >= N) continue;\n\n                    bool has_target = false;\n                    if (leaves[i].holding) { if (t_grid[tr][tc]) has_target = true; }\n                    else { if (s_grid[tr][tc]) has_target = true; }\n\n                    if (has_target) {\n                        int cost = get_rot_cost(get_rot_diff(leaves[i].dir, d));\n                        if (cost < min_cost) {\n                            min_cost = cost;\n                            best_d = d;\n                        }\n                    }\n                }\n                \n                if (best_d != -1) {\n                     rot_cmds[i] = get_rot_cmd(get_rot_diff(leaves[i].dir, best_d));\n                }\n            }\n        }\n\n        // -------------------------------------------------\n        // Output & State Update\n        // -------------------------------------------------\n        cout << (move_dir == -1 ? '.' : MOVE_CHARS[move_dir]);\n        for(char c : rot_cmds) cout << c;\n        for(int k=0; k<V; ++k) cout << act_cmds[k];\n        cout << \"\\n\";\n\n        // Update positions/directions\n        root_r = next_rr;\n        root_c = next_rc;\n        for(int i=0; i<V-1; ++i) {\n            if (rot_cmds[i] == 'R') leaves[i].dir = (leaves[i].dir + 1) % 4;\n            else if (rot_cmds[i] == 'L') leaves[i].dir = (leaves[i].dir + 3) % 4;\n            \n            // Handle Pick/Drop\n            if (act_cmds[i+1] == 'P') {\n                auto [tr, tc] = get_leaf_pos(root_r, root_c, leaves[i].len, leaves[i].dir);\n                if (leaves[i].holding) {\n                    if (tr>=0 && tr<N && tc>=0 && tc<N && t_grid[tr][tc]) {\n                        t_grid[tr][tc] = 0;\n                        delivered_count++;\n                        leaves[i].holding = false;\n                    }\n                } else {\n                    if (tr>=0 && tr<N && tc>=0 && tc<N && s_grid[tr][tc]) {\n                        s_grid[tr][tc] = 0;\n                        // If the picked spot was originally a target, mark it as open target\n                        if (t_original[tr][tc]) t_grid[tr][tc] = 1;\n                        leaves[i].holding = true;\n                    }\n                }\n            }\n        }\n\n        turns++;\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <set>\n#include <queue>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int MAX_COORD = 100000;\nconst long long MAX_PERIMETER = 400000;\nconst int MAX_VERTICES = 1000;\nconst double TIME_LIMIT = 1.95; \n\nstruct Point {\n    int x, y;\n};\n\nint N;\nvector<Point> mackerels;\nvector<Point> sardines;\n\nlong long start_time;\nlong long get_time_ms() {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(\n        std::chrono::steady_clock::now().time_since_epoch()).count();\n}\n\ntypedef vector<Point> Polygon;\n\n// Global buffer variables to reduce allocation overhead\nvector<int> _grid_score_buf;\nvector<uint8_t> _active_buf;\nvector<uint8_t> _visited_buf;\nvector<int> _q_buf;\nvector<int> _smooth_buf;\n\n// Optimized Ray Casting\nbool is_inside(const Polygon& poly, const Point& p) {\n    bool inside = false;\n    size_t n = poly.size();\n    for (size_t i = 0; i < n; ++i) {\n        const Point& p1 = poly[i];\n        const Point& p2 = poly[(i + 1) % n];\n        if (p1.x == p2.x) { \n            if (p1.x == p.x && p.y >= min(p1.y, p2.y) && p.y <= max(p1.y, p2.y)) return true;\n        } else { \n             if (p1.y == p.y && p.x >= min(p1.x, p2.x) && p.x <= max(p1.x, p2.x)) return true;\n        }\n        if ((p1.y > p.y) != (p2.y > p.y)) {\n            long long dy = p2.y - p1.y;\n            long long dx = p2.x - p1.x;\n            long long lhs = dx * (p.y - p1.y);\n            long long rhs = (long long)(p.x - p1.x) * dy;\n            if (dy > 0) { if (rhs < lhs) inside = !inside; }\n            else { if (rhs > lhs) inside = !inside; }\n        }\n    }\n    return inside;\n}\n\nint raw_score_poly(const Polygon& poly) {\n    if (poly.empty()) return 0;\n    int m = 0, s = 0;\n    int min_x = MAX_COORD, max_x = 0, min_y = MAX_COORD, max_y = 0;\n    for (const auto& p : poly) {\n        min_x = min(min_x, p.x); max_x = max(max_x, p.x);\n        min_y = min(min_y, p.y); max_y = max(max_y, p.y);\n    }\n    for (const auto& p : mackerels) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) m++;\n    }\n    for (const auto& p : sardines) {\n        if (p.x < min_x || p.x > max_x || p.y < min_y || p.y > max_y) continue;\n        if (is_inside(poly, p)) s++;\n    }\n    return m - s;\n}\n\nlong long perimeter(const Polygon& poly) {\n    long long perim = 0;\n    size_t n = poly.size();\n    for (size_t i = 0; i < n; ++i) {\n        perim += abs(poly[i].x - poly[(i + 1) % n].x) + abs(poly[i].y - poly[(i + 1) % n].y);\n    }\n    return perim;\n}\n\nstruct GridSolver {\n    int cell_size;\n    int offset_x, offset_y;\n    int GX, GY;\n    mt19937& rng;\n    int bb_min_x, bb_max_x, bb_min_y, bb_max_y;\n    \n    GridSolver(int cs, int ox, int oy, mt19937& r) : cell_size(cs), offset_x(ox), offset_y(oy), rng(r) {\n        GX = (MAX_COORD + offset_x) / cell_size + 2; \n        GY = (MAX_COORD + offset_y) / cell_size + 2;\n        int sz = GX * GY;\n        if (_grid_score_buf.size() < (size_t)sz) _grid_score_buf.resize(sz);\n        if (_active_buf.size() < (size_t)sz) _active_buf.resize(sz);\n        if (_visited_buf.size() < (size_t)sz) _visited_buf.resize(sz);\n        \n        fill(_grid_score_buf.begin(), _grid_score_buf.begin() + sz, 0);\n        fill(_active_buf.begin(), _active_buf.begin() + sz, 0);\n    }\n    \n    inline int idx(int x, int y) const { return x * GY + y; }\n    \n    void build(double sardine_weight) {\n        for (const auto& p : mackerels) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) _grid_score_buf[idx(gx, gy)]++;\n        }\n        int sardine_penalty = (int)(sardine_weight * 1.0 + 0.5);\n        for (const auto& p : sardines) {\n            int gx = (p.x + offset_x) / cell_size;\n            int gy = (p.y + offset_y) / cell_size;\n            if (gx >= 0 && gx < GX && gy >= 0 && gy < GY) _grid_score_buf[idx(gx, gy)] -= sardine_penalty;\n        }\n    }\n    \n    void threshold_and_smooth(int smooth_mode, int thresh) {\n        if (smooth_mode > 0) {\n            if (_smooth_buf.size() < _grid_score_buf.size()) _smooth_buf.resize(_grid_score_buf.size());\n            int center_w = (smooth_mode == 1 ? 2 : 3);\n            for(int x=0; x<GX; ++x) {\n                for(int y=0; y<GY; ++y) {\n                    int sum = 0;\n                    int base = idx(x, y);\n                    if(x>0) {\n                        if(y>0) sum += _grid_score_buf[base-GY-1];\n                        sum += _grid_score_buf[base-GY];\n                        if(y<GY-1) sum += _grid_score_buf[base-GY+1];\n                    }\n                    if(y>0) sum += _grid_score_buf[base-1];\n                    sum += _grid_score_buf[base] * center_w;\n                    if(y<GY-1) sum += _grid_score_buf[base+1];\n                    if(x<GX-1) {\n                        if(y>0) sum += _grid_score_buf[base+GY-1];\n                        sum += _grid_score_buf[base+GY];\n                        if(y<GY-1) sum += _grid_score_buf[base+GY+1];\n                    }\n                    _smooth_buf[base] = sum;\n                }\n            }\n            for(int i=0; i<GX*GY; ++i) _active_buf[i] = (_smooth_buf[i] > thresh);\n        } else {\n            for(int i=0; i<GX*GY; ++i) _active_buf[i] = (_grid_score_buf[i] > thresh);\n        }\n        \n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                long long xR = (long long)(x + 1) * cell_size - offset_x;\n                long long xL = (long long)x * cell_size - offset_x;\n                long long yR = (long long)(y + 1) * cell_size - offset_y;\n                long long yL = (long long)y * cell_size - offset_y;\n                if (xR <= 0 || xL >= MAX_COORD || yR <= 0 || yL >= MAX_COORD) _active_buf[idx(x,y)] = 0;\n            }\n        }\n    }\n    \n    void repair_topology() {\n        for(int iter=0; iter<2; ++iter) {\n            bool changed = false;\n            for(int x=0; x<GX-1; ++x) {\n                int base = idx(x, 0);\n                for(int y=0; y<GY-1; ++y) {\n                    int bl = base + y; int tl = bl + 1;\n                    int br = bl + GY; int tr = br + 1;\n                    int cnt = _active_buf[bl] + _active_buf[br] + _active_buf[tl] + _active_buf[tr];\n                    if (cnt == 2) {\n                        if (_active_buf[bl] && _active_buf[tr]) {\n                            if (_grid_score_buf[tl] >= _grid_score_buf[br]) _active_buf[tl] = 1; else _active_buf[br] = 1;\n                            changed = true;\n                        } else if (_active_buf[tl] && _active_buf[br]) {\n                            if (_grid_score_buf[tr] >= _grid_score_buf[bl]) _active_buf[tr] = 1; else _active_buf[bl] = 1;\n                            changed = true;\n                        }\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n    }\n    \n    inline bool safe_remove(int x, int y) {\n        int c = idx(x, y);\n        bool n = (y+1 < GY) && _active_buf[c+1];\n        bool s = (y > 0) && _active_buf[c-1];\n        bool e = (x+1 < GX) && _active_buf[c+GY];\n        bool w = (x > 0) && _active_buf[c-GY];\n        \n        if (n && s && !e && !w) return false;\n        if (e && w && !n && !s) return false;\n        if (n && s && e && w) return false; \n        \n        bool ne = (x+1 < GX && y+1 < GY) && _active_buf[c+GY+1];\n        bool se = (x+1 < GX && y > 0) && _active_buf[c+GY-1];\n        bool sw = (x > 0 && y > 0) && _active_buf[c-GY-1];\n        bool nw = (x > 0 && y+1 < GY) && _active_buf[c-GY+1];\n        \n        if (n && e && !ne) return false; \n        if (e && s && !se) return false;\n        if (s && w && !sw) return false;\n        if (w && n && !nw) return false;\n        return true;\n    }\n\n    inline bool safe_add(int x, int y) {\n        int c = idx(x, y);\n        bool n = (y+1 < GY) && _active_buf[c+1];\n        bool s = (y > 0) && _active_buf[c-1];\n        bool e = (x+1 < GX) && _active_buf[c+GY];\n        bool w = (x > 0) && _active_buf[c-GY];\n        if (!n && !s && !e && !w) return false; \n        \n        bool ne = (x+1 < GX && y+1 < GY) && _active_buf[c+GY+1];\n        bool se = (x+1 < GX && y > 0) && _active_buf[c+GY-1];\n        bool sw = (x > 0 && y > 0) && _active_buf[c-GY-1];\n        bool nw = (x > 0 && y+1 < GY) && _active_buf[c-GY+1];\n        if (!n && !e && ne) return false;\n        if (!e && !s && se) return false;\n        if (!s && !w && sw) return false;\n        if (!w && !n && nw) return false;\n        return true;\n    }\n\n    void optimize_passes_bbox(int passes) {\n        for(int iter=0; iter<passes; ++iter) {\n            bool changed = false;\n            int x_start = max(0, bb_min_x - 1);\n            int x_end = min(GX, bb_max_x + 2);\n            int y_start = max(0, bb_min_y - 1);\n            int y_end = min(GY, bb_max_y + 2);\n            \n            // Forward\n            for(int x=x_start; x<x_end; ++x) {\n                for(int y=y_start; y<y_end; ++y) {\n                    int i = idx(x, y);\n                    if (_active_buf[i]) {\n                        if (_grid_score_buf[i] < 0) {\n                            if (safe_remove(x, y)) { _active_buf[i] = 0; changed = true; }\n                        }\n                    } else {\n                        if (_grid_score_buf[i] > 0) {\n                            long long xR = (long long)(x + 1) * cell_size - offset_x;\n                            long long xL = (long long)x * cell_size - offset_x;\n                            long long yR = (long long)(y + 1) * cell_size - offset_y;\n                            long long yL = (long long)y * cell_size - offset_y;\n                            if (xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                                if (safe_add(x, y)) { _active_buf[i] = 1; changed = true; }\n                            }\n                        }\n                    }\n                }\n            }\n            // Backward\n             for(int x=x_end-1; x>=x_start; --x) {\n                for(int y=y_end-1; y>=y_start; --y) {\n                    int i = idx(x, y);\n                    if (_active_buf[i]) {\n                        if (_grid_score_buf[i] < 0) {\n                            if (safe_remove(x, y)) { _active_buf[i] = 0; changed = true; }\n                        }\n                    } else {\n                        if (_grid_score_buf[i] > 0) {\n                            long long xR = (long long)(x + 1) * cell_size - offset_x;\n                            long long xL = (long long)x * cell_size - offset_x;\n                            long long yR = (long long)(y + 1) * cell_size - offset_y;\n                            long long yL = (long long)y * cell_size - offset_y;\n                            if (xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                                if (safe_add(x, y)) { _active_buf[i] = 1; changed = true; }\n                            }\n                        }\n                    }\n                }\n            }\n            if (!changed) break;\n            update_bbox(); \n        }\n    }\n    \n    void optimize_passes_global(int passes) {\n        int total = GX * GY;\n        int stride = 49279; \n        int start = rng() % total;\n        for(int iter=0; iter<passes; ++iter) {\n            bool changed = false;\n            start = (start + 12345) % total; \n            for(int i=0; i<total; ++i) {\n                int curr = (start + i * stride) % total;\n                int x = curr / GY;\n                int y = curr % GY;\n                if (_active_buf[curr]) {\n                    if (_grid_score_buf[curr] < 0 && safe_remove(x, y)) { _active_buf[curr] = 0; changed = true; }\n                } else {\n                    if (_grid_score_buf[curr] > 0) {\n                        long long xR = (long long)(x + 1) * cell_size - offset_x;\n                        long long xL = (long long)x * cell_size - offset_x;\n                        long long yR = (long long)(y + 1) * cell_size - offset_y;\n                        long long yL = (long long)y * cell_size - offset_y;\n                        if (xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                            if (safe_add(x, y)) { _active_buf[curr] = 1; changed = true; }\n                        }\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    void update_bbox() {\n        bb_min_x = GX; bb_max_x = -1;\n        bb_min_y = GY; bb_max_y = -1;\n        for(int x=0; x<GX; ++x) {\n            for(int y=0; y<GY; ++y) {\n                if (_active_buf[idx(x,y)]) {\n                    if(x < bb_min_x) bb_min_x = x;\n                    if(x > bb_max_x) bb_max_x = x;\n                    if(y < bb_min_y) bb_min_y = y;\n                    if(y > bb_max_y) bb_max_y = y;\n                }\n            }\n        }\n    }\n    \n    int calculate_current_grid_score() {\n        int s = 0; \n        int x_start = max(0, bb_min_x);\n        int x_end = min(GX, bb_max_x + 1);\n        int y_start = max(0, bb_min_y);\n        int y_end = min(GY, bb_max_y + 1);\n        for(int x=x_start; x<x_end; ++x) {\n            for(int y=y_start; y<y_end; ++y) {\n                int i = idx(x, y);\n                if (_active_buf[i]) s += _grid_score_buf[i];\n            }\n        }\n        return s;\n    }\n    \n    void kick() {\n        int moves = 0;\n        int max_moves = 5 + rng() % 10;\n        for(int i=0; i<500; ++i) { \n            if (moves >= max_moves) break;\n            int w = (bb_max_x - bb_min_x + 3);\n            int h = (bb_max_y - bb_min_y + 3);\n            if (w<=0 || h<=0) break;\n            int dx = rng() % w;\n            int dy = rng() % h;\n            int x = max(0, min(GX-1, bb_min_x - 1 + dx));\n            int y = max(0, min(GY-1, bb_min_y - 1 + dy));\n            int curr = idx(x, y);\n            \n            if (_active_buf[curr]) {\n                if (safe_remove(x, y)) { _active_buf[curr] = 0; moves++; }\n            } else {\n                long long xR = (long long)(x + 1) * cell_size - offset_x;\n                long long xL = (long long)x * cell_size - offset_x;\n                long long yR = (long long)(y + 1) * cell_size - offset_y;\n                long long yL = (long long)y * cell_size - offset_y;\n                if (xR > 0 && xL < MAX_COORD && yR > 0 && yL < MAX_COORD) {\n                    if (safe_add(x, y)) { _active_buf[curr] = 1; moves++; }\n                }\n            }\n        }\n        update_bbox();\n    }\n\n    void prune_tips() {\n        bool changed = true;\n        while(changed) {\n            changed = false;\n            int x_start = max(0, bb_min_x);\n            int x_end = min(GX, bb_max_x + 1);\n            int y_start = max(0, bb_min_y);\n            int y_end = min(GY, bb_max_y + 1);\n            for(int x=x_start; x<x_end; ++x) {\n                for(int y=y_start; y<y_end; ++y) {\n                    int c = idx(x, y);\n                    if (_active_buf[c]) {\n                        int neighbors = 0;\n                        if(y+1 < GY && _active_buf[c+1]) neighbors++;\n                        if(y > 0 && _active_buf[c-1]) neighbors++;\n                        if(x+1 < GX && _active_buf[c+GY]) neighbors++;\n                        if(x > 0 && _active_buf[c-GY]) neighbors++;\n                        \n                        if (neighbors <= 1) {\n                            if (safe_remove(x, y)) {\n                                _active_buf[c] = 0;\n                                changed = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        update_bbox();\n    }\n    \n    void fill_dents() {\n        bool changed = true;\n        while(changed) {\n            changed = false;\n            int x_start = max(0, bb_min_x - 1);\n            int x_end = min(GX, bb_max_x + 2);\n            int y_start = max(0, bb_min_y - 1);\n            int y_end = min(GY, bb_max_y + 2);\n            \n            for(int x=x_start; x<x_end; ++x) {\n                for(int y=y_start; y<y_end; ++y) {\n                    int i = idx(x, y);\n                    if (!_active_buf[i]) {\n                        int neighbors = 0;\n                        if(y+1 < GY && _active_buf[i+1]) neighbors++;\n                        if(y > 0 && _active_buf[i-1]) neighbors++;\n                        if(x+1 < GX && _active_buf[i+GY]) neighbors++;\n                        if(x > 0 && _active_buf[i-GY]) neighbors++;\n                        \n                        if (neighbors >= 3) {\n                            if (_grid_score_buf[i] >= -2) { // Allow slight score penalty to simplify shape\n                                if (safe_add(x, y)) {\n                                    _active_buf[i] = 1;\n                                    changed = true;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        update_bbox();\n    }\n\n    Polygon solve(int smooth_mode, int thresh) {\n        threshold_and_smooth(smooth_mode, thresh);\n        repair_topology();\n        optimize_passes_global(3);\n        \n        int best_root = -1;\n        int best_c_score = -1e9;\n        int sz = GX*GY;\n        fill(_visited_buf.begin(), _visited_buf.begin() + sz, 0);\n        \n        _q_buf.clear();\n        for(int i=0; i<sz; ++i) {\n            if (_active_buf[i] && !_visited_buf[i]) {\n                int current_score = 0;\n                _q_buf.clear(); _q_buf.push_back(i);\n                _visited_buf[i] = 1;\n                int head = 0;\n                while(head < (int)_q_buf.size()) {\n                    int curr = _q_buf[head++];\n                    current_score += _grid_score_buf[curr];\n                    int cx = curr / GY; int cy = curr % GY;\n                    if (cy+1 < GY && _active_buf[curr+1] && !_visited_buf[curr+1]) { _visited_buf[curr+1]=1; _q_buf.push_back(curr+1); }\n                    if (cy > 0 && _active_buf[curr-1] && !_visited_buf[curr-1]) { _visited_buf[curr-1]=1; _q_buf.push_back(curr-1); }\n                    if (cx+1 < GX && _active_buf[curr+GY] && !_visited_buf[curr+GY]) { _visited_buf[curr+GY]=1; _q_buf.push_back(curr+GY); }\n                    if (cx > 0 && _active_buf[curr-GY] && !_visited_buf[curr-GY]) { _visited_buf[curr-GY]=1; _q_buf.push_back(curr-GY); }\n                }\n                if (current_score > best_c_score) {\n                    best_c_score = current_score;\n                    best_root = i;\n                }\n            }\n        }\n        \n        if (best_root == -1) return {};\n        \n        fill(_visited_buf.begin(), _visited_buf.begin() + sz, 0);\n        _q_buf.clear(); _q_buf.push_back(best_root);\n        _visited_buf[best_root] = 1;\n        int head = 0;\n        while(head < (int)_q_buf.size()) {\n            int curr = _q_buf[head++];\n            int cx = curr / GY; int cy = curr % GY;\n            if (cy+1 < GY && _active_buf[curr+1] && !_visited_buf[curr+1]) { _visited_buf[curr+1]=1; _q_buf.push_back(curr+1); }\n            if (cy > 0 && _active_buf[curr-1] && !_visited_buf[curr-1]) { _visited_buf[curr-1]=1; _q_buf.push_back(curr-1); }\n            if (cx+1 < GX && _active_buf[curr+GY] && !_visited_buf[curr+GY]) { _visited_buf[curr+GY]=1; _q_buf.push_back(curr+GY); }\n            if (cx > 0 && _active_buf[curr-GY] && !_visited_buf[curr-GY]) { _visited_buf[curr-GY]=1; _q_buf.push_back(curr-GY); }\n        }\n        for(int i=0; i<sz; ++i) _active_buf[i] = _visited_buf[i];\n        update_bbox();\n        \n        vector<uint8_t> best_config = _active_buf;\n        int max_score = calculate_current_grid_score();\n        \n        for(int restart=0; restart<2; ++restart) {\n            optimize_passes_bbox(4);\n            int s = calculate_current_grid_score();\n            if (s > max_score) { max_score = s; best_config = _active_buf; }\n            kick();\n        }\n        for(int i=0; i<sz; ++i) _active_buf[i] = best_config[i];\n        optimize_passes_bbox(3);\n        \n        // Attempt to simplify shape\n        fill_dents();\n\n        auto get_poly = [&]() -> Polygon {\n            if (bb_max_x < bb_min_x) return {};\n            int min_x = GX, min_y = GY;\n            for(int x=bb_min_x; x<=bb_max_x; ++x) {\n                for(int y=bb_min_y; y<=bb_max_y; ++y) {\n                    if (_active_buf[idx(x, y)]) {\n                         if (y < min_y || (y == min_y && x < min_x)) { min_x = x; min_y = y; }\n                    }\n                }\n            }\n            if (min_x == GX) return {};\n\n            int vx = min_x, vy = min_y;\n            int dir = 0; \n            vector<pair<int,int>> path;\n            path.push_back({vx, vy});\n            int start_vx = vx, start_vy = vy;\n            int steps = 0;\n            bool closed = false;\n            \n            auto check = [&](int cx, int cy) { \n                if(cx < 0 || cx >= GX || cy < 0 || cy >= GY) return 0;\n                return (int)_active_buf[idx(cx, cy)];\n            };\n            \n            do {\n                int search_order[] = {(dir + 1) % 4, dir, (dir + 3) % 4, (dir + 2) % 4};\n                int next_dir = -1;\n                for (int nd : search_order) {\n                    int lx, ly, rx, ry;\n                    if (nd == 0) { lx=vx; ly=vy; rx=vx; ry=vy-1; }\n                    else if (nd == 1) { lx=vx-1; ly=vy; rx=vx; ry=vy; }\n                    else if (nd == 2) { lx=vx-1; ly=vy-1; rx=vx-1; ry=vy; }\n                    else { lx=vx; ly=vy-1; rx=vx-1; ry=vy-1; }\n                    if (check(lx, ly) && !check(rx, ry)) { next_dir = nd; break; }\n                }\n                if (next_dir == -1) return {};\n                dir = next_dir;\n                if (dir == 0) vx++; else if (dir == 1) vy++; else if (dir == 2) vx--; else vy--;\n                path.push_back({vx, vy});\n                steps++;\n                if (steps > 20000) return {}; \n                if (vx == start_vx && vy == start_vy) closed = true;\n            } while (!closed);\n            \n            path.pop_back();\n            if (path.empty()) return {};\n            \n            vector<Point> simple_poly;\n            auto get_pt = [&](pair<int,int> p) {\n                long long X = (long long)p.first * cell_size - offset_x;\n                long long Y = (long long)p.second * cell_size - offset_y;\n                return Point{(int)clamp(X, 0LL, (long long)MAX_COORD), (int)clamp(Y, 0LL, (long long)MAX_COORD)};\n            };\n            \n            simple_poly.push_back(get_pt(path[0]));\n            for(size_t i=1; i<path.size(); ++i) {\n                Point curr = get_pt(path[i]);\n                Point prev = simple_poly.back();\n                if (simple_poly.size() >= 2) {\n                    Point pprev = simple_poly[simple_poly.size()-2];\n                    bool pv = (prev.x == pprev.x), cv = (curr.x == prev.x);\n                    bool ph = (prev.y == pprev.y), ch = (curr.y == prev.y);\n                    if ((pv && cv) || (ph && ch)) simple_poly.back() = curr;\n                    else simple_poly.push_back(curr);\n                } else simple_poly.push_back(curr);\n            }\n            if (simple_poly.size() > 2) {\n                Point f = simple_poly[0], l = simple_poly.back(), p = simple_poly[simple_poly.size()-2];\n                bool lv = (l.x==p.x), cv = (f.x==l.x);\n                bool lh = (l.y==p.y), ch = (f.y==l.y);\n                if ((lv && cv) || (lh && ch)) { simple_poly.pop_back(); l = simple_poly.back(); }\n                Point s = simple_poly[1];\n                bool fv = (s.x==f.x), ncv = (f.x==l.x);\n                bool fh = (s.y==f.y), nch = (f.y==l.y);\n                if ((fv && ncv) || (fh && nch)) simple_poly.erase(simple_poly.begin());\n            }\n            return simple_poly;\n        };\n        \n        Polygon p = get_poly();\n        if (p.size() > MAX_VERTICES) {\n            prune_tips();\n            p = get_poly();\n        }\n        return p;\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    start_time = get_time_ms();\n    \n    if (!(cin >> N)) return 0;\n    mackerels.resize(N);\n    for(int i=0; i<N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    sardines.resize(N);\n    for(int i=0; i<N; ++i) cin >> sardines[i].x >> sardines[i].y;\n    \n    Polygon best_poly = {{0,0}, {1,0}, {1,1}, {0,1}};\n    int best_score = 0;\n    \n    mt19937 rng(1337);\n    vector<int> grid_sizes = {5000, 2500, 1000, 4000, 2000, 800, 1500, 3000, 1200, 600};\n    \n    int iter = 0;\n    while (get_time_ms() - start_time < TIME_LIMIT * 1000) {\n        iter++;\n        int cs;\n        if (iter <= (int)grid_sizes.size()) cs = grid_sizes[iter-1];\n        else cs = 500 + (rng() % 5500);\n        \n        int ox = rng() % cs;\n        int oy = rng() % cs;\n        int smooth = rng() % 3;\n        int thresh = (smooth > 0) ? (rng() % 5) : 0;\n        // Vary sardine weight slightly\n        double sw = 1.0 + (rng() % 100) / 200.0; // 1.0 to 1.5\n        \n        GridSolver solver(cs, ox, oy, rng);\n        solver.build(sw);\n        Polygon poly = solver.solve(smooth, thresh);\n        \n        if (poly.size() < 4) continue;\n        if (poly.size() <= MAX_VERTICES && perimeter(poly) <= MAX_PERIMETER) {\n            int s = raw_score_poly(poly);\n            if (s > best_score) {\n                best_score = s;\n                best_poly = poly;\n            }\n        }\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <iomanip>\n\nusing namespace std;\n\n// --- Constants ---\nconst int MAX_N = 105;\nconst int MAX_K = 3500; \nconst double TIME_LIMIT = 2.95;\nconst int CHILDREN_LIMIT = 3; // Max candidates per parent to preserve diversity\n\n// --- Globals ---\nint N, T, sigma_val;\nint w_prime[MAX_N], h_prime[MAX_N];\ndouble w_est[MAX_N], h_est[MAX_N];\ndouble w_orig[MAX_N], h_orig[MAX_N];\n\nstruct RectInt {\n    int x, y, w, h;\n};\n\nstruct Op {\n    short p, r, d, b;\n};\n\nstruct State {\n    RectInt rects[MAX_N]; \n    int W, H;\n    long long s1; // Primary: W + H\n    long long s2; // Secondary: W * H\n    int s3;       // Tertiary: |W - H|\n};\n\nstruct HistoryNode {\n    short parent_idx;\n    Op op;\n};\n\nstruct Candidate {\n    short parent_idx;\n    short r, d, b;\n    RectInt geometry;\n    long long s1, s2;\n    int s3;\n    \n    bool operator<(const Candidate& other) const {\n        if (s1 != other.s1) return s1 < other.s1;\n        if (s2 != other.s2) return s2 < other.s2;\n        return s3 < other.s3;\n    }\n};\n\n// Buffers\nState beam_buffers[2][MAX_K];\nHistoryNode history[MAX_N][MAX_K]; \nCandidate candidates[MAX_K * CHILDREN_LIMIT + 1000]; \nCandidate local_cands[MAX_N * 4]; // Temporary buffer per parent\npair<int, int> coord_buf[MAX_N];\n\nauto start_time = chrono::steady_clock::now();\n\n// Optimized Collision Check\ninline pair<int, int> get_pos(int idx, int d, int b, int rw, int rh, const RectInt* __restrict rects) {\n    int x = 0, y = 0;\n    if (d == 0) { // U\n        if (b != -1) x = rects[b].x + rects[b].w;\n        y = 0;\n        for (int j = 0; j < idx; ++j) {\n            if (x < rects[j].x + rects[j].w && x + rw > rects[j].x) {\n                int bot = rects[j].y + rects[j].h;\n                if (bot > y) y = bot;\n            }\n        }\n    } else { // L\n        if (b != -1) y = rects[b].y + rects[b].h;\n        x = 0;\n        for (int j = 0; j < idx; ++j) {\n            if (y < rects[j].y + rects[j].h && y + rh > rects[j].y) {\n                int right = rects[j].x + rects[j].w;\n                if (right > x) x = right;\n            }\n        }\n    }\n    return {x, y};\n}\n\nvoid solve() {\n    for(int i=0; i<N; ++i) {\n        w_est[i] = w_prime[i];\n        h_est[i] = h_prime[i];\n        w_orig[i] = w_prime[i];\n        h_orig[i] = h_prime[i];\n    }\n\n    for (int t = 0; t < T; ++t) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining_time = TIME_LIMIT - elapsed;\n        if (remaining_time < 0.01) remaining_time = 0.01;\n        \n        double ops_budget = remaining_time * 6.0e7;\n        double cost_per_turn_unit = (double)N * N * N / 2.0;\n        \n        int K = (int)(ops_budget / ((T - t) * cost_per_turn_unit));\n        \n        if (K < 5) K = 5;\n        if (K > MAX_K) K = MAX_K;\n        if (N > 80 && K > 50) K = 50; \n        if (N > 60 && K > 200) K = 200;\n\n        int curr = 0;\n        int prev = 1;\n        \n        beam_buffers[curr][0].W = 0;\n        beam_buffers[curr][0].H = 0;\n        beam_buffers[curr][0].s1 = 0;\n        beam_buffers[curr][0].s2 = 0;\n        beam_buffers[curr][0].s3 = 0;\n        int beam_size = 1;\n        \n        for (int i = 0; i < N; ++i) {\n            swap(curr, prev);\n            int global_cand_count = 0;\n            int max_global_cands = MAX_K * CHILDREN_LIMIT;\n            \n            int dims[2][2];\n            dims[0][0] = max(1, (int)lround(w_est[i])); dims[0][1] = max(1, (int)lround(h_est[i]));\n            dims[1][0] = dims[0][1]; dims[1][1] = dims[0][0];\n            \n            for (int s = 0; s < beam_size; ++s) {\n                if (global_cand_count >= max_global_cands) break;\n                \n                const State& S = beam_buffers[prev][s];\n                int local_count = 0;\n                \n                // Direction U\n                int c_len = 0;\n                coord_buf[c_len++] = {0, -1};\n                for(int j=0; j<i; ++j) coord_buf[c_len++] = {S.rects[j].x + S.rects[j].w, j};\n                sort(coord_buf, coord_buf + c_len);\n                int uniq = 1;\n                for(int k=1; k<c_len; ++k) if(coord_buf[k].first != coord_buf[k-1].first) coord_buf[uniq++] = coord_buf[k];\n                \n                for(int k=0; k<uniq; ++k) {\n                    int b = coord_buf[k].second;\n                    for(int r=0; r<2; ++r) {\n                        int rw = dims[r][0], rh = dims[r][1];\n                        pair<int, int> pos = get_pos(i, 0, b, rw, rh, S.rects);\n                        int nW = max(S.W, pos.first + rw);\n                        int nH = max(S.H, pos.second + rh);\n                        local_cands[local_count++] = {\n                            (short)s, (short)r, 0, (short)b,\n                            {pos.first, pos.second, rw, rh},\n                            (long long)nW + nH, (long long)nW * nH, abs(nW - nH)\n                        };\n                    }\n                }\n                \n                // Direction L\n                c_len = 0;\n                coord_buf[c_len++] = {0, -1};\n                for(int j=0; j<i; ++j) coord_buf[c_len++] = {S.rects[j].y + S.rects[j].h, j};\n                sort(coord_buf, coord_buf + c_len);\n                uniq = 1;\n                for(int k=1; k<c_len; ++k) if(coord_buf[k].first != coord_buf[k-1].first) coord_buf[uniq++] = coord_buf[k];\n                \n                for(int k=0; k<uniq; ++k) {\n                    int b = coord_buf[k].second;\n                    for(int r=0; r<2; ++r) {\n                        int rw = dims[r][0], rh = dims[r][1];\n                        pair<int, int> pos = get_pos(i, 1, b, rw, rh, S.rects);\n                        int nW = max(S.W, pos.first + rw);\n                        int nH = max(S.H, pos.second + rh);\n                        local_cands[local_count++] = {\n                            (short)s, (short)r, 1, (short)b,\n                            {pos.first, pos.second, rw, rh},\n                            (long long)nW + nH, (long long)nW * nH, abs(nW - nH)\n                        };\n                    }\n                }\n                \n                int keep_local = min(local_count, CHILDREN_LIMIT);\n                if (local_count > keep_local) {\n                    partial_sort(local_cands, local_cands + keep_local, local_cands + local_count);\n                } else {\n                    sort(local_cands, local_cands + local_count);\n                }\n                \n                for(int k=0; k<keep_local; ++k) {\n                    if (global_cand_count < max_global_cands) {\n                        candidates[global_cand_count++] = local_cands[k];\n                    }\n                }\n            }\n            \n            int keep_global = min(global_cand_count, K);\n            if (global_cand_count > K) {\n                nth_element(candidates, candidates + K, candidates + global_cand_count);\n            }\n            sort(candidates, candidates + keep_global);\n            \n            for(int k=0; k<keep_global; ++k) {\n                const Candidate& c = candidates[k];\n                State& ns = beam_buffers[curr][k];\n                const State& ps = beam_buffers[prev][c.parent_idx];\n                \n                if (i > 0) memcpy(ns.rects, ps.rects, sizeof(RectInt) * i);\n                \n                ns.rects[i] = c.geometry;\n                ns.W = max(ps.W, c.geometry.x + c.geometry.w);\n                ns.H = max(ps.H, c.geometry.y + c.geometry.h);\n                ns.s1 = c.s1; ns.s2 = c.s2; ns.s3 = c.s3;\n                \n                history[i][k] = { c.parent_idx, {(short)i, c.r, c.d, c.b} };\n            }\n            beam_size = keep_global;\n        }\n        \n        vector<Op> result_ops(N);\n        int track_idx = 0;\n        const State& best_state = beam_buffers[curr][0];\n        \n        for (int i = N - 1; i >= 0; --i) {\n            HistoryNode& h = history[i][track_idx];\n            result_ops[i] = h.op;\n            track_idx = h.parent_idx;\n        }\n        \n        cout << N << \"\\n\";\n        for(const auto& op : result_ops) {\n            cout << op.p << \" \" << op.r << \" \" << (op.d==0?'U':'L') << \" \" << op.b << \"\\n\";\n        }\n        cout << flush;\n        \n        int W_obs, H_obs;\n        if(!(cin >> W_obs >> H_obs)) break;\n        \n        int diff_W = W_obs - best_state.W;\n        int diff_H = H_obs - best_state.H;\n        \n        static int px[MAX_N], py[MAX_N];\n        for(int i=0; i<N; ++i) px[i] = py[i] = -1;\n        \n        for(int i=0; i<N; ++i) {\n            const auto& op = result_ops[i];\n            const auto& r = best_state.rects[i];\n            if(op.d == 0) {\n                px[i] = op.b;\n                int bk = -1, mv = 0;\n                for(int k=0; k<i; ++k) {\n                    if(best_state.rects[k].x < r.x + r.w && best_state.rects[k].x + best_state.rects[k].w > r.x) {\n                        int v = best_state.rects[k].y + best_state.rects[k].h;\n                        if(v > mv) { mv = v; bk = k; }\n                    }\n                }\n                py[i] = bk;\n            } else {\n                py[i] = op.b;\n                int bk = -1, mv = 0;\n                for(int k=0; k<i; ++k) {\n                    if(best_state.rects[k].y < r.y + r.h && best_state.rects[k].y + best_state.rects[k].h > r.y) {\n                        int v = best_state.rects[k].x + best_state.rects[k].w;\n                        if(v > mv) { mv = v; bk = k; }\n                    }\n                }\n                px[i] = bk;\n            }\n        }\n        \n        static bool crit[MAX_N];\n        double lr = 0.55;\n        \n        int cw = 0;\n        fill(crit, crit+N, false);\n        vector<int> q; q.reserve(N);\n        for(int i=0; i<N; ++i) if(best_state.rects[i].x + best_state.rects[i].w == best_state.W) { crit[i]=true; q.push_back(i); }\n        int hd = 0;\n        while(hd < (int)q.size()){\n            int u = q[hd++];\n            int p = px[u];\n            if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n        }\n        for(int i=0; i<N; ++i) if(crit[i]) cw++;\n        if(cw > 0) {\n            double d = (double)diff_W / cw * lr;\n            for(int i=0; i<N; ++i) if(crit[i]) {\n                if(result_ops[i].r == 0) w_est[i] += d; else h_est[i] += d;\n            }\n        }\n        \n        int ch = 0;\n        fill(crit, crit+N, false);\n        q.clear();\n        for(int i=0; i<N; ++i) if(best_state.rects[i].y + best_state.rects[i].h == best_state.H) { crit[i]=true; q.push_back(i); }\n        hd = 0;\n        while(hd < (int)q.size()){\n            int u = q[hd++];\n            int p = py[u];\n            if(p!=-1 && !crit[p]) { crit[p]=true; q.push_back(p); }\n        }\n        for(int i=0; i<N; ++i) if(crit[i]) ch++;\n        if(ch > 0) {\n            double d = (double)diff_H / ch * lr;\n            for(int i=0; i<N; ++i) if(crit[i]) {\n                if(result_ops[i].r == 0) h_est[i] += d; else w_est[i] += d;\n            }\n        }\n        \n        double lim = 3.0 * sigma_val;\n        for(int i=0; i<N; ++i) {\n            w_est[i] = min(w_orig[i]+lim, max(w_orig[i]-lim, w_est[i]));\n            h_est[i] = min(h_orig[i]+lim, max(h_orig[i]-lim, h_est[i]));\n            if(w_est[i] < 1) w_est[i] = 1;\n            if(h_est[i] < 1) h_est[i] = 1;\n            if(w_est[i] > 1e9) w_est[i] = 1e9;\n            if(h_est[i] > 1e9) h_est[i] = 1e9;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    if(cin >> N >> T >> sigma_val) {\n        for(int i=0; i<N; ++i) cin >> w_prime[i] >> h_prime[i];\n        solve();\n    }\n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <cstring>\n\nusing namespace std;\n\n// Problem Constants\nconst int MAXN = 1005;\nconst int H_LIMIT = 10;\n\n// Global Data\nint N, M, H_in;\nint A[MAXN];\nvector<int> adj[MAXN];\n\n// Solution State\nint p[MAXN];                  // Parent of u (-1 if root)\nint S[MAXN];                  // Sum of A in subtree u\nint d_max[MAXN];              // Height of subtree u (max distance to leaf)\nint cnt_h[MAXN][H_LIMIT + 5]; // cnt_h[u][h] = number of children with height contribution h\n\n// Random Generator\nmt19937 rng(12345);\n\n// Helper: Get depth of u (root is 0, returns -1 if u is -1)\n// Complexity: O(H)\nint get_depth(int u) {\n    int d = -1;\n    while (u != -1) {\n        d++;\n        u = p[u];\n    }\n    return d;\n}\n\n// Helper: Check if 'ancestor' is an ancestor of 'node'\n// Used to detect cycles (if we make 'node' the parent of 'ancestor', it's a cycle)\n// Complexity: O(H)\nbool is_ancestor(int ancestor, int node) {\n    if (ancestor == -1) return false;\n    if (ancestor == node) return true;\n    while (node != -1) {\n        if (node == ancestor) return true;\n        node = p[node];\n    }\n    return false;\n}\n\n// Forward declarations for recursive stat updates\nvoid add_stat(int u, int h_val);\nvoid remove_stat(int u, int h_val);\n\n// Add height contribution 'h_val' to node u and propagate changes up\nvoid add_stat(int u, int h_val) {\n    if (u == -1) return;\n    cnt_h[u][h_val]++;\n    \n    // If the new child path is deeper than current max\n    if (h_val > d_max[u]) {\n        int old_h = d_max[u];\n        d_max[u] = h_val;\n        // Propagate change: remove old contribution from parent, add new\n        remove_stat(p[u], old_h + 1);\n        add_stat(p[u], d_max[u] + 1);\n    }\n}\n\n// Remove height contribution 'h_val' from node u and propagate changes up\nvoid remove_stat(int u, int h_val) {\n    if (u == -1) return;\n    cnt_h[u][h_val]--;\n    \n    // If the removed path was defining the max height, we might need to reduce d_max\n    if (h_val == d_max[u]) {\n        if (cnt_h[u][h_val] == 0) {\n            int old_h = d_max[u];\n            int new_h = 0;\n            // Scan downwards to find the new max height\n            for (int k = old_h - 1; k >= 0; --k) {\n                if (cnt_h[u][k] > 0) {\n                    new_h = k;\n                    break;\n                }\n            }\n            d_max[u] = new_h;\n            // Propagate change\n            remove_stat(p[u], old_h + 1);\n            add_stat(p[u], d_max[u] + 1);\n        }\n    }\n}\n\n// Update Sum of Beauty values upwards\nvoid update_S(int u, int diff) {\n    while (u != -1) {\n        S[u] += diff;\n        u = p[u];\n    }\n}\n\n// Reset all state variables\nvoid clear_state() {\n    fill(p, p + N, -1);\n    copy(A, A + N, S);\n    fill(d_max, d_max + N, 0);\n    for(int i=0; i<N; ++i) {\n        memset(cnt_h[i], 0, sizeof(cnt_h[i]));\n    }\n}\n\n// Calculate total score for validation/best tracking\nlong long calculate_total_score() {\n    long long sc = 0;\n    for (int i = 0; i < N; ++i) {\n        sc += (long long)(get_depth(i) + 1) * A[i];\n    }\n    return sc;\n}\n\nint main() {\n    // Optimize I/O\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    if (!(cin >> N >> M >> H_in)) return 0;\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for (int i = 0; i < N; ++i) { int x, y; cin >> x >> y; }\n\n    auto start_time = chrono::steady_clock::now();\n\n    // ---------------------------------------------------------\n    // Phase 1: Randomized Greedy Construction\n    // ---------------------------------------------------------\n    vector<int> best_p(N);\n    long long best_score = -1;\n    int greedy_trials = 100; // Number of restarts\n\n    for (int t = 0; t < greedy_trials; ++t) {\n        clear_state();\n        \n        // Order vertices by Beauty (A), with noise for diversity\n        // Heuristic: Process smaller A first (likely to be roots/shallow), larger A later (deep).\n        vector<pair<float, int>> order(N);\n        for (int i = 0; i < N; ++i) {\n            float key = A[i];\n            if (t > 0) {\n                key *= (1.0f + std::uniform_real_distribution<float>(0.0f, 0.8f)(rng));\n            }\n            order[i] = {key, i};\n        }\n        sort(order.begin(), order.end());\n\n        for (auto& op : order) {\n            int v = op.second;\n            int best_u = -1;\n            int best_depth_val = -1;\n\n            vector<int>& neighbors = adj[v];\n            // Randomized start index for neighbor traversal\n            int start_idx = (t == 0) ? 0 : (rng() % (neighbors.size() + 1)); \n            if (neighbors.empty()) continue;\n\n            for(size_t k=0; k<neighbors.size(); ++k) {\n                int idx = (k + start_idx) % neighbors.size();\n                int u = neighbors[idx];\n                \n                // Check Cycle: u cannot be in v's subtree (v is ancestor of u)\n                if (is_ancestor(v, u)) continue; \n                \n                int depth_u = get_depth(u);\n                // Check Height: depth(u) + 1 + subtree_height(v) <= H\n                if (depth_u + 1 + d_max[v] <= H_in) {\n                    if (depth_u + 1 > best_depth_val) {\n                        best_depth_val = depth_u + 1;\n                        best_u = u;\n                        // Optimization: If we reached max possible improvement (greedy), stop\n                        if (best_depth_val == H_in - d_max[v]) break; \n                    }\n                }\n            }\n\n            if (best_u != -1) {\n                p[v] = best_u;\n                update_S(best_u, S[v]);\n                add_stat(best_u, d_max[v] + 1);\n            }\n        }\n\n        long long current_score = calculate_total_score();\n        if (current_score > best_score) {\n            best_score = current_score;\n            for(int i=0; i<N; ++i) best_p[i] = p[i];\n        }\n    }\n\n    // ---------------------------------------------------------\n    // Phase 2: Simulated Annealing\n    // ---------------------------------------------------------\n    \n    // Restore best greedy state\n    clear_state();\n    for(int i=0; i<N; ++i) p[i] = best_p[i];\n    \n    // Efficiently rebuild S, d_max, and cnt_h bottom-up\n    vector<vector<int>> kids(N);\n    for(int i=0; i<N; ++i) if (p[i] != -1) kids[p[i]].push_back(i);\n    \n    vector<int> depth(N);\n    vector<vector<int>> nodes_by_depth(H_in + 2);\n    for(int i=0; i<N; ++i) {\n        depth[i] = get_depth(i);\n        int d_idx = min(depth[i], H_in + 1);\n        nodes_by_depth[d_idx].push_back(i);\n    }\n    \n    // Bottom-up traversal to set stats\n    for (int d = H_in; d >= 0; --d) {\n        for (int u : nodes_by_depth[d]) {\n            S[u] = A[u];\n            d_max[u] = 0;\n            for (int c : kids[u]) {\n                S[u] += S[c];\n                int h_c = d_max[c] + 1;\n                if (h_c <= H_in + 1) {\n                    cnt_h[u][h_c]++;\n                    if (h_c > d_max[u]) d_max[u] = h_c;\n                }\n            }\n        }\n    }\n\n    // SA Configuration\n    double time_limit = 1.96;\n    double T0 = 300.0; \n    double T1 = 0.05;\n    const double time_mult = log(T1/T0) / time_limit;\n    \n    int iter = 0;\n    while (true) {\n        iter++;\n        if ((iter & 2047) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        // 1. Pick random node v\n        int v = rng() % N;\n        int old_parent = p[v];\n        \n        // 2. Pick random candidate parent u\n        int u = -1;\n        if (!adj[v].empty()) {\n            // 3% chance to detach and become root, otherwise pick neighbor\n            if ((rng() & 31) == 0) u = -1;\n            else u = adj[v][rng() % adj[v].size()];\n        }\n        \n        if (u == old_parent) continue;\n        \n        // 3. Validity Checks\n        // Cycle: is v an ancestor of u?\n        if (is_ancestor(v, u)) continue; \n        \n        // Height: new depth + subtree height <= H\n        int u_depth = get_depth(u);\n        int new_depth_v = u_depth + 1;\n        \n        if (new_depth_v + d_max[v] > H_in) continue;\n        \n        // 4. Score Delta\n        // Delta = (new_depth - old_depth) * SubtreeSum(v)\n        int old_depth_v = get_depth(old_parent) + 1;\n        long long diff = (long long)(new_depth_v - old_depth_v) * S[v];\n        \n        // 5. Acceptance\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            double T = T0 * exp(time_mult * elapsed);\n            if (generate_canonical<double, 10>(rng) < exp(diff / T)) {\n                accept = true;\n            }\n        }\n        \n        // 6. Apply Move\n        if (accept) {\n            if (old_parent != -1) {\n                update_S(old_parent, -S[v]);\n                remove_stat(old_parent, d_max[v] + 1);\n            }\n            p[v] = u;\n            if (u != -1) {\n                update_S(u, S[v]);\n                add_stat(u, d_max[v] + 1);\n            }\n        }\n    }\n\n    // Output\n    for(int i=0; i<N; ++i) cout << p[i] << (i==N-1?\"\":\" \");\n    cout << endl;\n\n    return 0;\n}","ahc042":"#pragma GCC optimize(\"O3,unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <array>\n#include <random>\n#include <cstring>\n#include <bit>\n#include <chrono>\n\nusing namespace std;\n\n// Constants\nconst int N = 20;\nconst int MAX_OPS = 4 * N * N;\nconst int INF = 1000000;\nconst char DIR_CHARS[] = {'L', 'R', 'U', 'D'};\n\n// Beam Search Settings\n// Reduced beam width and pool size to fit safely within 2.0s\nint BEAM_WIDTH = 600;\nconst int MAX_NODES = 1500000; \n\n// Dedup Table: Simple Hash Set with 4M entries (16MB)\n// Using Open Addressing with Linear Probing logic embedded\nstruct DedupEntry {\n    uint64_t key;\n    uint16_t cost;\n};\nconst int TABLE_SIZE = 1 << 22; // 4M\nconst int TABLE_MASK = TABLE_SIZE - 1;\nDedupEntry* dedup_table;\n\n// Timing\nauto start_time = chrono::high_resolution_clock::now();\ninline double get_time() {\n    return chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n}\n\n// Zobrist\nuint64_t zobrist[N][N][3];\nvoid init_zobrist() {\n    mt19937_64 rng(1337);\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) for(int k=0; k<3; ++k) zobrist[i][j][k] = rng();\n}\n\n// Compact Board (Rows Only)\nstruct CompactBoard {\n    uint32_t r_oni[N];\n    uint32_t r_fuku[N];\n    uint64_t hash;\n};\n\n// Full Board (Rows + Cols)\nstruct FullBoard {\n    uint32_t r_oni[N];\n    uint32_t r_fuku[N];\n    uint32_t c_oni[N];\n    uint32_t c_fuku[N];\n    uint64_t hash;\n\n    void load(const CompactBoard& cb) {\n        memcpy(r_oni, cb.r_oni, sizeof(r_oni));\n        memcpy(r_fuku, cb.r_fuku, sizeof(r_fuku));\n        hash = cb.hash;\n        \n        // Rebuild columns from rows\n        memset(c_oni, 0, sizeof(c_oni));\n        memset(c_fuku, 0, sizeof(c_fuku));\n        for(int i=0; i<N; ++i) {\n            if(r_oni[i]) {\n                for(int j=0; j<N; ++j) if((r_oni[i] >> j) & 1) c_oni[j] |= (1 << i);\n            }\n            if(r_fuku[i]) {\n                for(int j=0; j<N; ++j) if((r_fuku[i] >> j) & 1) c_fuku[j] |= (1 << i);\n            }\n        }\n    }\n\n    CompactBoard to_compact() const {\n        CompactBoard cb;\n        memcpy(cb.r_oni, r_oni, sizeof(r_oni));\n        memcpy(cb.r_fuku, r_fuku, sizeof(r_fuku));\n        cb.hash = hash;\n        return cb;\n    }\n\n    void recompute_hash() {\n        hash = 0;\n        for(int i=0; i<N; ++i) {\n            uint32_t ro = r_oni[i], rf = r_fuku[i];\n            for(int j=0; j<N; ++j) {\n                if((ro >> j) & 1) hash ^= zobrist[i][j][1];\n                else if((rf >> j) & 1) hash ^= zobrist[i][j][2];\n                else hash ^= zobrist[i][j][0];\n            }\n        }\n    }\n};\n\nstruct Move {\n    char type; \n    uint8_t dir;\n    uint8_t line;\n    uint8_t amount;\n};\n\nstruct Node {\n    int parent_id;\n    Move op;\n    int16_t cost;\n    int16_t heuristic;\n    int16_t removed;\n    uint64_t hash;\n    inline int total_score() const { return (int)cost + heuristic; }\n};\n\n// Memory Pools\nvector<Node> node_pool;\nvector<CompactBoard> board_pool;\n\n// Check/Update Dedup Table\n// Returns true if state is new or cheaper\nbool try_add_state(uint64_t hash, int cost) {\n    int idx = hash & TABLE_MASK;\n    // Simple probing (max 4 attempts to keep it fast)\n    for(int k=0; k<4; ++k) {\n        if (dedup_table[idx].cost == 0xFFFF) { // Empty slot\n            dedup_table[idx].key = hash;\n            dedup_table[idx].cost = (uint16_t)cost;\n            return true;\n        }\n        if (dedup_table[idx].key == hash) { // Match\n            if (cost < dedup_table[idx].cost) {\n                dedup_table[idx].cost = (uint16_t)cost;\n                return true; \n            }\n            return false;\n        }\n        idx = (idx + 1) & TABLE_MASK;\n    }\n    // Table full/collision - allow anyway (rare but safe for correctness, just suboptimal)\n    return true; \n}\n\n// Heuristic Calculation\n// O(N^2) but extremely optimized with bit manipulation\nint calc_heuristic(const FullBoard& b) {\n    int h = 0;\n    for(int r=0; r<N; ++r) {\n        uint32_t oni_row = b.r_oni[r];\n        if(!oni_row) continue;\n        uint32_t fuku_row = b.r_fuku[r];\n        \n        while(oni_row) {\n            int c = std::countr_zero(oni_row);\n            oni_row &= (oni_row - 1);\n            \n            int min_d = INF;\n            // L\n            if((fuku_row & ((1<<c)-1)) == 0) min_d = min(min_d, c + 1);\n            // R\n            if((fuku_row & ~((1<<(c+1))-1) & 0xFFFFF) == 0) min_d = min(min_d, N - c);\n            // U\n            uint32_t fuku_col = b.c_fuku[c];\n            if((fuku_col & ((1<<r)-1)) == 0) min_d = min(min_d, r + 1);\n            // D\n            if((fuku_col & ~((1<<(r+1))-1) & 0xFFFFF) == 0) min_d = min(min_d, N - r);\n            \n            if(min_d == INF) h += 500; // Penalty for being blocked\n            else h += min_d;\n        }\n    }\n    return h;\n}\n\nvoid apply_perm(FullBoard& b, int dir, int line, int amt) {\n    if(dir < 2) {\n        if(dir == 0) { b.r_oni[line] >>= amt; b.r_fuku[line] >>= amt; }\n        else { b.r_oni[line] = (b.r_oni[line] << amt) & 0xFFFFF; b.r_fuku[line] = (b.r_fuku[line] << amt) & 0xFFFFF; }\n        // Sync affected cols\n        uint32_t ro = b.r_oni[line], rf = b.r_fuku[line];\n        for(int j=0; j<N; ++j) {\n            if((ro >> j) & 1) b.c_oni[j] |= (1 << line); else b.c_oni[j] &= ~(1 << line);\n            if((rf >> j) & 1) b.c_fuku[j] |= (1 << line); else b.c_fuku[j] &= ~(1 << line);\n        }\n    } else {\n        if(dir == 2) { b.c_oni[line] >>= amt; b.c_fuku[line] >>= amt; }\n        else { b.c_oni[line] = (b.c_oni[line] << amt) & 0xFFFFF; b.c_fuku[line] = (b.c_fuku[line] << amt) & 0xFFFFF; }\n        // Sync affected rows\n        uint32_t co = b.c_oni[line], cf = b.c_fuku[line];\n        for(int i=0; i<N; ++i) {\n            if((co >> i) & 1) b.r_oni[i] |= (1 << line); else b.r_oni[i] &= ~(1 << line);\n            if((cf >> i) & 1) b.r_fuku[i] |= (1 << line); else b.r_fuku[i] &= ~(1 << line);\n        }\n    }\n    b.recompute_hash();\n}\n\nvoid apply_eject(FullBoard& b, int dir, int line, int amt) {\n    uint32_t mask;\n    if(dir == 0) mask = (1 << amt) - 1;\n    else if(dir == 1) mask = ~((1 << (N - amt)) - 1) & 0xFFFFF;\n    else if(dir == 2) mask = (1 << amt) - 1;\n    else mask = ~((1 << (N - amt)) - 1) & 0xFFFFF;\n    \n    if(dir < 2) {\n        b.r_oni[line] &= ~mask; b.r_fuku[line] &= ~mask;\n        uint32_t ro = b.r_oni[line], rf = b.r_fuku[line];\n        for(int j=0; j<N; ++j) {\n            if((ro >> j) & 1) b.c_oni[j] |= (1 << line); else b.c_oni[j] &= ~(1 << line);\n            if((rf >> j) & 1) b.c_fuku[j] |= (1 << line); else b.c_fuku[j] &= ~(1 << line);\n        }\n    } else {\n        b.c_oni[line] &= ~mask; b.c_fuku[line] &= ~mask;\n        uint32_t co = b.c_oni[line], cf = b.c_fuku[line];\n        for(int i=0; i<N; ++i) {\n            if((co >> i) & 1) b.r_oni[i] |= (1 << line); else b.r_oni[i] &= ~(1 << line);\n            if((cf >> i) & 1) b.r_fuku[i] |= (1 << line); else b.r_fuku[i] &= ~(1 << line);\n        }\n    }\n    b.recompute_hash();\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(NULL);\n    \n    dedup_table = new DedupEntry[TABLE_SIZE];\n    memset(dedup_table, 0xFF, sizeof(DedupEntry) * TABLE_SIZE);\n    init_zobrist();\n\n    int dummy; if(cin >> dummy){}\n    array<string, N> raw; for(int i=0; i<N; ++i) cin >> raw[i];\n    \n    CompactBoard start_cb; memset(&start_cb, 0, sizeof(start_cb));\n    uint64_t initial_hash = 0;\n    for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) {\n        if(raw[i][j] == 'x') { start_cb.r_oni[i] |= (1 << j); initial_hash ^= zobrist[i][j][1]; }\n        else if(raw[i][j] == 'o') { start_cb.r_fuku[i] |= (1 << j); initial_hash ^= zobrist[i][j][2]; }\n        else initial_hash ^= zobrist[i][j][0];\n    }\n    start_cb.hash = initial_hash;\n    \n    int start_oni = 0;\n    for(int i=0; i<N; ++i) start_oni += std::popcount(start_cb.r_oni[i]);\n    \n    node_pool.reserve(MAX_NODES); \n    board_pool.reserve(MAX_NODES);\n    \n    FullBoard temp_fb; temp_fb.load(start_cb);\n    Node root = {-1, {' ', 0, 0, 0}, 0, (int16_t)calc_heuristic(temp_fb), 0, start_cb.hash};\n    node_pool.push_back(root); board_pool.push_back(start_cb);\n    try_add_state(start_cb.hash, 0);\n    \n    vector<vector<int>> beams(start_oni + 1);\n    beams[0].push_back(0);\n    \n    for(int k=0; k<start_oni; ++k) {\n        if(beams[k].empty()) continue;\n        \n        // Check time every level\n        if(get_time() > 1.85) BEAM_WIDTH = 50; \n        \n        // Sort and Select Top Beam\n        if((int)beams[k].size() > BEAM_WIDTH) {\n            // Use partial_sort or nth_element for speed instead of full sort\n            nth_element(beams[k].begin(), beams[k].begin() + BEAM_WIDTH, beams[k].end(), [&](int a, int b){\n                return node_pool[a].total_score() < node_pool[b].total_score();\n            });\n            beams[k].resize(BEAM_WIDTH);\n        }\n        \n        // Sort remaining beam for best-first expansion (heuristic)\n        sort(beams[k].begin(), beams[k].end(), [&](int a, int b){\n            return node_pool[a].total_score() < node_pool[b].total_score();\n        });\n\n        if(node_pool.size() > MAX_NODES - 300000) BEAM_WIDTH = 1; // Emergency brake\n\n        for(int idx : beams[k]) {\n            Node curr_node = node_pool[idx];\n            FullBoard fb; fb.load(board_pool[idx]);\n            \n            if(curr_node.cost >= MAX_OPS) continue;\n            \n            for(int dir=0; dir<4; ++dir) {\n                for(int line=0; line<N; ++line) {\n                    uint32_t fuku = (dir<2) ? fb.r_fuku[line] : fb.c_fuku[line];\n                    \n                    int max_safe;\n                    if(dir%2==0) { // L or U\n                        max_safe = (fuku == 0) ? N : std::countr_zero(fuku);\n                    } else { // R or D\n                        max_safe = (fuku == 0) ? N : (std::countl_zero(fuku) - (32-N));\n                    }\n                    \n                    if(max_safe == 0) continue;\n                    \n                    uint32_t oni = (dir<2) ? fb.r_oni[line] : fb.c_oni[line];\n                    uint32_t target;\n                    if(dir%2==0) target = oni & ((1<<max_safe)-1);\n                    else target = oni & (~((1<<(N-max_safe))-1) & 0xFFFFF);\n                    \n                    if(target == 0) continue;\n                    \n                    while(target) {\n                        int bit = std::countr_zero(target);\n                        target &= (target-1);\n                        int s = (dir%2==0) ? (bit+1) : (N-bit);\n                        \n                        int delta;\n                        if(dir%2==0) delta = std::popcount(oni & ((1<<s)-1));\n                        else delta = std::popcount(oni & (~((1<<(N-s))-1) & 0xFFFFF));\n                        \n                        int next_rem = min(start_oni, curr_node.removed + delta);\n                        \n                        // Perm\n                        if(curr_node.cost + s <= MAX_OPS) {\n                            FullBoard next_b = fb; apply_perm(next_b, dir, line, s);\n                            if(try_add_state(next_b.hash, curr_node.cost + s)) {\n                                Node next_n = {idx, {'P', (uint8_t)dir, (uint8_t)line, (uint8_t)s}, (int16_t)(curr_node.cost + s), (int16_t)calc_heuristic(next_b), (int16_t)next_rem, next_b.hash};\n                                if(node_pool.size() < MAX_NODES) {\n                                    node_pool.push_back(next_n); board_pool.push_back(next_b.to_compact());\n                                    beams[next_rem].push_back((int)node_pool.size()-1);\n                                }\n                            }\n                        }\n                        // Eject\n                        if(curr_node.cost + 2*s <= MAX_OPS) {\n                            FullBoard next_b = fb; apply_eject(next_b, dir, line, s);\n                            if(try_add_state(next_b.hash, curr_node.cost + 2*s)) {\n                                Node next_n = {idx, {'E', (uint8_t)dir, (uint8_t)line, (uint8_t)s}, (int16_t)(curr_node.cost + 2*s), (int16_t)calc_heuristic(next_b), (int16_t)next_rem, next_b.hash};\n                                if(node_pool.size() < MAX_NODES) {\n                                    node_pool.push_back(next_n); board_pool.push_back(next_b.to_compact());\n                                    beams[next_rem].push_back((int)node_pool.size()-1);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        vector<int>().swap(beams[k]);\n    }\n    \n    int best_idx = -1, min_c = INF;\n    for(int k=start_oni; k>=0; --k) {\n        if(!beams[k].empty()) {\n            for(int idx : beams[k]) { if(node_pool[idx].cost < min_c) { min_c = node_pool[idx].cost; best_idx = idx; } }\n            break;\n        }\n    }\n    \n    if(best_idx != -1) {\n        vector<pair<string, int>> out;\n        int curr = best_idx;\n        while(node_pool[curr].parent_id != -1) {\n            const auto& m = node_pool[curr].op;\n            char d = DIR_CHARS[m.dir];\n            if(m.type == 'P') for(int i=0; i<m.amount; ++i) out.push_back({string(1, d), m.line});\n            else { char o = DIR_CHARS[m.dir^1]; for(int i=0; i<m.amount; ++i) out.push_back({string(1, o), m.line}); for(int i=0; i<m.amount; ++i) out.push_back({string(1, d), m.line}); }\n            curr = node_pool[curr].parent_id;\n        }\n        reverse(out.begin(), out.end());\n        for(const auto& p : out) cout << p.first << \" \" << p.second << \"\\n\";\n    }\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <cstring>\n\nusing namespace std;\n\n// ==========================================\n// Constants & Globals\n// ==========================================\nconst int N = 100;\nconst int L_TOTAL = 500000;\n\n// Input\nint T[N];\n\n// Graph State\n// Flattened Adjacency List for locality:\n// adj[2*i]     -> B_i (target for even visit counts)\n// adj[2*i + 1] -> A_i (target for odd visit counts)\nint adj[2 * N]; \nint best_adj[2 * N];\n\n// Simulation Counts\nint sim_counts[N];\nint backup_counts[N]; // To restore state upon rejection\n\n// Phase 1 State (Flow Proxy)\nint current_inflow[N];\nint est_flow[2 * N]; // est_flow[2*u] for B, [2*u+1] for A\n\n// Time Control\nauto start_time = chrono::high_resolution_clock::now();\nconst double TIME_LIMIT = 1.96; // Safe margin below 2.0s\n\n// Fast RNG\nstruct Xorshift {\n    uint32_t x = 123456789;\n    uint32_t y = 362436069;\n    uint32_t z = 521288629;\n    uint32_t w = 88675123;\n    inline uint32_t next() {\n        uint32_t t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return (double)next() / 4294967295.0;\n    }\n} rng;\n\n// ==========================================\n// Logic Functions\n// ==========================================\n\n// Phase 1: Static Flow Proxy Error\n// Calculates error based on expected flow vs target T.\n// Adds heavy penalty for unreachable nodes to ensure connectivity.\nlong long calc_flow_error() {\n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        int target = T[i];\n        if (i == 0 && target > 0) target--;\n        err += abs(current_inflow[i] - target);\n    }\n    \n    // Reachability BFS\n    static bool visited[N];\n    memset(visited, 0, N);\n    static int q[N];\n    int head = 0, tail = 0;\n    \n    if (T[0] > 0 || N==1) { \n         visited[0] = true;\n         q[tail++] = 0;\n    }\n\n    while(head < tail) {\n        int u = q[head++];\n        // Check A (odd -> index 2*u + 1)\n        if (est_flow[2*u + 1] > 0) {\n            int v = adj[2*u + 1];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n        // Check B (even -> index 2*u)\n        if (est_flow[2*u] > 0) {\n            int v = adj[2*u];\n            if (!visited[v]) { visited[v] = true; q[tail++] = v; }\n        }\n    }\n    \n    int unreached = 0;\n    for(int i=0; i<N; ++i) {\n        if (!visited[i]) unreached += T[i];\n    }\n    return err + (long long)unreached * 5000;\n}\n\n// Phase 2: Simulation\n// Runs the simulation for 'length' steps.\n// Returns sum of absolute errors |actual - target|.\n// Optimized for speed (minimal memory indirection).\nlong long run_simulation(int length, const int* targets) {\n    memset(sim_counts, 0, N * sizeof(int));\n    \n    int curr = 0;\n    sim_counts[0]++;\n    \n    // Local pointers for compiler optimization\n    const int* adj_ptr = adj;\n    int* counts_ptr = sim_counts;\n    \n    // Simulation Loop\n    // Week 1: curr=0. End of Week 1: sim_counts[0]=1.\n    // Week k: Check sim_counts[prev]. If odd -> A, even -> B.\n    // sim_counts[prev] & 1  => 1 if odd (A), 0 if even (B).\n    // Mapping: A is at index 2*curr+1, B is at index 2*curr.\n    // Formula: 2*curr + (count & 1) maps correctly.\n    \n    for (int k = 1; k < length; ++k) {\n        int cnt = counts_ptr[curr];\n        int type = cnt & 1; \n        int next_node = adj_ptr[2*curr + type];\n        counts_ptr[next_node]++;\n        curr = next_node;\n    }\n    \n    long long err = 0;\n    for(int i=0; i<N; ++i) {\n        err += abs(counts_ptr[i] - targets[i]);\n    }\n    return err;\n}\n\n// Helper for Directed Move Candidates\nstruct Candidate {\n    int u;     // Source node\n    int type;  // 0 for B, 1 for A\n    int prev_target;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int n_in, l_in;\n    if (cin >> n_in >> l_in) {}\n    for(int i=0; i<N; ++i) cin >> T[i];\n\n    // Setup Flow Estimates for Phase 1\n    for(int i=0; i<N; ++i) {\n        est_flow[2*i + 1] = (T[i] + 1) / 2; // A (Odd)\n        est_flow[2*i]     = T[i] / 2;       // B (Even)\n    }\n\n    // --- Initial Construction: Greedy Bin Packing ---\n    // Assign outgoing edges (Plugs) to nodes with capacity (Sockets)\n    struct Plug { int u; int type; int val; };\n    vector<Plug> plugs; \n    plugs.reserve(2*N);\n    for(int i=0; i<N; ++i) {\n        if (est_flow[2*i + 1] > 0) plugs.push_back({i, 1, est_flow[2*i + 1]});\n        if (est_flow[2*i] > 0)     plugs.push_back({i, 0, est_flow[2*i]});\n    }\n    sort(plugs.begin(), plugs.end(), [](const Plug& a, const Plug& b){\n        return a.val > b.val;\n    });\n\n    // Default initialization\n    for(int i=0; i<N; ++i) {\n        adj[2*i] = (i + 1) % N;\n        adj[2*i+1] = (i + 1) % N;\n    }\n    \n    vector<int> cap(N);\n    for(int i=0; i<N; ++i) cap[i] = T[i];\n    if (cap[0] > 0) cap[0]--;\n    \n    memset(current_inflow, 0, sizeof(current_inflow));\n    \n    for(const auto& p : plugs) {\n        int best = -1, max_rem = -2e9;\n        // Random start index to distribute flow more evenly\n        int start = rng.next_int(N);\n        for(int k=0; k<N; ++k) {\n            int v = (start + k) % N;\n            if (cap[v] > max_rem) { max_rem = cap[v]; best = v; }\n        }\n        adj[2*p.u + p.type] = best;\n        cap[best] -= p.val;\n        current_inflow[best] += p.val;\n    }\n    \n    memcpy(best_adj, adj, sizeof(adj));\n\n    // --- Phase 1: Flow Proxy Optimization (0.0s - 0.15s) ---\n    // Heuristic optimization to establish topology and rough flow balance.\n    {\n        long long cur_err = calc_flow_error();\n        double temp = 100.0;\n        while(true) {\n            if (chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count() > 0.15) break;\n            \n            int u = rng.next_int(N);\n            if (T[u] == 0) continue;\n            int type = (est_flow[2*u] > 0) ? rng.next_int(2) : 1;\n            int idx = 2*u + type;\n            int val = est_flow[idx];\n            if (val == 0) continue;\n            \n            int old_v = adj[idx];\n            int new_v = rng.next_int(N);\n            if (old_v == new_v) continue;\n            \n            // Apply\n            current_inflow[old_v] -= val;\n            current_inflow[new_v] += val;\n            adj[idx] = new_v;\n            \n            long long next_err = calc_flow_error();\n            long long delta = next_err - cur_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_err = next_err;\n            } else {\n                // Revert\n                current_inflow[old_v] += val;\n                current_inflow[new_v] -= val;\n                adj[idx] = old_v;\n            }\n            temp *= 0.995;\n            if (temp < 0.5) temp = 0.5;\n        }\n    }\n    \n    memcpy(best_adj, adj, sizeof(adj));\n\n    // --- Phase 2: Multi-Stage Simulation ---\n    // Run simulations of increasing length to fine-tune the solution.\n    // Stage 1: 30k steps (Fast, coarse adjustment)\n    // Stage 2: 100k steps (Medium precision)\n    // Stage 3: 500k steps (Exact, final tuning)\n    struct Stage { int L; double end_t; };\n    vector<Stage> stages = { {30000, 0.4}, {100000, 0.8}, {L_TOTAL, TIME_LIMIT} };\n    \n    vector<int> current_T(N);\n    vector<int> surplus, deficit;\n    surplus.reserve(N); deficit.reserve(N);\n    vector<Candidate> candidates;\n    candidates.reserve(N);\n    \n    long long global_best_err = -1;\n    \n    for(const auto& stage : stages) {\n        // Scale Target T to current stage length\n        long long sT = 0;\n        for(int i=0; i<N; ++i) {\n            current_T[i] = (long long)T[i] * stage.L / L_TOTAL;\n            sT += current_T[i];\n        }\n        // Fix rounding errors\n        while(sT < stage.L) {\n            int i = rng.next_int(N);\n            if (T[i] > 0) { current_T[i]++; sT++; }\n        }\n        \n        long long cur_err = run_simulation(stage.L, current_T.data());\n        memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n        \n        if (stage.L == L_TOTAL) {\n            global_best_err = cur_err;\n            memcpy(best_adj, adj, sizeof(adj));\n        }\n        \n        double temp = 50.0;\n        int iter_mask = 255; // Check time every 256 iterations\n\n        int iter_cnt = 0;\n        while(true) {\n            iter_cnt++;\n            if ((iter_cnt & iter_mask) == 0) {\n                 if (chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count() > stage.end_t) break;\n            }\n            \n            // --- Move Selection ---\n            int u = -1, type = -1, old_v = -1, new_v = -1;\n            bool directed = false;\n            \n            // Strategy 1: Directed Redirect (Surplus -> Deficit)\n            // Try to relieve pressure from a surplus node by redirecting one of its incoming edges\n            // to a deficit node.\n            if (rng.next_double() < 0.75) {\n                surplus.clear(); deficit.clear();\n                for(int i=0; i<N; ++i) {\n                    if (sim_counts[i] > current_T[i]) surplus.push_back(i);\n                    else if (sim_counts[i] < current_T[i]) deficit.push_back(i);\n                }\n                \n                if (!surplus.empty() && !deficit.empty()) {\n                    // Pick a random Deficit node as destination\n                    int target_def = deficit[rng.next_int(deficit.size())];\n                    \n                    // Find incoming edges to ANY surplus node (sampling for efficiency)\n                    candidates.clear();\n                    int attempts = 20; \n                    while(attempts--) {\n                         int cand_u = rng.next_int(N);\n                         if (T[cand_u] == 0) continue;\n                         \n                         // Check A (type 1)\n                         int vA = adj[2*cand_u + 1];\n                         // Condition: edge is used at least once AND points to surplus\n                         if (sim_counts[cand_u] >= 1 && sim_counts[vA] > current_T[vA]) {\n                             candidates.push_back({cand_u, 1, vA});\n                         }\n                         // Check B (type 0)\n                         if (T[cand_u] > 1) {\n                             int vB = adj[2*cand_u];\n                             if (sim_counts[cand_u] >= 2 && sim_counts[vB] > current_T[vB]) {\n                                 candidates.push_back({cand_u, 0, vB});\n                             }\n                         }\n                    }\n                    \n                    if (!candidates.empty()) {\n                        const auto& c = candidates[rng.next_int(candidates.size())];\n                        u = c.u; type = c.type; old_v = c.prev_target;\n                        new_v = target_def;\n                        if (old_v != new_v) directed = true;\n                    }\n                }\n            }\n            \n            // Strategy 2 & 3: Swap or Random Redirect\n            if (!directed) {\n                // Strategy 2: Swap Targets (Exploration)\n                if (rng.next_double() < 0.2) { \n                    int u1 = rng.next_int(N);\n                    if (T[u1] == 0) continue;\n                    int t1 = (T[u1] > 1) ? rng.next_int(2) : 1;\n                    \n                    int u2 = rng.next_int(N);\n                    if (T[u2] == 0 || u1 == u2) continue;\n                    int t2 = (T[u2] > 1) ? rng.next_int(2) : 1;\n                    \n                    int v1 = adj[2*u1 + t1];\n                    int v2 = adj[2*u2 + t2];\n                    \n                    if (v1 != v2) {\n                        // Apply Swap\n                        adj[2*u1 + t1] = v2;\n                        adj[2*u2 + t2] = v1;\n                        \n                        long long next_err = run_simulation(stage.L, current_T.data());\n                        long long delta = next_err - cur_err;\n                        \n                        if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                            cur_err = next_err;\n                            memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n                            if (stage.L == L_TOTAL && cur_err < global_best_err) {\n                                global_best_err = cur_err;\n                                memcpy(best_adj, adj, sizeof(adj));\n                            }\n                        } else {\n                            // Revert\n                            adj[2*u1 + t1] = v1;\n                            adj[2*u2 + t2] = v2;\n                            memcpy(sim_counts, backup_counts, sizeof(sim_counts));\n                        }\n                        temp *= 0.9995;\n                        if (temp < 0.5) temp = 0.5;\n                        continue; // Skip standard revert logic below\n                    }\n                }\n                \n                // Strategy 3: Random Redirect (Fallback)\n                u = rng.next_int(N);\n                if (T[u] == 0) continue;\n                type = (T[u] > 1) ? rng.next_int(2) : 1;\n                old_v = adj[2*u + type];\n                new_v = rng.next_int(N);\n            }\n            \n            if (u == -1 || old_v == new_v) continue;\n            \n            // Apply Redirect\n            adj[2*u + type] = new_v;\n            \n            long long next_err = run_simulation(stage.L, current_T.data());\n            long long delta = next_err - cur_err;\n            \n            if (delta <= 0 || rng.next_double() < exp(-delta/temp)) {\n                cur_err = next_err;\n                memcpy(backup_counts, sim_counts, sizeof(sim_counts));\n                if (stage.L == L_TOTAL && cur_err < global_best_err) {\n                    global_best_err = cur_err;\n                    memcpy(best_adj, adj, sizeof(adj));\n                }\n            } else {\n                // Revert\n                adj[2*u + type] = old_v;\n                // Restore sim_counts from backup (crucial for directed moves logic)\n                memcpy(sim_counts, backup_counts, sizeof(sim_counts));\n            }\n            \n            temp *= 0.9995;\n            if (temp < 0.5) temp = 0.5;\n        }\n    }\n\n    // Output Best Solution\n    for(int i=0; i<N; ++i) {\n        // Output format: A_i B_i\n        // adj stored as: adj[2*i] = B, adj[2*i+1] = A\n        cout << best_adj[2*i + 1] << \" \" << best_adj[2*i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#pragma GCC optimize(\"O3,unroll-loops\")\n#pragma GCC target(\"avx2,bmi,bmi2,lzcnt,popcnt\")\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n#include <iomanip>\n#include <chrono>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\n// --------------------------------------------------------------------------\n// Global Variables\n// --------------------------------------------------------------------------\nint N, M, Q, L, W;\nvector<int> G;\n\n// Remapping for cache locality\nvector<int> p_order;       // new_id -> old_id\nvector<int> old_to_new;    // old_id -> new_id\n\n// Positions (sorted by Hilbert)\nint pos_x[805];\nint pos_y[805];\n\n// Distance matrix (new IDs)\nint dist_matrix[805][805]; \n\n// Group management\nvector<int> city_group; \nvector<vector<int>> groups;\nvector<long long> grp_sum_x, grp_sum_y; \n\n// Parameters\nconst int K_NN = 20; \nconst int DENSE_THRESHOLD = 85; \nconst int CANDIDATE_SAMPLE_SIZE = 16; \n\nstruct Neighbor {\n    int to;\n    int w_sq;\n};\nvector<vector<Neighbor>> knn_adj; \n\n// --------------------------------------------------------------------------\n// Utils\n// --------------------------------------------------------------------------\nstruct XorShift {\n    unsigned int x = 123456789;\n    unsigned int y = 362436069;\n    unsigned int z = 521288629;\n    unsigned int w = 88675123;\n    inline unsigned int next() {\n        unsigned int t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));\n    }\n    inline int next_int(int n) {\n        return next() % n;\n    }\n    inline double next_double() {\n        return next() * (1.0 / 4294967296.0);\n    }\n} rng;\n\nlong long hilbert(int x, int y, int pow, int rotate) {\n    if (pow == 0) return 0;\n    int hpow = 1 << (pow - 1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rotate) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rotate + rotateDelta[seg]) & 3;\n    long long subSquareSize = 1LL << (2 * pow - 2);\n    long long ans = seg * subSquareSize;\n    long long add = hilbert(nx, ny, pow - 1, nrot);\n    ans += (seg == 1 || seg == 2) ? add : (subSquareSize - 1 - add);\n    return ans;\n}\n\n// --------------------------------------------------------------------------\n// DSU\n// --------------------------------------------------------------------------\nstruct DSU {\n    int p[805];\n    void reset() { memset(p, -1, sizeof(p)); }\n    int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (p[x] > p[y]) swap(x, y);\n        p[x] += p[y];\n        p[y] = x;\n        return true;\n    }\n} dsu_calc;\n\n// --------------------------------------------------------------------------\n// Cost Calculation\n// --------------------------------------------------------------------------\ndouble compute_dense_mst(const vector<int>& grp) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    static int min_dist[805];\n    static bool visited[805];\n    \n    for(int i=0; i<k; ++i) {\n        min_dist[i] = 2e9; \n        visited[i] = false;\n    }\n    \n    min_dist[0] = 0;\n    double total = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        int cur_min = 2e9;\n        \n        for(int j=0; j<k; ++j) {\n            if(!visited[j]) {\n                if (min_dist[j] < cur_min) {\n                    cur_min = min_dist[j];\n                    u = j;\n                }\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        if(i > 0) total += sqrt(cur_min);\n        \n        int city_u = grp[u];\n        const int* row_ptr = dist_matrix[city_u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                int d = row_ptr[grp[v]];\n                if(d < min_dist[v]) min_dist[v] = d;\n            }\n        }\n    }\n    return total;\n}\n\nstruct LocalEdge {\n    int u, v;\n    int w_sq;\n    bool operator<(const LocalEdge& other) const { return w_sq < other.w_sq; }\n};\n\nvector<LocalEdge> edge_buffer;\n\ndouble compute_sparse_mst(const vector<int>& grp, int group_idx) {\n    int k = grp.size();\n    if (k <= 1) return 0;\n    \n    edge_buffer.clear();\n    \n    for(int u : grp) {\n        const auto& neighbors = knn_adj[u];\n        for(const auto& nb : neighbors) {\n            int v = nb.to;\n            // Check if v is in the same group\n            if (city_group[v] == group_idx) {\n                // Canonicalize edge to avoid duplicates in undirected sense\n                if (u < v) edge_buffer.push_back({u, v, nb.w_sq});\n                else edge_buffer.push_back({v, u, nb.w_sq});\n            }\n        }\n    }\n    \n    if ((int)edge_buffer.size() < k - 1) return -1.0;\n    \n    sort(edge_buffer.begin(), edge_buffer.end());\n    \n    dsu_calc.reset();\n    int edges_count = 0;\n    double total = 0;\n    \n    for(const auto& e : edge_buffer) {\n        if(dsu_calc.unite(e.u, e.v)) {\n            total += sqrt(e.w_sq);\n            edges_count++;\n            if(edges_count == k - 1) return total;\n        }\n    }\n    \n    if (edges_count < k - 1) return -1.0;\n    return total;\n}\n\ndouble get_group_cost(const vector<int>& grp, int group_idx) {\n    if (grp.size() <= DENSE_THRESHOLD) {\n        return compute_dense_mst(grp);\n    } else {\n        double res = compute_sparse_mst(grp, group_idx);\n        if (res < 0) return compute_dense_mst(grp);\n        return res;\n    }\n}\n\n// --------------------------------------------------------------------------\n// Final Output MST\n// --------------------------------------------------------------------------\nvector<pair<int, int>> get_mst_edges_final(const vector<int>& grp) {\n    if (grp.size() <= 1) return {};\n    int k = grp.size();\n    vector<int> min_dist(k, 2e9);\n    vector<int> parent(k, -1);\n    vector<bool> visited(k, false);\n    min_dist[0] = 0;\n    \n    for(int i=0; i<k; ++i) {\n        int u = -1;\n        int cur = 2e9;\n        for(int j=0; j<k; ++j) {\n            if(!visited[j] && min_dist[j] < cur) {\n                cur = min_dist[j];\n                u = j;\n            }\n        }\n        if(u == -1) break;\n        visited[u] = true;\n        int city_u = grp[u];\n        const int* row_ptr = dist_matrix[city_u];\n        for(int v=0; v<k; ++v) {\n            if(!visited[v]) {\n                int d = row_ptr[grp[v]];\n                if(d < min_dist[v]) {\n                    min_dist[v] = d;\n                    parent[v] = u;\n                }\n            }\n        }\n    }\n    vector<pair<int, int>> result;\n    for(int i=1; i<k; ++i) {\n        if(parent[i] != -1) result.push_back({grp[i], grp[parent[i]]});\n    }\n    return result;\n}\n\nvector<int> rem_nodes;\nvector<vector<int>> planned_queries;\nvector<vector<int>> adj_tree;\n\nvoid dfs_query(int u, int p) {\n    int subtree_start = rem_nodes.size();\n    for (int v : adj_tree[u]) {\n        if (v == p) continue;\n        dfs_query(v, u);\n    }\n    rem_nodes.push_back(u);\n    \n    int count = rem_nodes.size() - subtree_start; \n    while (count >= L) {\n        vector<int> q;\n        q.reserve(L);\n        q.push_back(u);\n        for(int i=0; i<L-1; ++i) {\n            q.push_back(rem_nodes[subtree_start]);\n            rem_nodes.erase(rem_nodes.begin() + subtree_start);\n        }\n        planned_queries.push_back(q);\n        count -= (L - 1);\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    edge_buffer.reserve(30000);\n\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    G.resize(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    \n    struct RawCity {\n        int lx, rx, ly, ry;\n        int x, y;\n        int id;\n    };\n    vector<RawCity> raw_cities(N);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> raw_cities[i].lx >> raw_cities[i].rx >> raw_cities[i].ly >> raw_cities[i].ry;\n        raw_cities[i].x = (raw_cities[i].lx + raw_cities[i].rx) / 2;\n        raw_cities[i].y = (raw_cities[i].ly + raw_cities[i].ry) / 2;\n        raw_cities[i].id = i;\n    }\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // Reordering cities based on Hilbert curve to improve cache locality\n    p_order.resize(N);\n    iota(p_order.begin(), p_order.end(), 0);\n    sort(p_order.begin(), p_order.end(), [&](int i, int j) {\n        return hilbert(raw_cities[i].x, raw_cities[i].y, 14, 0) < hilbert(raw_cities[j].x, raw_cities[j].y, 14, 0);\n    });\n\n    old_to_new.resize(N);\n    for(int i=0; i<N; ++i) {\n        old_to_new[p_order[i]] = i;\n        pos_x[i] = raw_cities[p_order[i]].x;\n        pos_y[i] = raw_cities[p_order[i]].y;\n    }\n\n    // Fill dist matrix with new IDs\n    for(int i=0; i<N; ++i) {\n        dist_matrix[i][i] = 0;\n        for(int j=i+1; j<N; ++j) {\n            int dx = pos_x[i] - pos_x[j];\n            int dy = pos_y[i] - pos_y[j];\n            int d = dx*dx + dy*dy;\n            dist_matrix[i][j] = dist_matrix[j][i] = d;\n        }\n    }\n\n    // KNN with new IDs\n    knn_adj.resize(N);\n    vector<pair<int, int>> row_dists(N);\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if (i==j) row_dists[j] = {2e9, j}; \n            else row_dists[j] = {dist_matrix[i][j], j};\n        }\n        int k_target = min(N-1, K_NN + 5);\n        nth_element(row_dists.begin(), row_dists.begin() + k_target, row_dists.end());\n        \n        for(int k=0; k<k_target; ++k) {\n            knn_adj[i].push_back({row_dists[k].second, row_dists[k].first});\n        }\n    }\n\n    groups.resize(M);\n    city_group.resize(N);\n    grp_sum_x.assign(M, 0);\n    grp_sum_y.assign(M, 0);\n\n    // Initial Grouping: simple chunks of 0..N-1 (since already Hilbert sorted)\n    int current_idx = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].reserve(G[i] + 16);\n        for (int k = 0; k < G[i]; ++k) {\n            int u = current_idx++; \n            groups[i].push_back(u);\n            city_group[u] = i;\n            grp_sum_x[i] += pos_x[u];\n            grp_sum_y[i] += pos_y[u];\n        }\n    }\n\n    vector<double> group_costs(M);\n    double total_cost = 0;\n    for(int i=0; i<M; ++i) {\n        group_costs[i] = get_group_cost(groups[i], i);\n        total_cost += group_costs[i];\n    }\n\n    double time_limit = 1.85;\n    double start_temp = 250.0; \n    double end_temp = 0.01;\n    \n    int iter = 0;\n    int nb_candidates[64]; \n\n    while(true) {\n        iter++;\n        if ((iter & 127) == 0) { \n            double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n            if (elapsed > time_limit) break;\n        }\n\n        int u = rng.next_int(N);\n        int g1 = city_group[u];\n        int g2 = -1;\n        int v = -1;\n\n        int nb_count = 0;\n        const auto& nbs = knn_adj[u];\n        int limit = min((int)nbs.size(), 24); \n        for(int k=0; k<limit; ++k) {\n            int nb = nbs[k].to;\n            if (city_group[nb] != g1) {\n                nb_candidates[nb_count++] = nb;\n            }\n        }\n\n        if (nb_count > 0 && rng.next_double() < 0.80) {\n            int neighbor = nb_candidates[rng.next_int(nb_count)];\n            g2 = city_group[neighbor];\n            \n            long long g1_cx = grp_sum_x[g1] / (long long)groups[g1].size();\n            long long g1_cy = grp_sum_y[g1] / (long long)groups[g1].size();\n            \n            long long best_score = -4e18;\n            int g2_size = groups[g2].size();\n            int samples = min(g2_size, CANDIDATE_SAMPLE_SIZE);\n            \n            for(int k=0; k<samples; ++k) {\n                int cand;\n                if(g2_size <= CANDIDATE_SAMPLE_SIZE) cand = groups[g2][k];\n                else cand = groups[g2][rng.next_int(g2_size)];\n                \n                long long dx1 = pos_x[cand] - g1_cx;\n                long long dy1 = pos_y[cand] - g1_cy;\n                long long d1 = dx1*dx1 + dy1*dy1;\n\n                long long g2_cx = grp_sum_x[g2] / (long long)groups[g2].size();\n                long long g2_cy = grp_sum_y[g2] / (long long)groups[g2].size();\n                long long dx2 = pos_x[cand] - g2_cx;\n                long long dy2 = pos_y[cand] - g2_cy;\n                long long d2 = dx2*dx2 + dy2*dy2;\n                \n                long long score = d2 - (long long)(d1 * 1.2);\n\n                if (score > best_score) { best_score = score; v = cand; }\n            }\n\n        } else {\n            g2 = rng.next_int(M);\n            if (g1 == g2) continue;\n            \n            long long g1_cx = grp_sum_x[g1] / (long long)groups[g1].size();\n            long long g1_cy = grp_sum_y[g1] / (long long)groups[g1].size();\n             long long g2_cx = grp_sum_x[g2] / (long long)groups[g2].size();\n            long long g2_cy = grp_sum_y[g2] / (long long)groups[g2].size();\n            \n            long long best_score = -4e18;\n            int g2_size = groups[g2].size();\n            int samples = min(g2_size, CANDIDATE_SAMPLE_SIZE);\n            \n            for(int k=0; k<samples; ++k) {\n                int cand;\n                if(g2_size <= CANDIDATE_SAMPLE_SIZE) cand = groups[g2][k];\n                else cand = groups[g2][rng.next_int(g2_size)];\n                \n                long long dx1 = pos_x[cand] - g1_cx;\n                long long dy1 = pos_y[cand] - g1_cy;\n                long long d1 = dx1*dx1 + dy1*dy1;\n\n                long long dx2 = pos_x[cand] - g2_cx;\n                long long dy2 = pos_y[cand] - g2_cy;\n                long long d2 = dx2*dx2 + dy2*dy2;\n                \n                long long score = d2 - (long long)(d1 * 1.2);\n                if (score > best_score) { best_score = score; v = cand; }\n            }\n        }\n        \n        if (v == -1) continue;\n\n        int idx_u = -1;\n        for(int k=0; k<(int)groups[g1].size(); ++k) if(groups[g1][k] == u) { idx_u = k; break; }\n        \n        int idx_v = -1;\n        for(int k=0; k<(int)groups[g2].size(); ++k) if(groups[g2][k] == v) { idx_v = k; break; }\n        \n        swap(groups[g1][idx_u], groups[g2][idx_v]);\n        city_group[u] = g2;\n        city_group[v] = g1;\n        \n        double new_cost_g1 = get_group_cost(groups[g1], g1);\n        double new_cost_g2 = get_group_cost(groups[g2], g2);\n        \n        double diff = (new_cost_g1 + new_cost_g2) - (group_costs[g1] + group_costs[g2]);\n        \n        double elapsed = chrono::duration<double>(chrono::high_resolution_clock::now() - start_time).count();\n        double temp = start_temp * (1.0 - elapsed / time_limit);\n        if (temp < end_temp) temp = end_temp;\n        \n        if (diff < 0 || rng.next_double() < exp(-diff / temp)) {\n            total_cost += diff;\n            group_costs[g1] = new_cost_g1;\n            group_costs[g2] = new_cost_g2;\n            \n            grp_sum_x[g1] = grp_sum_x[g1] - pos_x[u] + pos_x[v];\n            grp_sum_y[g1] = grp_sum_y[g1] - pos_y[u] + pos_y[v];\n            grp_sum_x[g2] = grp_sum_x[g2] - pos_x[v] + pos_x[u];\n            grp_sum_y[g2] = grp_sum_y[g2] - pos_y[v] + pos_y[u];\n        } else {\n            swap(groups[g1][idx_u], groups[g2][idx_v]);\n            city_group[u] = g1;\n            city_group[v] = g2;\n        }\n    }\n\n    // Query Planning\n    for (int i = 0; i < M; ++i) {\n        if (groups[i].size() <= 1) continue;\n        if ((int)groups[i].size() <= L) {\n            planned_queries.push_back(groups[i]);\n            continue;\n        }\n        \n        vector<pair<int, int>> mst = get_mst_edges_final(groups[i]);\n        adj_tree.assign(N, {});\n        for (auto& e : mst) {\n            adj_tree[e.first].push_back(e.second);\n            adj_tree[e.second].push_back(e.first);\n        }\n        \n        rem_nodes.clear();\n        dfs_query(groups[i][0], -1);\n        \n        while (!rem_nodes.empty()) {\n            if ((int)rem_nodes.size() <= L) {\n                if (rem_nodes.size() > 1) planned_queries.push_back(rem_nodes);\n                rem_nodes.clear();\n            } else {\n                vector<int> q;\n                q.reserve(L);\n                for(int k=0; k<L; ++k) q.push_back(rem_nodes[k]);\n                planned_queries.push_back(q);\n                rem_nodes.erase(rem_nodes.begin(), rem_nodes.begin() + L - 1);\n            }\n        }\n    }\n    \n    shuffle(planned_queries.begin(), planned_queries.end(), mt19937(42));\n    int queries_to_run = min((int)planned_queries.size(), Q);\n    \n    vector<vector<pair<int, int>>> confirmed_edges(M);\n    \n    for(int i=0; i<queries_to_run; ++i) {\n        cout << \"? \" << planned_queries[i].size();\n        for(int c : planned_queries[i]) cout << \" \" << p_order[c];\n        cout << endl;\n        \n        for(size_t k=0; k<planned_queries[i].size()-1; ++k) {\n            int u_old, v_old;\n            cin >> u_old >> v_old;\n            int u = old_to_new[u_old];\n            int v = old_to_new[v_old];\n            confirmed_edges[city_group[u]].push_back({u, v});\n        }\n    }\n\n    cout << \"!\" << endl;\n    \n    struct FinEdge {\n        int u, v;\n        double w;\n        bool operator<(const FinEdge& o) const { return w < o.w; }\n    };\n    vector<FinEdge> cands;\n    cands.reserve(N);\n\n    for(int i=0; i<M; ++i) {\n        // Output using old_id\n        for(size_t k=0; k<groups[i].size(); ++k) {\n            cout << p_order[groups[i][k]] << (k==groups[i].size()-1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n        \n        cands.clear();\n        for(auto& e : confirmed_edges[i]) {\n            cands.push_back({e.first, e.second, -1.0});\n        }\n        \n        vector<pair<int, int>> est = get_mst_edges_final(groups[i]);\n        for(auto& e : est) {\n            double w = sqrt(dist_matrix[e.first][e.second]);\n            cands.push_back({e.first, e.second, w});\n        }\n        \n        sort(cands.begin(), cands.end());\n        \n        dsu_calc.reset();\n        int added = 0;\n        int needed = max(0, (int)groups[i].size() - 1);\n        \n        for(auto& e : cands) {\n            if(dsu_calc.unite(e.u, e.v)) {\n                cout << p_order[e.u] << \" \" << p_order[e.v] << \"\\n\";\n                added++;\n                if(added == needed) break;\n            }\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <bitset>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\nconst int INF = 1e9;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_chars[] = {'U', 'D', 'L', 'R'};\n\nstruct Point {\n    int r, c;\n};\n\nstruct Action {\n    char type; \n    char dir;\n};\n\nstruct NodeInfo {\n    int dist;\n    int parent_idx; \n    Action action_from_parent;\n    bool break_block;\n};\n\nNodeInfo nodes[N * N]; \nint dist_start[N * N];\nint dist_end[N * N];\n\ninline bool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\ninline int idx(int r, int c) {\n    return r * N + c;\n}\n\nvoid run_dijkstra_fwd(int start_idx, const bitset<400>& grid, int* dist_arr, int avoid_idx = -1) {\n    for(int i=0; i<400; ++i) {\n        dist_arr[i] = INF;\n        nodes[i].dist = INF; \n    }\n    \n    using P = pair<int, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    \n    dist_arr[start_idx] = 0;\n    nodes[start_idx] = {0, -1, {' ', ' '}, false};\n    pq.push({0, start_idx});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        \n        if (d > dist_arr[u]) continue;\n\n        int r = u / N;\n        int c = u % N;\n        \n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k];\n            int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int v = idx(nr, nc);\n                if (v == avoid_idx) continue;\n                bool is_blocked = grid[v];\n                int cost = is_blocked ? 2 : 1;\n                if (dist_arr[u] + cost < dist_arr[v]) {\n                    dist_arr[v] = dist_arr[u] + cost;\n                    nodes[v] = {dist_arr[v], u, {'M', dir_chars[k]}, is_blocked};\n                    pq.push({dist_arr[v], v});\n                }\n            }\n        }\n        \n        for (int k = 0; k < 4; ++k) {\n            int cr = r, cc = c;\n            while (true) {\n                int nr = cr + dr[k];\n                int nc = cc + dc[k];\n                if (!is_valid(nr, nc)) break;\n                int v_next = idx(nr, nc);\n                if (grid[v_next] || v_next == avoid_idx) break;\n                cr = nr;\n                cc = nc;\n            }\n            if (cr != r || cc != c) {\n                int v = idx(cr, cc);\n                if (dist_arr[u] + 1 < dist_arr[v]) {\n                    dist_arr[v] = dist_arr[u] + 1;\n                    nodes[v] = {dist_arr[v], u, {'S', dir_chars[k]}, false};\n                    pq.push({dist_arr[v], v});\n                }\n            }\n        }\n    }\n}\n\nvoid run_dijkstra_rev(int target_idx, const bitset<400>& grid, int* dist_arr) {\n    for(int i=0; i<400; ++i) dist_arr[i] = INF;\n    using P = pair<int, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    dist_arr[target_idx] = 0;\n    pq.push({0, target_idx});\n    while (!pq.empty()) {\n        auto [d, u] = pq.top();\n        pq.pop();\n        if (d > dist_arr[u]) continue;\n        int r = u / N; int c = u % N;\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k]; int nc = c + dc[k];\n            if (is_valid(nr, nc)) {\n                int v = idx(nr, nc);\n                bool u_blocked = grid[u];\n                int cost = u_blocked ? 2 : 1;\n                if (dist_arr[u] + cost < dist_arr[v]) {\n                    dist_arr[v] = dist_arr[u] + cost;\n                    pq.push({dist_arr[v], v});\n                }\n            }\n        }\n        if (!grid[u]) { \n            for (int k = 0; k < 4; ++k) { \n                int check_r = r + dr[k]; int check_c = c + dc[k];\n                bool is_stop = !is_valid(check_r, check_c) || grid[idx(check_r, check_c)];\n                if (is_stop) {\n                    int back_dir = (k==0?1:(k==1?0:(k==2?3:2)));\n                    int curr_r = r; int curr_c = c;\n                    while (true) {\n                        int nr = curr_r + dr[back_dir]; int nc = curr_c + dc[back_dir];\n                        if (!is_valid(nr, nc)) break;\n                        int v = idx(nr, nc);\n                        if (grid[v]) break; \n                        if (dist_arr[u] + 1 < dist_arr[v]) {\n                            dist_arr[v] = dist_arr[u] + 1;\n                            pq.push({dist_arr[v], v});\n                        }\n                        curr_r = nr; curr_c = nc;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvector<Action> extract_path(int start_idx, int end_idx) {\n    vector<Action> path;\n    int cur = end_idx;\n    while (cur != start_idx && cur != -1) {\n        NodeInfo& info = nodes[cur];\n        if (info.dist == INF) break; \n        if (info.break_block) {\n            path.push_back({'M', info.action_from_parent.dir});\n            path.push_back({'A', info.action_from_parent.dir});\n        } else {\n            path.push_back(info.action_from_parent);\n        }\n        cur = info.parent_idx;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Mini-BFS for short paths\nvector<Action> extract_path_bfs(int start_idx, int target_idx, const bitset<400>& grid, int avoid_idx) {\n    static int parent[400];\n    static char action_type[400];\n    static char action_dir[400];\n    static int visited_token[400];\n    static int token = 0;\n    token++;\n    \n    queue<int> q;\n    q.push(start_idx);\n    visited_token[start_idx] = token;\n    parent[start_idx] = -1;\n    \n    bool found = false;\n    while(!q.empty()) {\n        int u = q.front(); q.pop();\n        if(u == target_idx) { found = true; break; }\n        \n        int r = u/N, c = u%N;\n        for(int k=0; k<4; ++k) {\n            int nr = r+dr[k], nc=c+dc[k];\n            if(is_valid(nr, nc)) {\n                int v = idx(nr, nc);\n                if(v == avoid_idx) continue;\n                if(grid[v]) continue;\n                \n                if(visited_token[v] != token) {\n                    visited_token[v] = token;\n                    parent[v] = u;\n                    action_type[v] = 'M';\n                    action_dir[v] = dir_chars[k];\n                    q.push(v);\n                }\n            }\n        }\n    }\n    \n    vector<Action> path;\n    if(found) {\n        int cur = target_idx;\n        while(cur != start_idx) {\n            path.push_back({action_type[cur], action_dir[cur]});\n            cur = parent[cur];\n        }\n        reverse(path.begin(), path.end());\n    }\n    return path;\n}\n\n\nstruct BeamState {\n    int cost;\n    int heuristic;\n    int pos_idx;\n    bitset<400> grid;\n    vector<Action> history;\n    bool operator<(const BeamState& other) const {\n        return (cost + heuristic) < (other.cost + other.heuristic);\n    }\n};\n\nint calc_heuristic(int next_target_idx, const bitset<400>& grid, const vector<Point>& targets) {\n    int h = 0;\n    for (int i = next_target_idx; i < (int)targets.size(); ++i) {\n        Point prev = targets[i-1];\n        Point curr = targets[i];\n        int dist = abs(prev.r - curr.r) + abs(prev.c - curr.c);\n        if (dist == 0) continue;\n        \n        bool aligned = (prev.r == curr.r) || (prev.c == curr.c);\n        int cost_est = dist;\n        \n        if (aligned) {\n             int dr_dir = (curr.r > prev.r) ? 1 : ((curr.r < prev.r) ? -1 : 0);\n             int dc_dir = (curr.c > prev.c) ? 1 : ((curr.c < prev.c) ? -1 : 0);\n             int br = curr.r + dr_dir;\n             int bc = curr.c + dc_dir;\n             if (!is_valid(br, bc) || grid[idx(br, bc)]) {\n                 bool clear = true;\n                 int cr = prev.r + dr_dir;\n                 int cc = prev.c + dc_dir;\n                 while (cr != curr.r || cc != curr.c) {\n                     if (grid[idx(cr, cc)]) { clear = false; break; }\n                     cr += dr_dir;\n                     cc += dc_dir;\n                 }\n                 if (clear) cost_est = 1;\n             } else {\n                 cost_est = min(dist, max(2, dist/2));\n             }\n        } else {\n             int r_diff = curr.r - prev.r;\n             int c_diff = curr.c - prev.c;\n             bool catcher = false;\n             int vr = curr.r + ((r_diff > 0) ? 1 : -1);\n             int vc = curr.c;\n             if (!is_valid(vr, vc) || grid[idx(vr, vc)]) catcher = true;\n             int hr = curr.r;\n             int hc = curr.c + ((c_diff > 0) ? 1 : -1);\n             if (!is_valid(hr, hc) || grid[idx(hr, hc)]) catcher = true;\n             if (catcher) cost_est = min(dist, max(2, (int)(dist * 0.6)));\n        }\n        h += cost_est;\n    }\n    return h;\n}\n\nbool apply_action(BeamState& s, Action a) {\n    s.history.push_back(a);\n    s.cost += 1;\n    int r = s.pos_idx / N;\n    int c = s.pos_idx % N;\n    if(a.type == 'A') {\n        int nr = r, nc = c;\n        if (a.dir == 'U') nr--; else if (a.dir == 'D') nr++; else if (a.dir == 'L') nc--; else if (a.dir == 'R') nc++;\n        if (!is_valid(nr, nc)) return false;\n        s.grid.flip(idx(nr, nc));\n    } else if (a.type == 'M') {\n        int nr = r, nc = c;\n        if (a.dir == 'U') nr--; else if (a.dir == 'D') nr++; else if (a.dir == 'L') nc--; else if (a.dir == 'R') nc++;\n        if (!is_valid(nr, nc)) return false;\n        if (s.grid[idx(nr, nc)]) return false;\n        s.pos_idx = idx(nr, nc);\n    } else if (a.type == 'S') {\n        int d_idx = (a.dir=='U'?0:(a.dir=='D'?1:(a.dir=='L'?2:3)));\n        int cr = r, cc = c;\n        while(true) {\n            int nr = cr + dr[d_idx];\n            int nc = cc + dc[d_idx];\n            if (!is_valid(nr, nc) || s.grid[idx(nr, nc)]) break;\n            cr = nr; cc = nc;\n        }\n        s.pos_idx = idx(cr, cc);\n    }\n    return true;\n}\n\nbool apply_path(BeamState& s, const vector<Action>& path) {\n    for(const auto& a : path) {\n        if(!apply_action(s, a)) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    auto start_time = chrono::high_resolution_clock::now();\n\n    int _n, _m;\n    if (!(cin >> _n >> _m)) return 0;\n    \n    Point start_pos;\n    cin >> start_pos.r >> start_pos.c;\n    \n    vector<Point> targets(M);\n    targets[0] = start_pos;\n    for(int k=1; k<M; ++k) cin >> targets[k].r >> targets[k].c;\n\n    vector<BeamState> beam;\n    bitset<400> initial_grid; \n    beam.reserve(2000);\n    beam.push_back({0, calc_heuristic(1, initial_grid, targets), idx(start_pos.r, start_pos.c), initial_grid, {}});\n\n    int BEAM_WIDTH = 60; \n\n    for (int k = 0; k < M - 1; ++k) {\n        auto now = chrono::high_resolution_clock::now();\n        auto dur = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (dur > 1800) BEAM_WIDTH = 10;\n        else if (dur > 1500) BEAM_WIDTH = 30;\n        else if (dur > 1000) BEAM_WIDTH = 60;\n        else BEAM_WIDTH = 80;\n\n        int target_idx = idx(targets[k+1].r, targets[k+1].c);\n        vector<BeamState> next_beam;\n        next_beam.reserve(BEAM_WIDTH * 50);\n\n        for (const auto& s : beam) {\n            run_dijkstra_fwd(s.pos_idx, s.grid, dist_start);\n            run_dijkstra_rev(target_idx, s.grid, dist_end);\n            int direct_dist = dist_start[target_idx];\n            \n            if (direct_dist != INF) {\n                BeamState next_s = s; \n                vector<Action> path = extract_path(s.pos_idx, target_idx);\n                if (apply_path(next_s, path)) {\n                    next_s.heuristic = calc_heuristic(k + 2, next_s.grid, targets);\n                    next_beam.push_back(next_s);\n                }\n            }\n\n            // Lookahead 1\n            {\n                Point curr_target = targets[k+1];\n                for (int d = 0; d < 4; ++d) {\n                    int br = curr_target.r + dr[d];\n                    int bc = curr_target.c + dc[d];\n                    if (!is_valid(br, bc)) continue;\n                    int b_idx = idx(br, bc);\n                    if (s.grid[b_idx]) continue;\n\n                    int best_nb = -1; int best_nb_cost = INF;\n                    for(int d2=0; d2<4; ++d2) {\n                        int nr=br+dr[d2], nc=bc+dc[d2];\n                        if(is_valid(nr, nc)) {\n                            int nb = idx(nr, nc);\n                            if(dist_start[nb] < best_nb_cost) { best_nb_cost = dist_start[nb]; best_nb = nb; }\n                        }\n                    }\n                    if (best_nb_cost == INF) continue;\n                    if (best_nb_cost > direct_dist + 2) continue; \n\n                    int opp_d = (d==0?1:(d==1?0:(d==2?3:2)));\n                    int lr = curr_target.r + dr[opp_d];\n                    int lc = curr_target.c + dc[opp_d];\n                    int best_launch_cost = INF;\n                    while(is_valid(lr, lc)) {\n                        int l_idx = idx(lr, lc);\n                        if (s.grid[l_idx]) break;\n                        int dist_nb_l = abs((best_nb/N) - lr) + abs((best_nb%N) - lc);\n                        int total = best_nb_cost + 1 + dist_nb_l + 1;\n                        if (total < best_launch_cost) best_launch_cost = total;\n                        lr += dr[opp_d]; lc += dc[opp_d];\n                    }\n                    if (best_launch_cost > direct_dist + 2) continue; \n\n                    vector<Action> path2 = extract_path_bfs(best_nb, target_idx, s.grid, b_idx);\n                    if (path2.empty() && best_nb != target_idx) continue;\n\n                    vector<Action> path1 = extract_path(s.pos_idx, best_nb);\n                    \n                    BeamState next_s = s;\n                    if(apply_path(next_s, path1)) {\n                        int d_alter = -1;\n                        int nbr = best_nb/N, nbc=best_nb%N;\n                        for(int dd=0; dd<4; ++dd) if(nbr+dr[dd]==br && nbc+dc[dd]==bc) d_alter=dd;\n                        if(d_alter!=-1 && apply_action(next_s, {'A', dir_chars[d_alter]})) {\n                            if(apply_path(next_s, path2)) {\n                                next_s.heuristic = calc_heuristic(k+2, next_s.grid, targets);\n                                next_beam.push_back(next_s);\n                            }\n                        }\n                    }\n                }\n            }\n\n            // Lookahead 2+\n            for (int lookahead = 2; lookahead <= 4; ++lookahead) {\n                if (k + lookahead >= M) break;\n                \n                Point future_target = targets[k+lookahead];\n                int rd = future_target.r - targets[k+lookahead-1].r;\n                int cd = future_target.c - targets[k+lookahead-1].c;\n                vector<int> useful_dirs;\n                if (abs(rd) >= abs(cd)) { useful_dirs.push_back(rd > 0 ? 1 : 0); if (cd != 0) useful_dirs.push_back(cd > 0 ? 3 : 2); } \n                else { useful_dirs.push_back(cd > 0 ? 3 : 2); if (rd != 0) useful_dirs.push_back(rd > 0 ? 1 : 0); }\n                \n                for (int d : useful_dirs) {\n                    int br = future_target.r + dr[d];\n                    int bc = future_target.c + dc[d];\n                    if (!is_valid(br, bc)) continue;\n                    int b_idx = idx(br, bc);\n                    if (s.grid[b_idx]) continue; \n\n                    int best_nb_cost = INF;\n                    int best_nb_idx = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int nbr = br + dr[d2];\n                        int nbc = bc + dc[d2];\n                        if (!is_valid(nbr, nbc)) continue;\n                        int nb = idx(nbr, nbc);\n                        if (dist_start[nb] < best_nb_cost) {\n                            best_nb_cost = dist_start[nb];\n                            best_nb_idx = nb;\n                        }\n                    }\n                    \n                    if (best_nb_cost == INF || dist_end[best_nb_idx] == INF) continue;\n\n                    int total_est = best_nb_cost + 1 + dist_end[best_nb_idx];\n                    int threshold = direct_dist + (lookahead == 2 ? 10 : 4);\n                    if (total_est > threshold) continue;\n                    \n                    // Only verify exact cost if heuristic passed\n                    run_dijkstra_fwd(best_nb_idx, s.grid, dist_start, b_idx); \n                    if (nodes[target_idx].dist == INF) continue;\n                    if (best_nb_cost + 1 + nodes[target_idx].dist > threshold) continue;\n                    \n                    vector<Action> path2 = extract_path(best_nb_idx, target_idx);\n                    run_dijkstra_fwd(s.pos_idx, s.grid, dist_start); \n                    vector<Action> path1 = extract_path(s.pos_idx, best_nb_idx);\n                    \n                    BeamState next_s = s;\n                    if (apply_path(next_s, path1)) {\n                        int d_alter = -1;\n                        int nbr = best_nb_idx / N, nbc = best_nb_idx % N;\n                        for(int dd=0; dd<4; ++dd) if(nbr + dr[dd] == br && nbc + dc[dd] == bc) d_alter = dd;\n                        if (d_alter != -1 && apply_action(next_s, {'A', dir_chars[d_alter]})) {\n                            if (apply_path(next_s, path2)) {\n                                next_s.heuristic = calc_heuristic(k + 2, next_s.grid, targets);\n                                next_beam.push_back(next_s);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        sort(next_beam.begin(), next_beam.end());\n        \n        beam.clear();\n        if (!next_beam.empty()) {\n            beam.push_back(next_beam[0]);\n            for(size_t i=1; i<next_beam.size(); ++i) {\n                if (beam.size() >= BEAM_WIDTH) break;\n                if (next_beam[i].pos_idx == beam.back().pos_idx && \n                    next_beam[i].cost == beam.back().cost && \n                    next_beam[i].grid == beam.back().grid) {\n                    continue;\n                }\n                beam.push_back(next_beam[i]);\n            }\n        }\n        if (beam.empty()) break;\n    }\n    \n    if (!beam.empty()) {\n        for (const auto& a : beam[0].history) {\n            cout << a.type << \" \" << a.dir << \"\\n\";\n        }\n    }\n\n    return 0;\n}"}}}